diff --git a/common/space_lua/ast.ts b/common/space_lua/ast.ts index d9a47ba9..a7d53b41 100644 --- a/common/space_lua/ast.ts +++ b/common/space_lua/ast.ts @@ -93,7 +93,7 @@ export type LuaLocalFunctionStatement = { export type LuaFunctionName = { type: "FunctionName"; - propNames?: string[]; + propNames: string[]; colonName?: string; }; diff --git a/common/space_lua/eval.test.ts b/common/space_lua/eval.test.ts index 3686c854..5c1bde79 100644 --- a/common/space_lua/eval.test.ts +++ b/common/space_lua/eval.test.ts @@ -185,4 +185,17 @@ Deno.test("Statement evaluation", async () => { env7, ); assertEquals(env7.get("c"), 3); + + // Function definition and calling + const env8 = new LuaEnv(); + env8.set("print", new LuaNativeJSFunction(console.log)); + await evalBlock( + ` + function test(a) + return a + 1 + end + print("3 + 1 = " .. test(3)) + `, + env8, + ); }); diff --git a/common/space_lua/eval.ts b/common/space_lua/eval.ts index 773d4784..b470dc48 100644 --- a/common/space_lua/eval.ts +++ b/common/space_lua/eval.ts @@ -6,11 +6,15 @@ import type { import { evalPromiseValues } from "$common/space_lua/util.ts"; import { type ILuaFunction, + type ILuaGettable, + type ILuaSettable, LuaBreak, LuaEnv, + LuaFunction, luaGet, luaLen, type LuaLValueContainer, + LuaReturn, LuaTable, luaTruthy, type LuaValue, @@ -356,6 +360,39 @@ export async function evalStatement( case "FunctionCallStatement": { return evalExpression(s.call, env); } + case "Function": { + let body = s.body; + let propNames = s.name.propNames; + if (s.name.colonName) { + // function hello:there() -> function hello.there(self) transformation + body = { + ...s.body, + parameters: ["self", ...s.body.parameters], + }; + propNames = [...s.name.propNames, s.name.colonName]; + } + let settable: ILuaSettable & ILuaGettable = env; + for (let i = 0; i < propNames.length - 1; i++) { + settable = settable.get(propNames[i]); + if (!settable) { + throw new Error( + `Cannot find property ${propNames[i]}`, + ); + } + } + settable.set( + propNames[propNames.length - 1], + new LuaFunction(body, env), + ); + break; + } + case "Return": { + throw new LuaReturn( + await evalPromiseValues( + s.expressions.map((value) => evalExpression(value, env)), + ), + ); + } default: throw new Error(`Unknown statement type ${s.type}`); } diff --git a/common/space_lua/lua.grammar b/common/space_lua/lua.grammar index fe8fd229..74da6369 100644 --- a/common/space_lua/lua.grammar +++ b/common/space_lua/lua.grammar @@ -19,7 +19,7 @@ Block { statement* ReturnStatement? } -ReturnStatement { kw<"return"> exp? ";"?} +ReturnStatement { kw<"return"> ExpList? ";"?} @skip { newline | space | Comment } diff --git a/common/space_lua/parse-lua.js b/common/space_lua/parse-lua.js index 0d64dfb1..1d20ad88 100644 --- a/common/space_lua/parse-lua.js +++ b/common/space_lua/parse-lua.js @@ -3,9 +3,9 @@ import {LRParser} from "@lezer/lr" const spec_identifier = {__proto__:null,break:16, goto:20, do:24, end:26, while:30, nil:32, true:34, false:36, or:80, and:82, not:104, function:114, repeat:122, until:124, if:128, then:130, elseif:132, else:134, for:138, in:146, local:156, return:172} export const parser = LRParser.deserialize({ version: 14, - states: ">`O!ZQPOOOOQO'#Cc'#CcO!UQPO'#CaO!bQPOOOOQO'#Ei'#EiO!vQQO'#CwO$]QPO'#EhOOQO'#Eh'#EhO$gQPO'#EhOOQO'#EO'#EOO%vQPO'#D}OOQO'#Ed'#EdOOQO'#EV'#EVO%{QPO'#C_OOQO'#C_'#C_QOQPOOO!UQPO'#CeO&`QPO'#CgO!vQQO'#CjO&gQPO'#DjO!vQQO'#DmO!UQPO'#DrO!UQPO'#DyO&nQPO'#EPO&vQQO'#ETO'^QPO,58{OOQO'#Cq'#CqO!UQPO,59^O!vQQO,59`O(gQQO'#C|O(nQQO'#EnOOQO'#Ej'#EjOOQO,59f,59fO!UQPO,59fO(uQPO'#EfO,eQPO,59cOOQO'#Dc'#DcOOQO'#Dd'#DdOOQO'#De'#DeO!vQQO'#DaOOQO'#Ef'#EfO,lQPO'#DfO,qQPO'#E^O,yQPO,5;kO!vQQO,5:iOOQO-E8T-E8TOOQO,58y,58yOOQO,59P,59PO-RQPO,59RO-WQPO,59UO-_QPO,5:UO-dQPO,5:XO-kQPO'#FOOOQO'#Dv'#DvO-vQPO'#DuO-{QPO,5:^O.QQPO'#DzO,lQPO,5:eO.]QQO'#ERO/sQPO'#FQOOQO'#EQ'#EQO!UQPO,5:gO1WQPO,5:kO2hQPO,5:oOOQO,5:o,5:oOOQO1G.g1G.gOOQO1G.x1G.xO3OQPO1G.zO3VQSO'#EfO4cQSO'#EiO!vQQO'#DOO7WQSO'#DQOOQO'#Ek'#EkOOQO,59h,59hO7bQSO,59hO7jQPO'#EoOOQO,5;Y,5;YO9PQPO,5;YO9UQPO1G/QOOQO1G.}1G.}OOQO'#DX'#DXOOQO'#DY'#DYOOQO'#DZ'#DZOOQO'#D['#D[OOQO'#D^'#D^OOQO'#D_'#D_OOQO'#D`'#D`O!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO:eQPO,59{OoQQO,59kO?pQPO,59jO?wQQO1G/SO@OQSO1G/SOOQO1G/S1G/SO@WQSO,59{O!vQQO'#EXO@bQPO,5;ZOOQO1G0t1G0tOOQO7+$l7+$lOD_QPO1G/ZODfQPO1G/ZOGVQPO1G/ZOG^QPO1G/ZOIwQPO1G/ZOJUQPO1G/ZOLVQPO1G/ZO! lQPO1G/ZO! sQPO1G/ZO! zQPO'#EhO!!UQPO'#E}OOQO'#Di'#DiO!!^QPO,5:SO!!cQPO7+$[O!!hQPO7+%[O!#wQPO7+%_O!$SQPO1G/zOOQO,5:v,5:vOOQO-E8Y-E8YOOQO1G/{1G/{O!$ZQPO7+%dOOQO,5:w,5:wOOQO-E8Z-E8ZO!UQPO1G0QOOQO1G0Q1G0QO!$`QQO,5:nOOQO,5:y,5:yOOQO-E8]-E8]OOQO7+%m7+%mOOQO7+%q7+%qO!$eQSO1G/VO!$oQPO1G/UO!%{QSO1G/ZO!&SQSO1G/ZO!'bQSO1G/ZO!'iQSO1G/ZO!(qQSO1G/ZO!)OQSO1G/ZO!)nQSO1G/ZO!+rQSO1G/ZO!+yQSO1G/ZOOQO,5:r,5:rOOQO7+$n7+$nO!,QQQO7+$nOOQO-E8U-E8UO!,XQPO,5:sOOQO-E8V-E8VO!-nQQO'#EYO!-yQPO,5;iO&`QPO1G/nOOQO<oQQO7+$pOOQO<eAN>eO&`QPOAN>eO!.mQPO,5:uO!.tQPOAN>eO!.yQPO<lOOQOLD)kLD)kOOQO7+%{7+%{O!/dQPOG24WO>oQQO'#DaO>oQQO,59oO>oQQO,59oO>oQQO,59oO>oQQO,59oO>oQQO,59oO>oQQO,59oO>oQQO,59oO>oQQO,59oO>oQQO,59o", - stateData: "!/n~O#UOS#VOSPOS~OSZOUQOWZOY`O[aO_bOlTO!ZfO!_cO!bdO!geO!pgO!xhO#XPO~O#SRP~P]OgkOilOlnOoqOqmO#ZjO~O`xOaxObxOcxOdxOlTOqmO!UwO!ZyO#XPO#ZjO#fuO#itO#jtO#pvO~Og#[Xi#[Xl#[Xo#[Xq#[X#Z#[X~OvzO#`#sX~P#wOS#WXU#WXW#WXY#WX[#WX_#WXl#WX!Z#WX!_#WX!b#WX!g#WX!p#WX!x#WX#S#WX#X#WX]#WX!`#WX!d#WX!e#WX~P#wO#`|O~O#SRX]RX!`RX!dRX!eRX~P]O]RP~P]O!`RP~P]O!Z!_O#XPO~OS!bO#S!wX]!wX!`!wX!d!wX!e!wX~P!vOU!cO~O`xOaxObxOcxOdxOi!hOlTOqmO!U%oO!ZyO#XPO#ZjO#fuO#itO#jtO#pvO~Ou!kO~P'cOm!nO~P!vOm#YXx#YXy#YXz#YX!P#YX#d#YX#e#YX#f#YX#g#YX#h#YX#i#YX#j#YX#k#YX#l#YX#m#YX#n#YX#o#YX[#YX!c#YXS#YX#S#YXj#YXv#YXU#YXW#YXY#YX_#YX!Z#YX!_#YX!b#YX!g#YX!p#YX!x#YX#X#YX]#YX!`#YX!d#YX!e#YX~P!bOx#QOy#ROz!yO!P!}O#d!rO#e!sO#f!tO#g!uO#h!uO#i!vO#j!vO#k!wO#l!wO#m!wO#n!wO#o!xO~Om!qO~P+aOl#TO~OlTO#XPO~OvzO#`#sa~O]#ZO~O[#[O~P+aO!`#]O~O!c#^O~P+aOv#`O#`#_O!k#rX~O!k#bO~O[#cO~Og#dOo#fOl!nX~O#u#hOS!vPU!vPW!vPY!vP[!vP_!vPl!vPv!vP!Z!vP!_!vP!b!vP!g!vP!p!vP!x!vP#S!vP#X!vP#`!vP]!vP!`!vP!d!vP!e!vP~Ov#jOS#tXU#tXW#tXY#tX[#tX_#tXl#tX!Z#tX!_#tX!b#tX!g#tX!p#tX!x#tX#S#tX#X#tX#`#tX]#tX!`#tX!d#tX!e#tX~O#`#mOS!saU!saW!saY!sa[!sa_!sal!sa!Z!sa!_!sa!b!sa!g!sa!p!sa!x!sa#S!sa#X!sa]!sa!`!sa!d!sa!e!sa~OS#nO#S!wa]!wa!`!wa!d!wa!e!wa~P+aOj#oO~P+aOu#YXx#YXy#YXz#YX!P#YX#a#YX#d#YX#e#YX#f#YX#g#YX#h#YX#i#YX#j#YX#k#YX#l#YX#m#YX#n#YX#o#YX~P!bO#`#pOg#]Xi#]Xl#]Xo#]Xq#]Xu#]Xx#]Xy#]Xz#]X!P#]X#Z#]X#a#]X#d#]X#e#]X#f#]X#g#]X#h#]X#i#]X#j#]X#k#]X#l#]X#m#]X#n#]X#o#]X~Ox%wOy%xOz%pO!P%tO#d!rO#e!sO#f!tO#g!uO#h!uO#i!vO#j!vO#k!wO#l!wO#m!wO#n!wO#o!xO~OutX#atX~P6SOu#tO#a#rO~Ov#vOm#cXS#cXU#cXW#cXY#cX[#cX_#cXl#cX!Z#cX!_#cX!b#cX!g#cX!p#cX!x#cX#S#cX#X#cX]#cX!`#cX!d#cX!e#cX~P+aOm#xO~OlnOqmO#ZjO~O#o!xOx!Tay!Taz!Ta!P!Ta#d!Ta#e!Ta#f!Ta#g!Ta#h!Ta#i!Ta#j!Ta#k!Ta#l!Ta#m!Ta#n!Ta~Om!Ta[!Ta!c!TaS!Ta#S!Taj!Tav!TaU!TaW!TaY!Ta_!Tal!Ta!Z!Ta!_!Ta!b!Ta!g!Ta!p!Ta!x!Ta#X!Ta]!Ta!`!Ta!d!Ta!e!Ta~P9aOc$UOlTO#XPOm!]P~Ov#Qa#`#Qa~P#wO]RP!dRP!eRP~P]Ov#`O!k#ra~Og#dOo$cOl!na~Ov#jOS#taU#taW#taY#ta[#ta_#tal#ta!Z#ta!_#ta!b#ta!g#ta!p#ta!x#ta#S#ta#X#ta#`#ta]#ta!`#ta!d#ta!e#ta~O`xOaxObxOcxOdxOlTOqmO!U%oO!ZyO#XPO#ZjO#fuO#itO#jtO#pvO~Oj$kO~P+aOu$vO~P'cOu$vO#a$wO~Ou!Ta#a!Ta~P9aOv#vOm#caS#caU#caW#caY#ca[#ca_#cal#ca!Z#ca!_#ca!b#ca!g#ca!p#ca!x#ca#S#ca#X#ca]#ca!`#ca!d#ca!e#ca~O!P!}O#e!sO#f!tO#g!uO#h!uO#i!vO#j!vO#k!wO#l!wO#m!wO#n!wO#o!xOmwixwiywizwi[wi!cwiSwi#SwijwivwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~O#d!rO~PAuO#dwi~PAuO!P!}O#g!uO#h!uO#i!vO#j!vO#k!wO#l!wO#m!wO#n!wO#o!xOmwixwiywizwi#dwi#fwi[wi!cwiSwi#SwijwivwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~O#ewi~PDmO#e!sO~PDmO#k!wO#l!wO#m!wO#n!wO#o!xOmwixwiywizwi#dwi#ewi#fwi#gwi#hwi[wi!cwiSwi#SwijwivwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~O!P!}O#i!vO#j!vO~PGeO!Pwi#iwi#jwi~PGeO#o!xOmwixwiywi[wi!cwiSwi#SwijwivwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~Ozwi!Pwi#dwi#ewi#fwi#gwi#hwi#iwi#jwi#kwi#lwi#mwi#nwi~PJcOz!yO!P!}O#d!rO#e!sO#f!tO#g!uO#h!uO#i!vO#j!vO#k!wO#l!wO#m!wO#n!wO#o!xOmwixwi[wi!cwiSwi#SwijwivwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~Oy#RO~PMSOywi~PMSOv${Om#qX~P#wOv${Om#qX~Om$}O~O]%OO~OS!^qU!^qW!^qY!^q[!^q_!^ql!^q!Z!^q!_!^q!b!^q!g!^q!p!^q!x!^q#S!^q#X!^q]!^q!`!^q!d!^q!e!^q~P+aO]%RO!d%QO!e%SO~Ov%TO~P+aO]%UO~O#v%WO~Ousi#asi~P6SO#`%XO~O!P%tO#e!sO#f!tO#g!uO#h!uO#i!vO#j!vO#k!wO#l!wO#m!wO#n!wO#o!xOuwixwiywizwi#awi~O#d!rO~P!$tO#dwi~P!$tO!P%tO#g!uO#h!uO#i!vO#j!vO#k!wO#l!wO#m!wO#n!wO#o!xOuwixwiywizwi#awi#dwi#fwi~O#ewi~P!&ZO#e!sO~P!&ZO#k!wO#l!wO#m!wO#n!wO#o!xOuwixwiywizwi#awi#dwi#ewi#fwi#gwi#hwi~O!P%tO#i!vO#j!vO~P!'pO!Pwi#iwi#jwi~P!'pO#o!xOuwixwiywi#awi~Ozwi!Pwi#dwi#ewi#fwi#gwi#hwi#iwi#jwi#kwi#lwi#mwi#nwi~P!)]Oz%pO!P%tO#d!rO#e!sO#f!tO#g!uO#h!uO#i!vO#j!vO#k!wO#l!wO#m!wO#n!wO#o!xOuwixwi#awi~Oy%xO~P!*kOywi~P!*kOu%YO~P'cOm!{av!{aS!{aU!{aW!{aY!{a[!{a_!{al!{a!Z!{a!_!{a!b!{a!g!{a!p!{a!x!{a#S!{a#X!{a]!{a!`!{a!d!{a!e!{a~P+aOc%]OlTO#XPO~Ov${Om#qa~O]%aO!d%QO!e%bO~Om!|av!|a~P#wO]%gO~O!c%iO~P+aO]%jO~Ov%kO[!hy~P+aOury#ary~P6SO]%lO~O[!h!Z~P+aOP#j~", - goto: ";f#uPPP#vP$fP$sP$fP$fPP$fPPPPPP&{(PP(PPP)]PP*iP&{P+w+w+wPP'RPPP+},i-X-uP.g/Z0P'RP0y0y0y'RP1y2S$fPP$fPPPP$fP2V2V2YP2]$f2f$fP$f2i$f2v2y3P3SP3c3r3x4O4V4]4c4i4oPPPP4uP5SP7j8z:`:hPP:p:vPPPPPPPPPPPPP;O;R;U;cQ_OQ!QaQ!ScQ$X#[Q$Z#^Q$`#cQ%_$}Q%d%SQ%h%bR%m%igZO]ac#[#^#c$}%S%b%i#[SOT]abcdhlnwz|!h!y!z!{!|!}#O#P#Q#R#T#[#]#^#_#b#c#m#p#v${$}%Q%S%T%X%b%i%k%o%p%q%r%s%t%u%v%w%xQiQQ!P`Q!UeQ!YfS![g#jQ!dkW!gm#r$w%ZQ!pqQ#l!_Q$]#`Q$a#dQ$d#fQ$e#hR%V$cWoRr!f!p!wxTbdhlmnw|!h!y!z!{!|!}#O#P#Q#R#]#_#b#m#p#r#v$w%Q%T%X%Z%k%o%p%q%r%s%t%u%v%w%x#eSOT]abcdhlmnwz|!h!y!z!{!|!}#O#P#Q#R#T#[#]#^#_#b#c#m#p#r#v$w${$}%Q%S%T%X%Z%b%i%k%o%p%q%r%s%t%u%v%w%x#eVOT]abcdhlmnwz|!h!y!z!{!|!}#O#P#Q#R#T#[#]#^#_#b#c#m#p#r#v$w${$}%Q%S%T%X%Z%b%i%k%o%p%q%r%s%t%u%v%w%x!|VTbdhlmnwz|!h!y!z!{!|!}#O#P#Q#R#T#]#_#b#m#p#r#v$w${%Q%T%X%Z%k%o%p%q%r%s%t%u%v%w%xgWO]ac#[#^#c$}%S%b%iX!jm#r$w%Zp!zs!R!T!a!e!m#q#z$R$S$Y$[$y%c%e%n]%q!i$j$l$s$t%ft!{s!R!T!a!e!m#q#z#{#}$R$S$Y$[$y%c%e%na%r!i$j$l$m$o$s$t%fr!|s!R!T!a!e!m#q#z#{$R$S$Y$[$y%c%e%n_%s!i$j$l$m$s$t%fv!}s!R!T!a!e!m#q#z#{#|#}$R$S$Y$[$y%c%e%nc%t!i$j$l$m$n$o$s$t%fx#Os!R!T!a!e!m#q#z#{#|#}$O$R$S$Y$[$y%c%e%ne%u!i$j$l$m$n$o$p$s$t%fz#Ps!R!T!a!e!m#q#z#{#|#}$O$P$R$S$Y$[$y%c%e%ng%v!i$j$l$m$n$o$p$q$s$t%f!O#Ps!R!T!a!e!m#S#q#z#{#|#}$O$P$Q$R$S$Y$[$y%c%e%nk%v!i#u$j$l$m$n$o$p$q$r$s$t%f!UwTbdhlnw|!h!y!z!{!|!}#O#P#Q#R#]#_#b#m#v%Q%T%kq%om#p#r$w%X%Z%o%p%q%r%s%t%u%v%w%xQ#UyQ#g!ZR$h#lR$W#TR!XeR!WeQ#Y|Q$_#bR$i#mR!ZfgYO]ac#[#^#c$}%S%b%iR!`gQ!]gR$f#jR#i![d^Oac#[#^#c$}%S%b%iR!O]d]Oac#[#^#c$}%S%b%iR}]Q#s!lR$x#sQ#w!mR$z#wS$|$T$UR%^$|Q%P$ZR%`%PQ#a!UR$^#aQ#e!YR$b#eQ{UR#W{Q#k!]R$g#kg[O]ac#[#^#c$}%S%b%iQsTQ!RbQ!TdQ!ahQ!elW!im#r$w%ZW!mn|#b#mQ#SwQ#q!hQ#u%oQ#z!yQ#{!zQ#|!{Q#}!|Q$O!}Q$P#OQ$Q#PQ$R#QQ$S#RQ$Y#]Q$[#_Q$j#pQ$l%pQ$m%qQ$n%rQ$o%sQ$p%tQ$q%uQ$r%vQ$s%wQ$t%xQ$y#vQ%c%QQ%e%TQ%f%XR%n%klRO]acz#T#[#^#c${$}%S%b%i!UrTbdhlnw|!h!y!z!{!|!}#O#P#Q#R#]#_#b#m#v%Q%T%kq!fm#p#r$w%X%Z%o%p%q%r%s%t%u%v%w%xfUO]ac#[#^#c$}%S%b%i!vVTbdhlmnw|!h!y!z!{!|!}#O#P#Q#R#]#_#b#m#p#r#v$w%Q%T%X%Z%k%o%p%q%r%s%t%u%v%w%xQ#VzQ$T#TR%[${UpRr!fR#y!pQ!lmV$u#r$w%ZXoRr!f!pQ!onV#X|#b#mR$V#TR!VegXO]ac#[#^#c$}%S%b%iR!^g", + states: ">`O!ZQPOOOOQO'#Cc'#CcO!UQPO'#CaO!bQPOOOOQO'#Ei'#EiO!vQQO'#CwO$]QPO'#EhOOQO'#Eh'#EhO$gQPO'#EhOOQO'#EO'#EOO%vQPO'#D}OOQO'#Ed'#EdOOQO'#EV'#EVO%{QPO'#C_OOQO'#C_'#C_QOQPOOO!UQPO'#CeO&`QPO'#CgO!vQQO'#CjO&gQPO'#DjO!vQQO'#DmO!UQPO'#DrO!UQPO'#DyO&nQPO'#EPO&vQQO'#ETO'^QPO,58{OOQO'#Cq'#CqO!UQPO,59^O!vQQO,59`O(gQQO'#C|O(nQQO'#EnOOQO'#Ej'#EjOOQO,59f,59fO!UQPO,59fO(uQPO'#EfO,eQPO,59cOOQO'#Dc'#DcOOQO'#Dd'#DdOOQO'#De'#DeO!vQQO'#DaOOQO'#Ef'#EfO,lQPO'#DfO,qQPO'#E^O,yQPO,5;kO!vQQO,5:iOOQO-E8T-E8TOOQO,58y,58yOOQO,59P,59PO-RQPO,59RO-WQPO,59UO-_QPO,5:UO-dQPO,5:XO-kQPO'#FOOOQO'#Dv'#DvO-vQPO'#DuO-{QPO,5:^O.QQPO'#DzO,lQPO,5:eO.]QQO'#ERO/sQPO'#FQOOQO'#EQ'#EQO!UQPO,5:gO1WQPO,5:kO2hQPO'#EoOOQO'#Dx'#DxOOQO,5:o,5:oO3}QPO,5:oOOQO1G.g1G.gOOQO1G.x1G.xO4cQPO1G.zO4jQSO'#EfO5vQSO'#EiO!vQQO'#DOO8kQSO'#DQOOQO'#Ek'#EkOOQO,59h,59hO8uQSO,59hOOQO,5;Y,5;YO8}QPO,5;YO9SQPO1G/QOOQO1G.}1G.}OOQO'#DX'#DXOOQO'#DY'#DYOOQO'#DZ'#DZOOQO'#D['#D[OOQO'#D^'#D^OOQO'#D_'#D_OOQO'#D`'#D`O!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO!vQQO,59oO:cQPO,59{OmQPO,5;ZOOQO1G0Z1G0ZOOQO7+$f7+$fO@QQQO,59kOARQPO,59jOAYQQO1G/SOAaQSO1G/SOOQO1G/S1G/SOAiQSO,59{OOQO1G0t1G0tOOQO7+$l7+$lOD]QPO1G/ZODdQPO1G/ZOGTQPO1G/ZOG[QPO1G/ZOIuQPO1G/ZOJSQPO1G/ZOLTQPO1G/ZO! jQPO1G/ZO! qQPO1G/ZO! xQPO'#EhO!!SQPO'#E}OOQO'#Di'#DiO!![QPO,5:SO!!aQPO7+$[O!!fQPO7+%[O!#uQPO7+%_O!$QQPO1G/zOOQO,5:v,5:vOOQO-E8Y-E8YOOQO1G/{1G/{O!$XQPO7+%dOOQO,5:w,5:wOOQO-E8Z-E8ZO!UQPO1G0QOOQO1G0Q1G0QO!$^QQO,5:nOOQO,5:y,5:yOOQO-E8]-E8]OOQO7+%m7+%mOOQO7+%q7+%qO!$cQPO,5:sOOQO-E8V-E8VO!%xQSO1G/VO!&SQPO1G/UO!'`QSO1G/ZO!'gQSO1G/ZO!(uQSO1G/ZO!(|QSO1G/ZO!*UQSO1G/ZO!*cQSO1G/ZO!+RQSO1G/ZO!-VQSO1G/ZO!-^QSO1G/ZOOQO,5:r,5:rOOQO7+$n7+$nO!-eQQO7+$nOOQO-E8U-E8UO!-lQQO'#EYO!-wQPO,5;iO&`QPO1G/nOOQO<eAN>eO&`QPOAN>eO!.kQPO,5:uO!.rQPOAN>eO!.wQPO<lOOQOLD)kLD)kOOQO7+%{7+%{O!/bQPOG24WO@QQQO'#DaO@QQQO,59oO@QQQO,59oO@QQQO,59oO@QQQO,59oO@QQQO,59oO@QQQO,59oO@QQQO,59oO@QQQO,59oO@QQQO,59o", + stateData: "!/l~O#UOS#VOSPOS~OSZOUQOWZOY`O[aO_bOlTO!ZfO!_cO!bdO!geO!pgO!xhO#XPO~O#SRP~P]OgkOilOlnOoqOqmO#ZjO~O`xOaxObxOcxOdxOlTOqmO!UwO!ZyO#XPO#ZjO#fuO#itO#jtO#pvO~Og#[Xi#[Xl#[Xo#[Xq#[X#Z#[X~OvzO#`#sX~P#wOS#WXU#WXW#WXY#WX[#WX_#WXl#WX!Z#WX!_#WX!b#WX!g#WX!p#WX!x#WX#S#WX#X#WX]#WX!`#WX!d#WX!e#WX~P#wO#`|O~O#SRX]RX!`RX!dRX!eRX~P]O]RP~P]O!`RP~P]O!Z!_O#XPO~OS!cO#S!wX]!wX!`!wX!d!wX!e!wX~P!vOU!eO~O`xOaxObxOcxOdxOi!jOlTOqmO!U%oO!ZyO#XPO#ZjO#fuO#itO#jtO#pvO~Ou!mO~P'cOm!oO~P!vOm#YXx#YXy#YXz#YX!P#YX#d#YX#e#YX#f#YX#g#YX#h#YX#i#YX#j#YX#k#YX#l#YX#m#YX#n#YX#o#YX[#YX!c#YXS#YXv#YX#S#YXj#YXU#YXW#YXY#YX_#YX!Z#YX!_#YX!b#YX!g#YX!p#YX!x#YX#X#YX]#YX!`#YX!d#YX!e#YX~P!bOx#ROy#SOz!zO!P#OO#d!sO#e!tO#f!uO#g!vO#h!vO#i!wO#j!wO#k!xO#l!xO#m!xO#n!xO#o!yO~Om!rO~P+aOl#UO~OlTO#XPO~OvzO#`#sa~O]#ZO~O[#[O~P+aO!`#]O~O!c#^O~P+aOv#`O#`#_O!k#rX~O!k#bO~O[#cO~Og#dOo#fOl!nX~O#u#hOS!vPU!vPW!vPY!vP[!vP_!vPl!vPv!vP!Z!vP!_!vP!b!vP!g!vP!p!vP!x!vP#S!vP#X!vP#`!vP]!vP!`!vP!d!vP!e!vP~Ov#jOS#tXU#tXW#tXY#tX[#tX_#tXl#tX!Z#tX!_#tX!b#tX!g#tX!p#tX!x#tX#S#tX#X#tX#`#tX]#tX!`#tX!d#tX!e#tX~O#`#mOS!saU!saW!saY!sa[!sa_!sal!sa!Z!sa!_!sa!b!sa!g!sa!p!sa!x!sa#S!sa#X!sa]!sa!`!sa!d!sa!e!sa~Ov#nOS#cX#S#cXm#cXU#cXW#cXY#cX[#cX_#cXl#cX!Z#cX!_#cX!b#cX!g#cX!p#cX!x#cX#X#cX]#cX!`#cX!d#cX!e#cX~P+aOS#pO#S!wa]!wa!`!wa!d!wa!e!wa~Oj#qO~P+aOu#YXx#YXy#YXz#YX!P#YX#a#YX#d#YX#e#YX#f#YX#g#YX#h#YX#i#YX#j#YX#k#YX#l#YX#m#YX#n#YX#o#YX~P!bO#`#rOg#]Xi#]Xl#]Xo#]Xq#]Xu#]Xx#]Xy#]Xz#]X!P#]X#Z#]X#a#]X#d#]X#e#]X#f#]X#g#]X#h#]X#i#]X#j#]X#k#]X#l#]X#m#]X#n#]X#o#]X~Ox%wOy%xOz%pO!P%tO#d!sO#e!tO#f!uO#g!vO#h!vO#i!wO#j!wO#k!xO#l!xO#m!xO#n!xO#o!yO~OutX#atX~P7gOu#vO#a#tO~Om#xO~OlnOqmO#ZjO~O#o!yOx!Tay!Taz!Ta!P!Ta#d!Ta#e!Ta#f!Ta#g!Ta#h!Ta#i!Ta#j!Ta#k!Ta#l!Ta#m!Ta#n!Ta~Om!Ta[!Ta!c!TaS!Tav!Ta#S!Taj!TaU!TaW!TaY!Ta_!Tal!Ta!Z!Ta!_!Ta!b!Ta!g!Ta!p!Ta!x!Ta#X!Ta]!Ta!`!Ta!d!Ta!e!Ta~P9_Oc$UOlTO#XPOm!]P~Ov#Qa#`#Qa~P#wO]RP!dRP!eRP~P]Ov#`O!k#ra~Og#dOo$cOl!na~Ov#jOS#taU#taW#taY#ta[#ta_#tal#ta!Z#ta!_#ta!b#ta!g#ta!p#ta!x#ta#S#ta#X#ta#`#ta]#ta!`#ta!d#ta!e#ta~Ov#nOS#ca#S#cam#caU#caW#caY#ca[#ca_#cal#ca!Z#ca!_#ca!b#ca!g#ca!p#ca!x#ca#X#ca]#ca!`#ca!d#ca!e#ca~O`xOaxObxOcxOdxOlTOqmO!U%oO!ZyO#XPO#ZjO#fuO#itO#jtO#pvO~Oj$mO~P+aOu$xO~P'cOu$xO#a$yO~Ou!Ta#a!Ta~P9_O!P#OO#e!tO#f!uO#g!vO#h!vO#i!wO#j!wO#k!xO#l!xO#m!xO#n!xO#o!yOmwixwiywizwi[wi!cwiSwivwi#SwijwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~O#d!sO~PAsO#dwi~PAsO!P#OO#g!vO#h!vO#i!wO#j!wO#k!xO#l!xO#m!xO#n!xO#o!yOmwixwiywizwi#dwi#fwi[wi!cwiSwivwi#SwijwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~O#ewi~PDkO#e!tO~PDkO#k!xO#l!xO#m!xO#n!xO#o!yOmwixwiywizwi#dwi#ewi#fwi#gwi#hwi[wi!cwiSwivwi#SwijwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~O!P#OO#i!wO#j!wO~PGcO!Pwi#iwi#jwi~PGcO#o!yOmwixwiywi[wi!cwiSwivwi#SwijwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~Ozwi!Pwi#dwi#ewi#fwi#gwi#hwi#iwi#jwi#kwi#lwi#mwi#nwi~PJaOz!zO!P#OO#d!sO#e!tO#f!uO#g!vO#h!vO#i!wO#j!wO#k!xO#l!xO#m!xO#n!xO#o!yOmwixwi[wi!cwiSwivwi#SwijwiUwiWwiYwi_wilwi!Zwi!_wi!bwi!gwi!pwi!xwi#Xwi]wi!`wi!dwi!ewi~Oy#SO~PMQOywi~PMQOv${Om#qX~P#wOv${Om#qX~Om$}O~O]%OO~OS!^qU!^qW!^qY!^q[!^q_!^ql!^q!Z!^q!_!^q!b!^q!g!^q!p!^q!x!^q#S!^q#X!^q]!^q!`!^q!d!^q!e!^q~P+aO]%RO!d%QO!e%SO~Ov%TO~P+aO]%UO~O#v%WO~OS!{av!{a#S!{am!{aU!{aW!{aY!{a[!{a_!{al!{a!Z!{a!_!{a!b!{a!g!{a!p!{a!x!{a#X!{a]!{a!`!{a!d!{a!e!{a~P+aOusi#asi~P7gO#`%XO~O!P%tO#e!tO#f!uO#g!vO#h!vO#i!wO#j!wO#k!xO#l!xO#m!xO#n!xO#o!yOuwixwiywizwi#awi~O#d!sO~P!&XO#dwi~P!&XO!P%tO#g!vO#h!vO#i!wO#j!wO#k!xO#l!xO#m!xO#n!xO#o!yOuwixwiywizwi#awi#dwi#fwi~O#ewi~P!'nO#e!tO~P!'nO#k!xO#l!xO#m!xO#n!xO#o!yOuwixwiywizwi#awi#dwi#ewi#fwi#gwi#hwi~O!P%tO#i!wO#j!wO~P!)TO!Pwi#iwi#jwi~P!)TO#o!yOuwixwiywi#awi~Ozwi!Pwi#dwi#ewi#fwi#gwi#hwi#iwi#jwi#kwi#lwi#mwi#nwi~P!*pOz%pO!P%tO#d!sO#e!tO#f!uO#g!vO#h!vO#i!wO#j!wO#k!xO#l!xO#m!xO#n!xO#o!yOuwixwi#awi~Oy%xO~P!,OOywi~P!,OOu%YO~P'cOc%]OlTO#XPO~Ov${Om#qa~O]%aO!d%QO!e%bO~Om!|av!|a~P#wO]%gO~O!c%iO~P+aO]%jO~Ov%kO[!hy~P+aOury#ary~P7gO]%lO~O[!h!Z~P+aOP#j~", + goto: ";a#uPPP#vP$fP$sP$fP$fPP$fPPPPPP&{(PP(PPP)]PP*iP&{P+w+w+wPP'RPPP+},h-V-rP.c/U/y'RP0r0r0r'RP1r1{$fPP$fPPPP$fP2O2O2RP2U$f2b$fP$f2e$f2r2u2{3OP3_3n3t3z4R4X4_4e4kPPPP4qP5OP7d8t:Y:bPP:j:pPPPPPPPPPPPPP:y:|;P;^Q_OQ!QaQ!ScQ$X#[Q$Z#^Q$`#cQ%_$}Q%d%SQ%h%bR%m%igZO]ac#[#^#c$}%S%b%i#[SOT]abcdhlnwz|!j!z!{!|!}#O#P#Q#R#S#U#[#]#^#_#b#c#m#n#r${$}%Q%S%T%X%b%i%k%o%p%q%r%s%t%u%v%w%xQiQQ!P`Q!UeQ!YfS![g#jQ!fkW!im#t$y%ZQ!qqQ#l!_Q$]#`Q$a#dQ$d#fQ$e#hR%V$cWoRr!h!q!wxTbdhlmnw|!j!z!{!|!}#O#P#Q#R#S#]#_#b#m#n#r#t$y%Q%T%X%Z%k%o%p%q%r%s%t%u%v%w%x#eSOT]abcdhlmnwz|!j!z!{!|!}#O#P#Q#R#S#U#[#]#^#_#b#c#m#n#r#t$y${$}%Q%S%T%X%Z%b%i%k%o%p%q%r%s%t%u%v%w%x#eVOT]abcdhlmnwz|!j!z!{!|!}#O#P#Q#R#S#U#[#]#^#_#b#c#m#n#r#t$y${$}%Q%S%T%X%Z%b%i%k%o%p%q%r%s%t%u%v%w%x!|VTbdhlmnwz|!j!z!{!|!}#O#P#Q#R#S#U#]#_#b#m#n#r#t$y${%Q%T%X%Z%k%o%p%q%r%s%t%u%v%w%xgWO]ac#[#^#c$}%S%b%iX!lm#t$y%Zn!{s!R!T!a!g#s#z$R$S$Y$[$j%c%e%n]%q!k$l$n$u$v%fr!|s!R!T!a!g#s#z#{#}$R$S$Y$[$j%c%e%na%r!k$l$n$o$q$u$v%fp!}s!R!T!a!g#s#z#{$R$S$Y$[$j%c%e%n_%s!k$l$n$o$u$v%ft#Os!R!T!a!g#s#z#{#|#}$R$S$Y$[$j%c%e%nc%t!k$l$n$o$p$q$u$v%fv#Ps!R!T!a!g#s#z#{#|#}$O$R$S$Y$[$j%c%e%ne%u!k$l$n$o$p$q$r$u$v%fx#Qs!R!T!a!g#s#z#{#|#}$O$P$R$S$Y$[$j%c%e%ng%v!k$l$n$o$p$q$r$s$u$v%f|#Qs!R!T!a!g#T#s#z#{#|#}$O$P$Q$R$S$Y$[$j%c%e%nk%v!k#w$l$n$o$p$q$r$s$t$u$v%f!UwTbdhlnw|!j!z!{!|!}#O#P#Q#R#S#]#_#b#m#n%Q%T%kq%om#r#t$y%X%Z%o%p%q%r%s%t%u%v%w%xQ#VyQ#g!ZR$h#lR$W#UR!XeR!WeQ!dhQ#Y|Q$_#bR$i#mR!ZfgYO]ac#[#^#c$}%S%b%iR!`gQ!]gR$f#jR#i![d^Oac#[#^#c$}%S%b%iR!O]d]Oac#[#^#c$}%S%b%iR}]Q#u!nR$z#uQ#o!aR$k#oS$|$T$UR%^$|Q%P$ZR%`%PQ#a!UR$^#aQ#e!YR$b#eQ{UR#X{Q#k!]R$g#kg[O]ac#[#^#c$}%S%b%iQsTQ!RbQ!TdY!ahn|#b#mQ!glW!km#t$y%ZQ#TwQ#s!jQ#w%oQ#z!zQ#{!{Q#|!|Q#}!}Q$O#OQ$P#PQ$Q#QQ$R#RQ$S#SQ$Y#]Q$[#_Q$j#nQ$l#rQ$n%pQ$o%qQ$p%rQ$q%sQ$r%tQ$s%uQ$t%vQ$u%wQ$v%xQ%c%QQ%e%TQ%f%XR%n%klRO]acz#U#[#^#c${$}%S%b%i!UrTbdhlnw|!j!z!{!|!}#O#P#Q#R#S#]#_#b#m#n%Q%T%kq!hm#r#t$y%X%Z%o%p%q%r%s%t%u%v%w%xfUO]ac#[#^#c$}%S%b%i!vVTbdhlmnw|!j!z!{!|!}#O#P#Q#R#S#]#_#b#m#n#r#t$y%Q%T%X%Z%k%o%p%q%r%s%t%u%v%w%xQ#WzQ$T#UR%[${UpRr!hR#y!qQ!nmV$w#t$y%ZXoRr!h!qW!bh|#b#mR!pnR$V#UR!VegXO]ac#[#^#c$}%S%b%iR!^g", nodeNames: "⚠ Comment Chunk Block ; Label :: Name break Goto goto Scope do end WhileStatement while nil true false Ellipsis Number LiteralString Property . MemberExpression [ ] Parens ( ) FunctionCall : TableConstructor { FieldDynamic FieldProp FieldExp } , BinaryExpression or and CompareOp BitOp BitOp BitOp BitOp Concat ArithOp ArithOp ArithOp UnaryExpression not ArithOp BitOp LenOp FunctionDef function FuncBody ArgList RepeatStatement repeat until IfStatement if then elseif else ForStatement for ForNumeric ForGeneric NameList in ExpList Function FuncName LocalFunction local Assign VarList Local AttNameList AttName Attrib ReturnStatement return", maxTerm: 130, nodeProps: [ @@ -13,10 +13,10 @@ export const parser = LRParser.deserialize({ ], skippedNodes: [0,1], repeatNodeCount: 9, - tokenData: "7O~RsXY#`YZ#z[]#`]^$Xpq#`rs$ast)duv)ivw)nwx)sxy.qyz.vz{.{{|/Q|}/V}!O/^!O!P0Q!P!Q0g!Q!R0|!R![2b![!]4f!]!^4s!^!_4z!_!`5^!`!a5f!c!}5x!}#O6W#O#P#q#P#Q6]#Q#R6b#T#o5x#o#p6g#p#q6l#q#r6q#r#s6v~#eS#V~XY#`[]#`pq#`#O#P#q~#tQYZ#`]^#`~$PP#U~]^$S~$XO#U~~$^P#U~YZ$S~$dWOY$|Z]$|^r$|s#O$|#O#P%q#P;'S$|;'S;=`(R<%lO$|~%PXOY$|Z]$|^r$|rs%ls#O$|#O#P%q#P;'S$|;'S;=`(R<%lO$|~%qO#Z~~%tZrs$|wx$|!Q![&g#O#P$|#T#U$|#U#V$|#Y#Z$|#b#c$|#i#j(X#l#m(z#n#o$|~&jZOY$|Z]$|^r$|rs%ls!Q$|!Q![']![#O$|#O#P%q#P;'S$|;'S;=`(R<%lO$|~'`ZOY$|Z]$|^r$|rs%ls!Q$|!Q![$|![#O$|#O#P%q#P;'S$|;'S;=`(R<%lO$|~(UP;=`<%l$|~([P#o#p(_~(bR!Q![(k!c!i(k#T#Z(k~(nS!Q![(k!c!i(k#T#Z(k#q#r$|~(}R!Q![)W!c!i)W#T#Z)W~)ZR!Q![$|!c!i$|#T#Z$|~)iO#p~~)nO#m~~)sO#e~~)vWOY*`Z]*`^w*`x#O*`#O#P+O#P;'S*`;'S;=`-`<%lO*`~*cXOY*`Z]*`^w*`wx%lx#O*`#O#P+O#P;'S*`;'S;=`-`<%lO*`~+RZrs*`wx*`!Q![+t#O#P*`#T#U*`#U#V*`#Y#Z*`#b#c*`#i#j-f#l#m.X#n#o*`~+wZOY*`Z]*`^w*`wx%lx!Q*`!Q![,j![#O*`#O#P+O#P;'S*`;'S;=`-`<%lO*`~,mZOY*`Z]*`^w*`wx%lx!Q*`!Q![*`![#O*`#O#P+O#P;'S*`;'S;=`-`<%lO*`~-cP;=`<%l*`~-iP#o#p-l~-oR!Q![-x!c!i-x#T#Z-x~-{S!Q![-x!c!i-x#T#Z-x#q#r*`~.[R!Q![.e!c!i.e#T#Z.e~.hR!Q![*`!c!i*`#T#Z*`~.vOl~~.{Om~~/QO#k~~/VO#i~V/^OvR#aS~/cP#j~}!O/f~/kTP~OY/fZ]/f^;'S/f;'S;=`/z<%lO/f~/}P;=`<%l/fV0VPgT!O!P0YV0_P!PT!O!P0bQ0gOcQ~0lQ#l~!P!Q0r!_!`0w~0wO#n~T0|OzT~1RUd~!O!P1e!Q![2b!g!h1y!z!{2s#X#Y1y#l#m2s~1hP!Q![1k~1pRd~!Q![1k!g!h1y#X#Y1y~1|Q{|2S}!O2S~2VP!Q![2Y~2_Pd~!Q![2Y~2gSd~!O!P1e!Q![2b!g!h1y#X#Y1y~2vR!Q![3P!c!i3P#T#Z3P~3UUd~!O!P3h!Q![3P!c!i3P!r!s4Y#T#Z3P#d#e4Y~3kR!Q![3t!c!i3t#T#Z3t~3yTd~!Q![3t!c!i3t!r!s4Y#T#Z3t#d#e4Y~4]R{|2S}!O2S!P!Q2S~4kPo~![!]4n~4sOU~V4zOSR#aSV5RQ#uQzT!^!_5X!_!`0wT5^O#gT~5cP#`~!_!`0wV5mQ#vQzT!_!`0w!`!a5sT5xO#hT~5}R#X~!Q![5x!c!}5x#T#o5x~6]Oi~~6bOj~~6gO#o~~6lOq~~6qO#d~~6vOu~~6{P#f~!_!`0w", + tokenData: "7X~RtXY#cYZ#}[]#c]^$[pq#cqr$drs$ost)ruv)wvw)|wx*Rxy/Pyz/Uz{/Z{|/`|}/e}!O/l!O!P0`!P!Q0u!Q!R1V!R![2k![!]4o!]!^4|!^!_5T!_!`5g!`!a5o!c!}6R!}#O6a#O#P#t#P#Q6f#Q#R6k#T#o6R#o#p6p#p#q6u#q#r6z#r#s7P~#hS#V~XY#c[]#cpq#c#O#P#t~#wQYZ#c]^#c~$SP#U~]^$V~$[O#U~~$aP#U~YZ$VT$gP!_!`$jT$oOzT~$rWOY%[Z]%[^r%[s#O%[#O#P&P#P;'S%[;'S;=`(a<%lO%[~%_XOY%[Z]%[^r%[rs%zs#O%[#O#P&P#P;'S%[;'S;=`(a<%lO%[~&PO#Z~~&SZrs%[wx%[!Q![&u#O#P%[#T#U%[#U#V%[#Y#Z%[#b#c%[#i#j(g#l#m)Y#n#o%[~&xZOY%[Z]%[^r%[rs%zs!Q%[!Q!['k![#O%[#O#P&P#P;'S%[;'S;=`(a<%lO%[~'nZOY%[Z]%[^r%[rs%zs!Q%[!Q![%[![#O%[#O#P&P#P;'S%[;'S;=`(a<%lO%[~(dP;=`<%l%[~(jP#o#p(m~(pR!Q![(y!c!i(y#T#Z(y~(|S!Q![(y!c!i(y#T#Z(y#q#r%[~)]R!Q![)f!c!i)f#T#Z)f~)iR!Q![%[!c!i%[#T#Z%[~)wO#p~~)|O#m~~*RO#e~~*UWOY*nZ]*n^w*nx#O*n#O#P+^#P;'S*n;'S;=`-n<%lO*n~*qXOY*nZ]*n^w*nwx%zx#O*n#O#P+^#P;'S*n;'S;=`-n<%lO*n~+aZrs*nwx*n!Q![,S#O#P*n#T#U*n#U#V*n#Y#Z*n#b#c*n#i#j-t#l#m.g#n#o*n~,VZOY*nZ]*n^w*nwx%zx!Q*n!Q![,x![#O*n#O#P+^#P;'S*n;'S;=`-n<%lO*n~,{ZOY*nZ]*n^w*nwx%zx!Q*n!Q![*n![#O*n#O#P+^#P;'S*n;'S;=`-n<%lO*n~-qP;=`<%l*n~-wP#o#p-z~-}R!Q![.W!c!i.W#T#Z.W~.ZS!Q![.W!c!i.W#T#Z.W#q#r*n~.jR!Q![.s!c!i.s#T#Z.s~.vR!Q![*n!c!i*n#T#Z*n~/UOl~~/ZOm~~/`O#k~~/eO#i~V/lOvR#aS~/qP#j~}!O/t~/yTP~OY/tZ]/t^;'S/t;'S;=`0Y<%lO/t~0]P;=`<%l/tV0ePgT!O!P0hV0mP!PT!O!P0pQ0uOcQ~0zQ#l~!P!Q1Q!_!`$j~1VO#n~~1[Ud~!O!P1n!Q![2k!g!h2S!z!{2|#X#Y2S#l#m2|~1qP!Q![1t~1yRd~!Q![1t!g!h2S#X#Y2S~2VQ{|2]}!O2]~2`P!Q![2c~2hPd~!Q![2c~2pSd~!O!P1n!Q![2k!g!h2S#X#Y2S~3PR!Q![3Y!c!i3Y#T#Z3Y~3_Ud~!O!P3q!Q![3Y!c!i3Y!r!s4c#T#Z3Y#d#e4c~3tR!Q![3}!c!i3}#T#Z3}~4STd~!Q![3}!c!i3}!r!s4c#T#Z3}#d#e4c~4fR{|2]}!O2]!P!Q2]~4tPo~![!]4w~4|OU~V5TOSR#aSV5[Q#uQzT!^!_5b!_!`$jT5gO#gT~5lP#`~!_!`$jV5vQ#vQzT!_!`$j!`!a5|T6RO#hT~6WR#X~!Q![6R!c!}6R#T#o6R~6fOi~~6kOj~~6pO#o~~6uOq~~6zO#d~~7POu~~7UP#f~!_!`$j", tokenizers: [0, 1, 2], topRules: {"Chunk":[0,2]}, dynamicPrecedences: {"110":1}, specialized: [{term: 101, get: (value) => spec_identifier[value] || -1}], - tokenPrec: 2787 + tokenPrec: 2785 }) diff --git a/common/space_lua/parse.test.ts b/common/space_lua/parse.test.ts index e7273f5b..7ab69125 100644 --- a/common/space_lua/parse.test.ts +++ b/common/space_lua/parse.test.ts @@ -81,4 +81,9 @@ Deno.test("Test Lua parser", () => { parse(`a(1, 2, 3)`); parse(`print "Sup"`); parse(`e(1 + print "8")`); + + // Return statements + parse(`return`); + parse(`return 1`); + parse(`return 1, 2, 3`); }); diff --git a/common/space_lua/parse.ts b/common/space_lua/parse.ts index 1b0892d4..5a343c94 100644 --- a/common/space_lua/parse.ts +++ b/common/space_lua/parse.ts @@ -165,6 +165,10 @@ function parseStatement(n: CrudeAST): LuaStatement { names: parseAttNames(t[2]), expressions: t[4] ? parseExpList(t[4]) : [], }; + case "ReturnStatement": { + const expressions = t[2] ? parseExpList(t[2]) : []; + return { type: "Return", expressions }; + } case "break": return { type: "Break" }; default: diff --git a/common/space_lua/runtime.ts b/common/space_lua/runtime.ts index f0e0d1f3..20ead596 100644 --- a/common/space_lua/runtime.ts +++ b/common/space_lua/runtime.ts @@ -1,6 +1,7 @@ import type { LuaFunctionBody } from "./ast.ts"; +import { evalStatement } from "$common/space_lua/eval.ts"; -export class LuaEnv implements ILuaSettable { +export class LuaEnv implements ILuaSettable, ILuaGettable { variables = new Map(); constructor(readonly parent?: LuaEnv) { @@ -18,7 +19,7 @@ export class LuaEnv implements ILuaSettable { } } - get(name: string): LuaValue { + get(name: string): LuaValue | undefined { if (this.variables.has(name)) { return this.variables.get(name); } @@ -61,6 +62,10 @@ export interface ILuaSettable { set(key: LuaValue, value: LuaValue): void; } +export interface ILuaGettable { + get(key: LuaValue): LuaValue | undefined; +} + export class LuaFunction implements ILuaFunction { constructor(private body: LuaFunctionBody, private closure: LuaEnv) { } @@ -76,7 +81,19 @@ export class LuaFunction implements ILuaFunction { } env.set(this.body.parameters[i], arg); } - throw new Error("Not yet implemented funciton call"); + return evalStatement(this.body.block, env).catch((e: any) => { + if (e instanceof LuaReturn) { + if (e.values.length === 0) { + return; + } else if (e.values.length === 1) { + return e.values[0]; + } else { + return new LuaMultiRes(e.values); + } + } else { + throw e; + } + }); } } @@ -94,7 +111,7 @@ export class LuaNativeJSFunction implements ILuaFunction { } } -export class LuaTable implements ILuaSettable { +export class LuaTable implements ILuaSettable, ILuaGettable { // To optimize the table implementation we use a combination of different data structures // When tables are used as maps, the common case is that they are string keys, so we use a simple object for that private stringKeys: Record; @@ -131,7 +148,7 @@ export class LuaTable implements ILuaSettable { } } - get(key: LuaValue): LuaValue { + get(key: LuaValue): LuaValue | undefined { if (typeof key === "string") { return this.stringKeys[key]; } else if (Number.isInteger(key) && key >= 1) { @@ -202,6 +219,12 @@ export function luaLen(obj: any): number { export class LuaBreak extends Error { } +export class LuaReturn extends Error { + constructor(readonly values: LuaValue[]) { + super(); + } +} + export function luaTruthy(value: any): boolean { if (value === undefined || value === null || value === false) { return false;