From 9c62c32376ad3657f53bb5a3bf21ae7ca270c7b5 Mon Sep 17 00:00:00 2001 From: Simeon Schaub Date: Fri, 9 Oct 2020 01:57:10 +0200 Subject: [PATCH] Add jl_expand_in_world (#37902) This allows specifying a particular world age for macro expansion. --- src/ast.c | 38 ++++++++++++++++++++++---------------- src/julia.h | 2 ++ test/meta.jl | 10 ++++++++++ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/ast.c b/src/ast.c index cd26a1654134e..54714666b3018 100644 --- a/src/ast.c +++ b/src/ast.c @@ -132,7 +132,7 @@ struct macroctx_stack { static jl_value_t *scm_to_julia(fl_context_t *fl_ctx, value_t e, jl_module_t *mod); static value_t julia_to_scm(fl_context_t *fl_ctx, jl_value_t *v); -static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel); +static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel, size_t world); static value_t fl_defined_julia_global(fl_context_t *fl_ctx, value_t *args, uint32_t nargs) { @@ -948,7 +948,7 @@ int jl_has_meta(jl_array_t *body, jl_sym_t *sym) JL_NOTSAFEPOINT return 0; } -static jl_value_t *jl_invoke_julia_macro(jl_array_t *args, jl_module_t *inmodule, jl_module_t **ctx) +static jl_value_t *jl_invoke_julia_macro(jl_array_t *args, jl_module_t *inmodule, jl_module_t **ctx, size_t world) { jl_ptls_t ptls = jl_get_ptls_states(); JL_TIMING(MACRO_INVOCATION); @@ -969,8 +969,7 @@ static jl_value_t *jl_invoke_julia_macro(jl_array_t *args, jl_module_t *inmodule margs[i] = jl_array_ptr_ref(args, i - 1); size_t last_age = ptls->world_age; - size_t world = jl_world_counter; - ptls->world_age = world; + ptls->world_age = world < jl_world_counter ? world : jl_world_counter; jl_value_t *result; JL_TRY { margs[0] = jl_toplevel_eval(*ctx, margs[0]); @@ -1004,7 +1003,7 @@ static jl_value_t *jl_invoke_julia_macro(jl_array_t *args, jl_module_t *inmodule return result; } -static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel) +static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, struct macroctx_stack *macroctx, int onelevel, size_t world) { if (!expr || !jl_is_expr(expr)) return expr; @@ -1024,7 +1023,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str jl_array_ptr_set(e2->args, 0, expr); expr = (jl_value_t*)e2; } - expr = jl_expand_macros(expr, inmodule, macroctx, onelevel); + expr = jl_expand_macros(expr, inmodule, macroctx, onelevel, world); JL_GC_POP(); return expr; } @@ -1034,7 +1033,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str JL_TYPECHK(hygienic-scope, module, (jl_value_t*)newctx.m); newctx.parent = macroctx; jl_value_t *a = jl_exprarg(e, 0); - jl_value_t *a2 = jl_expand_macros(a, inmodule, &newctx, onelevel); + jl_value_t *a2 = jl_expand_macros(a, inmodule, &newctx, onelevel, world); if (a != a2) jl_array_ptr_set(e->args, 0, a2); return expr; @@ -1043,7 +1042,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str struct macroctx_stack newctx; newctx.m = macroctx ? macroctx->m : inmodule; newctx.parent = macroctx; - jl_value_t *result = jl_invoke_julia_macro(e->args, inmodule, &newctx.m); + jl_value_t *result = jl_invoke_julia_macro(e->args, inmodule, &newctx.m, world); jl_value_t *wrap = NULL; JL_GC_PUSH3(&result, &wrap, &newctx.m); // copy and wrap the result in `(hygienic-scope ,result ,newctx) @@ -1053,7 +1052,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str wrap = (jl_value_t*)jl_exprn(hygienicscope_sym, 2); result = jl_copy_ast(result); if (!onelevel) - result = jl_expand_macros(result, inmodule, wrap ? &newctx : macroctx, onelevel); + result = jl_expand_macros(result, inmodule, wrap ? &newctx : macroctx, onelevel, world); if (wrap) { jl_exprargset(wrap, 0, result); jl_exprargset(wrap, 1, newctx.m); @@ -1075,7 +1074,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str for (j = 2; j < nm; j++) { jl_exprargset(mc2, j+1, jl_exprarg(mc, j)); } - jl_value_t *ret = jl_expand_macros((jl_value_t*)mc2, inmodule, macroctx, onelevel); + jl_value_t *ret = jl_expand_macros((jl_value_t*)mc2, inmodule, macroctx, onelevel, world); JL_GC_POP(); return ret; } @@ -1086,7 +1085,7 @@ static jl_value_t *jl_expand_macros(jl_value_t *expr, jl_module_t *inmodule, str size_t i; for (i = 0; i < jl_array_len(e->args); i++) { jl_value_t *a = jl_array_ptr_ref(e->args, i); - jl_value_t *a2 = jl_expand_macros(a, inmodule, macroctx, onelevel); + jl_value_t *a2 = jl_expand_macros(a, inmodule, macroctx, onelevel, world); if (a != a2) jl_array_ptr_set(e->args, i, a2); } @@ -1098,7 +1097,7 @@ JL_DLLEXPORT jl_value_t *jl_macroexpand(jl_value_t *expr, jl_module_t *inmodule) JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 0); + expr = jl_expand_macros(expr, inmodule, NULL, 0, jl_world_counter); expr = jl_call_scm_on_ast("jl-expand-macroscope", expr, inmodule); JL_GC_POP(); return expr; @@ -1109,7 +1108,7 @@ JL_DLLEXPORT jl_value_t *jl_macroexpand1(jl_value_t *expr, jl_module_t *inmodule JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 1); + expr = jl_expand_macros(expr, inmodule, NULL, 1, jl_world_counter); expr = jl_call_scm_on_ast("jl-expand-macroscope", expr, inmodule); JL_GC_POP(); return expr; @@ -1124,11 +1123,18 @@ JL_DLLEXPORT jl_value_t *jl_expand(jl_value_t *expr, jl_module_t *inmodule) // Lowering, with starting program location specified JL_DLLEXPORT jl_value_t *jl_expand_with_loc(jl_value_t *expr, jl_module_t *inmodule, const char *file, int line) +{ + return jl_expand_in_world(expr, inmodule, file, line, ~(size_t)0); +} + +// Lowering, with starting program location and worldage specified +JL_DLLEXPORT jl_value_t *jl_expand_in_world(jl_value_t *expr, jl_module_t *inmodule, + const char *file, int line, size_t world) { JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 0); + expr = jl_expand_macros(expr, inmodule, NULL, 0, world); expr = jl_call_scm_on_ast_and_loc("jl-expand-to-thunk", expr, inmodule, file, line); JL_GC_POP(); return expr; @@ -1141,7 +1147,7 @@ JL_DLLEXPORT jl_value_t *jl_expand_with_loc_warn(jl_value_t *expr, jl_module_t * JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 0); + expr = jl_expand_macros(expr, inmodule, NULL, 0, ~(size_t)0); jl_ast_context_t *ctx = jl_ast_ctx_enter(); fl_context_t *fl_ctx = &ctx->fl; JL_AST_PRESERVE_PUSH(ctx, old_roots, inmodule); @@ -1162,7 +1168,7 @@ JL_DLLEXPORT jl_value_t *jl_expand_stmt_with_loc(jl_value_t *expr, jl_module_t * JL_TIMING(LOWERING); JL_GC_PUSH1(&expr); expr = jl_copy_ast(expr); - expr = jl_expand_macros(expr, inmodule, NULL, 0); + expr = jl_expand_macros(expr, inmodule, NULL, 0, ~(size_t)0); expr = jl_call_scm_on_ast_and_loc("jl-expand-to-thunk-stmt", expr, inmodule, file, line); JL_GC_POP(); return expr; diff --git a/src/julia.h b/src/julia.h index bd3173b7cb79f..73cac24dee6dd 100644 --- a/src/julia.h +++ b/src/julia.h @@ -1604,6 +1604,8 @@ JL_DLLEXPORT jl_value_t *jl_expand_with_loc(jl_value_t *expr, jl_module_t *inmod const char *file, int line); JL_DLLEXPORT jl_value_t *jl_expand_with_loc_warn(jl_value_t *expr, jl_module_t *inmodule, const char *file, int line); +JL_DLLEXPORT jl_value_t *jl_expand_in_world(jl_value_t *expr, jl_module_t *inmodule, + const char *file, int line, size_t world); JL_DLLEXPORT jl_value_t *jl_expand_stmt(jl_value_t *expr, jl_module_t *inmodule); JL_DLLEXPORT jl_value_t *jl_expand_stmt_with_loc(jl_value_t *expr, jl_module_t *inmodule, const char *file, int line); diff --git a/test/meta.jl b/test/meta.jl index a237b853e2198..430fcf0008173 100644 --- a/test/meta.jl +++ b/test/meta.jl @@ -213,3 +213,13 @@ end @test Meta.parseatom("@foo", 1, filename=:bar)[1].args[2].file == :bar @test Meta.parseall("@foo", filename=:bar).args[1].file == :bar + +_lower(m::Module, ex, world::UInt) = ccall(:jl_expand_in_world, Any, (Any, Ref{Module}, Cstring, Cint, Csize_t), ex, m, "none", 0, world) + +module TestExpandInWorldModule +macro m() 1 end +wa = Base.get_world_counter() +macro m() 2 end +end + +@test _lower(TestExpandInWorldModule, :(@m), TestExpandInWorldModule.wa) == 1