JuliaSyntax.jl
JuliaSyntax.jl copied to clipboard
Change AST for iterations to use `iteration` kind
I got inspired to implement #432 as suggested there... This should be a complete implementation of that proposed solution, but may still need experimentation/thought to decide whether Cartesian iteration should be nested or flat.
The = node which has traditionally been used for iteration specifications in for loops and generators doesn't have normal assignment semantics. Let's consider
for x in xs
body
end
which has been parsed as (for (= x xs) (block body)).
Problems:
- The iteration does create a binding for
x, but not to the expression on the right hand side of the=. - The user may use
inor∈in the source code rather than=. The parser still uses a=node for consistency but this only emphasizes that there's something a bit weird going on.
So this use of = is not assignment; merely assignment-like.
In this change, we use a new iteration kind instead of = so the for loop parses as (for (iteration x xs) (block body)) instead.
We also reuse iteration to replace the cartesian_iteration head - cartesian iteration is just an iteration with an even number of children greater than two. Being less specific here with the naming (omitting the "cartesian") seems appropriate in trying to represent the surface syntax; cartesian semantics come later in lowering and a macro may decide to do something else with the iteration spec.
These changes are also used for generators.
After the changes we have tree structures such as
julia> parsestmt(SyntaxNode, "for i in is body end")
line:col│ tree │ file_name
1:1 │[for]
1:4 │ [iteration]
1:5 │ i
1:10 │ is
1:12 │ [block]
1:13 │ body
julia> parsestmt(SyntaxNode, "for i in is, j in js body end")
line:col│ tree │ file_name
1:1 │[for]
1:4 │ [iteration]
1:5 │ i
1:10 │ is
1:14 │ j
1:19 │ js
1:21 │ [block]
1:22 │ body
julia> parsestmt(SyntaxNode, "[a for i = is, j = js if z]")
line:col│ tree │ file_name
1:1 │[comprehension]
1:2 │ [generator]
1:2 │ a
1:7 │ [filter]
1:7 │ [iteration]
1:8 │ i
1:12 │ is
1:16 │ j
1:20 │ js
1:26 │ z
julia> parsestmt(SyntaxNode, "[a for i = is for j = js if z]")
line:col│ tree │ file_name
1:1 │[comprehension]
1:2 │ [generator]
1:2 │ a
1:7 │ [iteration]
1:8 │ i
1:12 │ is
1:18 │ [filter]
1:18 │ [iteration]
1:19 │ j
1:23 │ js
1:29 │ z