[a b] = [1 2 3]

This commit is contained in:
Chris Wanstrath 2025-10-29 19:13:03 -07:00
parent 2abf3558d5
commit 789481f4ef
6 changed files with 101 additions and 13 deletions

View File

@ -235,11 +235,31 @@ export class Compiler {
} }
case terms.Assign: { case terms.Assign: {
const { identifier, right } = getAssignmentParts(node) const assignParts = getAssignmentParts(node)
const instructions: ProgramItem[] = [] const instructions: ProgramItem[] = []
instructions.push(...this.#compileNode(right, input))
instructions.push(['DUP']) // Keep a copy on the stack after storing // right-hand side
const identifierName = input.slice(identifier.from, identifier.to) instructions.push(...this.#compileNode(assignParts.right, input))
// array destructuring: [ a b ] = [ 1 2 3 4 ]
if ('arrayPattern' in assignParts) {
const identifiers = assignParts.arrayPattern ?? []
if (identifiers.length === 0) return instructions
for (let i = 0; i < identifiers.length; i++) {
instructions.push(['DUP'])
instructions.push(['PUSH', i])
instructions.push(['DOT_GET'])
instructions.push(['STORE', input.slice(identifiers[i]!.from, identifiers[i]!.to)])
}
// original array still on stack as the return value
return instructions
}
// simple assignment: x = value
instructions.push(['DUP'])
const identifierName = input.slice(assignParts.identifier.from, assignParts.identifier.to)
instructions.push(['STORE', identifierName]) instructions.push(['STORE', identifierName])
return instructions return instructions

View File

@ -64,6 +64,28 @@ describe('compiler', () => {
expect('sum = 2 + 3; sum').toEvaluateTo(5) expect('sum = 2 + 3; sum').toEvaluateTo(5)
}) })
test('array destructuring with two variables', () => {
expect('[ a b ] = [ 1 2 3 4 ]; a').toEvaluateTo(1)
expect('[ a b ] = [ 1 2 3 4 ]; b').toEvaluateTo(2)
})
test('array destructuring with one variable', () => {
expect('[ x ] = [ 42 ]; x').toEvaluateTo(42)
})
test('array destructuring with missing elements assigns null', () => {
expect('[ a b c ] = [ 1 2 ]; c').toEvaluateTo(null)
})
test('array destructuring returns the original array', () => {
expect('[ a b ] = [ 1 2 3 4 ]').toEvaluateTo([1, 2, 3, 4])
})
test('array destructuring with emoji identifiers', () => {
expect('[ 🚀 💎 ] = [ 1 2 ]; 🚀').toEvaluateTo(1)
expect('[ 🚀 💎 ] = [ 1 2 ]; 💎').toEvaluateTo(2)
})
test('parentheses', () => { test('parentheses', () => {
expect('(2 + 3) * 4').toEvaluateTo(20) expect('(2 + 3) * 4').toEvaluateTo(20)
}) })

View File

@ -40,15 +40,23 @@ export const getAssignmentParts = (node: SyntaxNode) => {
const children = getAllChildren(node) const children = getAllChildren(node)
const [left, equals, right] = children const [left, equals, right] = children
if (!left || left.type.id !== terms.AssignableIdentifier) { if (!equals || !right) {
throw new CompilerError( throw new CompilerError(
`Assign left child must be an AssignableIdentifier, got ${left ? left.type.name : 'none'}`, `Assign expected 3 children, got ${children.length}`,
node.from, node.from,
node.to node.to
) )
} else if (!equals || !right) { }
// array destructuring
if (left && left.type.id === terms.Array) {
const identifiers = getAllChildren(left).filter(child => child.type.id === terms.Identifier)
return { arrayPattern: identifiers, right }
}
if (!left || left.type.id !== terms.AssignableIdentifier) {
throw new CompilerError( throw new CompilerError(
`Assign expected 3 children, got ${children.length}`, `Assign left child must be an AssignableIdentifier or Array, got ${left ? left.type.name : 'none'}`,
node.from, node.from,
node.to node.to
) )

View File

@ -148,7 +148,7 @@ Params {
} }
Assign { Assign {
AssignableIdentifier Eq consumeToTerminator (AssignableIdentifier | Array) Eq consumeToTerminator
} }
BinOp { BinOp {

View File

@ -7,9 +7,9 @@ import {highlighting} from "./highlight"
const spec_Identifier = {__proto__:null,end:80, null:86, if:96, elseif:104, else:108} const spec_Identifier = {__proto__:null,end:80, null:86, if:96, elseif:104, else:108}
export const parser = LRParser.deserialize({ export const parser = LRParser.deserialize({
version: 14, version: 14,
states: "3UQYQbOOO#hQcO'#CvO$eOSO'#CxO$sQbO'#EVOOQ`'#DR'#DROOQa'#DO'#DOO%vQbO'#DWO&{QcO'#DzOOQa'#Dz'#DzO)PQcO'#DyO)xQRO'#CwO*]QcO'#DuO*tQcO'#DuO+VQbO'#CuO+}OpO'#CsOOQ`'#Dv'#DvO,SQbO'#DuO,bQbO'#E]OOQ`'#D]'#D]O-VQRO'#DeOOQ`'#Du'#DuO-[QQO'#DtOOQ`'#Dt'#DtOOQ`'#Df'#DfQYQbOOO-dQbO'#DPOOQa'#Dy'#DyOOQ`'#DZ'#DZOOQ`'#E['#E[OOQ`'#Dm'#DmO-nQbO,59^O.RQbO'#CzO.ZQWO'#C{OOOO'#D|'#D|OOOO'#Dg'#DgO.oOSO,59dOOQa,59d,59dOOQ`'#Di'#DiO.}QbO'#DSO/VQQO,5:qOOQ`'#Dh'#DhO/[QbO,59rO/cQQO,59jOOQa,59r,59rO/nQbO,59rO,bQbO,59cO,bQbO,59cO,bQbO,59cO,bQbO,59tO,bQbO,59tO,bQbO,59tO/xQRO,59aO0PQRO,59aO0bQRO,59aO0]QQO,59aO0mQQO,59aO0uObO,59_O1QQbO'#DnO1]QbO,59]O1nQRO,5:wO1uQRO,5:wO2QQbO,5:POOQ`,5:`,5:`OOQ`-E7d-E7dOOQ`,59k,59kOOQ`-E7k-E7kOOOO,59f,59fOOOO,59g,59gOOOO-E7e-E7eOOQa1G/O1G/OOOQ`-E7g-E7gO2[QbO1G0]OOQ`-E7f-E7fO2iQQO1G/UOOQa1G/^1G/^O2tQbO1G/^OOQO'#Dk'#DkO2iQQO1G/UOOQa1G/U1G/UOOQ`'#Dl'#DlO2tQbO1G/^OOQa1G.}1G.}O3gQcO1G.}O3qQcO1G.}O3{QcO1G.}OOQa1G/`1G/`O5_QcO1G/`O5fQcO1G/`O5mQcO1G/`OOQa1G.{1G.{OOQa1G.y1G.yO!ZQbO'#CvO%}QbO'#CrOOQ`,5:Y,5:YOOQ`-E7l-E7lO5tQbO1G0cOOQ`1G/k1G/kO6RQbO7+%wO6WQbO7+%xO6hQQO7+$pOOQa7+$p7+$pO6sQbO7+$xOOQa7+$x7+$xOOQO-E7i-E7iOOQ`-E7j-E7jOOQ`'#D_'#D_O6}QbO7+%}O7SQbO7+&OOOQ`<<Ic<<IcOOQ`'#Dj'#DjO7jQQO'#DjO7oQbO'#EXO8VQbO<<IdOOQa<<H[<<H[OOQa<<Hd<<HdOOQ`<<Ii<<IiOOQ`'#D`'#D`O8[QbO<<IjOOQ`,5:U,5:UOOQ`-E7h-E7hOOQ`AN?OAN?OO,bQbO'#DaOOQ`'#Do'#DoO8gQbOAN?UO8rQQO'#DcOOQ`AN?UAN?UO8wQbOAN?UO8|QRO,59{O9TQRO,59{OOQ`-E7m-E7mOOQ`G24pG24pO9`QbOG24pO9eQQO,59}O9jQQO1G/gOOQ`LD*[LD*[O6WQbO1G/iO7SQbO7+%ROOQ`7+%T7+%TOOQ`<<Hm<<Hm", states: "3[QYQbOOO#hQcO'#CvO$eOSO'#CxO$sQbO'#EVOOQ`'#DR'#DROOQa'#DO'#DOO%vQbO'#DWO'RQcO'#DzOOQa'#Dz'#DzO(UQcO'#DzO)WQcO'#DyO*PQRO'#CwO*dQcO'#DuO*{QcO'#DuO+^QbO'#CuO,UOpO'#CsOOQ`'#Dv'#DvO,ZQbO'#DuO,iQbO'#E]OOQ`'#D]'#D]O-^QRO'#DeOOQ`'#Du'#DuO-cQQO'#DtOOQ`'#Dt'#DtOOQ`'#Df'#DfQYQbOOO-kQbO'#DPOOQa'#Dy'#DyOOQ`'#DZ'#DZOOQ`'#E['#E[OOQ`'#Dm'#DmO-uQbO,59^O.cQbO'#CzO.kQWO'#C{OOOO'#D|'#D|OOOO'#Dg'#DgO/POSO,59dOOQa,59d,59dOOQ`'#Di'#DiO/_QbO'#DSO/gQQO,5:qOOQ`'#Dh'#DhO/lQbO,59rO/sQQO,59jOOQa,59r,59rO0OQbO,59rO0YQbO,5:PO,iQbO,59cO,iQbO,59cO,iQbO,59cO,iQbO,59tO,iQbO,59tO,iQbO,59tO0dQRO,59aO0kQRO,59aO0|QRO,59aO0wQQO,59aO1XQQO,59aO1aObO,59_O1lQbO'#DnO1wQbO,59]O2YQRO,5:wO2aQRO,5:wOOQ`,5:`,5:`OOQ`-E7d-E7dOOQ`,59k,59kOOQ`-E7k-E7kOOOO,59f,59fOOOO,59g,59gOOOO-E7e-E7eOOQa1G/O1G/OOOQ`-E7g-E7gO2lQbO1G0]OOQ`-E7f-E7fO2yQQO1G/UOOQa1G/^1G/^O3UQbO1G/^OOQO'#Dk'#DkO2yQQO1G/UOOQa1G/U1G/UOOQ`'#Dl'#DlO3UQbO1G/^OOQ`1G/k1G/kOOQa1G.}1G.}O3wQcO1G.}O4RQcO1G.}O4]QcO1G.}OOQa1G/`1G/`O5oQcO1G/`O5vQcO1G/`O5}QcO1G/`OOQa1G.{1G.{OOQa1G.y1G.yO!ZQbO'#CvO6UQbO'#CrOOQ`,5:Y,5:YOOQ`-E7l-E7lO6cQbO1G0cO6pQbO7+%wO6uQbO7+%xO7VQQO7+$pOOQa7+$p7+$pO7bQbO7+$xOOQa7+$x7+$xOOQO-E7i-E7iOOQ`-E7j-E7jOOQ`'#D_'#D_O7lQbO7+%}O7qQbO7+&OOOQ`<<Ic<<IcOOQ`'#Dj'#DjO8XQQO'#DjO8^QbO'#EXO8tQbO<<IdOOQa<<H[<<H[OOQa<<Hd<<HdOOQ`<<Ii<<IiOOQ`'#D`'#D`O8yQbO<<IjOOQ`,5:U,5:UOOQ`-E7h-E7hOOQ`AN?OAN?OO,iQbO'#DaOOQ`'#Do'#DoO9UQbOAN?UO9aQQO'#DcOOQ`AN?UAN?UO9fQbOAN?UO9kQRO,59{O9rQRO,59{OOQ`-E7m-E7mOOQ`G24pG24pO9}QbOG24pO:SQQO,59}O:XQQO1G/gOOQ`LD*[LD*[O6uQbO1G/iO7qQbO7+%ROOQ`7+%T7+%TOOQ`<<Hm<<Hm",
stateData: "9r~O!fOS!gOS~O_PO`cOaWOb^OcROhWOpWOqWO{WO!QaO!l]O!oQO!vTO!wUO!xfO~O_jOaWOb^OcROhWOpWOqWOtiOykO{WO!l]O!oQO!vTO!wUO!OjX!xjX#RjX!}jXxjX~OP!mXQ!mXR!mXS!mXT!mXU!mXW!mXX!mXY!mXZ!mX[!mX]!mX^!mX~P!ZOmqO!otO!qoO!rpO~O_uOwvP~O_jOaWOb^OhWOpWOqWOtiO{WO!l]O!oQO!vTO!wUO!xxO~O!|{O~P${O_jOaWOb^OcROhWOpWOqWOtiOykO{WO!l]O!oQO!vTO!wUO~OP!nXQ!nXR!nXS!nXT!nXU!nXW!nXX!nXY!nXZ!nX[!nX]!nX^!nX!x!nX#R!nX!}!nXx!nX~P%}OP!mXQ!mXR!mXS!mXT!mXU!mXW!mXX!mXY!mXZ!mX[!mX]!mX^!mX~O!x!iX#R!iXx!iX~P(UOT!ROU!SOW!QOX!QOY!QOZ!QO[!QO]!QO~OP!OOQ!OOR!POS!PO^}O~P)^OP!OOQ!OOR!POS!PO!x!iX#R!iXx!iX~OT!ROU!SO!x!iX#R!iXx!iX~O_POaWOb^OcROhWOpWOqWO{WO!l]O!oQO!vTO!wUO~O!k!YO~O!O!ZO!x!iX#R!iXx!iX~O_jOaWOb^OhWOpWOqWO{WO!l]O!oQO!vTO!wUO~OV!_O~O!x!`O#R!`O~OcROy!bO~P,bO!Ofa!xfa#Rfa!}faxfa~P%}O_!dO!l]O~O!o!eO!q!eO!r!eO!s!eO!t!eO!u!eO~OmqO!o!gO!qoO!rpO~O_uOwvX~Ow!iO~O!|!lO~P${OtiO!x!nO!|!pO~O!x!qO!|!lO~P,bO!}!{O~P(UOP!OOQ!OOR!POS!PO!}!{O~OT!ROU!SO!}!{O~O!O!ZO!}!{O~O_!|Oh!|O!l]O~O_!}Ob^O!l]O~O!O!ZO!xea#Rea!}eaxea~Ow#RO~P)^OT!ROU!SOw#RO~O`cO!QaO~P+VO`cO!QaO!x#UO~P+VOtiO!x!nO!|#WO~O!x!qO!|#YO~P,bO^}ORkiSki!xki#Rki!}kixki~OPkiQki~P3OOP!OOQ!OO~P3OOP!OOQ!OORkiSki!xki#Rki!}kixki~OW!QOX!QOY!QOZ!QO[!QO]!QOT|i!x|i#R|i!}|iw|ix|i~OU!SO~P4gOU!SO~P4yOU|i~P4gO`cO!QaO!x#_O~P+VOx#`O~O`cO!QaO!x#aOx!{P~P+VOtiO!x!nO!|#eO~O!x!qO!|#fO~P,bOx#gO~O`cO!QaO!x#aOx!{P!U!{P!W!{P~P+VO!x#jO~O`cO!QaO!x#aOx!{X!U!{X!W!{X~P+VOx#lO~Ox#qO!U#mO!W#pO~Ox#vO!U#mO!W#pO~Ow#xO~Ox#vO~Ow#yO~P)^OT!ROU!SOw#yO~Ox#zO~O!x#{O~O!x#|O~Ohq~", stateData: ":a~O!fOS!gOS~O_PO`dOaWOb_OcROhWOpWOqWO{WO!QbO!l^O!oQO!vTO!wUO!xgO~O_kOaWOb_OcROhWOpWOqWOtjOylO{WO!l^O!oQO!vTO!wUO!OjX!xjX#RjX!}jXxjX~OP!mXQ!mXR!mXS!mXT!mXU!mXW!mXX!mXY!mXZ!mX[!mX]!mX^!mX~P!ZOmrO!ouO!qpO!rqO~O_vOwvP~O_kOaWOb_OhWOpWOqWOtjO{WO!l^O!oQO!vTO!wUO!xyO~O!||O~P${OP!nXQ!nXR!nXS!nXT!nXU!nXW!nXX!nXY!nXZ!nX[!nX]!nX^!nX!x!nX#R!nXx!nX~O_kOaWOb_OcROhWOpWOqWOtjOylO{WO!l^O!oQO!vTO!wUO!}!nX~P%}OV!OO~P%}OP!mXQ!mXR!mXS!mXT!mXU!mXW!mXX!mXY!mXZ!mX[!mX]!mX^!mX~O!x!iX#R!iXx!iX~P(]OT!TOU!UOW!SOX!SOY!SOZ!SO[!SO]!SO~OP!QOQ!QOR!ROS!RO^!PO~P)eOP!QOQ!QOR!ROS!RO!x!iX#R!iXx!iX~OT!TOU!UO!x!iX#R!iXx!iX~O_POaWOb_OcROhWOpWOqWO{WO!l^O!oQO!vTO!wUO~O!k![O~O!O!]O!x!iX#R!iXx!iX~O_kOaWOb_OhWOpWOqWO{WO!l^O!oQO!vTO!wUO~OV!OO~O!x!aO#R!aO~OcROy!cO~P,iOcROtjOylO!Ofa!xfa#Rfa!}faxfa~P,iO_!eO!l^O~O!o!fO!q!fO!r!fO!s!fO!t!fO!u!fO~OmrO!o!hO!qpO!rqO~O_vOwvX~Ow!jO~O!|!mO~P${OtjO!x!oO!|!qO~O!x!rO!|!mO~P,iO`dO!QbO~P+^O!}!}O~P(]OP!QOQ!QOR!ROS!RO!}!}O~OT!TOU!UO!}!}O~O!O!]O!}!}O~O_#OOh#OO!l^O~O_#POb_O!l^O~O!O!]O!xea#Rea!}eaxea~Ow#TO~P)eOT!TOU!UOw#TO~O`dO!QbO!x#VO~P+^OtjO!x!oO!|#XO~O!x!rO!|#ZO~P,iO^!PORkiSki!xki#Rki!}kixki~OPkiQki~P3`OP!QOQ!QO~P3`OP!QOQ!QORkiSki!xki#Rki!}kixki~OW!SOX!SOY!SOZ!SO[!SO]!SOT|i!x|i#R|i!}|iw|ix|i~OU!UO~P4wOU!UO~P5ZOU|i~P4wOcROtjOylO~P,iO`dO!QbO!x#`O~P+^Ox#aO~O`dO!QbO!x#bOx!{P~P+^OtjO!x!oO!|#fO~O!x!rO!|#gO~P,iOx#hO~O`dO!QbO!x#bOx!{P!U!{P!W!{P~P+^O!x#kO~O`dO!QbO!x#bOx!{X!U!{X!W!{X~P+^Ox#mO~Ox#rO!U#nO!W#qO~Ox#wO!U#nO!W#qO~Ow#yO~Ox#wO~Ow#zO~P)eOT!TOU!UOw#zO~Ox#{O~O!x#|O~O!x#}O~Ohq~",
goto: ".}#RPPPPPPPPPPPPPPPPPPPPP#S#c#qP$i#c%g%|P&o&oPP%|&sP'W'qPPP%|P't(aP(hP(t(w)QP)UP(h)[)b)h)n)t)}*X*c*l*sPPPP*y*}+cPP+u-SP-yPPPPPPPP-}-}.bPP.j.q.qddOh!_!i#R#U#_#c#{#|R!W]i_O]h!Z!_!i#R#U#_#c#{#|fPO]h!_!i#R#U#_#c#{#|xjPUVainy|}!O!P!Q!R!S!m!r!}#O#X#mR!}!ZfVO]h!_!i#R#U#_#c#{#|xWPUVainy|}!O!P!Q!R!S!m!r!}#O#X#mQ!doQ!|!YR#O!ZdZOh!_!i#R#U#_#c#{#|Q!U]Q!s!OR!v!P!aWOPUV]ahiny|}!O!P!Q!R!S!_!i!m!r!}#O#R#U#X#_#c#m#{#|TqQsYlPVn!}#OQzUQ!kyX!nz!k!o#VddOh!_!i#R#U#_#c#{#|YkPVn!}#OQ!W]R!biRwRd[Oh!_!i#R#U#_#c#{#|Q!V]Q!^aQ!w!SQ!y!RR#t#mZlPVn!}#OedOh!_!i#R#U#_#c#{#|R#^#RQ#i#_Q#}#{R$O#|T#n#i#oQ#r#iR#w#oQhOR!ahQsQR!fsQyUR!jyQvRR!hvW#c#U#_#{#|R#k#cQ!ozQ#V!kT#Z!o#VQ!r|Q#X!mT#[!r#XWnPV!}#OR!cnS![`!XR#Q![Q#o#iR#u#oTgOhSeOhQ#S!_Q#T!iQ#]#RZ#b#U#_#c#{#|d`Oh!_!i#R#U#_#c#{#|Q!X]R#P!ZfYO]h!_!i#R#U#_#c#{#|YkPVn!}#OQ|UQ!]aQ!biQ!myW!q|!m!r#XQ!s}Q!t!OQ!u!PQ!w!QQ!x!RQ!z!SR#s#mdXOh!_!i#R#U#_#c#{#|xjPUVainy|}!O!P!Q!R!S!m!r!}#O#X#mR!T]TrQssSOPV]hin!_!i!}#O#R#U#_#c#{#|Q#d#UV#h#_#{#|ZmPVn!}#OebOh!_!i#R#U#_#c#{#|", goto: "/r#RPPPPPPPPPPPPPPPPPPPPP#S#c#qP$i#c%g%|P&o&oPP%|&sP'W'qPPP'tP(i)UP)]P)i)l)uP)yP)]*P*V*]*c*i*r*|+W+a+hPPPP+n+r,WPP,j-wP.nPPPPPPPP.r.r/VPP/_/f/fdeOi!O!j#T#V#`#d#|#}R!Y^i`O^i!O!]!j#T#V#`#d#|#}fPO^i!O!j#T#V#`#d#|#}xkPUVbjoz}!P!Q!R!S!T!U!n!s#P#Q#Y#nR#P!]fVO^i!O!j#T#V#`#d#|#}xWPUVbjoz}!P!Q!R!S!T!U!n!s#P#Q#Y#nQ!epQ#O![R#Q!]d[Oi!O!j#T#V#`#d#|#}Q!W^Q!u!QR!x!R!aWOPUV^bijoz}!O!P!Q!R!S!T!U!j!n!s#P#Q#T#V#Y#`#d#n#|#}TrQtYmPVo#P#QQ{UQ!lzX!o{!l!p#WdeOi!O!j#T#V#`#d#|#}YlPVo#P#QQ!Y^R!cjRxRzWPUV^bjoz}!P!Q!R!S!T!U!n!s#P#Q#Y#neXOi!O!j#T#V#`#d#|#}d]Oi!O!j#T#V#`#d#|#}Q!X^Q!`bQ!y!UQ!{!TR#u#nZmPVo#P#QeeOi!O!j#T#V#`#d#|#}R#_#TQ#j#`Q$O#|R$P#}T#o#j#pQ#s#jR#x#pQiOR!biQtQR!gtQzUR!kzQwRR!iwW#d#V#`#|#}R#l#dQ!p{Q#W!lT#[!p#WQ!s}Q#Y!nT#]!s#YWoPV#P#QR!doS!^a!ZR#S!^Q#p#jR#v#pThOiSfOiQ!t!OQ#U!jQ#^#TZ#c#V#`#d#|#}daOi!O!j#T#V#`#d#|#}Q!Z^R#R!]fZO^i!O!j#T#V#`#d#|#}YlPVo#P#QQ}UQ!_bQ!cjQ!nzW!r}!n!s#YQ!u!PQ!v!QQ!w!RQ!y!SQ!z!TQ!|!UR#t#ndYOi!O!j#T#V#`#d#|#}xkPUVbjoz}!P!Q!R!S!T!U!n!s#P#Q#Y#nR!V^TsQtsSOPV^ijo!O!j#P#Q#T#V#`#d#|#}Q#e#VV#i#`#|#}ZnPVo#P#QecOi!O!j#T#V#`#d#|#}",
nodeNames: "⚠ Star Slash Plus Minus And Or Eq EqEq Neq Lt Lte Gt Gte Modulo Identifier AssignableIdentifier Word IdentifierBeforeDot Do Program PipeExpr FunctionCall DotGet Number ParenExpr FunctionCallOrIdentifier BinOp String StringFragment Interpolation EscapeSeq Boolean Regex Dict NamedArg NamedArgPrefix FunctionDef Params colon keyword Underscore Array Null ConditionalOp PositionalArg operator IfExpr keyword SingleLineThenBlock ThenBlock ElseIfExpr keyword ElseExpr keyword Assign", nodeNames: "⚠ Star Slash Plus Minus And Or Eq EqEq Neq Lt Lte Gt Gte Modulo Identifier AssignableIdentifier Word IdentifierBeforeDot Do Program PipeExpr FunctionCall DotGet Number ParenExpr FunctionCallOrIdentifier BinOp String StringFragment Interpolation EscapeSeq Boolean Regex Dict NamedArg NamedArgPrefix FunctionDef Params colon keyword Underscore Array Null ConditionalOp PositionalArg operator IfExpr keyword SingleLineThenBlock ThenBlock ElseIfExpr keyword ElseExpr keyword Assign",
maxTerm: 95, maxTerm: 95,
context: trackScope, context: trackScope,
@ -23,5 +23,5 @@ export const parser = LRParser.deserialize({
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!k~~", 11)], tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!k~~", 11)],
topRules: {"Program":[0,20]}, topRules: {"Program":[0,20]},
specialized: [{term: 15, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 15, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}], specialized: [{term: 15, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 15, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}],
tokenPrec: 1135 tokenPrec: 1164
}) })

View File

@ -594,6 +594,44 @@ describe('Comments', () => {
}) })
}) })
describe('Array destructuring', () => {
test('parses array pattern with two variables', () => {
expect('[ a b ] = [ 1 2 3 4]').toMatchTree(`
Assign
Array
Identifier a
Identifier b
Eq =
Array
Number 1
Number 2
Number 3
Number 4`)
})
test('parses array pattern with one variable', () => {
expect('[ x ] = [ 42 ]').toMatchTree(`
Assign
Array
Identifier x
Eq =
Array
Number 42`)
})
test('parses array pattern with emoji identifiers', () => {
expect('[ 🚀 💎 ] = [ 1 2 ]').toMatchTree(`
Assign
Array
Identifier 🚀
Identifier 💎
Eq =
Array
Number 1
Number 2`)
})
})
describe('Conditional ops', () => { describe('Conditional ops', () => {
test('or can be chained', () => { test('or can be chained', () => {
expect(` expect(`