Skip to content

Commit

Permalink
starting work on constructor redesign
Browse files Browse the repository at this point in the history
(issue #30)
  • Loading branch information
JeffBezanson committed Jun 10, 2011
1 parent 8087829 commit 3d4b00a
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 76 deletions.
13 changes: 4 additions & 9 deletions j/io.j
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,17 @@ sizeof_fd_set = ccall(:jl_sizeof_fd_set, Int32, ())
type IOStream
ios::Array{Uint8,1}

global make_stdout_stream, close

function close(s::IOStream)
ccall(:ios_close, Void, (Ptr{Void},), s.ios)
end

# TODO: delay adding finalizer, e.g. for memio with a small buffer, or
# in the case where we takebuf it.
IOStream() = (x = new(zeros(Uint8,sizeof_ios_t));
finalizer(x, close);
x)

make_stdout_stream() =
new(ccall(:jl_stdout_stream, Any, ()))
end

close(s::IOStream) = ccall(:ios_close, Void, (Ptr{Void},), s.ios)

make_stdout_stream() = new(ccall(:jl_stdout_stream, Any, ()))

fdio(fd::Int) = (s = IOStream();
ccall(:ios_fd, Void,
(Ptr{Uint8}, Long, Int32), s.ios, long(fd), 0);
Expand Down
36 changes: 26 additions & 10 deletions j/string.j
Original file line number Diff line number Diff line change
Expand Up @@ -145,10 +145,10 @@ end
type CharString <: String
chars::Array{Char,1}

CharString(a::Array{Char,1}) = new(a)
CharString(c::Char...) = new([ c[i] | i=1:length(c) ])
CharString(x...) = CharString(map(char,x)...)
CharString(a::Array{Char,1}) = (this.chars=a)
CharString(c::Char...) = (this.chars=[ c[i] | i=1:length(c) ])
end
CharString(x...) = CharString(map(char,x)...)

next(s::CharString, i::Index) = (s.chars[i], i+1)
length(s::CharString) = length(s.chars)
Expand All @@ -164,9 +164,12 @@ type SubString <: String
offset::Index
length::Index

SubString(s::String, i::Index, j::Index) = new(s, i-1, j-i+1)
SubString(s::SubString, i::Index, j::Index) =
new(s.string, i-1+s.offset, j-i+1)
SubString(s::String, i::Index, j::Index) = (this.string = s;
this.offset = i;
this.length = j)
SubString(s::SubString, i::Index, j::Index) = (this.string = s;
this.offset = i-1+s.offset;
this.length = j-i+1)
end

function next(s::SubString, i::Index)
Expand Down Expand Up @@ -230,20 +233,33 @@ type RopeString <: String
RopeString(h::RopeString, t::RopeString) =
depth(h.tail) + depth(t) < depth(h.head) ?
RopeString(h.head, RopeString(h.tail, t)) :
new(h, t, max(h.depth, t.depth)+1, length(h)+length(t))
new(h,
t,
max(h.depth,
t.depth)+1,
length(h)+length(t))

RopeString(h::RopeString, t::String) =
depth(h.tail) < depth(h.head) ?
RopeString(h.head, RopeString(h.tail, t)) :
new(h, t, h.depth+1, length(h)+length(t))
new(h,
t,
h.depth+1,
length(h)+length(t))

RopeString(h::String, t::RopeString) =
depth(t.head) < depth(t.tail) ?
RopeString(RopeString(h, t.head), t.tail) :
new(h, t, t.depth+1, length(h)+length(t))
new(h,
t,
t.depth+1,
length(h)+length(t))

RopeString(h::String, t::String) =
new(h, t, 1, length(h)+length(t))
new(h,
t,
1,
length(h)+length(t))
end

depth(s::String) = 0
Expand Down
20 changes: 11 additions & 9 deletions j/table.j
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,15 @@ type HashTable{K,V}
deleted::IntSet
deleter::Function

HashTable() = HashTable(Any,Any)
HashTable(n::Int) = HashTable(Any,Any,n)
HashTable(k, v) = HashTable(k, v, 16)
HashTable(k, v, n) = (n = _tablesz(n);
new(Array(k,n), Array(v,n), IntSet(n+1), IntSet(n+1),
identity))
HashTable(n) = (n = _tablesz(n);
this.keys = Array(K,n);
this.vals = Array(V,n);
this.used = IntSet(n+1);
this.deleted = IntSet(n+1);
this.deleter = identity)
end
HashTable() = HashTable(0)
HashTable(n::Int) = HashTable{Any,Any}(n)

hashindex(key, sz) = (int32(hash(key)) & (sz-1)) + 1

Expand All @@ -107,7 +109,7 @@ function rehash{K,V}(h::HashTable{K,V}, newsz)
oldv = h.vals
oldu = h.used
oldd = h.deleted
newht = HashTable(K,V,newsz)
newht = HashTable{K,V}(newsz)

for i = oldu
if !has(oldd,i)
Expand Down Expand Up @@ -273,9 +275,9 @@ end
type WeakKeyHashTable{K,V}
ht::HashTable{K,V}
WeakKeyHashTable() = new(HashTable())
WeakKeyHashTable(k, v) = new(HashTable(k, v))
WeakKeyHashTable() = (this.ht = HashTable{K,V}(0))
end
WeakKeyHashTable() = WeakKeyHashTable{Any,Any}()
assign(wkh::WeakKeyHashTable, v, key) = add_weak_key(wkh.ht, key, v)
Expand Down
2 changes: 1 addition & 1 deletion j/tree.j
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ end
type BTree{K,V}
root:: Tree{K,V}

BTree(k,v) = new(EmptyTree{k,v}())
BTree() = (this.root = EmptyTree{K,V}())
end

has(t::EmptyTree, key) = false
Expand Down
1 change: 1 addition & 0 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *ex, int fast)
int i;
for(i=0; i < vinfos->length; i++) {
if (jl_cellref(jl_cellref(vinfos,i),2)!=jl_false) {
// interpreter doesn't handle closure environment
ewc = 1;
break;
}
Expand Down
3 changes: 3 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1654,13 +1654,15 @@ static void init_julia_llvm_env(Module *m)
Function::Create(FunctionType::get(T_void, args1, false),
Function::ExternalLinkage,
"jl_error", jl_Module);
jlerror_func->setDoesNotReturn();
jl_ExecutionEngine->addGlobalMapping(jlerror_func, (void*)&jl_error);

std::vector<const Type*> empty_args(0);
jluniniterror_func =
Function::Create(FunctionType::get(T_void, empty_args, false),
Function::ExternalLinkage,
"jl_undef_ref_error", jl_Module);
jluniniterror_func->setDoesNotReturn();
jl_ExecutionEngine->addGlobalMapping(jluniniterror_func,
(void*)&jl_undef_ref_error);

Expand All @@ -1678,6 +1680,7 @@ static void init_julia_llvm_env(Module *m)
Function::Create(FunctionType::get(T_void, te_args, false),
Function::ExternalLinkage,
"jl_type_error_rt", jl_Module);
jltypeerror_func->setDoesNotReturn();
jl_ExecutionEngine->addGlobalMapping(jltypeerror_func,
(void*)&jl_type_error_rt);

Expand Down
19 changes: 15 additions & 4 deletions src/interpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,21 +228,32 @@ static jl_value_t *eval_body(jl_array_t *stmts, jl_value_t **locals, size_t nl,
return NULL;
}

jl_value_t *jl_interpret_toplevel_thunk(jl_lambda_info_t *lam)
jl_value_t *jl_interpret_toplevel_thunk_with(jl_lambda_info_t *lam,
jl_value_t **loc, size_t nl)
{
jl_expr_t *ast = (jl_expr_t*)lam->ast;
jl_array_t *stmts = jl_lam_body(ast)->args;
jl_array_t *l = jl_lam_locals(ast);
jl_value_t **names = &((jl_value_t**)l->data)[0];
jl_value_t **locals = (jl_value_t**)alloca(l->length*2*sizeof(void*));
nl += l->length;
jl_value_t **locals = (jl_value_t**)alloca(nl*2*sizeof(void*));
jl_value_t *r = (jl_value_t*)jl_null;
size_t i=0;
for(i=0; i < l->length; i++) {
locals[i*2] = names[i];
locals[i*2+1] = NULL;
}
JL_GC_PUSHARGS(locals, l->length*2);
r = eval_body(stmts, locals, l->length, 0);
for(; i < nl; i++) {
locals[i*2] = loc[(i-l->length)*2];
locals[i*2+1] = loc[(i-l->length)*2+1];
}
JL_GC_PUSHARGS(locals, nl*2);
r = eval_body(stmts, locals, nl, 0);
JL_GC_POP();
return r;
}

jl_value_t *jl_interpret_toplevel_thunk(jl_lambda_info_t *lam)
{
return jl_interpret_toplevel_thunk_with(lam, NULL, 0);
}
124 changes: 81 additions & 43 deletions src/julia-syntax.scm
Original file line number Diff line number Diff line change
Expand Up @@ -243,18 +243,67 @@
(params bounds) (sparam-name-bounds params '() '())
(struct-def-expr- name params bounds super fields)))

(define *ctor-factory-name* (gensym))
(define (default-inner-ctor name field-names field-types)
`(function (call ,name ,@(map (lambda (n t) `(:: ,n ,t))
field-names field-types))
(block
,@(map (lambda (n) `(= (|.| this ,n) ,n))
field-names))))

(define (default-outer-ctor name field-names field-types params)
`(function (call (curly ,name ,@params)
,@(map (lambda (n t) `(:: ,n ,t))
field-names field-types))
(block
(call (curly ,name ,@params) ,@field-names))))

(define (rewrite-ctor ctor Tname params)
;; insert definition and return of "this" variable
(define (ctor-body body)
`(block ;; hack - make the type parameters "global" so they can be
;; shadowed by static parameters
(global (vars ,Tname ,@params))
(= this (new ,(if (null? params)
Tname
`(curly ,Tname ,@params))))
,body
(return this)))
;; TODO: error if return occurs in constructor
(or
((pattern-lambda (function (call name . sig) body)
(if (eq? name Tname)
`(function ,(cadr ctor) ,(ctor-body body))
ctor))
ctor)
((pattern-lambda (= (call name . sig) body)
(if (eq? name Tname)
`(= ,(cadr ctor) ,(ctor-body body))
ctor))
ctor)
((pattern-lambda (function (call (curly name . p) . sig) body)
(if (eq? name Tname)
`(function ,(cadr ctor) ,(ctor-body body))
ctor))
ctor)
((pattern-lambda (= (call (curly name . p) . sig) body)
(if (eq? name Tname)
`(= ,(cadr ctor) ,(ctor-body body))
ctor))
ctor)
ctor))

(define (struct-def-expr- name params bounds super fields)
(receive
(fields defs) (separate (lambda (x) (or (symbol? x)
(and (pair? x)
(eq? (car x) '|::|))))
fields)
(let ((field-names (map decl-var fields))
(field-types (map decl-type fields))
(T (gensym)))
(if (and (null? defs) (null? params))
(let* ((field-names (map decl-var fields))
(field-types (map decl-type fields))
(defs2 (if (null? defs)
(list (default-inner-ctor name field-names field-types))
defs)))
(if (null? params)
`(block
(= ,name
(call (top new_struct_type)
Expand All @@ -263,44 +312,33 @@
(tuple ,@(map (lambda (x) `',x) field-names))
(null)))
(call (top new_struct_fields)
,name ,super (tuple ,@field-types)))
`(call
(lambda (,@params)
; the static parameters are bound to new TypeVars in here,
; so everything that sees the TypeVars is evaluated here.
(block
(local! ,*ctor-factory-name*)
(local! ,T)
,(if (null? defs)
`(null)
; create a function that defines constructors, given
; the type and a "new" function.
; a mild hack to feed inference the type of "new":
; when "new" is created internally by the runtime, it is
; tagged with a specific function type. this type is captured
; as a static parameter which is visible to inference through
; a declaration.
`(scope-block
(block
(function (call (curly ,*ctor-factory-name* ,T)
,name (|::| new ,T))
(block
(|::| new ,T)
,@defs
(null))))))
(= ,name
(call (top new_struct_type)
(quote ,name)
(tuple ,@params)
(tuple ,@(map (lambda (x) `',x) field-names))
,(if (null? defs)
`(null)
; pass constructor factory function
*ctor-factory-name*)))
; now add the type fields, which might reference the type itself.
(call (top new_struct_fields)
,name ,super (tuple ,@field-types))))
,@(symbols->typevars params bounds))))))
,name ,super (tuple ,@field-types))
,@(map (lambda (c)
(rewrite-ctor c name '()))
defs2)
(null))
`(block
(call
(lambda (,@params)
(block
(= ,name
(call (top new_struct_type)
(quote ,name)
(tuple ,@params)
(tuple ,@(map (lambda (x) `',x) field-names))
(lambda (,name ,@params)
(scope-block
(block
,@(map (lambda (c)
(rewrite-ctor c name params))
defs2))))))
(call (top new_struct_fields)
,name ,super (tuple ,@field-types))))
,@(symbols->typevars params bounds))
,@(if (null? defs)
`(,(default-outer-ctor name field-names field-types params))
'())
(null))))))

(define (abstract-type-def-expr name params super)
(receive
Expand Down

0 comments on commit 3d4b00a

Please sign in to comment.