Skip to content

Commit 9f5c892

Browse files
authored
More flattened form for multiple frakentuple parameters (#133)
Here we emit `(a, b; c, d; e, f)` as (tuple a b (parameters c d) (parameters e f)) which should make these simpler to process, rather than using the nested form (tuple a b (parameters c d parameters e f)))
1 parent 15b4eb8 commit 9f5c892

File tree

3 files changed

+47
-23
lines changed

3 files changed

+47
-23
lines changed

src/expr.jl

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,25 @@ function is_stringchunk(node)
1111
return k == K"String" || k == K"CmdString"
1212
end
1313

14+
function reorder_parameters!(args, params_pos)
15+
p = 0
16+
for i = length(args):-1:1
17+
if !Meta.isexpr(args[i], :parameters)
18+
break
19+
end
20+
p = i
21+
end
22+
if p == 0
23+
return
24+
end
25+
# nest frankentuples parameters sections
26+
for i = length(args)-1:-1:p
27+
pushfirst!(args[i].args, pop!(args))
28+
end
29+
# Move parameters to args[params_pos]
30+
insert!(args, params_pos, pop!(args))
31+
end
32+
1433
function _to_expr(node::SyntaxNode; iteration_spec=false, need_linenodes=true,
1534
eq_to_kw=false, inside_dot_expr=false, inside_vect_or_braces=false)
1635
if !haschildren(node)
@@ -145,17 +164,11 @@ function _to_expr(node::SyntaxNode; iteration_spec=false, need_linenodes=true,
145164
popfirst!(args)
146165
headsym = Symbol("'")
147166
end
148-
# Move parameters block to args[2]
149-
if length(args) > 1 && Meta.isexpr(args[end], :parameters)
150-
insert!(args, 2, args[end])
151-
pop!(args)
152-
end
153-
elseif headsym in (:tuple, :parameters, :vect, :braces)
167+
# Move parameters blocks to args[2]
168+
reorder_parameters!(args, 2)
169+
elseif headsym in (:tuple, :vect, :braces)
154170
# Move parameters blocks to args[1]
155-
if length(args) > 1 && Meta.isexpr(args[end], :parameters)
156-
pushfirst!(args, args[end])
157-
pop!(args)
158-
end
171+
reorder_parameters!(args, 1)
159172
elseif headsym in (:try, :try_finally_catch)
160173
# Try children in source order:
161174
# try_block catch_var catch_block else_block finally_block

src/parser.jl

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2934,8 +2934,8 @@ function parse_paren(ps::ParseState, check_identifiers=true)
29342934
# Extra credit: nested parameters and frankentuples
29352935
# (x...;) ==> (tuple (... x) (parameters))
29362936
# (x...; y) ==> (tuple (... x) (parameters y))
2937-
# (; a=1; b=2) ==> (tuple (parameters (= a 1) (parameters (= b 2))))
2938-
# (a; b; c,d) ==> (tuple a (parameters b (parameters c d)))
2937+
# (; a=1; b=2) ==> (tuple (parameters (= a 1)) (parameters (= b 2)))
2938+
# (a; b; c,d) ==> (tuple a (parameters b) (parameters c d))
29392939
# (a=1, b=2; c=3) ==> (tuple (= a 1) (= b 2) (parameters (= c 3)))
29402940
emit(ps, mark, K"tuple")
29412941
elseif opts.is_block
@@ -2968,7 +2968,7 @@ end
29682968
# syntax so the parse tree is pretty strange in these cases! Some macros
29692969
# probably use it though. Example:
29702970
#
2971-
# (a,b=1; c,d=2; e,f=3) ==> (tuple a (= b 1) (parameters c (= d 2) (parameters e (= f 3))))
2971+
# (a,b=1; c,d=2; e,f=3) ==> (tuple a (= b 1) (parameters c (= d 2)) (parameters e (= f 3)))
29722972
#
29732973
# flisp: parts of parse-paren- and parse-arglist
29742974
function parse_brackets(after_parse::Function,
@@ -2977,12 +2977,13 @@ function parse_brackets(after_parse::Function,
29772977
space_sensitive=false,
29782978
where_enabled=true,
29792979
whitespace_newline=true)
2980-
params_marks = acquire_positions(ps.stream)
2980+
params_positions = acquire_positions(ps.stream)
29812981
last_eq_before_semi = 0
29822982
num_subexprs = 0
29832983
num_semis = 0
29842984
had_commas = false
29852985
had_splat = false
2986+
param_start = nothing
29862987
while true
29872988
bump_trivia(ps)
29882989
k = peek(ps)
@@ -2991,8 +2992,11 @@ function parse_brackets(after_parse::Function,
29912992
elseif k == K";"
29922993
# Start of parameters list
29932994
# a, b; c d ==> a b (parameters c d)
2994-
push!(params_marks, position(ps))
2995+
if !isnothing(param_start)
2996+
push!(params_positions, emit(ps, param_start, K"TOMBSTONE"))
2997+
end
29952998
num_semis += 1
2999+
param_start = position(ps)
29963000
bump(ps, TRIVIA_FLAG)
29973001
bump_trivia(ps)
29983002
elseif is_closing_token(ps, k)
@@ -3025,14 +3029,17 @@ function parse_brackets(after_parse::Function,
30253029
end
30263030
end
30273031
end
3032+
if !isnothing(param_start) && position(ps) != param_start
3033+
push!(params_positions, emit(ps, param_start, K"TOMBSTONE"))
3034+
end
30283035
opts = after_parse(had_commas, had_splat, num_semis, num_subexprs)
30293036
# Emit nested parameter nodes if necessary
30303037
if opts.needs_parameters
3031-
for mark in Iterators.reverse(params_marks)
3032-
emit(ps, mark, K"parameters")
3038+
for pos in params_positions
3039+
reset_node!(ps, pos, kind=K"parameters")
30333040
end
30343041
end
3035-
release_positions(ps.stream, params_marks)
3042+
release_positions(ps.stream, params_positions)
30363043
bump_closing_token(ps, closing_kind)
30373044
return opts
30383045
end

test/parser.jl

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,8 @@ tests = [
244244
"f(a,b)" => "(call f a b)"
245245
"f(a=1; b=2)" => "(call f (= a 1) (parameters (= b 2)))" =>
246246
Expr(:call, :f, Expr(:parameters, Expr(:kw, :b, 2)), Expr(:kw, :a, 1))
247+
"f(a; b; c)" => "(call f a (parameters b) (parameters c))" =>
248+
Expr(:call, :f, Expr(:parameters, Expr(:parameters, :c), :b), :a)
247249
"(a=1)()" => "(call (= a 1))" => Expr(:call, Expr(:(=), :a, 1))
248250
"f (a)" => "(call f (error-t) a)"
249251
"f(a).g(b)" => "(call (. (call f a) (quote g)) b)"
@@ -568,13 +570,15 @@ tests = [
568570
"(x,y)" => "(tuple x y)"
569571
"(x=1, y=2)" => "(tuple (= x 1) (= y 2))"
570572
# Named tuples with initial semicolon
571-
"(;)" => "(tuple (parameters))"
572-
"(; a=1)" => "(tuple (parameters (= a 1)))"
573+
"(;)" => "(tuple (parameters))" => Expr(:tuple, Expr(:parameters))
574+
"(; a=1)" => "(tuple (parameters (= a 1)))" => Expr(:tuple, Expr(:parameters, Expr(:kw, :a, 1)))
573575
# Extra credit: nested parameters and frankentuples
574576
"(x...; y)" => "(tuple (... x) (parameters y))"
575577
"(x...;)" => "(tuple (... x) (parameters))"
576-
"(; a=1; b=2)" => "(tuple (parameters (= a 1) (parameters (= b 2))))"
577-
"(a; b; c,d)" => "(tuple a (parameters b (parameters c d)))"
578+
"(; a=1; b=2)" => "(tuple (parameters (= a 1)) (parameters (= b 2)))" =>
579+
Expr(:tuple, Expr(:parameters, Expr(:parameters, Expr(:kw, :b, 2)), Expr(:kw, :a, 1)))
580+
"(a; b; c,d)" => "(tuple a (parameters b) (parameters c d))" =>
581+
Expr(:tuple, Expr(:parameters, Expr(:parameters, :c, :d), :b), :a)
578582
"(a=1, b=2; c=3)" => "(tuple (= a 1) (= b 2) (parameters (= c 3)))"
579583
# Block syntax
580584
"(;;)" => "(block)"
@@ -668,7 +672,7 @@ tests = [
668672
"[x,\n y]" => "(vect x y)"
669673
"[x\n, y]" => "(vect x y)"
670674
"[x\n,, y]" => "(vect x (error-t ✘ y))"
671-
"[x,y ; z]" => "(vect x y (parameters z))"
675+
"[x,y ; z]" => "(vect x y (parameters z))" => Expr(:vect, Expr(:parameters, :z), :x, :y)
672676
"[x=1, y=2]" => "(vect (= x 1) (= y 2))"
673677
"[x=1, ; y=2]" => "(vect (= x 1) (parameters (= y 2)))"
674678
# parse_paren

0 commit comments

Comments
 (0)