From 49626e7c7e427723645cb24e926a16741af37efb Mon Sep 17 00:00:00 2001 From: Chris Foster Date: Mon, 30 Mar 2020 18:06:06 +1000 Subject: [PATCH] Remove flisp code from jl_parse_eval_all This makes the top level parse-lower-eval loop independent of flisp internals. --- base/loading.jl | 2 +- src/ast.c | 109 +------------------------------------------ src/julia_internal.h | 2 - src/toplevel.c | 78 ++++++++++++++++++++++++++----- 4 files changed, 70 insertions(+), 121 deletions(-) diff --git a/base/loading.jl b/base/loading.jl index fedc25280c0d4..2deb39c1d4b17 100644 --- a/base/loading.jl +++ b/base/loading.jl @@ -1083,7 +1083,7 @@ actually evaluates `mapexpr(expr)`. If it is omitted, `mapexpr` defaults to [`i """ function include_string(mapexpr::Function, m::Module, txt_::AbstractString, fname::AbstractString="string") txt = String(txt_) - ccall(:jl_load_rewrite_file_string, Any, (Any, Any, Any, Any), + ccall(:jl_parse_eval_all, Any, (Any, Any, Any, Any), m, txt, String(fname), mapexpr === identity ? nothing : mapexpr) end diff --git a/src/ast.c b/src/ast.c index 154cbe2ea99fa..8fd852edb957d 100644 --- a/src/ast.c +++ b/src/ast.c @@ -783,6 +783,8 @@ typedef enum { JL_PARSE_TOPLEVEL = 3, } jl_parse_rule_t; +// Parse string `content` starting at byte offset `start_pos` attributing it to +// `filename`. Return an svec of (parse_result, final_pos) JL_DLLEXPORT jl_value_t *jl_fl_parse(const char *content, size_t content_len, const char *filename, size_t filename_len, int start_pos, jl_parse_rule_t rule) @@ -856,113 +858,6 @@ JL_DLLEXPORT jl_value_t *jl_parse_input_line(const char *str, size_t len, return jl_parse_all(str, len, filename, filename_len); } -// Parse a string `text` at top level, attributing source locations to -// `filename`. Each expression is optionally modified by `mapexpr` (if -// non-NULL) before evaluating in module `inmodule`. -jl_value_t *jl_parse_eval_all(jl_module_t *inmodule, jl_value_t *text, - jl_value_t *filename, jl_value_t *mapexpr) -{ - jl_ptls_t ptls = jl_get_ptls_states(); - if (ptls->in_pure_callback) - jl_error("cannot use include inside a generated function"); - jl_ast_context_t *ctx = jl_ast_ctx_enter(); - fl_context_t *fl_ctx = &ctx->fl; - value_t f, ast, expression; - f = cvalue_static_cstrn(fl_ctx, jl_string_data(filename), jl_string_len(filename)); - fl_gc_handle(fl_ctx, &f); - { - JL_TIMING(PARSING); - value_t t = cvalue_static_cstrn(fl_ctx, jl_string_data(text), - jl_string_len(text)); - fl_gc_handle(fl_ctx, &t); - ast = fl_applyn(fl_ctx, 2, symbol_value(symbol(fl_ctx, "jl-parse-all")), t, f); - fl_free_gc_handles(fl_ctx, 1); - } - fl_free_gc_handles(fl_ctx, 1); - if (ast == fl_ctx->F) { - jl_ast_ctx_leave(ctx); - jl_errorf("could not open file %s", jl_string_data(filename)); - } - fl_gc_handle(fl_ctx, &ast); - fl_gc_handle(fl_ctx, &expression); - - int last_lineno = jl_lineno; - const char *last_filename = jl_filename; - size_t last_age = jl_get_ptls_states()->world_age; - int lineno = 0; - jl_lineno = 0; - jl_filename = jl_string_data(filename); - jl_module_t *old_module = ctx->module; - ctx->module = inmodule; - jl_value_t *form = NULL; - jl_value_t *result = jl_nothing; - int err = 0; - JL_GC_PUSH2(&form, &result); - JL_TRY { - assert(iscons(ast) && car_(ast) == symbol(fl_ctx, "toplevel")); - ast = cdr_(ast); - while (iscons(ast)) { - expression = car_(ast); - { - JL_TIMING(LOWERING); - if (fl_ctx->T == fl_applyn(fl_ctx, 1, symbol_value(symbol(fl_ctx, "contains-macrocall")), expression)) { - form = scm_to_julia(fl_ctx, expression, inmodule); - if (mapexpr) - form = jl_call1(mapexpr, form); - form = jl_expand_macros(form, inmodule, NULL, 0); - expression = julia_to_scm(fl_ctx, form); - } - else if (mapexpr) { - form = scm_to_julia(fl_ctx, expression, inmodule); - form = jl_call1(mapexpr, form); - expression = julia_to_scm(fl_ctx, form); - } - // expand non-final expressions in statement position (value unused) - expression = - fl_applyn(fl_ctx, 4, - symbol_value(symbol(fl_ctx, "jl-expand-to-thunk-warn")), - expression, symbol(fl_ctx, jl_string_data(filename)), - fixnum(lineno), iscons(cdr_(ast)) ? fl_ctx->T : fl_ctx->F); - } - jl_get_ptls_states()->world_age = jl_world_counter; - form = scm_to_julia(fl_ctx, expression, inmodule); - JL_SIGATOMIC_END(); - jl_get_ptls_states()->world_age = jl_world_counter; - if (jl_is_linenode(form)) { - lineno = jl_linenode_line(form); - jl_lineno = lineno; - } - else { - result = jl_toplevel_eval_flex(inmodule, form, 1, 1); - } - JL_SIGATOMIC_BEGIN(); - ast = cdr_(ast); - } - } - JL_CATCH { - form = filename; - result = jl_box_long(jl_lineno); - err = 1; - goto finally; // skip jl_restore_excstack - } -finally: - jl_get_ptls_states()->world_age = last_age; - jl_lineno = last_lineno; - jl_filename = last_filename; - fl_free_gc_handles(fl_ctx, 2); - ctx->module = old_module; - jl_ast_ctx_leave(ctx); - if (err) { - if (jl_loaderror_type == NULL) - jl_rethrow(); - else - jl_rethrow_other(jl_new_struct(jl_loaderror_type, form, result, - jl_current_exception())); - } - JL_GC_POP(); - return result; -} - // returns either an expression or a thunk jl_value_t *jl_call_scm_on_ast(const char *funcname, jl_value_t *expr, jl_module_t *inmodule) { diff --git a/src/julia_internal.h b/src/julia_internal.h index 4479df55e5bd0..e7df5e61bcf66 100644 --- a/src/julia_internal.h +++ b/src/julia_internal.h @@ -473,8 +473,6 @@ jl_array_t *jl_get_loaded_modules(void); jl_value_t *jl_toplevel_eval_flex(jl_module_t *m, jl_value_t *e, int fast, int expanded); jl_value_t *jl_eval_global_var(jl_module_t *m JL_PROPAGATES_ROOT, jl_sym_t *e); -jl_value_t *jl_parse_eval_all(jl_module_t *inmodule, jl_value_t *text, - jl_value_t *filename, jl_value_t *mapexpr); jl_value_t *jl_interpret_toplevel_thunk(jl_module_t *m, jl_code_info_t *src); jl_value_t *jl_interpret_toplevel_expr_in(jl_module_t *m, jl_value_t *e, jl_code_info_t *src, diff --git a/src/toplevel.c b/src/toplevel.c index f1de71f7dd56b..b7977e7a768fc 100644 --- a/src/toplevel.c +++ b/src/toplevel.c @@ -869,19 +869,75 @@ JL_DLLEXPORT jl_value_t *jl_infer_thunk(jl_code_info_t *thk, jl_module_t *m) //------------------------------------------------------------------------------ // Code loading: combined parse+eval for include() and include_string() -// Parse julia code from the string `text`, attributing it to `filename`. Eval -// the resulting statements into `module` after applying `mapexpr` to each one -// (if not one of NULL or nothing). -JL_DLLEXPORT jl_value_t *jl_load_rewrite_file_string(jl_module_t *module, - jl_value_t *text, - jl_value_t *filename, - jl_value_t *mapexpr) +// Parse julia code from the string `text` at top level, attributing it to +// `filename`. Each resulting top level expression is optionally transformed by +// `mapexpr` (if not nothing) before being lowered and evaluated in module +// `module`. +JL_DLLEXPORT jl_value_t *jl_parse_eval_all(jl_module_t *module, jl_value_t *text, + jl_value_t *filename, jl_value_t *mapexpr) { if (!jl_is_string(text) || !jl_is_string(filename)) { jl_errorf("Expected `String`s for `text` and `filename`"); } - return jl_parse_eval_all(module, text, filename, - mapexpr == jl_nothing ? NULL : mapexpr); + jl_ptls_t ptls = jl_get_ptls_states(); + if (ptls->in_pure_callback) + jl_error("cannot use include inside a generated function"); + + jl_value_t *result = jl_nothing; + jl_value_t *ast = NULL; + jl_value_t *expression = NULL; + JL_GC_PUSH3(&ast, &result, &expression); + + ast = jl_parse_all(jl_string_data(text), jl_string_len(text), + jl_string_data(filename), jl_string_len(filename)); + if (!jl_is_expr(ast) || ((jl_expr_t*)ast)->head != toplevel_sym) { + jl_errorf("jl_parse_all() must generate a top level expression"); + } + + int last_lineno = jl_lineno; + const char *last_filename = jl_filename; + size_t last_age = jl_get_ptls_states()->world_age; + int lineno = 0; + jl_lineno = 0; + jl_filename = jl_string_data(filename); + int err = 0; + + JL_TRY { + for (size_t i = 0; i < jl_expr_nargs(ast); i++) { + expression = jl_exprarg(ast, i); + if (jl_is_linenode(expression)) { + // filename is already set above. + lineno = jl_linenode_line(expression); + jl_lineno = lineno; + continue; + } + if (mapexpr != jl_nothing) { + expression = jl_call1(mapexpr, expression); + } + expression = jl_expand_with_loc_warn(expression, module, + jl_string_data(filename), lineno); + jl_get_ptls_states()->world_age = jl_world_counter; + result = jl_toplevel_eval_flex(module, expression, 1, 1); + } + } + JL_CATCH { + result = jl_box_long(jl_lineno); // (ab)use result to root error line + err = 1; + goto finally; // skip jl_restore_excstack + } +finally: + jl_get_ptls_states()->world_age = last_age; + jl_lineno = last_lineno; + jl_filename = last_filename; + if (err) { + if (jl_loaderror_type == NULL) + jl_rethrow(); + else + jl_rethrow_other(jl_new_struct(jl_loaderror_type, filename, result, + jl_current_exception())); + } + JL_GC_POP(); + return result; } // Synchronously read content of entire file into a julia String @@ -910,7 +966,7 @@ JL_DLLEXPORT jl_value_t *jl_load_rewrite(jl_module_t *module, { jl_value_t *text = jl_file_content_as_string(filename); JL_GC_PUSH1(&text); - jl_value_t *result = jl_load_rewrite_file_string(module, text, filename, mapexpr); + jl_value_t *result = jl_parse_eval_all(module, text, filename, mapexpr); JL_GC_POP(); return result; } @@ -938,7 +994,7 @@ JL_DLLEXPORT jl_value_t *jl_load_file_string(const char *text, size_t len, JL_GC_PUSH2(&text_, &filename_); text_ = jl_pchar_to_string(text, len); filename_ = jl_cstr_to_string(filename); - jl_value_t *result = jl_load_rewrite_file_string(module, text_, filename_, jl_nothing); + jl_value_t *result = jl_parse_eval_all(module, text_, filename_, jl_nothing); JL_GC_POP(); return result; }