Skip to content

Commit 1278421

Browse files
mlechuaviateskc42f
authored
Compat behaviours: typeof quoted expressions, macro def signatures (#44)
Co-authored-by: Shuhei Kadowaki <[email protected]> Co-authored-by: Claire Foster <[email protected]>
1 parent 0d87b74 commit 1278421

13 files changed

+95
-51
lines changed

src/desugaring.jl

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,22 @@ struct DesugaringContext{GraphType} <: AbstractLoweringContext
55
bindings::Bindings
66
scope_layers::Vector{ScopeLayer}
77
mod::Module
8+
expr_compat_mode::Bool
89
end
910

10-
function DesugaringContext(ctx)
11+
function DesugaringContext(ctx, expr_compat_mode::Bool)
1112
graph = ensure_attributes(syntax_graph(ctx),
1213
kind=Kind, syntax_flags=UInt16,
1314
source=SourceAttrType,
1415
value=Any, name_val=String,
1516
scope_type=Symbol, # :hard or :soft
1617
var_id=IdTag,
1718
is_toplevel_thunk=Bool)
18-
DesugaringContext(graph, ctx.bindings, ctx.scope_layers, first(ctx.scope_layers).mod)
19+
DesugaringContext(graph,
20+
ctx.bindings,
21+
ctx.scope_layers,
22+
first(ctx.scope_layers).mod,
23+
expr_compat_mode)
1924
end
2025

2126
#-------------------------------------------------------------------------------
@@ -3246,20 +3251,39 @@ function expand_macro_def(ctx, ex)
32463251
name = sig[1]
32473252
args = remove_empty_parameters(children(sig))
32483253
@chk kind(args[end]) != K"parameters" (args[end], "macros cannot accept keyword arguments")
3249-
ret = @ast ctx ex [K"function"
3250-
[K"call"(sig)
3251-
_make_macro_name(ctx, name)
3252-
[K"::"
3253-
adopt_scope(@ast(ctx, sig, "__context__"::K"Identifier"),
3254-
kind(name) == K"." ? name[1] : name)
3255-
MacroContext::K"Value"
3254+
scope_ref = kind(name) == K"." ? name[1] : name
3255+
if ctx.expr_compat_mode
3256+
@ast ctx ex [K"function"
3257+
[K"call"(sig)
3258+
_make_macro_name(ctx, name)
3259+
[K"::"
3260+
# TODO: should we be adopting the scope of the K"macro" expression itself?
3261+
adopt_scope(@ast(ctx, sig, "__source__"::K"Identifier"), scope_ref)
3262+
LineNumberNode::K"Value"
3263+
]
3264+
[K"::"
3265+
adopt_scope(@ast(ctx, sig, "__module__"::K"Identifier"), scope_ref)
3266+
Module::K"Value"
3267+
]
3268+
map(e->_apply_nospecialize(ctx, e), args[2:end])...
32563269
]
3257-
# flisp: We don't mark these @nospecialize because all arguments to
3258-
# new macros will be of type SyntaxTree
3259-
args[2:end]...
3270+
ex[2]
32603271
]
3261-
ex[2]
3262-
]
3272+
else
3273+
@ast ctx ex [K"function"
3274+
[K"call"(sig)
3275+
_make_macro_name(ctx, name)
3276+
[K"::"
3277+
adopt_scope(@ast(ctx, sig, "__context__"::K"Identifier"), scope_ref)
3278+
MacroContext::K"Value"
3279+
]
3280+
# flisp: We don't mark these @nospecialize because all arguments to
3281+
# new macros will be of type SyntaxTree
3282+
args[2:end]...
3283+
]
3284+
ex[2]
3285+
]
3286+
end
32633287
end
32643288

32653289
#-------------------------------------------------------------------------------
@@ -4284,9 +4308,10 @@ function expand_module(ctx, ex::SyntaxTree)
42844308
[K"inert" ex]
42854309
]
42864310
[K"call"
4287-
eval_module ::K"Value"
4288-
ctx.mod ::K"Value"
4289-
modname ::K"String"
4311+
eval_module ::K"Value"
4312+
ctx.mod ::K"Value"
4313+
modname ::K"String"
4314+
ctx.expr_compat_mode ::K"Bool"
42904315
[K"inert"(body)
42914316
[K"toplevel"
42924317
std_defs
@@ -4477,14 +4502,21 @@ function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs=nothing)
44774502
elseif k == K"toplevel"
44784503
# The toplevel form can't be lowered here - it needs to just be quoted
44794504
# and passed through to a call to eval.
4480-
@ast ctx ex [K"block"
4505+
ex2 = @ast ctx ex [K"block"
44814506
[K"assert" "toplevel_only"::K"Symbol" [K"inert" ex]]
44824507
[K"call"
4483-
eval ::K"Value"
4484-
ctx.mod ::K"Value"
4508+
eval ::K"Value"
4509+
ctx.mod ::K"Value"
44854510
[K"inert" ex]
4511+
[K"parameters"
4512+
[K"="
4513+
"expr_compat_mode"::K"Identifier"
4514+
ctx.expr_compat_mode::K"Bool"
4515+
]
4516+
]
44864517
]
44874518
]
4519+
expand_forms_2(ctx, ex2)
44884520
elseif k == K"vect"
44894521
check_no_parameters(ex, "unexpected semicolon in array expression")
44904522
expand_array(ctx, ex, "vect")
@@ -4546,7 +4578,7 @@ function expand_forms_2(ctx::StatementListCtx, args...)
45464578
end
45474579

45484580
function expand_forms_2(ctx::MacroExpansionContext, ex::SyntaxTree)
4549-
ctx1 = DesugaringContext(ctx)
4581+
ctx1 = DesugaringContext(ctx, ctx.expr_compat_mode)
45504582
ex1 = expand_forms_2(ctx1, reparent(ctx1, ex))
45514583
ctx1, ex1
45524584
end

src/eval.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
function lower(mod::Module, ex0)
2-
ctx1, ex1 = expand_forms_1( mod, ex0)
1+
function lower(mod::Module, ex0, expr_compat_mode=false)
2+
ctx1, ex1 = expand_forms_1( mod, ex0, expr_compat_mode)
33
ctx2, ex2 = expand_forms_2( ctx1, ex1)
44
ctx3, ex3 = resolve_scopes( ctx2, ex2)
55
ctx4, ex4 = convert_closures(ctx3, ex3)
66
ctx5, ex5 = linearize_ir( ctx4, ex4)
77
ex5
88
end
99

10-
function macroexpand(mod::Module, ex)
11-
ctx1, ex1 = expand_forms_1(mod, ex)
10+
function macroexpand(mod::Module, ex, expr_compat_mode=false)
11+
ctx1, ex1 = expand_forms_1(mod, ex, expr_compat_mode)
1212
ex1
1313
end
1414

@@ -344,16 +344,16 @@ end
344344

345345
#-------------------------------------------------------------------------------
346346
# Our version of eval takes our own data structures
347-
function Core.eval(mod::Module, ex::SyntaxTree)
347+
function Core.eval(mod::Module, ex::SyntaxTree; expr_compat_mode::Bool=false)
348348
k = kind(ex)
349349
if k == K"toplevel"
350350
x = nothing
351351
for e in children(ex)
352-
x = eval(mod, e)
352+
x = eval(mod, e; expr_compat_mode)
353353
end
354354
return x
355355
end
356-
linear_ir = lower(mod, ex)
356+
linear_ir = lower(mod, ex, expr_compat_mode)
357357
expr_form = to_lowered_expr(mod, linear_ir)
358358
eval(mod, expr_form)
359359
end

src/hooks.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ function core_lowering_hook(@nospecialize(code), mod::Module,
1717

1818
st0 = code isa Expr ? expr_to_syntaxtree(code, LineNumberNode(line, file)) : code
1919
try
20-
ctx1, st1 = expand_forms_1( mod, st0)
20+
ctx1, st1 = expand_forms_1( mod, st0, true)
2121
ctx2, st2 = expand_forms_2( ctx1, st1)
2222
ctx3, st3 = resolve_scopes( ctx2, st2)
2323
ctx4, st4 = convert_closures(ctx3, st3)

src/macro_expansion.jl

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,12 @@ struct MacroExpansionContext{GraphType} <: AbstractLoweringContext
2020
bindings::Bindings
2121
scope_layers::Vector{ScopeLayer}
2222
scope_layer_stack::Vector{LayerId}
23+
expr_compat_mode::Bool
2324
end
2425

25-
function MacroExpansionContext(graph::SyntaxGraph, mod::Module)
26+
function MacroExpansionContext(graph::SyntaxGraph, mod::Module, expr_compat_mode::Bool)
2627
layers = ScopeLayer[ScopeLayer(1, mod, 0, false)]
27-
MacroExpansionContext(graph, Bindings(), layers, LayerId[length(layers)])
28+
MacroExpansionContext(graph, Bindings(), layers, LayerId[length(layers)], expr_compat_mode)
2829
end
2930

3031
current_layer(ctx::MacroExpansionContext) = ctx.scope_layers[last(ctx.scope_layer_stack)]
@@ -67,6 +68,7 @@ function expand_quote(ctx, ex)
6768
# (ex, @HERE) ?
6869
@ast ctx ex [K"call"
6970
interpolate_ast::K"Value"
71+
(ctx.expr_compat_mode ? Expr : SyntaxTree)::K"Value"
7072
[K"inert" ex]
7173
unquoted...
7274
]
@@ -447,18 +449,18 @@ function expand_forms_1(ctx::MacroExpansionContext, ex::SyntaxTree)
447449
end
448450
end
449451

450-
function expand_forms_1(mod::Module, ex::SyntaxTree)
452+
function expand_forms_1(mod::Module, ex::SyntaxTree, expr_compat_mode::Bool)
451453
graph = ensure_attributes(syntax_graph(ex),
452454
var_id=IdTag,
453455
scope_layer=LayerId,
454456
__macro_ctx__=Nothing,
455457
meta=CompileHints)
456-
ctx = MacroExpansionContext(graph, mod)
458+
ctx = MacroExpansionContext(graph, mod, expr_compat_mode)
457459
ex2 = expand_forms_1(ctx, reparent(ctx, ex))
458460
graph2 = delete_attributes(graph, :__macro_ctx__)
459461
# TODO: Returning the context with pass-specific mutable data is a bad way
460462
# to carry state into the next pass. We might fix this by attaching such
461463
# data to the graph itself as global attributes?
462-
ctx2 = MacroExpansionContext(graph2, ctx.bindings, ctx.scope_layers, LayerId[])
464+
ctx2 = MacroExpansionContext(graph2, ctx.bindings, ctx.scope_layers, LayerId[], expr_compat_mode)
463465
return ctx2, reparent(ctx2, ex2)
464466
end

src/runtime.jl

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ function _interpolate_ast(ctx::InterpolationContext, ex, depth)
7171
makenode(ctx, ex, head(ex), expanded_children)
7272
end
7373

74-
function interpolate_ast(ex, values...)
74+
function interpolate_ast(::Type{SyntaxTree}, ex, values...)
7575
# Construct graph for interpolation context. We inherit this from the macro
7676
# context where possible by detecting it using __macro_ctx__. This feels
7777
# hacky though.
@@ -108,6 +108,14 @@ function interpolate_ast(ex, values...)
108108
end
109109
end
110110

111+
function interpolate_ast(::Type{Expr}, ex, values...)
112+
# TODO: Adjust `_interpolated_value` to ensure that incoming `Expr` data
113+
# structures are treated as AST in Expr compat mode, rather than `K"Value"`?
114+
# Or convert `ex` to `Expr` early during lowering and implement
115+
# `interpolate_ast` for `Expr`?
116+
Expr(interpolate_ast(SyntaxTree, ex, values...))
117+
end
118+
111119
#--------------------------------------------------
112120
# Functions called by closure conversion
113121
function eval_closure_type(mod::Module, closure_type_name::Symbol, field_names, field_is_box)
@@ -154,7 +162,7 @@ end
154162
# public modname
155163
#
156164
# And run statments in the toplevel expression `body`
157-
function eval_module(parentmod, modname, body)
165+
function eval_module(parentmod, modname, expr_compat_mode, body)
158166
# Here we just use `eval()` with an Expr.
159167
# If we wanted to avoid this we'd need to reproduce a lot of machinery from
160168
# jl_eval_module_expr()
@@ -171,7 +179,7 @@ function eval_module(parentmod, modname, body)
171179
name = Symbol(modname)
172180
eval(parentmod, :(
173181
baremodule $name
174-
$eval($name, $body)
182+
$eval($name, $body; expr_compat_mode=$expr_compat_mode)
175183
end
176184
))
177185
end
@@ -296,7 +304,7 @@ function (g::GeneratedFunctionStub)(world::UInt, source::Method, @nospecialize a
296304
)
297305

298306
# Macro expansion
299-
ctx1 = MacroExpansionContext(graph, mod)
307+
ctx1 = MacroExpansionContext(graph, mod, false)
300308

301309
# Run code generator - this acts like a macro expander and like a macro
302310
# expander it gets a MacroContext.
@@ -315,7 +323,7 @@ function (g::GeneratedFunctionStub)(world::UInt, source::Method, @nospecialize a
315323
# Expand any macros emitted by the generator
316324
ex1 = expand_forms_1(ctx1, reparent(ctx1, ex0))
317325
ctx1 = MacroExpansionContext(delete_attributes(graph, :__macro_ctx__),
318-
ctx1.bindings, ctx1.scope_layers, LayerId[])
326+
ctx1.bindings, ctx1.scope_layers, LayerId[], false)
319327
ex1 = reparent(ctx1, ex1)
320328

321329
# Desugaring

src/syntax_graph.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -653,9 +653,10 @@ macro SyntaxTree(ex_old)
653653
ex = _find_SyntaxTree_macro(full_ex, __source__.line)
654654
# 4. Do the first step of JuliaLowering's syntax lowering to get
655655
# syntax interpolations to work
656-
_, ex1 = expand_forms_1(__module__, ex)
656+
_, ex1 = expand_forms_1(__module__, ex, false)
657657
@assert kind(ex1) == K"call" && ex1[1].value == interpolate_ast
658-
Expr(:call, :interpolate_ast, ex1[2][1], map(e->_scope_layer_1_to_esc!(Expr(e)), ex1[3:end])...)
658+
Expr(:call, :interpolate_ast, SyntaxTree, ex1[3][1],
659+
map(e->_scope_layer_1_to_esc!(Expr(e)), ex1[4:end])...)
659660
end
660661

661662
#-------------------------------------------------------------------------------

test/arrays_ir.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,3 +496,4 @@ a[] = rhs
496496
2 TestMod.a
497497
3 (call top.setindex! %%₁)
498498
4 (return %₁)
499+

test/demo.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ end
3535
# Currently broken - need to push info back onto src
3636
# function annotate_scopes(mod, ex)
3737
# ex = ensure_attributes(ex, var_id=Int)
38-
# ctx1, ex_macroexpand = JuliaLowering.expand_forms_1(mod, ex)
38+
# ctx1, ex_macroexpand = JuliaLowering.expand_forms_1(mod, ex, false)
3939
# ctx2, ex_desugar = JuliaLowering.expand_forms_2(ctx1, ex_macroexpand)
4040
# ctx3, ex_scoped = JuliaLowering.resolve_scopes(ctx2, ex_desugar)
4141
# ex
@@ -859,7 +859,7 @@ ex = ensure_attributes(ex, var_id=Int)
859859

860860
in_mod = M
861861
# in_mod=Main
862-
ctx1, ex_macroexpand = JuliaLowering.expand_forms_1(in_mod, ex)
862+
ctx1, ex_macroexpand = JuliaLowering.expand_forms_1(in_mod, ex, false)
863863
@info "Macro expanded" formatsrc(ex_macroexpand, color_by=:scope_layer)
864864
#@info "Macro expanded" formatsrc(ex_macroexpand, color_by=e->JuliaLowering.flattened_provenance(e)[1:end-1])
865865

test/functions_ir.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,9 +1565,9 @@ end
15651565
10 (call core.svec %%%₉)
15661566
11 --- method core.nothing %₁₀
15671567
slots: [slot₁/#self#(!read) slot₂/__context__(!read) slot₃/#self#(!read) slot₄/x(nospecialize,!read) slot₅/y(nospecialize,!read)]
1568-
1 (call JuliaLowering.interpolate_ast (inert (block (= maybe_gen_stuff (call some_gen_stuff x y)))))
1568+
1 (call JuliaLowering.interpolate_ast SyntaxTree (inert (block (= maybe_gen_stuff (call some_gen_stuff x y)))))
15691569
2 (call core.tuple %₁)
1570-
3 (call JuliaLowering.interpolate_ast (inert (block (block (= nongen_stuff (call bothgen x y)) ($ (block (call JuliaLowering.interpolate_ast (inert (block (= maybe_gen_stuff (call some_gen_stuff x y))))))) (tuple-p nongen_stuff maybe_gen_stuff)))) %₂)
1570+
3 (call JuliaLowering.interpolate_ast SyntaxTree (inert (block (block (= nongen_stuff (call bothgen x y)) ($ (block (call JuliaLowering.interpolate_ast SyntaxTree (inert (block (= maybe_gen_stuff (call some_gen_stuff x y))))))) (tuple-p nongen_stuff maybe_gen_stuff)))) %₂)
15711571
4 (return %₃)
15721572
12 latestworld
15731573
13 TestMod.f_partially_generated

test/generators_ir.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ LoweringError:
171171
9 (call core.svec %%%₈)
172172
10 --- method core.nothing %
173173
slots: [slot₁/#self#(!read) slot₂/_(!read)]
174-
1 (call JuliaLowering.interpolate_ast (inert (return x)))
174+
1 (call JuliaLowering.interpolate_ast SyntaxTree (inert (return x)))
175175
2 (return %₁)
176176
11 latestworld
177177
12 TestMod.#->##6

0 commit comments

Comments
 (0)