Skip to content

Commit e586a37

Browse files
committed
Make trivial interpolations like :($x) work
Perhaps surprisingly this is a special case because there's no enclosing expression.
1 parent eb721cb commit e586a37

File tree

7 files changed

+54
-10
lines changed

7 files changed

+54
-10
lines changed

src/macro_expansion.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ end
2525
# Expansion of quoted expressions
2626
function collect_unquoted!(ctx, unquoted, ex, depth)
2727
if kind(ex) == K"$" && depth == 0
28+
# children(ex) is usually length 1, but for double interpolation it may
29+
# be longer and the children may contain K"..." expressions. Wrapping
30+
# in a tuple groups the arguments together correctly in those cases.
2831
push!(unquoted, @ast ctx ex [K"tuple" children(ex)...])
2932
else
3033
inner_depth = kind(ex) == K"quote" ? depth + 1 :

src/runtime.jl

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@ function _interpolate_ast(ctx::InterpolationContext, ex, depth)
6262
end
6363

6464
function interpolate_ast(ex, values...)
65-
if kind(ex) == K"$"
66-
TODO(ex, "\$ in interpolate_ast")
67-
end
6865
# Construct graph for interpolation context. We inherit this from the macro
6966
# context where possible by detecting it using __macro_ctx__. This feels
7067
# hacky though.
@@ -88,7 +85,17 @@ function interpolate_ast(ex, values...)
8885
# We must copy the AST into our context to use it as the source reference
8986
# of generated expressions.
9087
ex1 = copy_ast(ctx, ex)
91-
_interpolate_ast(ctx, ex1, 0)
88+
if kind(ex1) == K"$"
89+
@assert length(values) == 1
90+
vs = values[1]
91+
if length(vs) > 1
92+
# :($($(xs...))) where xs is more than length 1
93+
throw(LoweringError(ex1, "More than one value in bare `\$` expression"))
94+
end
95+
_interpolated_value(ctx, ex1, only(vs))
96+
else
97+
_interpolate_ast(ctx, ex1, 0)
98+
end
9299
end
93100

94101
# Construct new bare module including only the "default names"

test/demo.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,11 @@ src = """
260260
"""
261261

262262
src = """
263-
x = :hi
263+
begin
264+
a = 1
265+
xs = [:(a),]
266+
x = :(:(\$(\$(xs...))))
267+
end
264268
"""
265269

266270
ex = parsestmt(SyntaxTree, src, filename="foo.jl")

test/loops.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,11 @@ let
4545
end
4646
""") == [2,4]
4747

48-
@test_throws JuliaLowering.LoweringError JuliaLowering.include_string(test_mod, """
48+
@test_throws LoweringError JuliaLowering.include_string(test_mod, """
4949
break
5050
""")
5151

52-
@test_throws JuliaLowering.LoweringError JuliaLowering.include_string(test_mod, """
52+
@test_throws LoweringError JuliaLowering.include_string(test_mod, """
5353
continue
5454
""")
5555

test/quoting.jl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,16 @@ let
5757
end
5858
"""))
5959

60+
# Test that trivial interpolation without any nesting works.
61+
ex = JuliaLowering.include_string(test_mod, """
62+
let
63+
x = 123
64+
:(\$x)
65+
end
66+
""")
67+
@test kind(ex) == K"Value"
68+
@test ex.value == 123
69+
6070
# interpolations at multiple depths
6171
ex = JuliaLowering.include_string(test_mod, """
6272
let
@@ -102,4 +112,24 @@ ex2 = JuliaLowering.eval(test_mod, ex)
102112
@test JuliaLowering.include_string(test_mod, ":x") isa Symbol
103113
@test JuliaLowering.include_string(test_mod, ":(x)") isa SyntaxTree
104114

115+
# Double interpolation
116+
ex = JuliaLowering.include_string(test_mod, """
117+
let
118+
args = (:(xxx),)
119+
:(:(\$\$(args...)))
120+
end
121+
""")
122+
Base.eval(test_mod, :(xxx = 111))
123+
ex2 = JuliaLowering.eval(test_mod, ex)
124+
@test kind(ex2) == K"Value"
125+
@test ex2.value == 111
126+
127+
double_interp_ex = JuliaLowering.include_string(test_mod, """
128+
let
129+
args = (:(x), :(y))
130+
:(:(\$\$(args...)))
131+
end
132+
""")
133+
@test_throws LoweringError JuliaLowering.eval(test_mod, double_interp_ex)
134+
105135
end

test/runtests.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,12 +292,12 @@ end == [
292292
]
293293

294294

295-
@test_throws JuliaLowering.LoweringError JuliaLowering.include_string(test_mod, """
295+
@test_throws LoweringError JuliaLowering.include_string(test_mod, """
296296
macro mmm(a; b=2)
297297
end
298298
""")
299299

300-
@test_throws JuliaLowering.LoweringError JuliaLowering.include_string(test_mod, """
300+
@test_throws LoweringError JuliaLowering.include_string(test_mod, """
301301
macro A.b(ex)
302302
end
303303
""")

test/utils.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ using JuliaLowering:
1010
Kind, SourceRef, SyntaxTree, NodeId,
1111
makenode, makeleaf, setattr!, sethead!,
1212
haschildren, numchildren, children,
13-
@ast, flattened_provenance, showprov
13+
@ast, flattened_provenance, showprov, LoweringError
1414

1515
function _ast_test_graph()
1616
graph = SyntaxGraph()

0 commit comments

Comments
 (0)