Skip to content

Commit

Permalink
Add jl_expand_in_world (#37902)
Browse files Browse the repository at this point in the history
This allows specifying a particular world age for macro expansion.
  • Loading branch information
simeonschaub authored Oct 8, 2020
1 parent 025d106 commit 9c62c32
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 16 deletions.
38 changes: 22 additions & 16 deletions src/ast.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);
Expand All @@ -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]);
Expand Down Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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)
Expand All @@ -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);
Expand All @@ -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;
}
Expand All @@ -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);
}
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 10 additions & 0 deletions test/meta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 9c62c32

Please sign in to comment.