Skip to content

Commit 4390927

Browse files
committed
Fix to allow named tuple unpacking in let syntax left hand side
1 parent e5dd569 commit 4390927

File tree

4 files changed

+74
-9
lines changed

4 files changed

+74
-9
lines changed

JuliaLowering/src/desugaring.jl

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1843,19 +1843,21 @@ end
18431843
#-------------------------------------------------------------------------------
18441844
# Expand for loops
18451845

1846+
# Extract the variable names assigned to from a "fancy assignment left hand
1847+
# side" such as nested tuple destructuring.
18461848
function foreach_lhs_var(f::Function, ex)
18471849
k = kind(ex)
18481850
if k == K"Identifier" || k == K"BindingId"
18491851
f(ex)
1850-
elseif k == K"Placeholder"
1851-
# Ignored
1852-
elseif k == K"tuple"
1852+
elseif k == K"::" && numchildren(ex) == 2
1853+
foreach_lhs_var(f, ex[1])
1854+
elseif k == K"tuple" || k == K"parameters"
18531855
for e in children(ex)
18541856
foreach_lhs_var(f, e)
18551857
end
1856-
else
1857-
TODO(ex, "LHS vars")
18581858
end
1859+
# k == K"Placeholder" ignored, along with everything else - we assume
1860+
# validation is done elsewhere.
18591861
end
18601862

18611863
function expand_for(ctx, ex)
@@ -1874,7 +1876,6 @@ function expand_for(ctx, ex)
18741876
lhs = iterspec[1]
18751877
if kind(lhs) != K"outer"
18761878
foreach_lhs_var(lhs) do var
1877-
@chk kind(var) == K"Identifier"
18781879
push!(copied_vars, @ast ctx var [K"=" var var])
18791880
end
18801881
end

JuliaLowering/test/loops.jl

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

48-
# TODO: Test soft scope rules
49-
5048
end
5149

52-
5350
@testset "for loops" begin
5451

5552
test_mod = Module()
@@ -144,6 +141,19 @@ let
144141
end
145142
""") == 2
146143

144+
# Fancy for loop left hand side - unpacking and scoping
145+
@test JuliaLowering.include_string(test_mod, """
146+
let
147+
a = []
148+
i = 100
149+
j = 200
150+
for (i,j) in [('a', 'b'), (1,2)]
151+
push!(a, (i,j))
152+
end
153+
(a, i, j)
154+
end
155+
""") == ([('a', 'b'), (1,2)], 100, 200)
156+
147157
end
148158

149159

@@ -162,6 +172,7 @@ end
162172
""") == [(1,3), (1,4), (2,3), (2,4)]
163173

164174
@testset "break/continue" begin
175+
165176
@test JuliaLowering.include_string(test_mod, """
166177
let
167178
a = []
@@ -198,6 +209,8 @@ let
198209
a
199210
end
200211
""") == [(1,2), (1,4), (2,2), (2,4)]
212+
213+
201214
end
202215

203216

JuliaLowering/test/loops_ir.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,47 @@ end
7272
16 (goto label₇)
7373
17 (return core.nothing)
7474

75+
########################################
76+
# Syntax sugar for nested for loop
77+
for x in xs, y in ys
78+
x = 10 # Copy of x; does not overwrite x iteration var
79+
end
80+
#---------------------
81+
1 TestMod.xs
82+
2 (= slot₂/next (call top.iterate %₁))
83+
3 slot₂/next
84+
4 (call core.=== %₃ core.nothing)
85+
5 (call top.not_int %₄)
86+
6 (gotoifnot %₅ label₃₄)
87+
7 slot₂/next
88+
8 (= slot₃/x (call core.getfield %1))
89+
9 (call core.getfield %2)
90+
10 TestMod.ys
91+
11 (= slot₁/next (call top.iterate %₁₀))
92+
12 slot₁/next
93+
13 (call core.=== %₁₂ core.nothing)
94+
14 (call top.not_int %₁₃)
95+
15 (gotoifnot %₁₄ label₂₈)
96+
16 slot₃/x
97+
17 (= slot₄/x %₁₆)
98+
18 slot₁/next
99+
19 (= slot₅/y (call core.getfield %₁₈ 1))
100+
20 (call core.getfield %₁₈ 2)
101+
21 (= slot₄/x 10)
102+
22 (= slot₁/next (call top.iterate %₁₀ %₂₀))
103+
23 slot₁/next
104+
24 (call core.=== %₂₃ core.nothing)
105+
25 (call top.not_int %₂₄)
106+
26 (gotoifnot %₂₅ label₂₈)
107+
27 (goto label₁₆)
108+
28 (= slot₂/next (call top.iterate %%₉))
109+
29 slot₂/next
110+
30 (call core.=== %₂₉ core.nothing)
111+
31 (call top.not_int %₃₀)
112+
32 (gotoifnot %₃₁ label₃₄)
113+
33 (goto label₇)
114+
34 (return core.nothing)
115+
75116
########################################
76117
# Error: break outside for/while
77118
break

JuliaLowering/test/scopes_ir.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,16 @@ end
4040
7 (= slot₃/y (call core.getfield %1))
4141
8 (return core.nothing)
4242

43+
########################################
44+
# let syntax with named tuple on lhs creates locals for the unpacked vars
45+
let (; x,y) = rhs
46+
end
47+
#---------------------
48+
1 TestMod.rhs
49+
2 (= slot₁/x (call top.getproperty %:x))
50+
3 (= slot₂/y (call top.getproperty %:y))
51+
4 (return core.nothing)
52+
4353
########################################
4454
# Let syntax with the same name creates nested bindings
4555
let x = f(x), x = g(x)

0 commit comments

Comments
 (0)