diff --git a/src/ast.ls b/src/ast.ls index a191f7ef9..43cf634af 100644 --- a/src/ast.ls +++ b/src/ast.ls @@ -1624,14 +1624,17 @@ class exports.Assign extends Node else if (ret or len > 1) and (not ID.test rite.to-string! or left.assigns rite.to-string!) cache = sn(this, (rref = o.scope.temporary!), " = ", rite) rite = rref - list = @"rend#{ left.constructor.display-name }" o, items, rite + if rite.to-string! is \arguments and not ret + arg = true + if left not instanceof Arr then @carp 'arguments can only destructure to array' + list = @"rend#{ left.constructor.display-name }" o, items, rite, arg o.scope.free rref if rref list.unshift cache if cache list.push rite if ret or not list.length code = [] + sep = if arg then '; ' else ', ' for item in list - code.push item - code.push ", " + code.push item, sep code.pop! if list.length < 2 or o.level < LEVEL_LIST then sn(this, ...code) else sn(this, "(", ...code, ")") @@ -1644,7 +1647,11 @@ class exports.Assign extends Node .add Index (Key \concat), \. true .add Call [right-node])]; right] .compile o, LEVEL_LIST)) - rendArr: (o, nodes, rite) -> + rendArr: (o, nodes, rite, arg) -> + ~function arg-slice(begin, end) + # [&[..] for from (begin) til (end)] + new For {+ref, from: begin, op: \til, to: end} + .make-comprehension (Chain Var \arguments .add Index Literal \..), [] for node, i in nodes continue if node.is-empty! if node instanceof Splat @@ -1652,17 +1659,26 @@ class exports.Assign extends Node skip = (node.=it).is-empty! if i+1 is len = nodes.length break if skip - val = Arr.wrap JS do - util(\slice) + \.call( + rite + if i then ", #i)" else \) + if arg + val = arg-slice do # from i to &length + Literal(i) + (Chain Var \arguments .add Index Key \length) + else + val = Arr.wrap JS do + util(\slice) + \.call( + rite + if i then ", #i)" else \) else val = ivar = "#rite.length - #{ len - i - 1 }" # Optimize `[..., a] = b`. continue if skip and i+2 is len start = i+1 - @temps = [ivar = o.scope.temporary \i] + @.[]temps.push ivar = o.scope.temporary \i val = switch | skip Arr.wrap JS "#i < (#ivar = #val) ? #i : (#ivar = #i)" + | arg + arg-slice do + JS "#i < (#ivar = #val) ? #i : (#ivar = #i)" + Var ivar | _ Arr.wrap JS do "#i < (#ivar = #val) @@ -1673,7 +1689,7 @@ class exports.Assign extends Node val = Chain rcache||=Literal(rite), [Index JS inc || i] if node instanceof Assign node = Binary node.op, node.left, node.right, (node.logic or true) - (this with {left: node, right: val, +void})compile o, LEVEL_PAREN + (this with {left: node, right: val, +void})compile o, if arg then LEVEL_TOP else LEVEL_PAREN rendObj: (o, nodes, rite) -> for node in nodes @@ -1899,7 +1915,7 @@ class exports.Fun extends Node # `(a = x) ->` => `(a ? x) ->` else if p.op is \= params[i] = Binary (p.logic or \?), p.left, p.right - # `(a, ...b, c) ->` => `(a) -> [[] ...b, c] = @@` + # `(a, ...b, c) ->` => `(a) -> [[] ...b, c] = &` if splace? rest = params.splice splace, 9e9 else if @accessor @@ -1908,30 +1924,28 @@ class exports.Fun extends Node params.0 = Var \it if body.traverse-children -> it.value is \it or null names = [] assigns = [] - if params.length - dic = {} - for p in params - vr = p - vr.=first if df = vr.get-default! - if vr.is-empty! - vr = Var scope.temporary \arg - else if vr.value is \.. - vr = Var o.ref = scope.temporary! - else if vr not instanceof Var - unaries = [] - while vr instanceof Unary - has-unary = true - unaries.push vr - vr.=it - v = Var delete (vr.it || vr)name || vr.var-name! || scope.temporary \arg - assigns.push Assign vr, switch - | df => Binary p.op, v, p.second - | has-unary => fold ((x, y) -> y.it = x; y), v, unaries.reverse! - | otherwise => v - vr = v - else if df - assigns.push Assign vr, p.second, \=, p.op, true - names.push (scope.add vr.value, \arg, p), ', ' + for p in params + vr = p + vr.=first if df = vr.get-default! + if vr.is-empty! + vr = Var scope.temporary \arg + else if vr.value is \.. + vr = Var o.ref = scope.temporary! + else if vr not instanceof Var + unaries = [] + while vr instanceof Unary + has-unary = true + unaries.push vr + vr.=it + v = Var delete (vr.it || vr)name || vr.var-name! || scope.temporary \arg + assigns.push Assign vr, switch + | df => Binary p.op, v, p.second + | has-unary => fold ((x, y) -> y.it = x; y), v, unaries.reverse! + | otherwise => v + vr = v + else if df + assigns.push Assign vr, p.second, \=, p.op, true + names.push (scope.add vr.value, \arg, p), ', ' if rest while splace-- then rest.unshift Arr! assigns.push Assign Arr(rest), Literal \arguments