Add Exceptions to Prelude #15

Merged
probablycorey merged 6 commits from add-exceptions into main 2025-10-31 17:05:07 +00:00
4 changed files with 298 additions and 6 deletions
Showing only changes of commit 4f961d3039 - Show all commits

View File

@ -62,7 +62,7 @@
"hono": ["hono@4.9.8", "", {}, "sha512-JW8Bb4RFWD9iOKxg5PbUarBYGM99IcxFl2FPBo2gSJO11jjUDqlP1Bmfyqt8Z/dGhIQ63PMA9LdcLefXyIasyg=="],
"reefvm": ["reefvm@git+https://git.nose.space/defunkt/reefvm#030eb7487165b3ba502965a8b7fa09c4b5fdb0da", { "peerDependencies": { "typescript": "^5" } }, "030eb7487165b3ba502965a8b7fa09c4b5fdb0da"],
"reefvm": ["reefvm@git+https://git.nose.space/defunkt/reefvm#9618dd64148ccf6f0cdfd8a80a0f58efe3e0819d", { "peerDependencies": { "typescript": "^5" } }, "9618dd64148ccf6f0cdfd8a80a0f58efe3e0819d"],
"style-mod": ["style-mod@4.1.2", "", {}, "sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw=="],

View File

@ -0,0 +1,292 @@
import { describe, test, expect } from 'bun:test'
import { Compiler } from '#compiler/compiler'
import { VM } from 'reefvm'
describe('Native Function Exceptions', () => {
test('native function error caught by try/catch', async () => {
const code = `
result = try:
failing-fn
catch e:
'caught: ' + e
end
result
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('failing-fn', () => {
throw new Error('native function failed')
})
const result = await vm.run()
expect(result).toEqual({ type: 'string', value: 'caught: native function failed' })
})
test('async native function error caught by try/catch', async () => {
const code = `
result = try:
async-fail
catch e:
'async caught: ' + e
end
result
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('async-fail', async () => {
await new Promise(resolve => setTimeout(resolve, 1))
throw new Error('async error')
})
const result = await vm.run()
expect(result).toEqual({ type: 'string', value: 'async caught: async error' })
})
test('native function with arguments throwing error', async () => {
const code = `
result = try:
read-file missing.txt
catch e:
'default content'
end
result
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('read-file', (path: string) => {
if (path === 'missing.txt') {
throw new Error('file not found')
}
return 'file contents'
})
const result = await vm.run()
expect(result).toEqual({ type: 'string', value: 'default content' })
})
test('native function error with finally block', async () => {
const code = `
cleanup-count = 0
result = try:
failing-fn
catch e:
'error handled'
finally:
cleanup-count = cleanup-count + 1
end
cleanup-count
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('failing-fn', () => {
throw new Error('native error')
})
const result = await vm.run()
expect(result).toEqual({ type: 'number', value: 1 })
})
test('native function error without catch propagates', async () => {
const code = `
failing-fn
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('failing-fn', () => {
throw new Error('uncaught error')
})
await expect(vm.run()).rejects.toThrow('Uncaught exception in native function: uncaught error')
})
test('native function in function-level catch', async () => {
const code = `
safe-read = do path:
read-file path
catch e:
'default: ' + e
end
result = safe-read missing.txt
result
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('read-file', (path: string) => {
throw new Error('file not found: ' + path)
})
const result = await vm.run()
expect(result).toEqual({ type: 'string', value: 'default: file not found: missing.txt' })
})
test('nested native function errors', async () => {
const code = `
result = try:
try:
inner-fail
catch e:
throw 'wrapped: ' + e
end
catch e:
'outer caught: ' + e
end
result
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('inner-fail', () => {
throw new Error('inner error')
})
const result = await vm.run()
expect(result).toEqual({ type: 'string', value: 'outer caught: wrapped: inner error' })
})
test('native function error with multiple named args', async () => {
const code = `
result = try:
process-file path=missing.txt mode=strict
catch e:
'error: ' + e
end
result
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('process-file', (path: string, mode: string = 'lenient') => {
if (mode === 'strict' && path === 'missing.txt') {
throw new Error('strict mode: file required')
}
return 'processed'
})
const result = await vm.run()
expect(result).toEqual({ type: 'string', value: 'error: strict mode: file required' })
})
test('native function returning normally after other functions threw', async () => {
const code = `
result1 = try:
failing-fn
catch e:
'caught'
end
result2 = success-fn
result1 + ' then ' + result2
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('failing-fn', () => {
throw new Error('error')
})
vm.set('success-fn', () => {
return 'success'
})
const result = await vm.run()
expect(result).toEqual({ type: 'string', value: 'caught then success' })
})
test('native function error message preserved', async () => {
const code = `
result = try:
throw-custom-message
catch e:
e
end
result
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('throw-custom-message', () => {
throw new Error('This is a very specific error message with details')
})
const result = await vm.run()
expect(result).toEqual({
type: 'string',
value: 'This is a very specific error message with details'
})
})
test('native function throwing non-Error value', async () => {
const code = `
result = try:
throw-string
catch e:
'caught: ' + e
end
result
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('throw-string', () => {
throw 'plain string error'
})
const result = await vm.run()
expect(result).toEqual({ type: 'string', value: 'caught: plain string error' })
})
test('multiple native function calls with mixed success/failure', async () => {
const code = `
r1 = try: success-fn catch e: 'error' end
r2 = try: failing-fn catch e: 'caught' end
r3 = try: success-fn catch e: 'error' end
results = [r1 r2 r3]
results
`
const compiler = new Compiler(code)
const vm = new VM(compiler.bytecode)
vm.set('success-fn', () => 'ok')
vm.set('failing-fn', () => {
throw new Error('failed')
})
const result = await vm.run()
expect(result.type).toBe('array')
const arr = result.value as any[]
expect(arr.length).toBe(3)
expect(arr[0]).toEqual({ type: 'string', value: 'ok' })
expect(arr[1]).toEqual({ type: 'string', value: 'caught' })
expect(arr[2]).toEqual({ type: 'string', value: 'ok' })
})
})

View File

@ -159,7 +159,7 @@ TryBlock {
}
Throw {
@specialize[@name=keyword]<Identifier, "throw"> expression
@specialize[@name=keyword]<Identifier, "throw"> (BinOp | ConditionalOp | expression)
}
ConditionalOp {

View File

@ -7,9 +7,9 @@ import {highlighting} from "./highlight"
const spec_Identifier = {__proto__:null,catch:82, finally:88, end:90, null:96, try:106, throw:110, if:114, elseif:122, else:126}
export const parser = LRParser.deserialize({
version: 14,
states: "8lQYQbOOO#tQcO'#CvO$qOSO'#CxO%PQbO'#E`OOQ`'#DR'#DROOQa'#DO'#DOO&SQbO'#D]O'XQcO'#ETOOQa'#ET'#ETO)cQcO'#ESO*bQRO'#CwO+WQcO'#EOO+hQcO'#EOO+rQbO'#CuO,jOpO'#CsOOQ`'#EP'#EPO,oQbO'#EOO,vQQO'#EfOOQ`'#Db'#DbO,{QbO'#DdO,{QbO'#EhOOQ`'#Df'#DfO-pQRO'#DnOOQ`'#EO'#EOO-uQQO'#D}OOQ`'#D}'#D}OOQ`'#Do'#DoQYQbOOO-}QbO'#DPOOQa'#ES'#ESOOQ`'#D`'#D`OOQ`'#Ee'#EeOOQ`'#Dv'#DvO.XQbO,59^O.rQbO'#CzO.zQWO'#C{OOOO'#EV'#EVOOOO'#Dp'#DpO/`OSO,59dOOQa,59d,59dOOQ`'#Dr'#DrO/nQbO'#DSO/vQQO,5:zOOQ`'#Dq'#DqO/{QbO,59wO0SQQO,59jOOQa,59w,59wO0_QbO,59wO,{QbO,59cO,{QbO,59cO,{QbO,59cO,{QbO,59yO,{QbO,59yO,{QbO,59yO0iQRO,59aO0pQRO,59aO1RQRO,59aO0|QQO,59aO1^QQO,59aO1fObO,59_O1qQbO'#DwO1|QbO,59]O2eQbO,5;QOOQ`,5:O,5:OO2xQRO,5;SO3PQRO,5;SO3[QbO,5:YOOQ`,5:i,5:iOOQ`-E7m-E7mOOQ`,59k,59kOOQ`-E7t-E7tOOOO,59f,59fOOOO,59g,59gOOOO-E7n-E7nOOQa1G/O1G/OOOQ`-E7p-E7pO3lQbO1G0fOOQ`-E7o-E7oO4PQQO1G/UOOQa1G/c1G/cO4[QbO1G/cOOQO'#Dt'#DtO4PQQO1G/UOOQa1G/U1G/UOOQ`'#Du'#DuO4[QbO1G/cOOQa1G.}1G.}O5TQcO1G.}O5_QcO1G.}O5iQcO1G.}OOQa1G/e1G/eO7XQcO1G/eO7`QcO1G/eO7gQcO1G/eOOQa1G.{1G.{OOQa1G.y1G.yO!aQbO'#CvO&ZQbO'#CrOOQ`,5:c,5:cOOQ`-E7u-E7uO7nQbO1G0lO7yQbO1G0mO8gQbO1G0nOOQ`1G/t1G/tO8zQbO7+&QO7yQbO7+&SO9VQQO7+$pOOQa7+$p7+$pO9bQbO7+$}OOQa7+$}7+$}OOQO-E7r-E7rOOQ`-E7s-E7sO9lQbO'#DUO9qQQO'#DXOOQ`7+&W7+&WO9vQbO7+&WO9{QbO7+&WOOQ`'#Ds'#DsO:TQQO'#DsO:YQbO'#EaOOQ`'#DW'#DWO:|QbO7+&XOOQ`'#Dh'#DhO;XQbO7+&YO;^QbO7+&ZOOQ`<<Il<<IlO;zQbO<<IlO<PQbO<<IlO<XQbO<<InOOQa<<H[<<H[OOQa<<Hi<<HiO<dQQO,59pO<iQbO,59sOOQ`<<Ir<<IrO<|QbO<<IrOOQ`,5:_,5:_OOQ`-E7q-E7qOOQ`<<Is<<IsO=RQbO<<IsO=WQbO<<IsOOQ`<<It<<ItOOQ`'#Di'#DiO=`QbO<<IuOOQ`AN?WAN?WO=kQbOAN?WOOQ`AN?YAN?YO=pQbOAN?YO=uQbOAN?YO=}QbO1G/[O>bQbO1G/_OOQ`1G/_1G/_OOQ`AN?^AN?^OOQ`AN?_AN?_O>xQbOAN?_O,{QbO'#DjOOQ`'#Dx'#DxO>}QbOAN?aO?YQQO'#DlOOQ`AN?aAN?aO?_QbOAN?aOOQ`G24rG24rOOQ`G24tG24tO?dQbOG24tO?iQbO7+$vOOQ`7+$v7+$vOOQ`7+$y7+$yOOQ`G24yG24yO@SQRO,5:UO@ZQRO,5:UOOQ`-E7v-E7vOOQ`G24{G24{O@fQbOG24{O@kQQO,5:WOOQ`LD*`LD*`OOQ`<<Hb<<HbO@pQQO1G/pOOQ`LD*gLD*gO>bQbO1G/rO;^QbO7+%[OOQ`7+%^7+%^OOQ`<<Hv<<Hv",
stateData: "@x~O!oOS!pOS~O_PO`fOaWOb^OcROhWOpWOqWO!QWO!VaO!XcO!ZdO!u]O!xQO#PTO#QUO#RiO~O_mOaWOb^OcROhWOpWOqWOtlO!OnO!QWO!u]O!xQO#PTO#QUO!TjX#RjX#^jX#WjXyjX|jX}jX~OP!vXQ!vXR!vXS!vXT!vXU!vXW!vXX!vXY!vXZ!vX[!vX]!vX^!vX~P!aOmtO!xwO!zrO!{sO~O_xOwvP~O_mOaWOb^OhWOpWOqWOtlO!QWO!u]O!xQO#PTO#QUO#R{O~O#V!OO~P%XO_mOaWOb^OcROhWOpWOqWOtlO!OnO!QWO!u]O!xQO#PTO#QUO~OP!wXQ!wXR!wXS!wXT!wXU!wXW!wXX!wXY!wXZ!wX[!wX]!wX^!wX#R!wX#^!wX#W!wXy!wX|!wX}!wX~P&ZOP!vXQ!vXR!vXS!vXT!vXU!vXW!vXX!vXY!vXZ!vX[!vX]!vX^!vX~O#R!rX#^!rXy!rX|!rX}!rX~P(hOT!UOU!VOW!TOX!TOY!TOZ!TO[!TO]!TO~OP!ROQ!ROR!SOS!SO^!QO~P)vO#R!rX#^!rXy!rX|!rX}!rX~OP!ROQ!ROR!SOS!SO~P*uOT!UOU!VO~P*uO_POaWOb^OcROhWOpWOqWO!QWO!u]O!xQO#PTO#QUO~O!t!]O~O!T!^O~P*uOw!`O~O_mOaWOb^OhWOpWOqWO!QWO!u]O!xQO#PTO#QUO~OV!dO~O#R!eO#^!eO~OcRO!O!gO~P,{O!Tfa#Rfa#^fa#Wfayfa|fa}fa~P&ZO_!iO!u]O~O!x!jO!z!jO!{!jO!|!jO!}!jO#O!jO~OmtO!x!lO!zrO!{sO~O_xOwvX~Ow!nO~O#V!qO~P%XOtlO#R!sO#V!uO~O#R!vO#V!qO~P,{O#W#QO~P(hOP!ROQ!ROR!SOS!SO#W#QO~OT!UOU!VO#W#QO~O!T!^O#W#QO~O_#ROh#RO!u]O~O_#SOb^O!u]O~O!T!^O#Rea#^ea#Weayea|ea}ea~O`fO!VaO!XcO!ZdO#R#XO~P+rOw#YO~P)vOT!UOU!VOw#YO~O`fO!VaO!XcO!ZdO~P+rO`fO!VaO!XcO!ZdO#R#]O~P+rOtlO#R!sO#V#_O~O#R!vO#V#aO~P,{O^!QORkiSki#Rki#^ki#Wkiyki|ki}ki~OPkiQki~P4fOP!ROQ!RO~P4fOP!ROQ!RORkiSki#Rki#^ki#Wkiyki|ki}ki~OW!TOX!TOY!TOZ!TO[!TO]!TOT!Ri#R!Ri#^!Ri#W!Riw!Riy!Ri|!Ri}!Ri~OU!VO~P6ZOU!VO~P6mOU!Ri~P6ZOy#dO|#eO}#fO~O`fO!VaO!XcO!ZdO#R#iOy#TP|#TP}#TP~P+rO`fO!VaO!XcO!ZdO#R#pO~P+rOy#dO|#eO}#qO~OtlO#R!sO#V#uO~O#R!vO#V#vO~P,{O_#wO~Ow#xO~O}#yO~O|#eO}#yO~O#R#{O~O`fO!VaO!XcO!ZdO#R#iOy#TX|#TX}#TX!_#TX!a#TX~P+rOy#dO|#eO}#}O~O}$QO~O`fO!VaO!XcO!ZdO#R#iO}#TP!_#TP!a#TP~P+rO}$TO~O|#eO}$TO~Oy#dO|#eO}$VO~Ow$YO~O`fO!VaO!XcO!ZdO#R$ZO~P+rO}$]O~O}$^O~O|#eO}$^O~O}$dO!_$`O!a$cO~O}$fO~O}$gO~O|#eO}$gO~O`fO!VaO!XcO!ZdO#R$iO~P+rO`fO!VaO!XcO!ZdO#R#iO}#TP~P+rO}$lO~O}$pO!_$`O!a$cO~Ow$rO~O}$pO~O}$sO~O`fO!VaO!XcO!ZdO#R#iO|#TP}#TP~P+rOw$uO~P)vOT!UOU!VOw$uO~O}$vO~O#R$wO~O#R$xO~Ohq~",
goto: "3O#^PPPPPPPPPPPPPPPPPPPPP#_#t$YP%X#t&^&yP's'sPP&y'wP([({P)OP)[)ePPP&yP)}*pP*wP*wP*wP+Z+^+gP+kP*w+q+w+},T,Z,g,q,{-U-]PPPP-c-g.XPP.q0XP1VPPPPPPPP1Z1t1ZPP2R2Y2Y2l2lpgOk!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xR!Z]u_O]k!^!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xrPO]k!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xzmPUVcdlq|!P!Q!R!S!T!U!V!r!w#S#T#`$`R#S!^rVO]k!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xzWPUVcdlq|!P!Q!R!S!T!U!V!r!w#S#T#`$`Q!irQ#R!]R#T!^pZOk!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xQ!X]Q!x!RR!{!S!oWOPUV]cdklq|!P!Q!R!S!T!U!V!`!d!n!r!w#S#T#X#Y#]#`#k#p#x$Y$Z$`$i$w$xTtQvYoPVq#S#TQ}UQ!p|X!s}!p!t#^pgOk!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xYnPVq#S#TQ!Z]R!glRzRQ#h#WQ#s#[Q$P#mR$X#tQ#m#XQ$k$ZR$t$iQ#g#WQ#r#[Q#z#hQ$O#mQ$U#sQ$W#tQ$_$PR$h$Xp[Ok!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xQ!Y]Q!cdQ!|!VQ#O!UR$n$`ZoPVq#S#TqgOk!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xR#o#YQ$S#pQ$y$wR$z$xT$a$S$bQ$e$SR$q$bQkOR!fkQvQR!kvQ|UR!o|QyRR!my^#k#X#]#p$Z$i$w$xR#|#kQ!t}Q#^!pT#b!t#^Q!w!PQ#`!rT#c!w#`WqPV#S#TR!hqS!_`![R#V!_Q$b$SR$o$bTjOkShOkQ#W!`Q#Z!dQ#[!n`#j#X#]#k#p$Z$i$w$xQ#n#YQ$[#xR$j$Yp`Ok!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xQ![]R#U!^rYO]k!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xYnPVq#S#TQ!PUQ!acQ!bdQ!glQ!r|W!v!P!r!w#`Q!x!QQ!y!RQ!z!SQ!|!TQ!}!UQ#P!VR$m$`pXOk!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xzmPUVcdlq|!P!Q!R!S!T!U!V!r!w#S#T#`$`R!W]TuQv!PSOPV]klq!`!d!n#S#T#X#Y#]#k#p#x$Y$Z$i$w$xU#l#X$Z$iQ#t#]V$R#p$w$xZpPVq#S#TqbOk!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$xqeOk!`!d!n#X#Y#]#k#p#x$Y$Z$i$w$x",
states: "8xQYQbOOO#tQcO'#CvO$qOSO'#CxO%PQbO'#E`OOQ`'#DR'#DROOQa'#DO'#DOO&SQbO'#D]O'XQcO'#ETOOQa'#ET'#ETO)cQcO'#ESO)vQRO'#CwO+SQcO'#EOO+dQcO'#EOO+nQbO'#CuO,fOpO'#CsOOQ`'#EP'#EPO,kQbO'#EOO,rQQO'#EfOOQ`'#Db'#DbO,wQbO'#DdO,wQbO'#EhOOQ`'#Df'#DfO-lQRO'#DnOOQ`'#EO'#EOO-qQQO'#D}OOQ`'#D}'#D}OOQ`'#Do'#DoQYQbOOO-yQbO'#DPOOQa'#ES'#ESOOQ`'#D`'#D`OOQ`'#Ee'#EeOOQ`'#Dv'#DvO.TQbO,59^O.nQbO'#CzO.vQWO'#C{OOOO'#EV'#EVOOOO'#Dp'#DpO/[OSO,59dOOQa,59d,59dOOQ`'#Dr'#DrO/jQbO'#DSO/rQQO,5:zOOQ`'#Dq'#DqO/wQbO,59wO0OQQO,59jOOQa,59w,59wO0ZQbO,59wO,wQbO,59cO,wQbO,59cO,wQbO,59cO,wQbO,59yO,wQbO,59yO,wQbO,59yO0eQRO,59aO0lQRO,59aO0}QRO,59aO0xQQO,59aO1YQQO,59aO1bObO,59_O1mQbO'#DwO1xQbO,59]O2aQbO,5;QO2tQcO,5:OO3jQcO,5:OO3zQcO,5:OO4pQRO,5;SO4wQRO,5;SO5SQbO,5:YOOQ`,5:i,5:iOOQ`-E7m-E7mOOQ`,59k,59kOOQ`-E7t-E7tOOOO,59f,59fOOOO,59g,59gOOOO-E7n-E7nOOQa1G/O1G/OOOQ`-E7p-E7pO5dQbO1G0fOOQ`-E7o-E7oO5wQQO1G/UOOQa1G/c1G/cO6SQbO1G/cOOQO'#Dt'#DtO5wQQO1G/UOOQa1G/U1G/UOOQ`'#Du'#DuO6SQbO1G/cOOQa1G.}1G.}O6{QcO1G.}O7VQcO1G.}O7aQcO1G.}OOQa1G/e1G/eO9PQcO1G/eO9WQcO1G/eO9_QcO1G/eOOQa1G.{1G.{OOQa1G.y1G.yO!aQbO'#CvO&ZQbO'#CrOOQ`,5:c,5:cOOQ`-E7u-E7uO9fQbO1G0lO9qQbO1G0mO:_QbO1G0nOOQ`1G/t1G/tO:rQbO7+&QO9qQbO7+&SO:}QQO7+$pOOQa7+$p7+$pO;YQbO7+$}OOQa7+$}7+$}OOQO-E7r-E7rOOQ`-E7s-E7sO;dQbO'#DUO;iQQO'#DXOOQ`7+&W7+&WO;nQbO7+&WO;sQbO7+&WOOQ`'#Ds'#DsO;{QQO'#DsO<QQbO'#EaOOQ`'#DW'#DWO<tQbO7+&XOOQ`'#Dh'#DhO=PQbO7+&YO=UQbO7+&ZOOQ`<<Il<<IlO=rQbO<<IlO=wQbO<<IlO>PQbO<<InOOQa<<H[<<H[OOQa<<Hi<<HiO>[QQO,59pO>aQbO,59sOOQ`<<Ir<<IrO>tQbO<<IrOOQ`,5:_,5:_OOQ`-E7q-E7qOOQ`<<Is<<IsO>yQbO<<IsO?OQbO<<IsOOQ`<<It<<ItOOQ`'#Di'#DiO?WQbO<<IuOOQ`AN?WAN?WO?cQbOAN?WOOQ`AN?YAN?YO?hQbOAN?YO?mQbOAN?YO?uQbO1G/[O@YQbO1G/_OOQ`1G/_1G/_OOQ`AN?^AN?^OOQ`AN?_AN?_O@pQbOAN?_O,wQbO'#DjOOQ`'#Dx'#DxO@uQbOAN?aOAQQQO'#DlOOQ`AN?aAN?aOAVQbOAN?aOOQ`G24rG24rOOQ`G24tG24tOA[QbOG24tOAaQbO7+$vOOQ`7+$v7+$vOOQ`7+$y7+$yOOQ`G24yG24yOAzQRO,5:UOBRQRO,5:UOOQ`-E7v-E7vOOQ`G24{G24{OB^QbOG24{OBcQQO,5:WOOQ`LD*`LD*`OOQ`<<Hb<<HbOBhQQO1G/pOOQ`LD*gLD*gO@YQbO1G/rO=UQbO7+%[OOQ`7+%^7+%^OOQ`<<Hv<<Hv",
stateData: "Bp~O!oOS!pOS~O_PO`fOaWOb^OcROhWOpWOqWO!QWO!VaO!XcO!ZdO!u]O!xQO#PTO#QUO#RiO~O_mOaWOb^OcROhWOpWOqWOtlO!OnO!QWO!u]O!xQO#PTO#QUO!TjX#RjX#^jX#WjXyjX|jX}jX~OP!vXQ!vXR!vXS!vXT!vXU!vXW!vXX!vXY!vXZ!vX[!vX]!vX^!vX~P!aOmtO!xwO!zrO!{sO~O_xOwvP~O_mOaWOb^OhWOpWOqWOtlO!QWO!u]O!xQO#PTO#QUO#R{O~O#V!OO~P%XO_mOaWOb^OcROhWOpWOqWOtlO!OnO!QWO!u]O!xQO#PTO#QUO~OP!wXQ!wXR!wXS!wXT!wXU!wXW!wXX!wXY!wXZ!wX[!wX]!wX^!wX#R!wX#^!wX#W!wXy!wX|!wX}!wX~P&ZOP!vXQ!vXR!vXS!vXT!vXU!vXW!vXX!vXY!vXZ!vX[!vX]!vX^!vX~O#R!rX#^!rXy!rX|!rX}!rX~P(hOP!ROQ!ROR!SOS!SOT!UOU!VOW!TOX!TOY!TOZ!TO[!TO]!TO^!QO~O#R!rX#^!rXy!rX|!rX}!rX~OP!ROQ!ROR!SOS!SO~P*qOT!UOU!VO~P*qO_POaWOb^OcROhWOpWOqWO!QWO!u]O!xQO#PTO#QUO~O!t!]O~O!T!^O~P*qOw!`O~O_mOaWOb^OhWOpWOqWO!QWO!u]O!xQO#PTO#QUO~OV!fO~O#R!gO#^!gO~OcRO!O!iO~P,wO!Tfa#Rfa#^fa#Wfayfa|fa}fa~P&ZO_!kO!u]O~O!x!lO!z!lO!{!lO!|!lO!}!lO#O!lO~OmtO!x!nO!zrO!{sO~O_xOwvX~Ow!pO~O#V!sO~P%XOtlO#R!uO#V!wO~O#R!xO#V!sO~P,wO#W#SO~P(hOP!ROQ!ROR!SOS!SO#W#SO~OT!UOU!VO#W#SO~O!T!^O#W#SO~O_#TOh#TO!u]O~O_#UOb^O!u]O~O!T!^O#Rea#^ea#Weayea|ea}ea~O`fO!VaO!XcO!ZdO#R#ZO~P+nO#R!Wa#^!Way!Wa|!Wa}!Wa~P)vO#R!Wa#^!Way!Wa|!Wa}!Wa~OP!ROQ!ROR!SOS!SO~P3XOT!UOU!VO~P3XOT!UOU!VOW!TOX!TOY!TOZ!TO[!TO]!TO~Ow#[O~P4UOT!UOU!VOw#[O~O`fO!VaO!XcO!ZdO~P+nO`fO!VaO!XcO!ZdO#R#_O~P+nOtlO#R!uO#V#aO~O#R!xO#V#cO~P,wO^!QORkiSki#Rki#^ki#Wkiyki|ki}ki~OPkiQki~P6^OP!ROQ!RO~P6^OP!ROQ!RORkiSki#Rki#^ki#Wkiyki|ki}ki~OW!TOX!TOY!TOZ!TO[!TO]!TOT!Ri#R!Ri#^!Ri#W!Riw!Riy!Ri|!Ri}!Ri~OU!VO~P8ROU!VO~P8eOU!Ri~P8ROy#fO|#gO}#hO~O`fO!VaO!XcO!ZdO#R#kOy#TP|#TP}#TP~P+nO`fO!VaO!XcO!ZdO#R#rO~P+nOy#fO|#gO}#sO~OtlO#R!uO#V#wO~O#R!xO#V#xO~P,wO_#yO~Ow#zO~O}#{O~O|#gO}#{O~O#R#}O~O`fO!VaO!XcO!ZdO#R#kOy#TX|#TX}#TX!_#TX!a#TX~P+nOy#fO|#gO}$PO~O}$SO~O`fO!VaO!XcO!ZdO#R#kO}#TP!_#TP!a#TP~P+nO}$VO~O|#gO}$VO~Oy#fO|#gO}$XO~Ow$[O~O`fO!VaO!XcO!ZdO#R$]O~P+nO}$_O~O}$`O~O|#gO}$`O~O}$fO!_$bO!a$eO~O}$hO~O}$iO~O|#gO}$iO~O`fO!VaO!XcO!ZdO#R$kO~P+nO`fO!VaO!XcO!ZdO#R#kO}#TP~P+nO}$nO~O}$rO!_$bO!a$eO~Ow$tO~O}$rO~O}$uO~O`fO!VaO!XcO!ZdO#R#kO|#TP}#TP~P+nOw$wO~P4UOT!UOU!VOw$wO~O}$xO~O#R$yO~O#R$zO~Ohq~",
goto: "3U#^PPPPPPPPPPPPPPPPPPPPP#_#t$YP%X#t&^&|P'v'vPP&|'zP(_)OP)RP)_)hPPP&|P*Q*vP*}P*}P*}P+a+d+mP+qP*}+w+},T,Z,a,m,w-R-[-cPPPP-i-m._PP.w0_P1]PPPPPPPP1a1z1aPP2X2`2`2r2rpgOk!`!f!p#Z#[#_#m#r#z$[$]$k$y$zR!Z]u_O]k!^!`!f!p#Z#[#_#m#r#z$[$]$k$y$zrPO]k!`!f!p#Z#[#_#m#r#z$[$]$k$y$zzmPUVcdlq|!P!Q!R!S!T!U!V!t!y#U#V#b$bR#U!^rVO]k!`!f!p#Z#[#_#m#r#z$[$]$k$y$zzWPUVcdlq|!P!Q!R!S!T!U!V!t!y#U#V#b$bQ!krQ#T!]R#V!^pZOk!`!f!p#Z#[#_#m#r#z$[$]$k$y$zQ!X]Q!bcQ!z!RR!}!S!oWOPUV]cdklq|!P!Q!R!S!T!U!V!`!f!p!t!y#U#V#Z#[#_#b#m#r#z$[$]$b$k$y$zTtQvYoPVq#U#VQ}UQ!r|X!u}!r!v#`pgOk!`!f!p#Z#[#_#m#r#z$[$]$k$y$zYnPVq#U#VQ!Z]R!ilRzRQ#j#YQ#u#^Q$R#oR$Z#vQ#o#ZQ$m$]R$v$kQ#i#YQ#t#^Q#|#jQ$Q#oQ$W#uQ$Y#vQ$a$RR$j$Zp[Ok!`!f!p#Z#[#_#m#r#z$[$]$k$y$zQ!Y]Q!ccQ!edQ#O!VQ#Q!UR$p$bZoPVq#U#VqgOk!`!f!p#Z#[#_#m#r#z$[$]$k$y$zR#q#[Q$U#rQ${$yR$|$zT$c$U$dQ$g$UR$s$dQkOR!hkQvQR!mvQ|UR!q|QyRR!oy^#m#Z#_#r$]$k$y$zR$O#mQ!v}Q#`!rT#d!v#`Q!y!PQ#b!tT#e!y#bWqPV#U#VR!jqS!_`![R#X!_Q$d$UR$q$dTjOkShOkQ#Y!`Q#]!fQ#^!p`#l#Z#_#m#r$]$k$y$zQ#p#[Q$^#zR$l$[p`Ok!`!f!p#Z#[#_#m#r#z$[$]$k$y$zQ![]R#W!^rYO]k!`!f!p#Z#[#_#m#r#z$[$]$k$y$zYnPVq#U#VQ!PUQ!acQ!ddQ!ilQ!t|W!x!P!t!y#bQ!z!QQ!{!RQ!|!SQ#O!TQ#P!UQ#R!VR$o$bpXOk!`!f!p#Z#[#_#m#r#z$[$]$k$y$zzmPUVcdlq|!P!Q!R!S!T!U!V!t!y#U#V#b$bR!W]TuQv!PSOPV]klq!`!f!p#U#V#Z#[#_#m#r#z$[$]$k$y$zU#n#Z$]$kQ#v#_V$T#r$y$zZpPVq#U#VqbOk!`!f!p#Z#[#_#m#r#z$[$]$k$y$zqeOk!`!f!p#Z#[#_#m#r#z$[$]$k$y$z",
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 CatchExpr keyword TryBlock FinallyExpr keyword keyword Underscore Array Null ConditionalOp PositionalArg operator TryExpr keyword Throw keyword IfExpr keyword SingleLineThenBlock ThenBlock ElseIfExpr keyword ElseExpr keyword Assign",
maxTerm: 106,
context: trackScope,
@ -23,5 +23,5 @@ export const parser = LRParser.deserialize({
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO!t~~", 11)],
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}],
tokenPrec: 1463
tokenPrec: 1547
})