Skip to content

Commit e6591cf

Browse files
committed
Fix gkz#857 Better handling of splat func arguments
See gkz#857 .
1 parent a83bd08 commit e6591cf

File tree

1 file changed

+47
-33
lines changed

1 file changed

+47
-33
lines changed

src/ast.ls

Lines changed: 47 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1624,14 +1624,17 @@ class exports.Assign extends Node
16241624
else if (ret or len > 1) and (not ID.test rite.to-string! or left.assigns rite.to-string!)
16251625
cache = sn(this, (rref = o.scope.temporary!), " = ", rite)
16261626
rite = rref
1627-
list = @"rend#{ left.constructor.display-name }" o, items, rite
1627+
if rite.to-string! is \arguments and not ret
1628+
arg = true
1629+
if left not instanceof Arr then @carp 'arguments can only destructure to array'
1630+
list = @"rend#{ left.constructor.display-name }" o, items, rite, arg
16281631
o.scope.free rref if rref
16291632
list.unshift cache if cache
16301633
list.push rite if ret or not list.length
16311634
code = []
1635+
sep = if arg then '; ' else ', '
16321636
for item in list
1633-
code.push item
1634-
code.push ", "
1637+
code.push item, sep
16351638
code.pop!
16361639
if list.length < 2 or o.level < LEVEL_LIST then sn(this, ...code) else sn(this, "(", ...code, ")")
16371640

@@ -1644,25 +1647,38 @@ class exports.Assign extends Node
16441647
.add Index (Key \concat), \. true .add Call [right-node])]; right]
16451648
.compile o, LEVEL_LIST))
16461649

1647-
rendArr: (o, nodes, rite) ->
1650+
rendArr: (o, nodes, rite, arg) ->
1651+
~function arg-slice(begin, end)
1652+
# [&[..] for from (begin) til (end)]
1653+
new For {+ref, from: begin, op: \til, to: end}
1654+
.make-comprehension (Chain Var \arguments .add Index Literal \..), []
16481655
for node, i in nodes
16491656
continue if node.is-empty!
16501657
if node instanceof Splat
16511658
len and node.carp 'multiple splat in an assignment'
16521659
skip = (node.=it).is-empty!
16531660
if i+1 is len = nodes.length
16541661
break if skip
1655-
val = Arr.wrap JS do
1656-
util(\slice) + \.call( + rite + if i then ", #i)" else \)
1662+
if arg
1663+
val = arg-slice do # from i to &length
1664+
Literal(i)
1665+
(Chain Var \arguments .add Index Key \length)
1666+
else
1667+
val = Arr.wrap JS do
1668+
util(\slice) + \.call( + rite + if i then ", #i)" else \)
16571669
else
16581670
val = ivar = "#rite.length - #{ len - i - 1 }"
16591671
# Optimize `[..., a] = b`.
16601672
continue if skip and i+2 is len
16611673
start = i+1
1662-
@temps = [ivar = o.scope.temporary \i]
1674+
@.[]temps.push ivar = o.scope.temporary \i
16631675
val = switch
16641676
| skip
16651677
Arr.wrap JS "#i < (#ivar = #val) ? #i : (#ivar = #i)"
1678+
| arg
1679+
arg-slice do
1680+
JS "#i < (#ivar = #val) ? #i : (#ivar = #i)"
1681+
Var ivar
16661682
| _
16671683
Arr.wrap JS do
16681684
"#i < (#ivar = #val)
@@ -1673,7 +1689,7 @@ class exports.Assign extends Node
16731689
val = Chain rcache||=Literal(rite), [Index JS inc || i]
16741690
if node instanceof Assign
16751691
node = Binary node.op, node.left, node.right, (node.logic or true)
1676-
(this with {left: node, right: val, +void})compile o, LEVEL_PAREN
1692+
(this with {left: node, right: val, +void})compile o, if arg then LEVEL_TOP else LEVEL_PAREN
16771693

16781694
rendObj: (o, nodes, rite) ->
16791695
for node in nodes
@@ -1899,7 +1915,7 @@ class exports.Fun extends Node
18991915
# `(a = x) ->` => `(a ? x) ->`
19001916
else if p.op is \=
19011917
params[i] = Binary (p.logic or \?), p.left, p.right
1902-
# `(a, ...b, c) ->` => `(a) -> [[] ...b, c] = @@`
1918+
# `(a, ...b, c) ->` => `(a) -> [[] ...b, c] = &`
19031919
if splace?
19041920
rest = params.splice splace, 9e9
19051921
else if @accessor
@@ -1908,30 +1924,28 @@ class exports.Fun extends Node
19081924
params.0 = Var \it if body.traverse-children -> it.value is \it or null
19091925
names = []
19101926
assigns = []
1911-
if params.length
1912-
dic = {}
1913-
for p in params
1914-
vr = p
1915-
vr.=first if df = vr.get-default!
1916-
if vr.is-empty!
1917-
vr = Var scope.temporary \arg
1918-
else if vr.value is \..
1919-
vr = Var o.ref = scope.temporary!
1920-
else if vr not instanceof Var
1921-
unaries = []
1922-
while vr instanceof Unary
1923-
has-unary = true
1924-
unaries.push vr
1925-
vr.=it
1926-
v = Var delete (vr.it || vr)name || vr.var-name! || scope.temporary \arg
1927-
assigns.push Assign vr, switch
1928-
| df => Binary p.op, v, p.second
1929-
| has-unary => fold ((x, y) -> y.it = x; y), v, unaries.reverse!
1930-
| otherwise => v
1931-
vr = v
1932-
else if df
1933-
assigns.push Assign vr, p.second, \=, p.op, true
1934-
names.push (scope.add vr.value, \arg, p), ', '
1927+
for p in params
1928+
vr = p
1929+
vr.=first if df = vr.get-default!
1930+
if vr.is-empty!
1931+
vr = Var scope.temporary \arg
1932+
else if vr.value is \..
1933+
vr = Var o.ref = scope.temporary!
1934+
else if vr not instanceof Var
1935+
unaries = []
1936+
while vr instanceof Unary
1937+
has-unary = true
1938+
unaries.push vr
1939+
vr.=it
1940+
v = Var delete (vr.it || vr)name || vr.var-name! || scope.temporary \arg
1941+
assigns.push Assign vr, switch
1942+
| df => Binary p.op, v, p.second
1943+
| has-unary => fold ((x, y) -> y.it = x; y), v, unaries.reverse!
1944+
| otherwise => v
1945+
vr = v
1946+
else if df
1947+
assigns.push Assign vr, p.second, \=, p.op, true
1948+
names.push (scope.add vr.value, \arg, p), ', '
19351949
if rest
19361950
while splace-- then rest.unshift Arr!
19371951
assigns.push Assign Arr(rest), Literal \arguments

0 commit comments

Comments
 (0)