From 598bf66a2fe6b2fac9c27cf609ee0b6a9fb6df22 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Sat, 8 Nov 2025 00:47:10 -0800 Subject: [PATCH] ref keyword --- src/compiler/compiler.ts | 21 +++++++++++++++++++++ src/compiler/tests/compiler.test.ts | 12 ++++++++++++ src/parser/shrimp.grammar | 6 ++++++ src/parser/shrimp.terms.ts | 7 ++++--- src/parser/shrimp.ts | 18 +++++++++--------- 5 files changed, 52 insertions(+), 12 deletions(-) diff --git a/src/compiler/compiler.ts b/src/compiler/compiler.ts index 408bdc2..b43cdd4 100644 --- a/src/compiler/compiler.ts +++ b/src/compiler/compiler.ts @@ -735,6 +735,27 @@ export class Compiler { return instructions } + case terms.Ref: { + const instructions: ProgramItem[] = [] + let [_ref, child] = getAllChildren(node) + child = child?.firstChild! + + if (child.type.id === terms.Identifier) { + const name = input.slice(child.from, child.to) + instructions.push(['LOAD', name]) + } else if (child.type.id === terms.DotGet) { + instructions.push(...this.#compileNode(child, input)) + } else { + throw new CompilerError( + `Bad ref argument: ${child.type.name}`, + child.from, + child.to + ) + } + + return instructions + } + case terms.Comment: { return [] // ignore comments } diff --git a/src/compiler/tests/compiler.test.ts b/src/compiler/tests/compiler.test.ts index 263eeb7..f2b8d3a 100644 --- a/src/compiler/tests/compiler.test.ts +++ b/src/compiler/tests/compiler.test.ts @@ -316,3 +316,15 @@ describe('default params', () => { ).toEvaluateTo({ name: 'Jon', age: 21 }) }) }) + +describe('ref keyword', () => { + expect(`rnd = do x: true end; rnd | type`).toEvaluateTo('boolean') + expect(`rnd = do x: true end; ref rnd | type`).toEvaluateTo('function') + + expect(`math.random | type`).toEvaluateTo('number') + expect(`ref math.random | type`).toEvaluateTo('native') + + expect(`rnd = math.random; rnd | type`).toEvaluateTo('number') + expect(`rnd = ref math.random; rnd | type`).toEvaluateTo('number') + expect(`rnd = ref math.random; ref rnd | type`).toEvaluateTo('native') +}) \ No newline at end of file diff --git a/src/parser/shrimp.grammar b/src/parser/shrimp.grammar index 97908d9..07f0acf 100644 --- a/src/parser/shrimp.grammar +++ b/src/parser/shrimp.grammar @@ -35,6 +35,7 @@ try { @specialize[@name=keyword] } catch { @specialize[@name=keyword] } finally { @specialize[@name=keyword] } throw { @specialize[@name=keyword] } +ref { @specialize[@name=keyword] } null { @specialize[@name=Null] } @external tokens tokenizer from "./tokenizer" { Identifier, AssignableIdentifier, Word, IdentifierBeforeDot } @@ -63,6 +64,7 @@ consumeToTerminator { ambiguousFunctionCall | TryExpr | Throw | + Ref | IfExpr | FunctionDef | CompoundAssign | @@ -148,6 +150,10 @@ FinallyExpr { finally colon Block } +Ref { + ref FunctionCallOrIdentifier +} + Throw { throw (BinOp | ConditionalOp | expression) } diff --git a/src/parser/shrimp.terms.ts b/src/parser/shrimp.terms.ts index 04cb710..1de6148 100644 --- a/src/parser/shrimp.terms.ts +++ b/src/parser/shrimp.terms.ts @@ -28,7 +28,7 @@ export const Program = 26, PipeExpr = 27, WhileExpr = 29, - keyword = 70, + keyword = 72, ConditionalOp = 31, ParenExpr = 32, IfExpr = 33, @@ -62,5 +62,6 @@ export const FunctionCallWithBlock = 66, TryExpr = 67, Throw = 69, - CompoundAssign = 71, - Assign = 72 + Ref = 71, + CompoundAssign = 73, + Assign = 74 diff --git a/src/parser/shrimp.ts b/src/parser/shrimp.ts index fa41719..bff3299 100644 --- a/src/parser/shrimp.ts +++ b/src/parser/shrimp.ts @@ -4,14 +4,14 @@ import {operatorTokenizer} from "./operatorTokenizer" import {tokenizer, specializeKeyword} from "./tokenizer" import {trackScope} from "./parserScopeContext" import {highlighting} from "./highlight" -const spec_Identifier = {__proto__:null,while:60, if:68, null:96, catch:102, finally:108, end:110, else:118, try:136, throw:140} +const spec_Identifier = {__proto__:null,while:60, if:68, null:96, catch:102, finally:108, end:110, else:118, try:136, throw:140, ref:144} export const parser = LRParser.deserialize({ version: 14, - states: "9UQYQbOOO!dOpO'#DQO!iOSO'#DXO$_QcO'#DkO&rQcO'#EYOOQ`'#Eh'#EhO'uQRO'#DlO)[QcO'#EWO)lQbO'#C|OOQa'#Dn'#DnO+nQbO'#DoOOQa'#EY'#EYO+uQcO'#EYO+|QcO'#EXO,yQcO'#EWO-TQRO'#DuOOQ`'#EW'#EWO-iQbO'#EWO-pQQO'#EVOOQ`'#EV'#EVOOQ`'#Dw'#DwQYQbOOO-{QbO'#DTO.WQbO'#C}O.{QbO'#CyO/pQQO'#DqO.{QbO'#DsO/uObO,59lO0QQbO'#DZO0YQWO'#D[OOOO'#E`'#E`OOOO'#D|'#D|O0nOSO,59sOOQa,59s,59sOOQ`'#DS'#DSO0|QbO'#DgOOQ`'#E^'#E^OOQ`'#Dy'#DyO1WQbO,59kOOQa'#EX'#EXO.{QbO,5:WO.{QbO,5:WO.{QbO,5:WO.{QbO,59gO.{QbO,59gO.{QbO,59gO2QQRO,59hO2^QQO,59hO2fQQO,59hO2qQRO,59hO3[QRO,59hO3jQQO'#CwOOQ`'#EP'#EPO3oQbO,5:ZO3vQQO,5:YOOQa,5:Z,5:ZO4RQbO,5:ZO)lQbO,5:bO)lQbO,5:aO4]QbO,5:[O4dQbO,59cOOQ`,5:q,5:qO)lQbO'#DxOOQ`-E7u-E7uOOQ`'#Dz'#DzO5OQbO'#DUO5ZQbO'#DVOOQO'#D{'#D{O5RQQO'#DUO5iQQO,59oO5nQcO'#EXO5uQRO'#E[O6lQRO'#E[OOQO'#E['#E[O6sQQO,59iO6xQRO,59eO7PQRO,59eO4]QbO,5:]O7[QcO,5:_O8dQcO,5:_O8tQcO,5:_OOQa1G/W1G/WOOOO,59u,59uOOOO,59v,59vOOOO-E7z-E7zOOQa1G/_1G/_OOQ`,5:R,5:ROOQ`-E7w-E7wOOQa1G/r1G/rO9sQcO1G/rO9}QcO1G/rO:XQcO1G/rOOQa1G/R1G/ROVQbO'#DbO>hQbO'#DbO>{QbO1G/vOOQ`-E7v-E7vOOQ`,5:d,5:dOOQ`-E7x-E7xO?WQQO,59pOOQO,59q,59qOOQO-E7y-E7yO?`QbO1G/ZO4]QbO1G/TO4]QbO1G/PO?gQbO1G/wO?rQQO7+%`OOQa7+%`7+%`O?}QbO7+%aOOQa7+%a7+%aOOQO-E8O-E8OOOQ`-E8P-E8POOQ`'#D}'#D}O@XQQO'#D}O@aQbO'#EgOOQ`,59|,59|O@tQbO'#D`O@yQQO'#DcOOQ`7+%b7+%bOAOQbO7+%bOATQbO7+%bOA]QbO7+$uOAkQbO7+$uOA{QbO7+$oOBTQbO7+$kOOQ`7+%c7+%cOBYQbO7+%cOB_QbO7+%cOOQa<hAN>hOOQ`AN={AN={OCuQbOAN={OCzQbOAN={OOQ`-E7|-E7|OOQ`AN=uAN=uODSQbOAN=uO.WQbO,5:SO4]QbO,5:UOOQ`AN>iAN>iOOQ`7+%Q7+%QOOQ`G23gG23gODXQbOG23gPD^QbO'#DhOOQ`G23aG23aODcQQO1G/nOOQ`1G/p1G/pOOQ`LD)RLD)RO4]QbO7+%YOOQ`<eQbO'#DbO>vQbO'#DbO?ZQbO1G/vOOQ`-E7x-E7xOOQ`,5:f,5:fOOQ`-E7z-E7zO?fQQO,59pOOQO,59q,59qOOQO-E7{-E7{O?nQbO1G/ZO4kQbO1G/TO4kQbO1G/PO?uQbO1G/wO@QQQO7+%`OOQa7+%`7+%`O@]QbO7+%aOOQa7+%a7+%aOOQO-E8Q-E8QOOQ`-E8R-E8ROOQ`'#EP'#EPO@gQQO'#EPO@oQbO'#EiOOQ`,59|,59|OASQbO'#D`OAXQQO'#DcOOQ`7+%b7+%bOA^QbO7+%bOAcQbO7+%bOAkQbO7+$uOAyQbO7+$uOBZQbO7+$oOBcQbO7+$kOOQ`7+%c7+%cOBhQbO7+%cOBmQbO7+%cOOQa<hAN>hOOQ`AN={AN={ODTQbOAN={ODYQbOAN={OOQ`-E8O-E8OOOQ`AN=uAN=uODbQbOAN=uO.^QbO,5:SO4kQbO,5:UOOQ`AN>iAN>iOOQ`7+%Q7+%QOOQ`G23gG23gODgQbOG23gPDlQbO'#DhOOQ`G23aG23aODqQQO1G/nOOQ`1G/p1G/pOOQ`LD)RLD)RO4kQbO7+%YOOQ`<c#Y#o,w#o;'S#{;'S;=`$d<%lO#{U>j[!PQ|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^?g[#VW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^@d[#XW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^Aa^#WW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#f,w#f#gB]#g#o,w#o;'S#{;'S;=`$d<%lO#{UBb^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#i,w#i#j=b#j#o,w#o;'S#{;'S;=`$d<%lO#{UCeUlQ|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~C|O#a~", - tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO#P~~", 11)], + tokenData: "C|~R|OX#{XY$jYZ%TZp#{pq$jqs#{st%ntu'tuw#{wx'yxy(Oyz(iz{#{{|)S|}#{}!O+v!O!P#{!P!Q.]!Q![)q![!]6x!]!^%T!^!}#{!}#O7c#O#P9X#P#Q9^#Q#R#{#R#S9w#S#T#{#T#Y,w#Y#Z:b#Z#b,w#b#c?`#c#f,w#f#g@]#g#h,w#h#iAY#i#o,w#o#p#{#p#qC^#q;'S#{;'S;=`$d<%l~#{~O#{~~CwS$QU|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qU|S!zYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[U|S#[QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%sW|SOp#{pq&]qt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^&dZiY|SOY&]YZ#{Zt&]tu'Vuw&]wx'Vx#O&]#O#P'V#P;'S&];'S;=`'n<%lO&]Y'[SiYOY'VZ;'S'V;'S;=`'h<%lO'VY'kP;=`<%l'V^'qP;=`<%l&]~'yO#V~~(OO#T~U(VU|S#PQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(pU|S#_QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U)XW|SOt#{uw#{x!Q#{!Q![)q![#O#{#P;'S#{;'S;=`$d<%lO#{U)xY|SuQOt#{uw#{x!O#{!O!P*h!P!Q#{!Q![)q![#O#{#P;'S#{;'S;=`$d<%lO#{U*mW|SOt#{uw#{x!Q#{!Q![+V![#O#{#P;'S#{;'S;=`$d<%lO#{U+^W|SuQOt#{uw#{x!Q#{!Q![+V![#O#{#P;'S#{;'S;=`$d<%lO#{U+{^|SOt#{uw#{x}#{}!O,w!O!Q#{!Q![)q![!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{U,|[|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{U-yUzQ|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U.bW|SOt#{uw#{x!P#{!P!Q.z!Q#O#{#P;'S#{;'S;=`$d<%lO#{U/P^|SOY/{YZ#{Zt/{tu1Ouw/{wx1Ox!P/{!P!Q#{!Q!}/{!}#O5q#O#P3^#P;'S/{;'S;=`6r<%lO/{U0S^|S!aQOY/{YZ#{Zt/{tu1Ouw/{wx1Ox!P/{!P!Q3s!Q!}/{!}#O5q#O#P3^#P;'S/{;'S;=`6r<%lO/{Q1TX!aQOY1OZ!P1O!P!Q1p!Q!}1O!}#O2_#O#P3^#P;'S1O;'S;=`3m<%lO1OQ1sP!P!Q1vQ1{U!aQ#Z#[1v#]#^1v#a#b1v#g#h1v#i#j1v#m#n1vQ2bVOY2_Z#O2_#O#P2w#P#Q1O#Q;'S2_;'S;=`3W<%lO2_Q2zSOY2_Z;'S2_;'S;=`3W<%lO2_Q3ZP;=`<%l2_Q3aSOY1OZ;'S1O;'S;=`3m<%lO1OQ3pP;=`<%l1OU3xW|SOt#{uw#{x!P#{!P!Q4b!Q#O#{#P;'S#{;'S;=`$d<%lO#{U4ib|S!aQOt#{uw#{x#O#{#P#Z#{#Z#[4b#[#]#{#]#^4b#^#a#{#a#b4b#b#g#{#g#h4b#h#i#{#i#j4b#j#m#{#m#n4b#n;'S#{;'S;=`$d<%lO#{U5v[|SOY5qYZ#{Zt5qtu2_uw5qwx2_x#O5q#O#P2w#P#Q/{#Q;'S5q;'S;=`6l<%lO5qU6oP;=`<%l5qU6uP;=`<%l/{U7PU|S!RQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U7jW#aQ|SOt#{uw#{x!_#{!_!`8S!`#O#{#P;'S#{;'S;=`$d<%lO#{U8XV|SOt#{uw#{x#O#{#P#Q8n#Q;'S#{;'S;=`$d<%lO#{U8uU#`Q|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~9^O#W~U9eU#bQ|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U:OU|S!YQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U:g]|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#U;`#U#o,w#o;'S#{;'S;=`$d<%lO#{U;e^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#`,w#`#ac#Y#o,w#o;'S#{;'S;=`$d<%lO#{U>j[!PQ|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^?g[#XW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^@d[#ZW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^Aa^#YW|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#f,w#f#gB]#g#o,w#o;'S#{;'S;=`$d<%lO#{UBb^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#i,w#i#j=b#j#o,w#o;'S#{;'S;=`$d<%lO#{UCeUlQ|SOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~C|O#c~", + tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO#R~~", 11)], topRules: {"Program":[0,26]}, specialized: [{term: 20, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 20, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}], - tokenPrec: 1634 + tokenPrec: 1648 })