diff --git a/j/base.j b/j/base.j index 24b000b01c3d2..b9f288ab944b2 100644 --- a/j/base.j +++ b/j/base.j @@ -1,5 +1,67 @@ # important core definitions +convert(T, x) = convert_default(T, x, convert) +convert(T::Tuple, x::Tuple) = convert_tuple(T, x, convert) + +type ErrorException <: Exception + msg::String +end + +type SystemError <: Exception + prefix::String + errnum::Int32 + SystemError(p::String, e::Integer) = new(p, int32(e)) + SystemError(p::String) = new(p, errno()) +end + +type TypeError <: Exception + func::Symbol + context::String + expected::Type + got +end + +type ParseError <: Exception + msg::String +end + +type ArgumentError <: Exception + msg::String +end + +type UnboundError <: Exception + var::Symbol +end + +type KeyError <: Exception + key +end + +type LoadError <: Exception + file::String + line::Int32 + error +end + +type MethodError <: Exception + f + args +end + +type UnionTooComplexError <: Exception + types::Tuple +end + +type BackTrace <: Exception + e + trace::Array{Any,1} +end + +method_missing(f, args...) = throw(MethodError(f, args)) + +ccall(:jl_get_system_hooks, Void, ()) + + int(x) = convert(Int, x) int(x::Int) = x uint(x) = convert(Uint, x) @@ -72,6 +134,9 @@ function compile_hint(f, args::Tuple) nothing end +# we share Array with Base so we can add definitions to it +const Array = eval(Base, :Array) + Array{T} (::Type{T}, d::(Integer,)) = ccall(:jl_alloc_array_1d, Array{T,1}, (Any,Int), Array{T,1}, int(d[1])) diff --git a/j/inference.j b/j/inference.j index 6392f7e0526cb..a9df861dbbd1b 100644 --- a/j/inference.j +++ b/j/inference.j @@ -158,23 +158,27 @@ function static_convert(to::ANY, from::ANY) end # tuple conversion calls convert recursively if isseqtype(ce) - R = abstract_call_gf(convert, (), (Type{pe}, ce.parameters[1]), ()) + #R = abstract_call_gf(convert, (), (Type{pe}, ce.parameters[1]), ()) + R = static_convert(pe, ce.parameters[1]) isType(R) && (R = R.parameters[1]) result[i] = ...{R} else - R = abstract_call_gf(convert, (), (Type{pe}, ce), ()) + #R = abstract_call_gf(convert, (), (Type{pe}, ce), ()) + R = static_convert(pe, ce) isType(R) && (R = R.parameters[1]) result[i] = R end end a2t(result) end -t_func[:convert] = - (2, 2, (t,x)->(if isa(t,Tuple) && allp(isType,t) - t = Type{map(t->t.parameters[1],t)} - end; - isType(t) ? static_convert(t.parameters[1],x) : - Any)) +t_func[convert_default] = + (3, 3, (t,x,f)->(isType(t) ? static_convert(t.parameters[1],x) : Any)) +t_func[convert_tuple] = + (3, 3, (t,x,f)->(if isa(t,Tuple) && allp(isType,t) + t = Type{map(t->t.parameters[1],t)} + end; + isType(t) ? static_convert(t.parameters[1],x) : + Any)) typeof_tfunc = function (t) if isType(t) t = t.parameters[1] @@ -486,6 +490,9 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e) end end end + if !is(f,apply) && isa(e,Expr) && isa(f,Function) + e.head = :call1 + end rt = builtin_tfunction(f, fargs, argtypes) #print("=> ", rt, "\n") return rt @@ -497,8 +504,8 @@ function abstract_call(f, fargs, argtypes, vtypes, sv::StaticVarInfo, e) end end -ft_tfunc(ft, argtypes) = ccall(:jl_func_type_tfunc, Any, - (Any, Any), ft, argtypes) +ft_tfunc(ft, argtypes) = ccall(:jl_func_type_tfunc, Any, (Any, Any), + ft, argtypes) function abstract_eval_call(e, vtypes, sv::StaticVarInfo) fargs = a2t_butfirst(e.args) @@ -828,10 +835,6 @@ end typeinf(linfo,atypes,sparams) = typeinf(linfo,atypes,sparams,linfo,true) typeinf(linfo,atypes,sparams,linfo) = typeinf(linfo,atypes,sparams,linfo,true) -abstract RecPending{T} - -isRecPending(t) = isa(t, AbstractKind) && is(t.name, RecPending.name) - ast_rettype(ast) = ast.args[3].typ # def is the original unspecialized version of a method. we aggregate all @@ -840,8 +843,6 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) #dbg = #dotrace = true#is(linfo,sizestr) local ast::Expr - redo = false - curtype = None # check cached t-functions tf = def.tfunc while !is(tf,()) @@ -853,15 +854,9 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) # if the frame above this one recurred, rerun type inf # here instead of returning, and update the cache, until the new # inferred type equals the cached type (fixed point) - rt = ast_rettype(tf[2]) - if isRecPending(rt) - curtype = rt.parameters[1] - redo = true - ast = tf[2] - break - else - return (tf[2], rt) - end + ast = tf[2] + rt = ast_rettype(ast) + return (ast, rt) end tf = tf[3] end @@ -893,12 +888,9 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) f = f.prev end - rec = false - #print("typeinf ", linfo.name, " ", atypes, "\n") - if redo - elseif cop + if cop sparams = append(sparams, linfo.sparams) ast = ccall(:jl_prepare_ast, Any, (Any,Any), linfo, sparams)::Expr else @@ -910,8 +902,20 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) locals = (ast.args[2].args[1].args)::Array{Any,1} vars = append(args, locals) body = (ast.args[3].args)::Array{Any,1} - n = length(body) + + # our stack frame + frame = CallStack(ast0, linfo.module, atypes, inference_stack) + inference_stack = frame + curtype = None + frame.result = curtype + + local s, sv + + while true + + rec = false + s = { () | i=1:n } recpts = IntSet(n+1) # statements that depend recursively on our value W = IntSet(n+1) @@ -958,11 +962,6 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) end sv = StaticVarInfo(sparams, cenv) - # our stack frame - frame = CallStack(ast0, linfo.module, atypes, inference_stack) - frame.result = curtype - inference_stack = frame - # exception handlers cur_hand = () handler_at = { () | i=1:n } @@ -1069,23 +1068,23 @@ function typeinf(linfo::LambdaStaticData,atypes::Tuple,sparams::Tuple, def, cop) end #print("\n",ast,"\n") #print("==> ", frame.result,"\n") - if redo && typeseq(curtype, frame.result) - rec = false - end - fulltree = type_annotate(ast, s, sv, - rec ? RecPending{frame.result} : frame.result, - vars) - if !rec - fulltree.args[3] = inlining_pass(fulltree.args[3], s[1]) - tuple_elim_pass(fulltree) - linfo.inferred = true - end - if !redo - compressed = ccall(:jl_compress_ast, Any, (Any,), fulltree) - fulltree = compressed - #compressed = fulltree - def.tfunc = (atypes, compressed, def.tfunc) - end + if !rec || typeseq(curtype, frame.result) + break + end + curtype = frame.result + end # while + + fulltree = type_annotate(ast, s, sv, frame.result, vars) + + fulltree.args[3] = inlining_pass(fulltree.args[3], s[1]) + tuple_elim_pass(fulltree) + linfo.inferred = true + + compressed = ccall(:jl_compress_ast, Any, (Any,), fulltree) + fulltree = compressed + #compressed = fulltree + def.tfunc = (atypes, compressed, def.tfunc) + inference_stack = (inference_stack::CallStack).prev return (fulltree, frame.result) end @@ -1173,11 +1172,6 @@ function type_annotate(ast::Expr, states::Array{Any,1}, end end - # do inference on inner functions - if isRecPending(rettype) - return ast - end - for li in closures if !li.inferred a = li.ast @@ -1286,6 +1280,15 @@ end function inlineable(f, e::Expr, vars) argexprs = a2t_butfirst(e.args) atypes = map(exprtype, argexprs) + + if is(f, convert_default) && length(atypes)==3 + # builtin case of convert. convert(T,x::S) => x, when S<:T + if isType(atypes[1]) && subtype(atypes[2],atypes[1].parameters[1]) + # todo: if T expression has side effects??! + return e.args[3] + end + end + meth = getmethods(f, atypes) if length(meth) != 1 return NF @@ -1297,13 +1300,6 @@ function inlineable(f, e::Expr, vars) if !subtype(atypes, meth[1]) return NF end - if is(meth[3],:convert) && length(atypes)==2 - # builtin case of convert. convert(T,x::S) => x, when S<:T - if isType(atypes[1]) && subtype(atypes[2],atypes[1].parameters[1]) - # todo: if T expression has side effects??! - return e.args[3] - end - end if !isa(meth[3],LambdaStaticData) || !is(meth[4],()) return NF end diff --git a/j/show.j b/j/show.j index 8621e4cf6331e..ef4bbc38b77e5 100644 --- a/j/show.j +++ b/j/show.j @@ -1,3 +1,8 @@ +# formerly built-in methods. can be replaced any time. +print(a::Array{Uint8,1}) = ccall(:jl_print_array_uint8, Void, (Any,), a) +print(s::Symbol) = ccall(:jl_print_symbol, Void, (Any,), s) +show(x) = ccall(:jl_show_any, Void, (Any,), x) + print(x) = show(x) showcompact(x) = show(x) show_to_string(x) = print_to_string(show, x) @@ -7,7 +12,7 @@ show(s::Symbol) = print(s) show(tn::TypeName) = show(tn.name) show(::Nothing) = print("nothing") show(b::Bool) = print(b ? "true" : "false") -show(n::Integer) = show(int64(n)) +show(n::Integer) = print(dec(int64(n))) function show_trailing_hex(n::Uint64, ndig::Integer) for s = ndig-1:-1:0 diff --git a/j/stage0.j b/j/stage0.j index 572de5ba3a162..4fe88b5c13057 100644 --- a/j/stage0.j +++ b/j/stage0.j @@ -4,14 +4,17 @@ if false # simple print definitions for debugging. enable these if something # goes wrong during bootstrap before printing code is available. length(a::Array) = arraylen(a) + print(a::Array{Uint8,1}) = ccall(:jl_print_array_uint8, Void, (Any,), a) + print(s::Symbol) = ccall(:jl_print_symbol, Void, (Any,), s) print(s::ASCIIString) = print(s.data) print(x) = show(x) println(x) = (print(x);print("\n")) + show(x) = ccall(:jl_show_any, Void, (Any,), x) show(s::ASCIIString) = print(s.data) show(s::Symbol) = print(s) show(b::Bool) = print(b ? "true" : "false") + show(n::Int64) = ccall(:jl_print_int64, Void, (Int64,), n) show(n::Integer) = show(int64(n)) - show(n::Unsigned) = show(uint64(n)) print(a...) = for x=a; print(x); end function show(e::Expr) print(e.head) diff --git a/src/alloc.c b/src/alloc.c index cc19fbdcc9d45..6e9923619baf0 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -32,7 +32,6 @@ jl_typename_t *jl_array_typename; jl_type_t *jl_array_uint8_type; jl_type_t *jl_array_any_type; jl_struct_type_t *jl_weakref_type; -jl_tag_type_t *jl_string_type; jl_struct_type_t *jl_ascii_string_type; jl_struct_type_t *jl_utf8_string_type; jl_struct_type_t *jl_expr_type; @@ -70,7 +69,7 @@ jl_sym_t *goto_sym; jl_sym_t *goto_ifnot_sym; jl_sym_t *label_sym; jl_sym_t *return_sym; jl_sym_t *lambda_sym; jl_sym_t *assign_sym; jl_sym_t *null_sym; jl_sym_t *body_sym; -jl_sym_t *isbound_sym; jl_sym_t *macro_sym; +jl_sym_t *macro_sym; jl_sym_t *locals_sym; jl_sym_t *colons_sym; jl_sym_t *Any_sym; jl_sym_t *method_sym; jl_sym_t *enter_sym; jl_sym_t *leave_sym; @@ -625,18 +624,6 @@ jl_typector_t *jl_new_type_ctor(jl_tuple_t *params, jl_type_t *body) return (jl_typector_t*)tc; } -// struct constructors -------------------------------------------------------- - -JL_CALLABLE(jl_weakref_ctor) -{ - if (nargs > 1) { - JL_NARGS(WeakRef, 1, 1); - } - if (nargs == 1) - return (jl_value_t*)jl_gc_new_weakref(args[0]); - return (jl_value_t*)jl_gc_new_weakref((jl_value_t*)jl_nothing); -} - // bits constructors ---------------------------------------------------------- #define BOX_FUNC(typ,c_type,pfx,nw) \ diff --git a/src/boot.j b/src/boot.j index 4254d8d51d692..167bb0c9f2cbf 100644 --- a/src/boot.j +++ b/src/boot.j @@ -149,96 +149,45 @@ else const boxuint = boxui32 end -type WeakRef - value -end +abstract Exception + +type BoundsError <: Exception end +type DivideByZeroError <: Exception end +type MemoryError <: Exception end +type IOError <: Exception end +type StackOverflowError <: Exception end +type EOFError <: Exception end +type UndefRefError <: Exception end +type InterruptException <: Exception end abstract String abstract DirectIndexString <: String -type ASCIIString <: DirectIndexString - data::Array{Uint8,1} -end -type UTF8String <: String - data::Array{Uint8,1} -end - -typealias ByteString Union(ASCIIString,UTF8String) - abstract Associative +# simple convert for use by constructors of types in Base +convert(T, x) = convert_default(T, x, convert) + type SymbolNode name::Symbol typ + SymbolNode(name::Symbol, t::ANY) = new(name, t) end -abstract Exception - -type ErrorException <: Exception - msg::String -end - -type SystemError <: Exception - prefix::String - errnum::Int32 - SystemError(p::String, e::Integer) = new(p, int32(e)) - SystemError(p::String) = new(p, errno()) -end - -type TypeError <: Exception - func::Symbol - context::String - expected::Type - got -end - -type ParseError <: Exception - msg::String -end - -type ArgumentError <: Exception - msg::String -end - -type BoundsError <: Exception -end - -type UnboundError <: Exception - var::Symbol -end - -type KeyError <: Exception - key -end - -type LoadError <: Exception - file::String - line::Int32 - error -end - -type MethodError <: Exception - f - args +type WeakRef + value + WeakRef() = WeakRef(nothing) + WeakRef(v::ANY) = ccall(:jl_gc_new_weakref, WeakRef, (Any,), v) end -type DivideByZeroError <: Exception end -type MemoryError <: Exception end -type IOError <: Exception end -type StackOverflowError <: Exception end -type EOFError <: Exception end -type UndefRefError <: Exception end -type InterruptException <: Exception end - -type UnionTooComplexError <: Exception - types::Tuple +type ASCIIString <: DirectIndexString + data::Array{Uint8,1} end -type BackTrace <: Exception - e - trace::Array{Any,1} +type UTF8String <: String + data::Array{Uint8,1} end -method_missing(f, args...) = throw(MethodError(f, args)) +typealias ByteString Union(ASCIIString,UTF8String) load(fname::ByteString) = ccall(:jl_load, Void, (Ptr{Uint8},), fname) diff --git a/src/builtin_proto.h b/src/builtin_proto.h index 2fc1ea22c9204..a818c7c8cb5ad 100644 --- a/src/builtin_proto.h +++ b/src/builtin_proto.h @@ -5,7 +5,6 @@ JL_CALLABLE(jl_f_new_expr); JL_CALLABLE(jl_f_new_box); -JL_CALLABLE(jl_weakref_ctor); JL_CALLABLE(jl_f_throw); JL_CALLABLE(jl_f_is); JL_CALLABLE(jl_f_no_function); @@ -27,14 +26,10 @@ JL_CALLABLE(jl_f_arrayref); JL_CALLABLE(jl_f_arrayset); JL_CALLABLE(jl_f_arraysize); JL_CALLABLE(jl_f_instantiate_type); -JL_CALLABLE(jl_f_convert); +JL_CALLABLE(jl_f_convert_default); JL_CALLABLE(jl_f_convert_tuple); -JL_CALLABLE(jl_f_print_array_uint8); -JL_CALLABLE(jl_f_show_int64); -JL_CALLABLE(jl_f_show_uint64); JL_CALLABLE(jl_f_show_linfo); JL_CALLABLE(jl_f_show_any); -JL_CALLABLE(jl_f_print_symbol); JL_CALLABLE(jl_trampoline); JL_CALLABLE(jl_f_new_struct_type); JL_CALLABLE(jl_f_new_struct_fields); diff --git a/src/builtins.c b/src/builtins.c index c61f7446765c8..05f62f375dbdb 100644 --- a/src/builtins.c +++ b/src/builtins.c @@ -17,7 +17,7 @@ #include "julia.h" #include "builtin_proto.h" -// --- exceptions --- +// exceptions ----------------------------------------------------------------- DLLEXPORT char *julia_home = NULL; @@ -112,7 +112,7 @@ void jl_pop_handler(int n) } } -// --- primitives --- +// primitives ----------------------------------------------------------------- JL_CALLABLE(jl_f_is) { @@ -231,7 +231,7 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex, volatile size_t *plineno) if (name == jl_current_module->name) { jl_errorf("module name %s conflicts with enclosing module", name->name); } - jl_binding_t *b = jl_get_binding(jl_current_module, name); + jl_binding_t *b = jl_get_binding_wr(jl_current_module, name); jl_declare_constant(b); if (b->value != NULL) { ios_printf(ios_stderr, "Warning: redefinition of module %s ignored\n", @@ -275,8 +275,8 @@ jl_value_t *jl_eval_module_expr(jl_expr_t *ex, volatile size_t *plineno) static int is_intrinsic(jl_sym_t *s) { - jl_value_t **bp = jl_get_bindingp(jl_current_module, s); - return (*bp != NULL && jl_typeof(*bp)==(jl_type_t*)jl_intrinsic_type); + jl_value_t *v = jl_get_global(jl_current_module, s); + return (v != NULL && jl_typeof(v)==(jl_type_t*)jl_intrinsic_type); } static int has_intrinsics(jl_expr_t *e) @@ -325,6 +325,8 @@ static int eval_with_compiler_p(jl_expr_t *expr, int compileloops) jl_value_t *jl_new_closure_internal(jl_lambda_info_t *li, jl_value_t *env); +extern int jl_in_inference; + jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, volatile size_t *plineno) { @@ -334,8 +336,7 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, return jl_interpret_toplevel_expr(e); jl_expr_t *ex = (jl_expr_t*)e; - if (ex->head == null_sym || ex->head == isbound_sym || - ex->head == error_sym) { + if (ex->head == null_sym || ex->head == error_sym) { // expression types simple enough not to need expansion return jl_interpret_toplevel_expr(e); } @@ -387,6 +388,9 @@ jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, if (ewc) { thunk = jl_new_closure_internal(thk, (jl_value_t*)jl_null); + if (fast && !jl_in_inference) { + jl_type_infer(thk, jl_tuple_type, thk); + } result = jl_apply((jl_function_t*)thunk, NULL, 0); } else { @@ -645,7 +649,16 @@ JL_CALLABLE(jl_f_field_type) return jl_tupleref(st->types, i); } -// --- conversions --- +// conversion ----------------------------------------------------------------- + +static jl_value_t *convert(jl_type_t *to, jl_value_t *x, jl_function_t *conv_f) +{ + jl_value_t *args[2]; + if (jl_subtype(x, (jl_value_t*)to, 1)) + return x; + args[0] = (jl_value_t*)to; args[1] = x; + return jl_apply(conv_f, args, 2); +} JL_CALLABLE(jl_f_convert_tuple) { @@ -658,6 +671,7 @@ JL_CALLABLE(jl_f_convert_tuple) JL_GC_PUSH(&out); jl_value_t *ce, *pe=NULL; int pseq=0; + jl_function_t *f = (jl_function_t*)args[2]; for(i=0; i < cl; i++) { ce = jl_tupleref(x,i); if (pseq) { @@ -674,7 +688,7 @@ JL_CALLABLE(jl_f_convert_tuple) break; } assert(pe != NULL); - jl_tupleset(out, i, jl_convert((jl_type_t*)pe, ce)); + jl_tupleset(out, i, convert((jl_type_t*)pe, ce, f)); } JL_GC_POP(); if (out == NULL) @@ -682,23 +696,12 @@ JL_CALLABLE(jl_f_convert_tuple) return (jl_value_t*)out; } -jl_function_t *jl_convert_gf; - -jl_value_t *jl_convert(jl_type_t *to, jl_value_t *x) -{ - jl_value_t *args[2]; - args[0] = (jl_value_t*)to; args[1] = x; - return jl_apply(jl_convert_gf, args, 2); -} - -JL_CALLABLE(jl_f_convert) +JL_CALLABLE(jl_f_convert_default) { - JL_NARGS(convert, 2, 2); - JL_TYPECHK(convert, type, args[0]); jl_type_t *to = (jl_type_t*)args[0]; jl_value_t *x = args[1]; if (!jl_subtype(x, (jl_value_t*)to, 1)) { - jl_no_method_error(jl_convert_gf, args, 2); + jl_no_method_error((jl_function_t*)args[2], args, 2); } return x; } @@ -713,21 +716,23 @@ DLLEXPORT void *jl_array_ptr(jl_array_t *a) return a->data; } -// --- printing --- +// printing ------------------------------------------------------------------- -JL_CALLABLE(jl_f_print_array_uint8) +DLLEXPORT void jl_print_array_uint8(jl_array_t *b) { - ios_t *s = jl_current_output_stream(); - jl_array_t *b = (jl_array_t*)args[0]; - ios_write(s, (char*)b->data, b->length); - return (jl_value_t*)jl_nothing; + ios_write(jl_current_output_stream(), (char*)b->data, b->length); } -JL_CALLABLE(jl_f_print_symbol) +DLLEXPORT void jl_print_symbol(jl_sym_t *sym) +{ + ios_puts(sym->name, jl_current_output_stream()); +} + +// for bootstrap +DLLEXPORT void jl_print_int64(int64_t i) { ios_t *s = jl_current_output_stream(); - ios_puts(((jl_sym_t*)args[0])->name, s); - return (jl_value_t*)jl_nothing; + ios_printf(s, "%lld", i); } DLLEXPORT @@ -752,13 +757,18 @@ int jl_strtof(char *str, float *out) return 0; } -// --- showing --- +// showing -------------------------------------------------------------------- -jl_function_t *jl_show_gf; +static jl_function_t *jl_show_gf=NULL; void jl_show(jl_value_t *v) { - jl_apply(jl_show_gf, &v, 1); + if (jl_system_module) { + if (jl_show_gf == NULL) { + jl_show_gf = (jl_function_t*)jl_get_global(jl_system_module, jl_symbol("show")); + } + jl_apply(jl_show_gf, &v, 1); + } } // comma_one prints a comma for 1 element, e.g. "(x,)" @@ -847,26 +857,10 @@ static void show_type(jl_value_t *t) } } -JL_CALLABLE(jl_f_show_int64) -{ - ios_t *s = jl_current_output_stream(); - ios_printf(s, "%lld", *(int64_t*)jl_bits_data(args[0])); - return (jl_value_t*)jl_nothing; -} - -JL_CALLABLE(jl_f_show_uint64) +DLLEXPORT void jl_show_any(jl_value_t *v) { - ios_t *s = jl_current_output_stream(); - ios_printf(s, "%llu", *(uint64_t*)jl_bits_data(args[0])); - return (jl_value_t*)jl_nothing; -} - -JL_CALLABLE(jl_f_show_any) -{ - JL_NARGS(print, 1, 1); // fallback for printing some other builtin types ios_t *s = jl_current_output_stream(); - jl_value_t *v = args[0]; if (jl_is_tuple(v)) { show_tuple((jl_tuple_t*)v, '(', ')', 1); } @@ -881,11 +875,7 @@ JL_CALLABLE(jl_f_show_any) } else { jl_value_t *t = (jl_value_t*)jl_typeof(v); - if (jl_is_bits_type(t)) { - jl_no_method_error(jl_show_gf, args, 1); - } - else { - assert(jl_is_struct_type(t)); + if (jl_is_struct_type(t)) { jl_struct_type_t *st = (jl_struct_type_t*)t; ios_puts(st->name->name->name, s); ios_putc('(', s); @@ -899,23 +889,21 @@ JL_CALLABLE(jl_f_show_any) ios_putc(')', s); } } - return (jl_value_t*)jl_nothing; } -// --- RTS primitives --- - -extern int jl_in_inference; +// internal functions --------------------------------------------------------- JL_CALLABLE(jl_trampoline) { jl_function_t *f = (jl_function_t*)jl_t0(env); assert(jl_is_func(f)); assert(f->linfo != NULL); + /* // to run inference on all thunks. slows down loading files. if (f->linfo->inferred == jl_false) { if (!jl_in_inference) { jl_type_infer(f->linfo, jl_tuple_type, f->linfo); } - } + }*/ jl_compile(f); assert(f->fptr == &jl_trampoline); jl_generate_fptr(f); @@ -965,8 +953,7 @@ static int all_typevars(jl_tuple_t *p) static void check_supertype(jl_value_t *super, char *name) { - if (!(/*jl_is_struct_type(super) || */jl_is_tag_type(super)) || - super == (jl_value_t*)jl_sym_type || + if (!jl_is_tag_type(super) || super == (jl_value_t*)jl_sym_type || super == (jl_value_t*)jl_undef_type || jl_subtype(super,(jl_value_t*)jl_type_type,0) || jl_subtype(super,(jl_value_t*)jl_array_type,0)) { @@ -1013,28 +1000,11 @@ JL_CALLABLE(jl_f_new_struct_fields) return (jl_value_t*)jl_nothing; } check_type_tuple(ftypes, st->name->name, "type definition"); - jl_tuple_t *fnames = st->names; check_supertype(super, st->name->name->name); st->super = (jl_tag_type_t*)super; - if (jl_is_struct_type(super)) { - // UNUSED - assert(0); - st->names = jl_tuple_append(((jl_struct_type_t*)super)->names, - fnames); - } - else { - assert(jl_is_tag_type(super)); - } + assert(jl_is_tag_type(super)); - /* - if (jl_is_struct_type(super)) - pft = ((jl_struct_type_t*)super)->types; - else if (jl_is_tag_type(super)) - pft = jl_null; - else - assert(0); - */ st->types = ftypes; jl_add_constructors(st); return (jl_value_t*)jl_nothing; @@ -1150,7 +1120,7 @@ JL_CALLABLE(jl_f_union) return u; } -// --- method definition --- +// method definition ---------------------------------------------------------- static void check_type_tuple(jl_tuple_t *t, jl_sym_t *name, const char *ctx) { @@ -1195,7 +1165,7 @@ jl_value_t *jl_method_def(jl_sym_t *name, jl_value_t **bp, jl_binding_t *bnd, return gf; } -// --- generic function reflection --- +// generic function reflection ------------------------------------------------ JL_CALLABLE(jl_f_methodexists) { @@ -1255,11 +1225,11 @@ jl_value_t *jl_closure_linfo(jl_function_t *f) return (jl_value_t*)f->linfo; } -// --- eq hash table --- +// eq hash table -------------------------------------------------------------- #include "table.c" -// --- hashing --- +// hashing -------------------------------------------------------------------- DLLEXPORT uptrint_t jl_hash_symbol(jl_sym_t *s) { @@ -1271,12 +1241,7 @@ DLLEXPORT uptrint_t jl_uid(jl_value_t *v) return (uptrint_t)v; } -// --- init --- - -static void add_builtin_method1(jl_function_t *gf, jl_type_t *t, jl_fptr_t f) -{ - jl_add_method(gf, jl_tuple1(t), jl_new_closure(f, NULL)); -} +// init ----------------------------------------------------------------------- static void add_builtin(const char *name, jl_value_t *v) { @@ -1307,6 +1272,8 @@ void jl_init_primitives(void) add_builtin_func("yieldto", jl_f_yieldto); // functions for internal use + add_builtin_func("convert_default", jl_f_convert_default); + add_builtin_func("convert_tuple", jl_f_convert_tuple); add_builtin_func("tupleref", jl_f_tupleref); add_builtin_func("tuplelen", jl_f_tuplelen); add_builtin_func("getfield", jl_f_get_field); @@ -1375,31 +1342,3 @@ void jl_init_primitives(void) add_builtin("ANY", jl_ANY_flag); } - -void jl_init_builtins(void) -{ - jl_function_t *jl_print_gf = jl_new_generic_function(jl_symbol("print")); - - add_builtin_method1(jl_print_gf, - (jl_type_t*)jl_array_uint8_type, - jl_f_print_array_uint8); - add_builtin_method1(jl_print_gf, (jl_type_t*)jl_sym_type, - jl_f_print_symbol); - - jl_show_gf = jl_new_generic_function(jl_symbol("show")); - - add_builtin_method1(jl_show_gf, (jl_type_t*)jl_any_type, jl_f_show_any); - add_builtin_method1(jl_show_gf, (jl_type_t*)jl_int64_type, jl_f_show_int64); - - jl_convert_gf = jl_new_generic_function(jl_symbol("convert")); - jl_add_method(jl_convert_gf, - jl_tuple2(jl_any_type, jl_any_type), - jl_new_closure(jl_f_convert, NULL)); - jl_add_method(jl_convert_gf, - jl_tuple2(jl_tuple_type, jl_tuple_type), - jl_new_closure(jl_f_convert_tuple, NULL)); - - add_builtin("print", (jl_value_t*)jl_print_gf); - add_builtin("show", (jl_value_t*)jl_show_gf); - add_builtin("convert", (jl_value_t*)jl_convert_gf); -} diff --git a/src/codegen.cpp b/src/codegen.cpp index 7b18a00efc51f..0178c34ea0d23 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -94,7 +94,6 @@ static Function *jlerror_func; static Function *jluniniterror_func; static Function *jldiverror_func; static Function *jltypeerror_func; -static Function *jlgetbindingp_func; static Function *jlcheckassign_func; static Function *jldeclareconst_func; static Function *jltuple_func; @@ -248,18 +247,15 @@ static bool is_constant(jl_value_t *ex, jl_codectx_t *ctx, bool sparams=true) } } } - if (jl_boundp(ctx->module, sym)) { - jl_binding_t *b = jl_get_binding(ctx->module, sym); - if (b->constp) - return true; - } + if (jl_is_const(ctx->module, sym)) + return true; } return false; } if (jl_is_topnode(ex)) { jl_binding_t *b = jl_get_binding(ctx->module, (jl_sym_t*)jl_fieldref(ex,0)); - if (b->constp && b->value) + if (b && b->constp && b->value) return true; } if (jl_is_bits_type(jl_typeof(ex))) @@ -822,14 +818,14 @@ static Value *emit_call(jl_value_t **args, size_t arglen, jl_codectx_t *ctx, if (jl_is_symbol(a0) && is_global((jl_sym_t*)a0, ctx) && jl_boundp(ctx->module, (jl_sym_t*)a0)) { b = jl_get_binding(ctx->module, (jl_sym_t*)a0); - if (!b->constp) + if (!b || !b->constp) b = NULL; } if (jl_is_topnode(a0)) { headIsGlobal = true; // (top x) is also global b = jl_get_binding(ctx->module, (jl_sym_t*)jl_fieldref(a0,0)); - if (b->value==NULL || !b->constp) + if (!b || b->value==NULL || !b->constp) b = NULL; } jl_value_t *f = NULL; @@ -906,28 +902,9 @@ static bool isBoxed(char *varname, jl_codectx_t *ctx) return (*ctx->isAssigned)[varname] && (*ctx->isCaptured)[varname]; } -static Value *globalvar_binding_pointer(jl_sym_t *s, jl_binding_t **pbnd, - jl_codectx_t *ctx) -{ - jl_value_t **bp; - if (pbnd) { - *pbnd = jl_get_binding(ctx->module, s); - bp = &(*pbnd)->value; - } - else { - bp = jl_get_bindingp(ctx->module, s); - } - return literal_pointer_val(bp, jl_ppvalue_llvmt); - /* - return builder.CreateCall2(jlgetbindingp_func, - literal_pointer_val(ctx->module, T_pint8), - literal_pointer_val(s, T_pint8)); - */ -} - // yields a jl_value_t** giving the binding location of a variable static Value *var_binding_pointer(jl_sym_t *s, jl_binding_t **pbnd, - jl_codectx_t *ctx) + bool assign, jl_codectx_t *ctx) { if (jl_is_symbolnode(s)) s = jl_symbolnode_sym(s); @@ -947,7 +924,15 @@ static Value *var_binding_pointer(jl_sym_t *s, jl_binding_t **pbnd, } return l; } - return globalvar_binding_pointer(s, pbnd, ctx); + jl_binding_t *b=NULL; + if (!assign) + b = jl_get_binding(ctx->module, s); + // if b is NULL, this might be a global that is not set yet but will be, + // so get a pointer for writing even when not assigning. + if (assign || b==NULL) + b = jl_get_binding_wr(ctx->module, s); + if (pbnd) *pbnd = b; + return literal_pointer_val(&b->value, jl_ppvalue_llvmt); } static int is_var_closed(jl_sym_t *s, jl_codectx_t *ctx) @@ -996,7 +981,7 @@ static Value *emit_var(jl_sym_t *sym, jl_value_t *ty, jl_codectx_t *ctx) } } } - Value *bp = var_binding_pointer(sym, NULL, ctx); + Value *bp = var_binding_pointer(sym, NULL, false, ctx); Value *arg = (*ctx->arguments)[sym->name]; // arguments are always defined if (arg != NULL || @@ -1017,7 +1002,7 @@ static void emit_assignment(jl_value_t *l, jl_value_t *r, jl_codectx_t *ctx) else assert(false); jl_binding_t *bnd=NULL; - Value *bp = var_binding_pointer(s, &bnd, ctx); + Value *bp = var_binding_pointer(s, &bnd, true, ctx); if (bnd) { builder.CreateCall2(jlcheckassign_func, literal_pointer_val((void*)bnd), @@ -1079,8 +1064,10 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool value) else if (jl_is_topnode(expr)) { jl_sym_t *var = (jl_sym_t*)jl_fieldref(expr,0); jl_value_t *etype = jl_fieldref(expr,1); - jl_binding_t *b; - Value *bp = globalvar_binding_pointer(var, &b, ctx); + jl_binding_t *b = jl_get_binding(ctx->module, var); + if (b == NULL) + b = jl_get_binding_wr(ctx->module, var); + Value *bp = literal_pointer_val(&b->value, jl_ppvalue_llvmt); if ((b->constp && b->value!=NULL) || (etype!=(jl_value_t*)jl_any_type && !jl_subtype((jl_value_t*)jl_undef_type, etype, 0))) { @@ -1165,7 +1152,7 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool value) int last_depth = ctx->argDepth; Value *name = literal_pointer_val(mn); jl_binding_t *bnd = NULL; - Value *bp = var_binding_pointer((jl_sym_t*)mn, &bnd, ctx); + Value *bp = var_binding_pointer((jl_sym_t*)mn, &bnd, true, ctx); Value *a1 = emit_expr(args[1], ctx, true); make_gcroot(boxed(a1), ctx); Value *a2 = emit_expr(args[2], ctx, true); @@ -1175,39 +1162,10 @@ static Value *emit_expr(jl_value_t *expr, jl_codectx_t *ctx, bool value) ctx->argDepth = last_depth; return m; } - else if (ex->head == isbound_sym) { - jl_sym_t *sy=NULL; - jl_value_t *a = args[0]; - if (jl_is_symbol(a)) - sy = (jl_sym_t*)a; - else if (jl_is_symbolnode(a)) - sy = jl_symbolnode_sym(a); - else - assert(false); - Value *bp = var_binding_pointer(sy, NULL, ctx); - if (bp->getType()->getContainedType(0) != jl_pvalue_llvmt) { - // unboxed vars will never be referenced undefined - return ConstantInt::get(T_int1, 1); - } - jl_value_t *st = expr_type(args[0]); - if (st == (jl_value_t*)jl_undef_type) { - // type==Undef => definitely not assigned - return ConstantInt::get(T_int1, 0); - } - if (ctx->linfo->specTypes != NULL && - !is_var_closed(sy, ctx) && - !jl_subtype((jl_value_t*)jl_undef_type, st, 0)) { - // Undef ⊄ expr_type => definitely assigned - return ConstantInt::get(T_int1, 1); - } - Value *v = builder.CreateLoad(bp, false); - Value *isbnd = builder.CreateICmpNE(v, V_null); - return isbnd; - } else if (ex->head == const_sym) { jl_sym_t *sym = (jl_sym_t*)args[0]; jl_binding_t *bnd = NULL; - (void)var_binding_pointer(sym, &bnd, ctx); + (void)var_binding_pointer(sym, &bnd, true, ctx); if (bnd) { builder.CreateCall(jldeclareconst_func, literal_pointer_val((void*)bnd)); @@ -1885,16 +1843,6 @@ static void init_julia_llvm_env(Module *m) jl_ExecutionEngine->addGlobalMapping(jltypeerror_func, (void*)&jl_type_error_rt); - std::vector<Type *> args2(0); - args2.push_back(T_pint8); - args2.push_back(T_pint8); - jlgetbindingp_func = - Function::Create(FunctionType::get(jl_ppvalue_llvmt, args2, false), - Function::ExternalLinkage, - "jl_get_bindingp", jl_Module); - jl_ExecutionEngine->addGlobalMapping(jlgetbindingp_func, - (void*)&jl_get_bindingp); - std::vector<Type *> args_2ptrs(0); args_2ptrs.push_back(T_pint8); args_2ptrs.push_back(jl_pvalue_llvmt); diff --git a/src/dump.c b/src/dump.c index d306b4d03e899..35f549b999f27 100644 --- a/src/dump.c +++ b/src/dump.c @@ -344,7 +344,12 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v) jl_lambda_info_t *li = (jl_lambda_info_t*)v; jl_serialize_value(s, li->ast); jl_serialize_value(s, (jl_value_t*)li->sparams); - jl_serialize_value(s, (jl_value_t*)li->tfunc); + // don't save cached type info for code in the Base module, because + // it might reference types in the old System module. + if (li->module == jl_base_module) + jl_serialize_value(s, (jl_value_t*)jl_null); + else + jl_serialize_value(s, (jl_value_t*)li->tfunc); jl_serialize_value(s, (jl_value_t*)li->name); jl_serialize_value(s, (jl_value_t*)li->specTypes); jl_serialize_value(s, (jl_value_t*)li->specializations); @@ -704,7 +709,7 @@ static jl_value_t *jl_deserialize_value(ios_t *s) jl_value_t *name = jl_deserialize_value(s); if (name == NULL) break; - jl_binding_t *b = jl_get_binding(m, (jl_sym_t*)name); + jl_binding_t *b = jl_get_binding_wr(m, (jl_sym_t*)name); b->value = jl_deserialize_value(s); b->type = (jl_type_t*)jl_deserialize_value(s); b->constp = read_int8(s); @@ -817,7 +822,7 @@ void jl_save_system_image(char *fname, char *startscriptname) // loaded and we are loading an updated copy in a separate module. // step 1: set Base.System = current_module - jl_binding_t *b = jl_get_binding(jl_base_module, jl_symbol("System")); + jl_binding_t *b = jl_get_binding_wr(jl_base_module, jl_symbol("System")); b->value = (jl_value_t*)jl_current_module; assert(b->constp); @@ -825,12 +830,12 @@ void jl_save_system_image(char *fname, char *startscriptname) jl_set_const(jl_current_module, jl_symbol("Base"), (jl_value_t*)jl_base_module); // step 3: current_module.System = current_module - b = jl_get_binding(jl_current_module, jl_symbol("System")); + b = jl_get_binding_wr(jl_current_module, jl_symbol("System")); b->value = (jl_value_t*)jl_current_module; assert(b->constp); // step 4: remove current_module.current_module - b = jl_get_binding(jl_current_module, jl_current_module->name); + b = jl_get_binding_wr(jl_current_module, jl_current_module->name); b->value = NULL; b->constp = 0; // step 5: rename current_module to System @@ -868,6 +873,7 @@ void jl_save_system_image(char *fname, char *startscriptname) extern jl_function_t *jl_typeinf_func; extern int jl_boot_file_loaded; extern void jl_get_builtin_hooks(void); +extern void jl_get_system_hooks(void); DLLEXPORT void jl_restore_system_image(char *fname) @@ -921,12 +927,10 @@ void jl_restore_system_image(char *fname) } jl_get_builtin_hooks(); + jl_get_system_hooks(); jl_boot_file_loaded = 1; - jl_typeinf_func = - (jl_function_t*)*(jl_get_bindingp(jl_system_module, - jl_symbol("typeinf_ext"))); - jl_show_gf = (jl_function_t*)jl_get_global(jl_system_module,jl_symbol("show")); - jl_convert_gf = (jl_function_t*)jl_get_global(jl_system_module,jl_symbol("convert")); + jl_typeinf_func = (jl_function_t*)jl_get_global(jl_system_module, + jl_symbol("typeinf_ext")); jl_init_box_caches(); //jl_deserialize_finalizers(&f); @@ -1133,7 +1137,7 @@ void jl_init_serializer(void) VALUE_TAGS = (ptrint_t)ptrhash_get(&ser_tag, jl_null); void *fptrs[] = { jl_f_new_expr, jl_f_new_box, - jl_weakref_ctor, jl_f_throw, jl_f_is, + jl_f_throw, jl_f_is, jl_f_no_function, jl_f_typeof, jl_f_subtype, jl_f_isa, jl_f_typeassert, jl_f_apply, @@ -1143,10 +1147,8 @@ void jl_init_serializer(void) jl_f_set_field, jl_f_field_type, jl_f_arraylen, jl_f_arrayref, jl_f_arrayset, jl_f_arraysize, - jl_f_instantiate_type, jl_f_convert, - jl_f_convert_tuple, jl_f_print_array_uint8, - jl_f_show_int64, jl_f_show_uint64, - jl_f_show_any, jl_f_print_symbol, + jl_f_instantiate_type, + jl_f_convert_default, jl_f_convert_tuple, jl_trampoline, jl_f_new_struct_type, jl_f_new_struct_fields, jl_f_new_type_constructor, jl_f_new_tag_type, jl_f_new_tag_type_super, diff --git a/src/gc.c b/src/gc.c index 49530871d6817..1e76a3df7234e 100644 --- a/src/gc.c +++ b/src/gc.c @@ -130,7 +130,7 @@ void jl_gc_unpreserve(void) (void)arraylist_pop(&preserved_values); } -jl_weakref_t *jl_gc_new_weakref(jl_value_t *value) +DLLEXPORT jl_weakref_t *jl_gc_new_weakref(jl_value_t *value) { jl_weakref_t *wr = (jl_weakref_t*)alloc_2w(); wr->type = (jl_type_t*)jl_weakref_type; diff --git a/src/init.c b/src/init.c index 660b0085ea74b..8de6b1fd29572 100644 --- a/src/init.c +++ b/src/init.c @@ -129,7 +129,6 @@ void julia_init(char *imageFile) jl_load_boot_j(); jl_get_builtin_hooks(); jl_boot_file_loaded = 1; - jl_init_builtins(); jl_init_box_caches(); } @@ -246,12 +245,12 @@ DLLEXPORT void jl_enable_inference(void) if (jl_boundp(jl_system_module, jl_symbol("typeinf_ext"))) { //clear_method_caches(); jl_typeinf_func = - (jl_function_t*)*(jl_get_bindingp(jl_system_module, - jl_symbol("typeinf_ext"))); + (jl_function_t*)jl_get_global(jl_system_module, + jl_symbol("typeinf_ext")); // warm up type inference to put the latency up front jl_value_t *one = jl_box_long(1); - jl_apply((jl_function_t*)*(jl_get_bindingp(jl_system_module, - jl_symbol("+"))), + jl_apply((jl_function_t*)jl_get_global(jl_system_module, + jl_symbol("+")), &one, 1); /* cached t-functions and inferred ASTs need to be cleared at @@ -279,60 +278,66 @@ DLLEXPORT void jl_enable_inference(void) } } -static jl_value_t *global(char *name) +static jl_value_t *base(char *name) { - return *jl_get_bindingp(jl_base_module, jl_symbol(name)); + return jl_get_global(jl_base_module, jl_symbol(name)); +} + +static jl_value_t *sysmod(char *name) +{ + return jl_get_global(jl_system_module, jl_symbol(name)); } -JL_CALLABLE(jl_weakref_ctor); jl_function_t *jl_method_missing_func=NULL; // fetch references to things defined in boot.j void jl_get_builtin_hooks(void) { - jl_nothing = global("nothing"); + jl_nothing = base("nothing"); jl_root_task->tls = jl_nothing; - jl_char_type = (jl_bits_type_t*)global("Char"); - jl_int8_type = (jl_bits_type_t*)global("Int8"); - jl_uint8_type = (jl_bits_type_t*)global("Uint8"); - jl_int16_type = (jl_bits_type_t*)global("Int16"); - jl_uint16_type = (jl_bits_type_t*)global("Uint16"); - jl_uint32_type = (jl_bits_type_t*)global("Uint32"); - jl_uint64_type = (jl_bits_type_t*)global("Uint64"); - - jl_float32_type = (jl_bits_type_t*)global("Float32"); - jl_float64_type = (jl_bits_type_t*)global("Float64"); - - jl_weakref_type = (jl_struct_type_t*)global("WeakRef"); - jl_weakref_type->fptr = jl_weakref_ctor; - jl_weakref_type->env = NULL; - jl_weakref_type->linfo = NULL; - jl_string_type = (jl_tag_type_t*)global("String"); - jl_ascii_string_type = (jl_struct_type_t*)global("ASCIIString"); - jl_utf8_string_type = (jl_struct_type_t*)global("UTF8String"); - jl_errorexception_type = (jl_struct_type_t*)global("ErrorException"); - jl_typeerror_type = (jl_struct_type_t*)global("TypeError"); - jl_loaderror_type = (jl_struct_type_t*)global("LoadError"); - jl_uniontoocomplex_type = (jl_struct_type_t*)global("UnionTooComplexError"); - jl_backtrace_type = (jl_struct_type_t*)global("BackTrace"); - jl_symbolnode_type = (jl_struct_type_t*)global("SymbolNode"); + jl_char_type = (jl_bits_type_t*)base("Char"); + jl_int8_type = (jl_bits_type_t*)base("Int8"); + jl_uint8_type = (jl_bits_type_t*)base("Uint8"); + jl_int16_type = (jl_bits_type_t*)base("Int16"); + jl_uint16_type = (jl_bits_type_t*)base("Uint16"); + jl_uint32_type = (jl_bits_type_t*)base("Uint32"); + jl_uint64_type = (jl_bits_type_t*)base("Uint64"); + + jl_float32_type = (jl_bits_type_t*)base("Float32"); + jl_float64_type = (jl_bits_type_t*)base("Float64"); jl_stackovf_exception = - jl_apply((jl_function_t*)global("StackOverflowError"), NULL, 0); + jl_apply((jl_function_t*)base("StackOverflowError"), NULL, 0); jl_divbyzero_exception = - jl_apply((jl_function_t*)global("DivideByZeroError"), NULL, 0); + jl_apply((jl_function_t*)base("DivideByZeroError"), NULL, 0); jl_undefref_exception = - jl_apply((jl_function_t*)global("UndefRefError"),NULL,0); + jl_apply((jl_function_t*)base("UndefRefError"),NULL,0); jl_interrupt_exception = - jl_apply((jl_function_t*)global("InterruptException"),NULL,0); + jl_apply((jl_function_t*)base("InterruptException"),NULL,0); jl_memory_exception = - jl_apply((jl_function_t*)global("MemoryError"),NULL,0); + jl_apply((jl_function_t*)base("MemoryError"),NULL,0); - jl_method_missing_func = (jl_function_t*)global("method_missing"); + jl_weakref_type = (jl_struct_type_t*)base("WeakRef"); + jl_ascii_string_type = (jl_struct_type_t*)base("ASCIIString"); + jl_utf8_string_type = (jl_struct_type_t*)base("UTF8String"); + jl_symbolnode_type = (jl_struct_type_t*)base("SymbolNode"); jl_array_uint8_type = (jl_type_t*)jl_apply_type((jl_value_t*)jl_array_type, jl_tuple2(jl_uint8_type, jl_box_long(1))); } + +DLLEXPORT void jl_get_system_hooks(void) +{ + if (jl_method_missing_func) return; // only do this once + + jl_errorexception_type = (jl_struct_type_t*)sysmod("ErrorException"); + jl_typeerror_type = (jl_struct_type_t*)sysmod("TypeError"); + jl_loaderror_type = (jl_struct_type_t*)sysmod("LoadError"); + jl_uniontoocomplex_type = (jl_struct_type_t*)sysmod("UnionTooComplexError"); + jl_backtrace_type = (jl_struct_type_t*)sysmod("BackTrace"); + + jl_method_missing_func = (jl_function_t*)sysmod("method_missing"); +} diff --git a/src/interpreter.c b/src/interpreter.c index 17b0fa718c23a..865abffa73cc3 100644 --- a/src/interpreter.c +++ b/src/interpreter.c @@ -61,30 +61,29 @@ static jl_value_t *do_call(jl_function_t *f, jl_value_t **args, size_t nargs, jl_value_t *jl_eval_global_var(jl_module_t *m, jl_sym_t *e) { - jl_value_t **bp = jl_get_bindingp(m, e); - if (*bp == NULL) + jl_value_t *v = jl_get_global(m, e); + if (v == NULL) jl_errorf("%s not defined", e->name); - return *bp; -} - -static jl_value_t **var_bp(jl_sym_t *s, jl_value_t **locals, size_t nl) -{ - size_t i; - for(i=0; i < nl; i++) { - if (locals[i*2] == (jl_value_t*)s) { - return &locals[i*2+1]; - } - } - return jl_get_bindingp(jl_current_module, s); + return v; } static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) { if (jl_is_symbol(e)) { - jl_value_t **bp = var_bp((jl_sym_t*)e, locals, nl); - if (*bp == NULL) + jl_value_t *v; + size_t i; + for(i=0; i < nl; i++) { + if (locals[i*2] == e) { + v = locals[i*2+1]; + break; + } + } + if (i >= nl) { + v = jl_get_global(jl_current_module, (jl_sym_t*)e); + } + if (v == NULL) jl_errorf("%s not defined", ((jl_sym_t*)e)->name); - return *bp; + return v; } if (jl_is_symbolnode(e)) { return eval((jl_value_t*)jl_symbolnode_sym(e), locals, nl); @@ -93,11 +92,11 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) return jl_fieldref(e,0); } if (jl_is_topnode(e)) { - jl_value_t **bp = jl_get_bindingp(jl_current_module, - (jl_sym_t*)jl_fieldref(e,0)); - if (*bp == NULL) + jl_value_t *v = jl_get_global(jl_current_module, + (jl_sym_t*)jl_fieldref(e,0)); + if (v == NULL) jl_errorf("%s not defined", ((jl_sym_t*)jl_fieldref(e,0))->name); - return *bp; + return v; } if (!jl_is_expr(e)) { if (jl_is_lambda_info(e)) { @@ -123,7 +122,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) return (locals[i*2+1] = eval(args[1], locals, nl)); } } - jl_binding_t *b = jl_get_binding(jl_current_module, (jl_sym_t*)sym); + jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)sym); jl_value_t *rhs = eval(args[1], locals, nl); jl_checked_assignment(b, rhs); return rhs; @@ -142,10 +141,6 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) else if (ex->head == body_sym) { return eval_body(ex->args, locals, nl, 0); } - else if (ex->head == isbound_sym) { - jl_value_t **bp = var_bp((jl_sym_t*)args[0], locals, nl); - return (*bp == NULL) ? jl_false : jl_true; - } else if (ex->head == exc_sym) { return jl_exception_in_transit; } @@ -164,7 +159,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) } } if (bp == NULL) { - b = jl_get_binding(jl_current_module, fname); + b = jl_get_binding_wr(jl_current_module, fname); bp = &b->value; } jl_value_t *atypes=NULL, *meth=NULL; @@ -184,7 +179,7 @@ static jl_value_t *eval(jl_value_t *e, jl_value_t **locals, size_t nl) return (jl_value_t*)jl_nothing; } } - jl_binding_t *b = jl_get_binding(jl_current_module, (jl_sym_t*)sym); + jl_binding_t *b = jl_get_binding_wr(jl_current_module, (jl_sym_t*)sym); jl_declare_constant(b); return (jl_value_t*)jl_nothing; } diff --git a/src/jltypes.c b/src/jltypes.c index c6d671ce2a979..94a5d4d036169 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2556,7 +2556,6 @@ void jl_init_types(void) module_sym = jl_symbol("module"); assign_sym = jl_symbol("="); null_sym = jl_symbol("null"); - isbound_sym = jl_symbol("isbound"); body_sym = jl_symbol("body"); locals_sym = jl_symbol("locals"); colons_sym = jl_symbol("::"); diff --git a/src/julia.expmap b/src/julia.expmap index eb96dbd60ad5b..b89c0878dc841 100644 --- a/src/julia.expmap +++ b/src/julia.expmap @@ -132,6 +132,8 @@ jl_gc_enable; jl_gc_disable; jl_gc_is_enabled; + jl_gc_new_weakref; + jl_get_system_hooks; jl_errno; jl_strerror; jl_environ; @@ -166,7 +168,10 @@ jl_enter_handler; jl_exception_in_transit; jl_show; - jl_show_float; + jl_show_any; + jl_print_array_uint8; + jl_print_symbol; + jl_print_int64; jl_pgcstack; jl_symbol; jl_system_module; diff --git a/src/julia.h b/src/julia.h index f8ef5ae8d2c59..bb3af408b7b57 100644 --- a/src/julia.h +++ b/src/julia.h @@ -275,7 +275,6 @@ extern jl_tag_type_t *jl_abstractarray_type; extern jl_struct_type_t *jl_array_type; extern jl_typename_t *jl_array_typename; extern jl_struct_type_t *jl_weakref_type; -extern jl_tag_type_t *jl_string_type; extern jl_struct_type_t *jl_ascii_string_type; extern jl_struct_type_t *jl_utf8_string_type; extern jl_struct_type_t *jl_errorexception_type; @@ -329,8 +328,6 @@ DLLEXPORT extern jl_value_t *jl_nothing; extern jl_func_type_t *jl_any_func; -extern jl_function_t *jl_show_gf; -extern jl_function_t *jl_convert_gf; extern jl_function_t *jl_bottom_func; extern jl_function_t *jl_method_missing_func; extern jl_function_t *jl_unprotect_stack_func; @@ -353,7 +350,7 @@ extern jl_sym_t *goto_sym; extern jl_sym_t *goto_ifnot_sym; extern jl_sym_t *label_sym; extern jl_sym_t *return_sym; extern jl_sym_t *lambda_sym; extern jl_sym_t *assign_sym; extern jl_sym_t *null_sym; extern jl_sym_t *body_sym; -extern jl_sym_t *isbound_sym; extern jl_sym_t *macro_sym; +extern jl_sym_t *macro_sym; extern jl_sym_t *locals_sym; extern jl_sym_t *colons_sym; extern jl_sym_t *Any_sym; extern jl_sym_t *method_sym; extern jl_sym_t *enter_sym; extern jl_sym_t *leave_sym; @@ -443,7 +440,6 @@ void *allocb_permanent(size_t sz); #define jl_is_ascii_string(v) jl_typeis(v,jl_ascii_string_type) #define jl_is_utf8_string(v) jl_typeis(v,jl_utf8_string_type) #define jl_is_byte_string(v) (jl_is_ascii_string(v) || jl_is_utf8_string(v)) -#define jl_is_string(v) jl_subtype(v,(jl_value_t*)jl_string_type,1) #define jl_is_cpointer(v) jl_is_cpointer_type(jl_typeof(v)) #define jl_is_pointer(v) jl_is_cpointer_type(jl_typeof(v)) #define jl_is_gf(f) (((jl_function_t*)(f))->fptr==jl_apply_generic) @@ -686,7 +682,6 @@ void jl_init_box_caches(void); void jl_init_frontend(void); void jl_shutdown_frontend(void); void jl_init_primitives(void); -void jl_init_builtins(void); void jl_init_codegen(void); void jl_init_intrinsic_functions(void); void jl_init_tasks(void *stack, size_t ssize); @@ -705,16 +700,18 @@ jl_lambda_info_t *jl_wrap_expr(jl_value_t *expr); // some useful functions DLLEXPORT void jl_show(jl_value_t *v); -jl_value_t *jl_convert(jl_type_t *to, jl_value_t *x); // modules extern jl_module_t *jl_base_module; extern DLLEXPORT jl_module_t *jl_system_module; extern jl_module_t *jl_current_module; jl_module_t *jl_new_module(jl_sym_t *name); +// get binding for reading jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var); -jl_value_t **jl_get_bindingp(jl_module_t *m, jl_sym_t *var); +// get binding for assignment +jl_binding_t *jl_get_binding_wr(jl_module_t *m, jl_sym_t *var); DLLEXPORT int jl_boundp(jl_module_t *m, jl_sym_t *var); +DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var); DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var); DLLEXPORT void jl_set_global(jl_module_t *m, jl_sym_t *var, jl_value_t *val); DLLEXPORT void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val); diff --git a/src/module.c b/src/module.c index 7821dd0aa5f92..5d5aea7f1dcdf 100644 --- a/src/module.c +++ b/src/module.c @@ -32,19 +32,12 @@ jl_module_t *jl_new_module(jl_sym_t *name) return m; } -jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var) +// get binding for assignment +jl_binding_t *jl_get_binding_wr(jl_module_t *m, jl_sym_t *var) { jl_binding_t **bp = (jl_binding_t**)ptrhash_bp(&m->bindings, var); jl_binding_t *b; if (*bp == HT_NOTFOUND) { - if (jl_base_module && m != jl_base_module) { - // for now, always chain to Base module. - // todo: imports/exports, maybe separate rules for read/write - b = (jl_binding_t*)ptrhash_get(&jl_base_module->bindings, var); - if (b != HT_NOTFOUND) { - return b; - } - } b = (jl_binding_t*)allocb(sizeof(jl_binding_t)); b->name = var; b->value = NULL; @@ -59,7 +52,7 @@ jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var) if (varlist_binding == NULL) { varlist_binding = jl_get_binding(jl_system_module, jl_symbol("VARIABLES")); } - if (varlist_binding->value != NULL && + if (varlist_binding && varlist_binding->value != NULL && jl_typeis(varlist_binding->value, jl_array_any_type)) { jl_array_t *a = (jl_array_t*)varlist_binding->value; jl_cell_1d_push(a, (jl_value_t*)var); @@ -69,31 +62,36 @@ jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var) return *bp; } -int jl_boundp(jl_module_t *m, jl_sym_t *var) -{ - jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); - if (b == HT_NOTFOUND && jl_base_module && m != jl_base_module) { - return jl_boundp(jl_base_module, var); - } - return (b != HT_NOTFOUND && b->value != NULL); -} - -jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var) +// get binding for reading. might return NULL for unbound. +jl_binding_t *jl_get_binding(jl_module_t *m, jl_sym_t *var) { if (m == NULL) return NULL; jl_binding_t *b = (jl_binding_t*)ptrhash_get(&m->bindings, var); if (b == HT_NOTFOUND) { if (jl_base_module && m != jl_base_module) { - return jl_get_global(jl_base_module, var); + return jl_get_binding(jl_base_module, var); } return NULL; } + return b; +} + +int jl_boundp(jl_module_t *m, jl_sym_t *var) +{ + jl_binding_t *b = jl_get_binding(m, var); + return b && (b->value != NULL); +} + +jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var) +{ + jl_binding_t *b = jl_get_binding(m, var); + if (b == NULL) return NULL; return b->value; } void jl_set_global(jl_module_t *m, jl_sym_t *var, jl_value_t *val) { - jl_binding_t *bp = jl_get_binding(m, var); + jl_binding_t *bp = jl_get_binding_wr(m, var); if (!bp->constp) { bp->value = val; } @@ -101,7 +99,7 @@ void jl_set_global(jl_module_t *m, jl_sym_t *var, jl_value_t *val) void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val) { - jl_binding_t *bp = jl_get_binding(m, var); + jl_binding_t *bp = jl_get_binding_wr(m, var); if (!bp->constp) { bp->value = val; bp->constp = 1; @@ -111,8 +109,8 @@ void jl_set_const(jl_module_t *m, jl_sym_t *var, jl_value_t *val) DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var) { if (m == NULL) m = jl_current_module; - jl_binding_t *bp = jl_get_binding(m, var); - return bp->constp; + jl_binding_t *b = jl_get_binding(m, var); + return b && b->constp; } void jl_checked_assignment(jl_binding_t *b, jl_value_t *rhs) @@ -140,12 +138,6 @@ jl_module_t *jl_add_module(jl_module_t *m, jl_module_t *child); jl_module_t *jl_get_module(jl_module_t *m, jl_sym_t *name); jl_module_t *jl_import_module(jl_module_t *to, jl_module_t *from); -jl_value_t **jl_get_bindingp(jl_module_t *m, jl_sym_t *var) -{ - jl_binding_t *b = jl_get_binding(m, var); - return &b->value; -} - jl_function_t *jl_get_expander(jl_module_t *m, jl_sym_t *macroname) { jl_function_t *f = (jl_function_t*)ptrhash_get(&m->macros, macroname); diff --git a/ui/repl.c b/ui/repl.c index f5fc93008fd1b..8b9cb5ed7dab6 100644 --- a/ui/repl.c +++ b/ui/repl.c @@ -302,12 +302,12 @@ int true_main(int argc, char *argv[]) } jl_array_t *args = jl_alloc_cell_1d(argc); - jl_set_global(jl_base_module, jl_symbol("ARGS"), (jl_value_t*)args); + jl_set_global(jl_current_module, jl_symbol("ARGS"), (jl_value_t*)args); int i; for (i=0; i < argc; i++) { jl_arrayset(args, i, (jl_value_t*)jl_cstr_to_string(argv[i])); } - jl_set_const(jl_base_module, jl_symbol("JULIA_HOME"), + jl_set_const(jl_current_module, jl_symbol("JULIA_HOME"), jl_cstr_to_string(julia_home)); // run program if specified, otherwise enter REPL