Skip to content

Commit

Permalink
Desugaring: vcat, hcat, hvcat
Browse files Browse the repository at this point in the history
  • Loading branch information
c42f committed Jan 9, 2025
1 parent e019a85 commit 7227d30
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 1 deletion.
79 changes: 78 additions & 1 deletion src/desugaring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,70 @@ function expand_setindex(ctx, ex)
]
end

function check_no_assignment(exs)
assign_pos = findfirst(kind(e) == K"=" for e in exs)
if !isnothing(assign_pos)
throw(LoweringError(exs[assign_pos], "misplaced assignment statement in `[ ... ]`"))
end
end

function expand_vcat(ctx, ex)
if has_parameters(ex)
throw(LoweringError(ex, "unexpected semicolon in array expression"))
end
check_no_assignment(children(ex))
had_row = false
had_row_splat = false
for e in children(ex)
k = kind(e)
if k == K"row"
had_row = true
had_row_splat = had_row_splat || any(kind(e1) == K"..." for e1 in children(e))
end
end
if had_row_splat
# In case there is splatting inside `hvcat`, collect each row as a
# separate tuple and pass those to `hvcat_rows` instead (ref #38844)
rows = SyntaxList(ctx)
for e in children(ex)
if kind(e) == K"row"
push!(rows, @ast ctx e [K"tuple" children(e)...])
else
push!(rows, @ast ctx e [K"tuple" e])
end
end
@ast ctx ex [K"call"
"hvcat_rows"::K"top"
rows...
]
else
row_sizes = SyntaxList(ctx)
elements = SyntaxList(ctx)
for e in children(ex)
if kind(e) == K"row"
rowsize = numchildren(e)
append!(elements, children(e))
else
rowsize = 1
push!(elements, e)
end
push!(row_sizes, @ast ctx e rowsize::K"Integer")
end
if had_row
@ast ctx ex [K"call"
"hvcat"::K"top"
[K"tuple" row_sizes...]
elements...
]
else
@ast ctx ex [K"call"
"vcat"::K"top"
elements...
]
end
end
end

# Expand UnionAll definitions, eg `X{T} = Y{T,T}`
function expand_unionall_def(ctx, srcref, lhs, rhs)
if numchildren(lhs) <= 1
Expand Down Expand Up @@ -2668,7 +2732,8 @@ function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs=nothing)
else
@ast ctx ex [K"if" cond true::K"Bool" cs[end]]
end
elseif k == K"::" && numchildren(ex) == 2
elseif k == K"::"
@chk numchildren(ex) == 2 "`::` must be written `value::type` outside function argument lists"
@ast ctx ex [K"call"
"typeassert"::K"core"
expand_forms_2(ctx, ex[1])
Expand Down Expand Up @@ -2787,10 +2852,22 @@ function expand_forms_2(ctx::DesugaringContext, ex::SyntaxTree, docs=nothing)
]
]
elseif k == K"vect"
if has_parameters(ex)
throw(LoweringError(ex, "unexpected semicolon in array expression"))
end
check_no_assignment(children(ex))
@ast ctx ex [K"call"
"vect"::K"top"
expand_forms_2(ctx, children(ex))...
]
elseif k == K"hcat"
check_no_assignment(children(ex))
@ast ctx ex [K"call"
"hcat"::K"top"
expand_forms_2(ctx, children(ex))...
]
elseif k == K"vcat"
expand_forms_2(ctx, expand_vcat(ctx, ex))
elseif k == K"while"
@chk numchildren(ex) == 2
@ast ctx ex [K"break_block" "loop_exit"::K"symbolic_label"
Expand Down
37 changes: 37 additions & 0 deletions test/arrays.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@testset "Array syntax" begin

test_mod = Module()

# vect
@test JuliaLowering.include_string(test_mod, """
[1,2,3]
""") == [1,2,3]

# hcat
@test JuliaLowering.include_string(test_mod, """
[1 2 3]
""") == [1 2 3]

@test JuliaLowering.include_string(test_mod, """
let
xs = (1,2)
[xs...; xs...]
end
""") == [1,2,1,2]

# hvcat
@test JuliaLowering.include_string(test_mod, """
[1 2 3; 4 5 6]
""") == [1 2 3;
4 5 6]

# hvcat_rows
@test JuliaLowering.include_string(test_mod, """
let
xs = (1,2)
[xs... 3; 4 xs...]
end
""") == [1 2 3;
4 1 2]

end
101 changes: 101 additions & 0 deletions test/arrays_ir.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
########################################
# vect syntax
[a, b, c]
#---------------------
1 TestMod.a
2 TestMod.b
3 TestMod.c
4 (call top.vect %%%₃)
5 (return %₄)

########################################
# Error: vect syntax with parameters
[a, b; c]
#---------------------
LoweringError:
[a, b; c]
└───────┘ ── unexpected semicolon in array expression

########################################
# Error: vect syntax with embedded assignments
[a=b, c]
#---------------------
LoweringError:
[a=b, c]
#└─┘ ── misplaced assignment statement in `[ ... ]`

########################################
# hcat syntax
[a b c]
#---------------------
1 TestMod.a
2 TestMod.b
3 TestMod.c
4 (call top.hcat %%%₃)
5 (return %₄)

########################################
# Error: hcat syntax with embedded assignments
[a b c=d]
#---------------------
LoweringError:
[a b c=d]
# └──┘ ── misplaced assignment statement in `[ ... ]`

########################################
# vcat syntax
[a; b; c]
#---------------------
1 TestMod.a
2 TestMod.b
3 TestMod.c
4 (call top.vcat %%%₃)
5 (return %₄)

########################################
# vcat with splats
[a...; b; c]
#---------------------
1 TestMod.a
2 TestMod.b
3 TestMod.c
4 (call core.tuple %%₃)
5 (call core._apply_iterate top.iterate top.vcat %%₄)
6 (return %₅)

########################################
# hvcat syntax
[a; b c; d e f]
#---------------------
1 (call core.tuple 1 2 3)
2 TestMod.a
3 TestMod.b
4 TestMod.c
5 TestMod.d
6 TestMod.e
7 TestMod.f
8 (call top.hvcat %%%%%%%₇)
9 (return %₈)

########################################
# hvcat with splats nested within rows
[a; b c...]
#---------------------
1 TestMod.a
2 (call core.tuple %₁)
3 TestMod.b
4 (call core.tuple %₃)
5 TestMod.c
6 (call core._apply_iterate top.iterate core.tuple %%₅)
7 (call core.tuple %%₆)
8 (call top.hvcat_rows %₇)
9 (return %₈)

########################################
# Error: vcat syntax with assignments
[a=b; c]
#---------------------
LoweringError:
[a=b; c]
#└─┘ ── misplaced assignment statement in `[ ... ]`

8 changes: 8 additions & 0 deletions test/misc_ir.jl
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,14 @@ x::T
3 (call core.typeassert %%₂)
4 (return %₃)

########################################
# Error: Invalid :: syntax outside function arg list
::T
#---------------------
LoweringError:
::T
└─┘ ── `::` must be written `value::type` outside function argument lists

########################################
# Error: braces vector syntax
{x, y}
Expand Down
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include("utils.jl")

include("ir_tests.jl")

include("arrays.jl")
include("branching.jl")
include("decls.jl")
include("desugaring.jl")
Expand Down

0 comments on commit 7227d30

Please sign in to comment.