Skip to content

Commit 7badaaa

Browse files
mlechuc42f
andauthored
Add hook for testing JuliaLowering in core (#32)
--------- Co-authored-by: Claire Foster <[email protected]>
1 parent 39b1eb4 commit 7badaaa

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

src/JuliaLowering.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ _include("syntax_macros.jl")
3333

3434
_include("eval.jl")
3535
_include("compat.jl")
36+
_include("hooks.jl")
3637

3738
function __init__()
3839
_register_kinds()

src/hooks.jl

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
Becomes `Core._lower()` upon activating JuliaLowering.
3+
4+
Returns an svec with the lowered code (usually expr) as its first element, and
5+
(until integration is less experimental) whatever we want after it
6+
"""
7+
function core_lowering_hook(@nospecialize(code), mod::Module,
8+
file="none", line=0, world=typemax(Csize_t), warn=false)
9+
if !(code isa SyntaxTree || code isa Expr)
10+
# e.g. LineNumberNode, integer...
11+
return Core.svec(code)
12+
end
13+
14+
# TODO: fix in base
15+
file = file isa Ptr{UInt8} ? unsafe_string(file) : file
16+
line = !(line isa Int64) ? Int64(line) : line
17+
18+
st0 = code isa Expr ? expr_to_syntaxtree(code, LineNumberNode(line, file)) : code
19+
try
20+
ctx1, st1 = expand_forms_1( mod, st0)
21+
ctx2, st2 = expand_forms_2( ctx1, st1)
22+
ctx3, st3 = resolve_scopes( ctx2, st2)
23+
ctx4, st4 = convert_closures(ctx3, st3)
24+
ctx5, st5 = linearize_ir( ctx4, st4)
25+
ex = to_lowered_expr(mod, st5)
26+
return Core.svec(ex, st5, ctx5)
27+
catch exc
28+
@error("JuliaLowering failed — falling back to flisp!",
29+
exception=(exc,catch_backtrace()),
30+
code=code, file=file, line=line, mod=mod)
31+
return Base.fl_lower(code, mod, file, line, world, warn)
32+
end
33+
end
34+
35+
# TODO: Write a parser hook here. The input to `core_lowering_hook` should
36+
# eventually be a (convertible to) SyntaxTree, but we need to make updates to
37+
# the parsing API to include a parameter for AST type.
38+
39+
const _has_v1_13_hooks = isdefined(Core, :_lower)
40+
41+
function activate!(enable=true)
42+
if !_has_v1_13_hooks
43+
error("Cannot use JuliaLowering without `Core._lower` binding or in $VERSION < 1.13")
44+
end
45+
46+
if enable
47+
Core._setlowerer!(core_lowering_hook)
48+
else
49+
Core._setlowerer!(Base.fl_lower)
50+
end
51+
end

test/hooks.jl

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const JL = JuliaLowering
2+
3+
@testset "hooks" begin
4+
test_mod = Module()
5+
6+
@testset "`core_lowering_hook`" begin
7+
# Non-AST types are often sent through lowering
8+
stuff = Any[LineNumberNode(1), 123, 123.123, true, "foo", test_mod]
9+
for s in stuff
10+
@test JL.core_lowering_hook(s, test_mod) == Core.svec(s)
11+
end
12+
13+
for ast_type in (Expr, JL.SyntaxTree)
14+
ex = parsestmt(ast_type, "[1,2,3] .+= 1")
15+
out = JL.core_lowering_hook(ex, test_mod)
16+
@test out isa Core.SimpleVector && out[1] isa Expr
17+
val = Core.eval(test_mod, out[1])
18+
@test val == [2,3,4]
19+
end
20+
end
21+
22+
@testset "integration: `JuliaLowering.activate!`" begin
23+
prog = parseall(Expr, "global asdf = 1")
24+
JL.activate!()
25+
out = Core.eval(test_mod, prog)
26+
JL.activate!(false)
27+
@test out === 1
28+
@test isdefined(test_mod, :asdf)
29+
30+
prog = parseall(Expr, "module M; x = 1; end")
31+
JL.activate!()
32+
out = Core.eval(test_mod, prog)
33+
JL.activate!(false)
34+
@test out isa Module
35+
@test isdefined(test_mod, :M)
36+
@test isdefined(test_mod.M, :x)
37+
end
38+
end

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,5 @@ include("utils.jl")
2626
include("scopes.jl")
2727
include("typedefs.jl")
2828
include("compat.jl")
29+
include("hooks.jl")
2930
end

0 commit comments

Comments
 (0)