jl_value_t *jl_toplevel_eval_flex(jl_value_t *ex, int fast) { //jl_show(ex); //ios_printf(ios_stdout, "\n"); jl_lambda_info_t *thk; int ewc = 0; if (jl_is_expr(ex) && ((jl_expr_t*)ex)->head == thunk_sym) { thk = (jl_lambda_info_t*)jl_exprarg(ex,0); assert(jl_is_lambda_info(thk)); ewc = eval_with_compiler_p(jl_lam_body((jl_expr_t*)thk->ast), fast); if (!ewc) { jl_array_t *vinfos = jl_lam_vinfo((jl_expr_t*)thk->ast); int i; for(i=0; i < vinfos->length; i++) { if (jl_vinfo_capt((jl_array_t*)jl_cellref(vinfos,i))) { // interpreter doesn't handle closure environment ewc = 1; break; } } } } else { if (jl_is_expr(ex) && eval_with_compiler_p((jl_expr_t*)ex, fast)) { thk = jl_wrap_expr(ex); ewc = 1; } else { return jl_interpret_toplevel_expr(ex); } } jl_value_t *thunk=NULL; jl_value_t *result; JL_GC_PUSH(&thunk, &thk); if (ewc) { thunk = jl_new_closure_internal(thk, (jl_value_t*)jl_null); result = jl_apply((jl_function_t*)thunk, NULL, 0); } else { result = jl_interpret_toplevel_thunk(thk); } JL_GC_POP(); return result; }
JL_DLLEXPORT void jl_depwarn_partial_indexing(size_t n) { static jl_value_t *depwarn_func = NULL; if (!depwarn_func && jl_base_module) { depwarn_func = jl_get_global(jl_base_module, jl_symbol("_depwarn_for_trailing_indices")); } if (!depwarn_func) { jl_safe_printf("WARNING: omitting indices for non-singleton trailing dimensions is deprecated. Use " "`reshape(A, Val(%zd))` or add trailing `1` indices to make the dimensionality of the array match " "the number of indices\n", n); return; } jl_value_t **depwarn_args; JL_GC_PUSHARGS(depwarn_args, 2); depwarn_args[0] = depwarn_func; depwarn_args[1] = jl_box_long(n); jl_apply(depwarn_args, 2); JL_GC_POP(); }
void jl_module_run_initializer(jl_module_t *m) { jl_ptls_t ptls = jl_get_ptls_states(); jl_function_t *f = jl_module_get_initializer(m); if (f == NULL) return; JL_TRY { jl_apply(&f, 1); } JL_CATCH { if (jl_initerror_type == NULL) { jl_rethrow(); } else { jl_rethrow_other(jl_new_struct(jl_initerror_type, m->name, ptls->exception_in_transit)); } } }
JL_DLLEXPORT jl_value_t *jl_call2(jl_function_t *f, jl_value_t *a, jl_value_t *b) { jl_value_t *v; JL_TRY { jl_value_t **argv; JL_GC_PUSHARGS(argv, 3); argv[0] = f; argv[1] = a; argv[2] = b; size_t last_age = jl_get_ptls_states()->world_age; jl_get_ptls_states()->world_age = jl_get_world_counter(); v = jl_apply(argv, 3); jl_get_ptls_states()->world_age = last_age; JL_GC_POP(); jl_exception_clear(); } JL_CATCH { v = NULL; } return v; }
DLLEXPORT void uv_atexit_hook() { #if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS) jl_print_gc_stats(JL_STDERR); #endif if (jl_compileropts.code_coverage) jl_write_coverage_data(); if (jl_base_module) { jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit")); if (f!=NULL && jl_is_function(f)) { JL_TRY { jl_apply((jl_function_t*)f, NULL, 0); } JL_CATCH { JL_PRINTF(JL_STDERR, "\natexit hook threw an error: "); jl_show(jl_stderr_obj(),jl_exception_in_transit); } } }
void jl_add_constructors(jl_struct_type_t *t) { if (t->name == jl_array_typename) { t->fptr = jl_f_no_function; return; } jl_initialize_generic_function((jl_function_t*)t, t->name->name); if (t->ctor_factory == (jl_value_t*)jl_nothing || t->ctor_factory == (jl_value_t*)jl_null) { assert(jl_tuple_len(t->parameters) == 0); } else { assert(jl_tuple_len(t->parameters) > 0); if (t != (jl_struct_type_t*)t->name->primary) { // instantiating assert(jl_is_function(t->ctor_factory)); // add type's static parameters to the ctor factory size_t np = jl_tuple_len(t->parameters); jl_tuple_t *sparams = jl_alloc_tuple_uninit(np*2); jl_function_t *cfactory = NULL; JL_GC_PUSH(&sparams, &cfactory); size_t i; for(i=0; i < np; i++) { jl_tupleset(sparams, i*2+0, jl_tupleref(((jl_struct_type_t*)t->name->primary)->parameters, i)); jl_tupleset(sparams, i*2+1, jl_tupleref(t->parameters, i)); } cfactory = jl_instantiate_method((jl_function_t*)t->ctor_factory, sparams); cfactory->linfo->ast = jl_prepare_ast(cfactory->linfo, cfactory->linfo->sparams); // call user-defined constructor factory on (type,) jl_value_t *cfargs[1] = { (jl_value_t*)t }; jl_apply(cfactory, cfargs, 1); JL_GC_POP(); } } }
static jl_value_t *do_call(jl_function_t *f, jl_value_t **args, size_t nargs, jl_value_t *eval0, jl_value_t **locals, size_t nl) { jl_value_t **argv; JL_GC_PUSHARGS(argv, nargs+1); size_t i; argv[0] = (jl_value_t*)f; for(i=1; i < nargs+1; i++) argv[i] = NULL; i = 0; if (eval0) { /* 0-th argument has already been evaluated */ argv[1] = eval0; i++; } for(; i < nargs; i++) { argv[i+1] = eval(args[i], locals, nl); } jl_value_t *result = jl_apply(f, &argv[1], nargs); JL_GC_POP(); return result; }
jl_value_t *jl_callback_call(jl_function_t *f,jl_value_t *val,int count,...) { if (val != 0) count += 1; else return NULL; jl_value_t **argv; JL_GC_PUSHARGS(argv,count); memset(argv, 0, count*sizeof(jl_value_t*)); jl_value_t *v; va_list argp; va_start(argp,count); int i; assert(val != 0); argv[0]=val; for(i=((val==0)?0:1); i<count; ++i) { switch(va_arg(argp,int)) { case CB_PTR: argv[i] = jl_box_voidpointer(va_arg(argp,void*)); break; case CB_INT32: argv[i] = jl_box_int32(va_arg(argp,int32_t)); break; case CB_UINT32: argv[i] = jl_box_uint32(va_arg(argp,uint32_t)); break; case CB_INT64: argv[i] = jl_box_int64(va_arg(argp,int64_t)); break; case CB_UINT64: argv[i] = jl_box_uint64(va_arg(argp,uint64_t)); break; default: jl_error("callback: only Ints and Pointers are supported at this time"); //excecution never reaches here break; } } va_end(argp); v = jl_apply(f,(jl_value_t**)argv,count); JL_GC_POP(); return v; }
void jl_module_run_initializer(jl_module_t *m) { jl_value_t *f = jl_get_global(m, jl_symbol("__init__")); if (f == NULL || !jl_is_function(f)) return; int build_mode = (jl_compileropts.build_path != NULL); if (build_mode) { if (jl_module_init_order == NULL) jl_module_init_order = jl_alloc_cell_1d(0); jl_cell_1d_push(jl_module_init_order, (jl_value_t*)m); } JL_TRY { jl_apply((jl_function_t*)f, NULL, 0); } JL_CATCH { JL_PRINTF(JL_STDERR, "Warning: error initializing module %s:\n", m->name->name); jl_static_show(JL_STDERR, jl_exception_in_transit); JL_PRINTF(JL_STDERR, "\n"); } }
DLLEXPORT void jl_atexit_hook(int exitcode) { if (exitcode == 0) julia_save(); jl_print_gc_stats(JL_STDERR); if (jl_options.code_coverage) jl_write_coverage_data(); if (jl_options.malloc_log) jl_write_malloc_log(); if (jl_base_module) { jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit")); if (f!=NULL && jl_is_function(f)) { JL_TRY { jl_apply((jl_function_t*)f, NULL, 0); } JL_CATCH { jl_printf(JL_STDERR, "\natexit hook threw an error: "); jl_static_show(JL_STDERR, jl_exception_in_transit); } } }
static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) { // in A.B.C, first find a binding for A in the chain of module scopes // following parent links. then evaluate the rest of the path from there. jl_sym_t *var = (jl_sym_t*)jl_cellref(args,0); assert(jl_is_symbol(var)); jl_module_t *m = jl_current_module; while (1) { jl_binding_t *mb = jl_get_binding(m, var); if (mb != NULL) { if (mb->value == NULL || !jl_is_module(mb->value)) jl_errorf("invalid module path"); m = (jl_module_t*)mb->value; break; } if (m == jl_main_module) { if (!retrying) { if (require_func == NULL && jl_base_module != NULL) require_func = jl_get_global(jl_base_module, jl_symbol("require")); if (require_func != NULL) { jl_value_t *str = jl_cstr_to_string(var->name); JL_GC_PUSH(&str); jl_apply((jl_function_t*)require_func, &str, 1); JL_GC_POP(); return eval_import_path_(args, 1); } } jl_errorf("in module path: %s not defined", var->name); } m = m->parent; } for(size_t i=1; i < jl_array_len(args)-1; i++) { jl_value_t *s = jl_cellref(args,i); assert(jl_is_symbol(s)); m = (jl_module_t*)jl_eval_global_var(m, (jl_sym_t*)s); if (!jl_is_module(m)) jl_errorf("invalid import statement"); } return m; }
JL_DLLEXPORT jl_value_t *jl_call(jl_function_t *f, jl_value_t **args, int32_t nargs) { jl_value_t *v; JL_TRY { jl_value_t **argv; JL_GC_PUSHARGS(argv, nargs+1); argv[0] = (jl_value_t*)f; for(int i=1; i<nargs+1; i++) argv[i] = args[i-1]; size_t last_age = jl_get_ptls_states()->world_age; jl_get_ptls_states()->world_age = jl_get_world_counter(); v = jl_apply(argv, nargs+1); jl_get_ptls_states()->world_age = last_age; JL_GC_POP(); jl_exception_clear(); } JL_CATCH { v = NULL; } return v; }
void jl_module_run_initializer(jl_module_t *m) { jl_function_t *f = jl_module_get_initializer(m); if (f == NULL) return; size_t last_age = jl_get_ptls_states()->world_age; JL_TRY { jl_get_ptls_states()->world_age = jl_world_counter; jl_apply(&f, 1); jl_get_ptls_states()->world_age = last_age; } JL_CATCH { if (jl_initerror_type == NULL) { jl_rethrow(); } else { jl_rethrow_other(jl_new_struct(jl_initerror_type, m->name, jl_exception_in_transit)); } } }
value_t fl_invoke_julia_macro(value_t *args, uint32_t nargs) { if (nargs < 1) argcount("invoke-julia-macro", nargs, 1); (void)tosymbol(args[0], "invoke-julia-macro"); jl_sym_t *name = jl_symbol(symbol_name(args[0])); jl_function_t *f = jl_get_expander(jl_current_module, name); if (f == NULL) return FL_F; jl_value_t **margs; int na = nargs-1; if (na > 0) margs = alloca(na * sizeof(jl_value_t*)); else margs = NULL; int i; for(i=0; i < na; i++) margs[i] = NULL; JL_GC_PUSHARGS(margs, na); for(i=0; i < na; i++) margs[i] = scm_to_julia(args[i+1]); jl_value_t *result; JL_TRY { result = jl_apply(f, margs, na); } JL_CATCH { JL_GC_POP(); jl_show(jl_exception_in_transit); ios_putc('\n', jl_current_output_stream()); return fl_cons(symbol("error"), FL_NIL); } // protect result from GC, otherwise it could be freed during future // macro expansions, since it will be referenced only from scheme and // not julia. // all calls to invoke-julia-macro happen under a single call to jl_expand, // so the preserved value stack is popped there. jl_gc_preserve(result); value_t scm = julia_to_scm(result); JL_GC_POP(); return scm; }
// handle a command line input event void handle_input(jl_value_t *ast, int end, int show_value) { if (end) { ios_printf(ios_stdout, "\n"); exit_repl(0); } if (ast == NULL) { ios_printf(ios_stdout, "\n"); repl_print_prompt(); return; } if (!jl_have_event_loop) { jl_eval_user_input(ast, show_value); } else { jl_value_t *f = jl_get_global(jl_system_module,jl_symbol("repl_callback")); assert(f != NULL); jl_value_t *fargs[] = { ast, jl_box_int32(show_value) }; jl_apply((jl_function_t*)f, fargs, 2); } }
static void run_finalizer(jl_value_t *o, jl_value_t *ff) { jl_function_t *f; while (1) { if (jl_is_tuple(ff)) f = (jl_function_t*)jl_t0(ff); else f = (jl_function_t*)ff; assert(jl_is_function(f)); JL_TRY { jl_apply(f, (jl_value_t**)&o, 1); } JL_CATCH { JL_PRINTF(JL_STDERR, "error in running finalizer: "); jl_static_show(JL_STDERR, jl_exception_in_transit); JL_PUTC('\n',JL_STDERR); } if (jl_is_tuple(ff)) ff = jl_t1(ff); else break; } }
/* static void clear_method_caches(void) { htable_t *t = &jl_system_module->bindings; size_t i; for(i=0; i < t->size; i+=2) { if (t->table[i+1] == HT_NOTFOUND) continue; jl_binding_t *b = (jl_binding_t*)t->table[i+1]; if (b->value != NULL && jl_is_func(b->value) && jl_is_gf(b->value)) { jl_function_t *f = (jl_function_t*)b->value; jl_methtable_t *mt = jl_gf_mtable(f); mt->cache = NULL; } } } */ 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"))); // 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("+"))), &one, 1); /* cached t-functions and inferred ASTs need to be cleared at this point, because during bootstrapping we might not be able to inline optimally. the reason is that we cache an AST before doing inlining, to prevent infinite recursion. for example, consider this function: > (x::Real, y::Real) = (y < x) after doing inference on this >, we cache its AST "(y < x)". now we begin inlining. the problem is that the inlining code itself will trigger compilation of functions that use >, so "(y < x)" will be inlined into those functions. ultimately we inline the definition of < into "(y < x)", but by then it's too late, since "(y < x)" has already been inlined into some functions. to fix this, we clear the t-function cache after all type-inference related code has been compiled. now we can inline everything fully without compilation of the compiler itself interfering. */ clear_tfunc_caches(); } }
int jl_array_isdefined(jl_value_t **args0, int nargs) { assert(jl_is_array(args0[0])); jl_value_t **depwarn_args; JL_GC_PUSHARGS(depwarn_args, 3); depwarn_args[0] = jl_get_global(jl_base_module, jl_symbol("depwarn")); depwarn_args[1] = jl_cstr_to_string("isdefined(a::Array, i::Int) is deprecated, use isassigned(a, i) instead"); depwarn_args[2] = (jl_value_t*) jl_symbol("isdefined"); jl_apply(depwarn_args, 3); JL_GC_POP(); jl_array_t *a = (jl_array_t*)args0[0]; jl_value_t **args = &args0[1]; size_t nidxs = nargs-1; size_t i=0; size_t k, stride=1; size_t nd = jl_array_ndims(a); for(k=0; k < nidxs; k++) { if (!jl_is_long(args[k])) jl_type_error("isdefined", (jl_value_t*)jl_long_type, args[k]); size_t ii = jl_unbox_long(args[k])-1; i += ii * stride; size_t d = k>=nd ? 1 : jl_array_dim(a, k); if (k < nidxs-1 && ii >= d) return 0; stride *= d; } for(; k < nd; k++) stride *= jl_array_dim(a, k); if (i >= stride) return 0; if (a->flags.ptrarray) return ((jl_value_t**)jl_array_data(a))[i] != NULL; return 1; }
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_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, int *plineno) { //jl_show(ex); //JL_PRINTF(JL_STDOUT, "\n"); if (!jl_is_expr(e)) return jl_interpret_toplevel_expr(e); jl_expr_t *ex = (jl_expr_t*)e; if (ex->head == null_sym || ex->head == error_sym) { // expression types simple enough not to need expansion return jl_interpret_toplevel_expr(e); } if (ex->head == module_sym) { return jl_eval_module_expr(ex, plineno); } // handle import, export toplevel-only forms if (ex->head == importall_sym) { jl_module_t *m = eval_import_path(ex->args); jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, ex->args->length-1); assert(jl_is_symbol(name)); m = (jl_module_t*)jl_eval_global_var(m, name); if (!jl_is_module(m)) jl_errorf("invalid import statement"); jl_module_importall(jl_current_module, m); return jl_nothing; } if (ex->head == import_sym) { jl_module_t *m = eval_import_path(ex->args); jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, ex->args->length-1); assert(jl_is_symbol(name)); jl_module_import(jl_current_module, m, name); return jl_nothing; } if (ex->head == export_sym) { for(size_t i=0; i < ex->args->length; i++) { jl_module_export(jl_current_module, (jl_sym_t*)jl_cellref(ex->args, i)); } return jl_nothing; } jl_value_t *thunk=NULL; jl_value_t *result; jl_lambda_info_t *thk=NULL; int ewc = 0; JL_GC_PUSH(&thunk, &thk, &ex); if (ex->head != body_sym && ex->head != thunk_sym) { // not yet expanded ex = (jl_expr_t*)jl_expand(e); } if (jl_is_expr(ex) && ex->head == thunk_sym) { thk = (jl_lambda_info_t*)jl_exprarg(ex,0); assert(jl_is_lambda_info(thk)); ewc = jl_eval_with_compiler_p(jl_lam_body((jl_expr_t*)thk->ast), fast); if (!ewc) { jl_array_t *vinfos = jl_lam_vinfo((jl_expr_t*)thk->ast); int i; for(i=0; i < vinfos->length; i++) { if (jl_vinfo_capt((jl_array_t*)jl_cellref(vinfos,i))) { // interpreter doesn't handle closure environment ewc = 1; break; } } } } else { if (jl_is_expr(ex) && jl_eval_with_compiler_p((jl_expr_t*)ex, fast)) { thk = jl_wrap_expr((jl_value_t*)ex); ewc = 1; } else { result = jl_interpret_toplevel_expr((jl_value_t*)ex); JL_GC_POP(); return result; } } if (ewc) { thunk = (jl_value_t*)jl_new_closure(NULL, (jl_value_t*)jl_null, thk); if (!jl_in_inference) { jl_type_infer(thk, jl_tuple_type, thk); } result = jl_apply((jl_function_t*)thunk, NULL, 0); } else { result = jl_interpret_toplevel_thunk(thk); } JL_GC_POP(); return result; }
DLLEXPORT void uv_atexit_hook() { #if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS) jl_print_gc_stats(JL_STDERR); #endif if (jl_base_module) { jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit")); if (f!=NULL && jl_is_function(f)) { jl_apply((jl_function_t*)f, NULL, 0); } } uv_loop_t* loop = jl_global_event_loop(); struct uv_shutdown_queue queue = {NULL, NULL}; uv_walk(loop, jl_uv_exitcleanup_walk, &queue); // close stdout and stderr last, since we like being // able to show stuff (incl. printf's) jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stdout, &queue); jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stderr, &queue); struct uv_shutdown_queue_item *item = queue.first; while (item) { uv_handle_t *handle = item->h; if (uv_is_closing(handle)) { item = item->next; continue; } switch(handle->type) { case UV_TTY: case UV_UDP: //#ifndef __WIN32__ // unix only supports shutdown on TCP and NAMED_PIPE // but uv_shutdown doesn't seem to be particularly reliable, so we'll avoid it in general jl_close_uv(handle); break; //#endif case UV_TCP: case UV_NAMED_PIPE: if (uv_is_writable((uv_stream_t*)handle)) { // uv_shutdown returns an error if not writable uv_shutdown_t *req = malloc(sizeof(uv_shutdown_t)); int err = uv_shutdown(req, (uv_stream_t*)handle, jl_shutdown_uv_cb); if (err != 0) { printf("shutdown err: %s\n", uv_strerror(uv_last_error(jl_global_event_loop()))); jl_close_uv(handle); } } else { jl_close_uv(handle); } break; case UV_POLL: case UV_TIMER: case UV_PREPARE: case UV_CHECK: case UV_IDLE: case UV_ASYNC: case UV_SIGNAL: case UV_PROCESS: case UV_FS_EVENT: case UV_FS_POLL: jl_close_uv(handle); break; case UV_HANDLE: case UV_STREAM: case UV_UNKNOWN_HANDLE: case UV_HANDLE_TYPE_MAX: case UV_RAW_FD: case UV_RAW_HANDLE: default: assert(0); } item = item->next; } uv_run(loop,UV_RUN_DEFAULT); //let libuv spin until everything has finished closing }
static NOINLINE int true_main(int argc, char *argv[]) { if (jl_core_module != NULL) { jl_array_t *args = (jl_array_t*)jl_get_global(jl_core_module, jl_symbol("ARGS")); if (args == NULL) { args = jl_alloc_cell_1d(0); JL_GC_PUSH1(&args); jl_set_const(jl_core_module, jl_symbol("ARGS"), (jl_value_t*)args); JL_GC_POP(); } assert(jl_array_len(args) == 0); jl_array_grow_end(args, argc); int i; for (i=0; i < argc; i++) { jl_value_t *s = (jl_value_t*)jl_cstr_to_string(argv[i]); jl_set_typeof(s,jl_utf8_string_type); jl_arrayset(args, s, i); } } jl_function_t *start_client = jl_base_module ? (jl_function_t*)jl_get_global(jl_base_module, jl_symbol("_start")) : NULL; if (start_client) { jl_apply(&start_client, 1); return 0; } // run program if specified, otherwise enter REPL if (argc > 0) { if (strcmp(argv[0], "-")) { return exec_program(argv[0]); } } ios_puts("WARNING: Base._start not defined, falling back to economy mode repl.\n", ios_stdout); if (!jl_errorexception_type) ios_puts("WARNING: jl_errorexception_type not defined; any errors will be fatal.\n", ios_stdout); while (!ios_eof(ios_stdin)) { char *volatile line = NULL; JL_TRY { ios_puts("\njulia> ", ios_stdout); ios_flush(ios_stdout); line = ios_readline(ios_stdin); jl_value_t *val = (jl_value_t*)jl_eval_string(line); if (jl_exception_occurred()) { jl_printf(JL_STDERR, "error during run:\n"); jl_static_show(JL_STDERR, jl_exception_in_transit); jl_exception_clear(); } else if (val) { jl_static_show(JL_STDOUT, val); } jl_printf(JL_STDOUT, "\n"); free(line); line = NULL; uv_run(jl_global_event_loop(),UV_RUN_NOWAIT); } JL_CATCH { if (line) { free(line); line = NULL; } jl_printf(JL_STDERR, "\nparser error:\n"); jl_static_show(JL_STDERR, jl_exception_in_transit); jl_printf(JL_STDERR, "\n"); jlbacktrace(); } } return 0; }
void jl_show(jl_value_t *v) { jl_apply(jl_show_gf, &v, 1); }
static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) { // in .A.B.C, first find a binding for A in the chain of module scopes // following parent links. then evaluate the rest of the path from there. // in A.B, look for A in Main first. jl_sym_t *var = (jl_sym_t*)jl_cellref(args,0); size_t i=1; assert(jl_is_symbol(var)); jl_module_t *m; if (var != dot_sym) { m = jl_main_module; } else { m = jl_current_module; while (1) { var = (jl_sym_t*)jl_cellref(args,i); i++; if (var != dot_sym) { if (i == jl_array_len(args)) return m; else break; } m = m->parent; } } while (1) { if (jl_binding_resolved_p(m, var)) { jl_binding_t *mb = jl_get_binding(m, var); assert(mb != NULL); if (mb->owner == m || mb->imported) { m = (jl_module_t*)mb->value; if (m == NULL || !jl_is_module(m)) jl_errorf("invalid module path (%s does not name a module)", var->name); break; } } if (m == jl_main_module) { if (!retrying && i==1) { // (i==1) => no require() for relative imports if (require_func == NULL && jl_base_module != NULL) require_func = jl_get_global(jl_base_module, jl_symbol("require")); if (require_func != NULL) { jl_value_t *str = jl_cstr_to_string(var->name); JL_GC_PUSH1(&str); jl_apply((jl_function_t*)require_func, &str, 1); JL_GC_POP(); return eval_import_path_(args, 1); } } } if (retrying && require_func) { JL_PRINTF(JL_STDERR, "Warning: requiring \"%s\" did not define a corresponding module.\n", var->name); return NULL; } else { jl_errorf("in module path: %s not defined", var->name); } } for(; i < jl_array_len(args)-1; i++) { jl_value_t *s = jl_cellref(args,i); assert(jl_is_symbol(s)); m = (jl_module_t*)jl_eval_global_var(m, (jl_sym_t*)s); if (!jl_is_module(m)) jl_errorf("invalid import statement"); } return m; }
jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast, volatile size_t *plineno) { //jl_show(ex); //ios_printf(ios_stdout, "\n"); if (!jl_is_expr(e)) return jl_interpret_toplevel_expr(e); jl_expr_t *ex = (jl_expr_t*)e; if (ex->head == null_sym || ex->head == error_sym) { // expression types simple enough not to need expansion return jl_interpret_toplevel_expr(e); } if (ex->head == module_sym) { return jl_eval_module_expr(ex, plineno); } jl_value_t *thunk=NULL; jl_value_t *result; jl_lambda_info_t *thk=NULL; int ewc = 0; JL_GC_PUSH(&thunk, &thk, &ex); if (ex->head == body_sym || ex->head == thunk_sym) { // already expanded } else { ex = (jl_expr_t*)jl_expand(e); } if (jl_is_expr(ex) && ex->head == thunk_sym) { thk = (jl_lambda_info_t*)jl_exprarg(ex,0); assert(jl_is_lambda_info(thk)); ewc = eval_with_compiler_p(jl_lam_body((jl_expr_t*)thk->ast), fast); if (!ewc) { jl_array_t *vinfos = jl_lam_vinfo((jl_expr_t*)thk->ast); int i; for(i=0; i < vinfos->length; i++) { if (jl_vinfo_capt((jl_array_t*)jl_cellref(vinfos,i))) { // interpreter doesn't handle closure environment ewc = 1; break; } } } } else { if (jl_is_expr(ex) && eval_with_compiler_p((jl_expr_t*)ex, fast)) { thk = jl_wrap_expr((jl_value_t*)ex); ewc = 1; } else { result = jl_interpret_toplevel_expr((jl_value_t*)ex); JL_GC_POP(); return result; } } 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 { result = jl_interpret_toplevel_thunk(thk); } JL_GC_POP(); return result; }
DLLEXPORT void uv_atexit_hook() { #if defined(JL_GC_MARKSWEEP) && defined(GC_FINAL_STATS) jl_print_gc_stats(JL_STDERR); #endif if (jl_base_module) { jl_value_t *f = jl_get_global(jl_base_module, jl_symbol("_atexit")); if (f!=NULL && jl_is_function(f)) { jl_apply((jl_function_t*)f, NULL, 0); } } uv_loop_t* loop = jl_global_event_loop(); struct uv_shutdown_queue queue = {NULL, NULL}; uv_walk(loop, jl_uv_exitcleanup_walk, &queue); // close stdout and stderr last, since we like being // able to show stuff (incl. printf's) jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stdout, &queue); jl_uv_exitcleanup_add((uv_handle_t*)jl_uv_stderr, &queue); struct uv_shutdown_queue_item *item = queue.first; while (item) { uv_handle_t *handle = item->h; if (uv_is_closing(handle)) { item = item->next; continue; } switch(handle->type) { case UV_TTY: case UV_UDP: //#ifndef _OS_WINDOWS_ // unix only supports shutdown on TCP and NAMED_PIPE // but uv_shutdown doesn't seem to be particularly reliable, so we'll avoid it in general jl_close_uv(handle); break; //#endif case UV_TCP: case UV_NAMED_PIPE: // These will be shut down in jl_close_uv. jl_close_uv(handle); break; //Don't close these directly, but rather let the GC take care of it case UV_POLL: uv_poll_stop((uv_poll_t*)handle); handle->data = NULL; uv_unref(handle); break; case UV_TIMER: uv_timer_stop((uv_timer_t*)handle); handle->data = NULL; uv_unref(handle); break; case UV_IDLE: uv_idle_stop((uv_idle_t*)handle); case UV_ASYNC: handle->data = NULL; uv_unref(handle); break; case UV_FS_EVENT: handle->data = NULL; uv_unref(handle); break; case UV_FS_POLL: uv_fs_poll_stop((uv_fs_poll_t*)handle); handle->data = NULL; uv_unref(handle); break; case UV_PREPARE: case UV_CHECK: case UV_SIGNAL: case UV_PROCESS: jl_close_uv(handle); break; case UV_HANDLE: case UV_STREAM: case UV_UNKNOWN_HANDLE: case UV_HANDLE_TYPE_MAX: case UV_RAW_FD: case UV_RAW_HANDLE: default: assert(0); } item = item->next; } uv_run(loop,UV_RUN_DEFAULT); //let libuv spin until everything has finished closing }
static jl_module_t *eval_import_path_(jl_array_t *args, int retrying) { // in .A.B.C, first find a binding for A in the chain of module scopes // following parent links. then evaluate the rest of the path from there. // in A.B, look for A in Main first. jl_sym_t *var = (jl_sym_t*)jl_cellref(args,0); size_t i=1; if (!jl_is_symbol(var)) jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); jl_module_t *m; if (var != dot_sym) { m = jl_main_module; } else { m = jl_current_module; while (1) { var = (jl_sym_t*)jl_cellref(args,i); if (!jl_is_symbol(var)) jl_type_error("import or using", (jl_value_t*)jl_sym_type, (jl_value_t*)var); i++; if (var != dot_sym) { if (i == jl_array_len(args)) return m; else break; } m = m->parent; } } while (1) { if (jl_binding_resolved_p(m, var)) { jl_binding_t *mb = jl_get_binding(m, var); jl_module_t *m0 = m; int isimp = jl_is_imported(m, var); assert(mb != NULL); if (mb->owner == m0 || isimp) { m = (jl_module_t*)mb->value; if ((mb->owner == m0 && m != NULL && !jl_is_module(m)) || (isimp && (m == NULL || !jl_is_module(m)))) jl_errorf("invalid module path (%s does not name a module)", var->name); // If the binding has been resolved but is (1) undefined, and (2) owned // by the module we're importing into, then allow the import into the // undefined variable (by setting m back to m0). if (m == NULL) m = m0; else break; } } if (m == jl_main_module) { if (!retrying && i==1) { // (i==1) => no require() for relative imports if (require_func == NULL && jl_base_module != NULL) require_func = jl_get_global(jl_base_module, jl_symbol("require")); if (require_func != NULL) { jl_apply((jl_function_t*)require_func, (jl_value_t**)&var, 1); return eval_import_path_(args, 1); } } } if (retrying && require_func) { jl_printf(JL_STDERR, "WARNING: requiring \"%s\" did not define a corresponding module.\n", var->name); return NULL; } else { jl_errorf("in module path: %s not defined", var->name); } } for(; i < jl_array_len(args)-1; i++) { jl_value_t *s = jl_cellref(args,i); assert(jl_is_symbol(s)); m = (jl_module_t*)jl_eval_global_var(m, (jl_sym_t*)s); if (!jl_is_module(m)) jl_errorf("invalid import statement"); } return m; }
jl_value_t *jl_toplevel_eval_flex(jl_value_t *e, int fast) { //jl_show(ex); //jl_printf(JL_STDOUT, "\n"); if (!jl_is_expr(e)) return jl_interpret_toplevel_expr(e); jl_expr_t *ex = (jl_expr_t*)e; if (ex->head == null_sym || ex->head == error_sym) { // expression types simple enough not to need expansion return jl_interpret_toplevel_expr(e); } if (ex->head == module_sym) { return jl_eval_module_expr(ex); } // handle import, using, importall, export toplevel-only forms if (ex->head == importall_sym) { jl_module_t *m = eval_import_path(ex->args); if (m==NULL) return jl_nothing; jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, jl_array_len(ex->args)-1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"importall\" statement"); m = (jl_module_t*)jl_eval_global_var(m, name); if (!jl_is_module(m)) jl_errorf("invalid %s statement: name exists but does not refer to a module", ex->head->name); jl_module_importall(jl_current_module, m); return jl_nothing; } if (ex->head == using_sym) { jl_module_t *m = eval_import_path(ex->args); if (m==NULL) return jl_nothing; jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, jl_array_len(ex->args)-1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"using\" statement"); jl_module_t *u = (jl_module_t*)jl_eval_global_var(m, name); if (jl_is_module(u)) { jl_module_using(jl_current_module, u); } else { jl_module_use(jl_current_module, m, name); } return jl_nothing; } if (ex->head == import_sym) { jl_module_t *m = eval_import_path(ex->args); if (m==NULL) return jl_nothing; jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, jl_array_len(ex->args)-1); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"import\" statement"); jl_module_import(jl_current_module, m, name); return jl_nothing; } if (ex->head == export_sym) { for(size_t i=0; i < jl_array_len(ex->args); i++) { jl_sym_t *name = (jl_sym_t*)jl_cellref(ex->args, i); if (!jl_is_symbol(name)) jl_error("syntax: malformed \"export\" statement"); jl_module_export(jl_current_module, name); } return jl_nothing; } if (ex->head == toplevel_sym) { int i=0; jl_value_t *res=jl_nothing; for(i=0; i < jl_array_len(ex->args); i++) { res = jl_toplevel_eval_flex(jl_cellref(ex->args, i), fast); } return res; } jl_value_t *thunk=NULL; jl_value_t *result; jl_lambda_info_t *thk=NULL; int ewc = 0; JL_GC_PUSH3(&thunk, &thk, &ex); if (ex->head != body_sym && ex->head != thunk_sym && ex->head != return_sym && ex->head != method_sym) { // not yet expanded ex = (jl_expr_t*)jl_expand(e); } jl_sym_t *head = jl_is_expr(ex) ? ex->head : NULL; if (head == toplevel_sym) { int i=0; jl_value_t *res=jl_nothing; for(i=0; i < jl_array_len(ex->args); i++) { res = jl_toplevel_eval_flex(jl_cellref(ex->args, i), fast); } JL_GC_POP(); return res; } if (head == thunk_sym) { thk = (jl_lambda_info_t*)jl_exprarg(ex,0); assert(jl_is_lambda_info(thk)); assert(jl_is_expr(thk->ast)); ewc = jl_eval_with_compiler_p((jl_expr_t*)thk->ast, jl_lam_body((jl_expr_t*)thk->ast), fast, jl_current_module); if (!ewc) { if (jl_lam_vars_captured((jl_expr_t*)thk->ast)) { // interpreter doesn't handle closure environment ewc = 1; } } } else { if (head && jl_eval_with_compiler_p(NULL, (jl_expr_t*)ex, fast, jl_current_module)) { thk = jl_wrap_expr((jl_value_t*)ex); ewc = 1; } else { if (head == body_sym) { result = jl_toplevel_eval_body(ex->args); } else if (jl_is_toplevel_only_expr((jl_value_t*)ex)) { result = jl_toplevel_eval((jl_value_t*)ex); } else { result = jl_interpret_toplevel_expr((jl_value_t*)ex); } JL_GC_POP(); return result; } } if (ewc) { thunk = (jl_value_t*)jl_new_closure(NULL, (jl_value_t*)jl_emptysvec, thk); if (!jl_in_inference) { jl_type_infer(thk, (jl_tupletype_t*)jl_typeof(jl_emptytuple), thk); } result = jl_apply((jl_function_t*)thunk, NULL, 0); } else { result = jl_interpret_toplevel_thunk(thk); } JL_GC_POP(); return result; }