Compare commits
13 Commits
4eafa00648
...
c741cfee51
| Author | SHA1 | Date | |
|---|---|---|---|
| c741cfee51 | |||
| 012b8c8cf1 | |||
| 4c3f7a8bfc | |||
| fe6f54b402 | |||
| 49f3f3e09f | |||
| 0d1dce4868 | |||
| d18ab2507c | |||
| 7e69356f79 | |||
| 9863f46f38 | |||
| 45f31d0678 | |||
| 49a6320fef | |||
| 51f67ac908 | |||
| d4a772e88b |
2
bun.lock
2
bun.lock
|
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
"hono": ["hono@4.10.4", "", {}, "sha512-YG/fo7zlU3KwrBL5vDpWKisLYiM+nVstBQqfr7gCPbSYURnNEP9BDxEMz8KfsDR9JX0lJWDRNc6nXX31v7ZEyg=="],
|
"hono": ["hono@4.10.4", "", {}, "sha512-YG/fo7zlU3KwrBL5vDpWKisLYiM+nVstBQqfr7gCPbSYURnNEP9BDxEMz8KfsDR9JX0lJWDRNc6nXX31v7ZEyg=="],
|
||||||
|
|
||||||
"reefvm": ["reefvm@git+https://git.nose.space/defunkt/reefvm#d7a971db24aea5ddcaae2c18ce9f10dab793db19", { "peerDependencies": { "typescript": "^5" } }, "d7a971db24aea5ddcaae2c18ce9f10dab793db19"],
|
"reefvm": ["reefvm@git+https://git.nose.space/defunkt/reefvm#3e2e68b31f504347225a4d705c7568a0957d629e", { "peerDependencies": { "typescript": "^5" } }, "3e2e68b31f504347225a4d705c7568a0957d629e"],
|
||||||
|
|
||||||
"style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="],
|
"style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
"repl": "bun generate-parser && bun bin/repl",
|
"repl": "bun generate-parser && bun bin/repl",
|
||||||
"update-reef": "rm -rf ~/.bun/install/cache/ && rm bun.lock && bun update reefvm",
|
"update-reef": "rm -rf ~/.bun/install/cache/ && rm bun.lock && bun update reefvm",
|
||||||
"cli:install": "ln -s \"$(pwd)/bin/shrimp\" ~/.bun/bin/shrimp",
|
"cli:install": "ln -s \"$(pwd)/bin/shrimp\" ~/.bun/bin/shrimp",
|
||||||
"cli:remove": "rm ~/.bun/bin/shrimp",
|
"cli:remove": "rm ~/.bun/bin/shrimp"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/view": "^6.38.3",
|
"@codemirror/view": "^6.38.3",
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,7 @@ function processEscapeSeq(escapeSeq: string): string {
|
||||||
|
|
||||||
export class Compiler {
|
export class Compiler {
|
||||||
instructions: ProgramItem[] = []
|
instructions: ProgramItem[] = []
|
||||||
|
labelCount = 0
|
||||||
fnLabelCount = 0
|
fnLabelCount = 0
|
||||||
ifLabelCount = 0
|
ifLabelCount = 0
|
||||||
tryLabelCount = 0
|
tryLabelCount = 0
|
||||||
|
|
@ -377,7 +378,29 @@ export class Compiler {
|
||||||
|
|
||||||
case terms.FunctionCallOrIdentifier: {
|
case terms.FunctionCallOrIdentifier: {
|
||||||
if (node.firstChild?.type.id === terms.DotGet) {
|
if (node.firstChild?.type.id === terms.DotGet) {
|
||||||
return this.#compileNode(node.firstChild, input)
|
const instructions: ProgramItem[] = []
|
||||||
|
const callLabel = `.call_dotget_${++this.labelCount}`
|
||||||
|
const afterLabel = `.after_dotget_${++this.labelCount}`
|
||||||
|
|
||||||
|
instructions.push(...this.#compileNode(node.firstChild, input))
|
||||||
|
instructions.push(['DUP'])
|
||||||
|
instructions.push(['TYPE'])
|
||||||
|
instructions.push(['PUSH', 'function'])
|
||||||
|
instructions.push(['EQ'])
|
||||||
|
instructions.push(['JUMP_IF_TRUE', callLabel])
|
||||||
|
instructions.push(['DUP'])
|
||||||
|
instructions.push(['TYPE'])
|
||||||
|
instructions.push(['PUSH', 'native'])
|
||||||
|
instructions.push(['EQ'])
|
||||||
|
instructions.push(['JUMP_IF_TRUE', callLabel])
|
||||||
|
instructions.push(['JUMP', afterLabel])
|
||||||
|
instructions.push([`${callLabel}:`])
|
||||||
|
instructions.push(['PUSH', 0])
|
||||||
|
instructions.push(['PUSH', 0])
|
||||||
|
instructions.push(['CALL'])
|
||||||
|
instructions.push([`${afterLabel}:`])
|
||||||
|
|
||||||
|
return instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
return [['TRY_CALL', value]]
|
return [['TRY_CALL', value]]
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,10 @@ describe('compiler', () => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test('function call with no args', () => {
|
test('function call with no args', () => {
|
||||||
expect(`bloop = do: 'bloop' end; bloop`).toEvaluateTo('bloop')
|
expect(`bloop = do: 'bleep' end; bloop`).toEvaluateTo('bleep')
|
||||||
|
expect(`bloop = [ go=do: 'bleep' end ]; bloop.go`).toEvaluateTo('bleep')
|
||||||
|
expect(`bloop = [ go=do: 'bleep' end ]; abc = do x: x end; abc (bloop.go)`).toEvaluateTo('bleep')
|
||||||
|
expect(`num = ((math.random) * 10 + 1) | math.floor; num >= 1 and num <= 10 `).toEvaluateTo(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('function call with if statement and multiple expressions', () => {
|
test('function call with if statement and multiple expressions', () => {
|
||||||
|
|
@ -298,6 +301,23 @@ describe('default params', () => {
|
||||||
expect('multiply = do x y=5: x * y end; multiply 5 2').toEvaluateTo(10)
|
expect('multiply = do x y=5: x * y end; multiply 5 2').toEvaluateTo(10)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('null triggers default value', () => {
|
||||||
|
expect('test = do n=true: n end; test').toEvaluateTo(true)
|
||||||
|
expect('test = do n=true: n end; test false').toEvaluateTo(false)
|
||||||
|
expect('test = do n=true: n end; test null').toEvaluateTo(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('null triggers default for named parameters', () => {
|
||||||
|
expect("greet = do name='World': name end; greet name=null").toEvaluateTo('World')
|
||||||
|
expect("greet = do name='World': name end; greet name='Bob'").toEvaluateTo('Bob')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('null triggers default with multiple parameters', () => {
|
||||||
|
expect('calc = do x=10 y=20: x + y end; calc null 5').toEvaluateTo(15)
|
||||||
|
expect('calc = do x=10 y=20: x + y end; calc 3 null').toEvaluateTo(23)
|
||||||
|
expect('calc = do x=10 y=20: x + y end; calc null null').toEvaluateTo(30)
|
||||||
|
})
|
||||||
|
|
||||||
test.skip('array default', () => {
|
test.skip('array default', () => {
|
||||||
expect('abc = do alpha=[a b c]: alpha end; abc').toEvaluateTo(['a', 'b', 'c'])
|
expect('abc = do alpha=[a b c]: alpha end; abc').toEvaluateTo(['a', 'b', 'c'])
|
||||||
expect('abc = do alpha=[a b c]: alpha end; abc [x y z]').toEvaluateTo(['x', 'y', 'z'])
|
expect('abc = do alpha=[a b c]: alpha end; abc [x y z]').toEvaluateTo(['x', 'y', 'z'])
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,11 @@
|
||||||
@precedence { Number Regex }
|
@precedence { Number Regex }
|
||||||
|
|
||||||
StringFragment { !['\\$]+ }
|
StringFragment { !['\\$]+ }
|
||||||
NamedArgPrefix { $[a-z-]+ "=" }
|
NamedArgPrefix { $[a-z] $[a-z0-9-]* "=" }
|
||||||
Number {
|
Number {
|
||||||
("-" | "+")? "0x" $[0-9a-fA-F]+ |
|
("-" | "+")? "0x" $[0-9a-fA-F]+ |
|
||||||
("-" | "+")? "0b" $[01]+ |
|
("-" | "+")? "0b" $[01]+ |
|
||||||
("-" | "+")? $[0-9]+ ('.' $[0-9]+)?
|
("-" | "+")? $[0-9]+ ("_"? $[0-9]+)* ('.' $[0-9]+ ("_"? $[0-9]+)*)?
|
||||||
}
|
}
|
||||||
Boolean { "true" | "false" }
|
Boolean { "true" | "false" }
|
||||||
newlineOrSemicolon { "\n" | ";" }
|
newlineOrSemicolon { "\n" | ";" }
|
||||||
|
|
@ -51,7 +51,8 @@ null { @specialize[@name=Null]<Identifier, "null"> }
|
||||||
comparison @left,
|
comparison @left,
|
||||||
multiplicative @left,
|
multiplicative @left,
|
||||||
additive @left,
|
additive @left,
|
||||||
call
|
call,
|
||||||
|
functionWithNewlines
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
|
|
@ -192,7 +193,21 @@ BinOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
ParenExpr {
|
ParenExpr {
|
||||||
leftParen (IfExpr | ambiguousFunctionCall | BinOp | expressionWithoutIdentifier | ConditionalOp | PipeExpr | FunctionDef) rightParen
|
leftParen newlineOrSemicolon* (
|
||||||
|
FunctionCallWithNewlines |
|
||||||
|
IfExpr |
|
||||||
|
ambiguousFunctionCall |
|
||||||
|
BinOp newlineOrSemicolon* |
|
||||||
|
expressionWithoutIdentifier |
|
||||||
|
ConditionalOp newlineOrSemicolon* |
|
||||||
|
PipeExpr |
|
||||||
|
FunctionDef
|
||||||
|
)
|
||||||
|
rightParen
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionCallWithNewlines[@name=FunctionCall] {
|
||||||
|
(DotGet | Identifier | ParenExpr) newlineOrSemicolon+ arg !functionWithNewlines (newlineOrSemicolon+ arg)* newlineOrSemicolon*
|
||||||
}
|
}
|
||||||
|
|
||||||
expression {
|
expression {
|
||||||
|
|
|
||||||
|
|
@ -28,39 +28,40 @@ export const
|
||||||
Program = 26,
|
Program = 26,
|
||||||
PipeExpr = 27,
|
PipeExpr = 27,
|
||||||
WhileExpr = 29,
|
WhileExpr = 29,
|
||||||
keyword = 70,
|
keyword = 71,
|
||||||
ConditionalOp = 31,
|
ConditionalOp = 31,
|
||||||
ParenExpr = 32,
|
ParenExpr = 32,
|
||||||
IfExpr = 33,
|
FunctionCallWithNewlines = 33,
|
||||||
FunctionCall = 35,
|
DotGet = 34,
|
||||||
DotGet = 36,
|
Number = 35,
|
||||||
Number = 37,
|
PositionalArg = 36,
|
||||||
PositionalArg = 38,
|
FunctionDef = 37,
|
||||||
FunctionDef = 39,
|
Params = 38,
|
||||||
Params = 40,
|
NamedParam = 39,
|
||||||
NamedParam = 41,
|
NamedArgPrefix = 40,
|
||||||
NamedArgPrefix = 42,
|
String = 41,
|
||||||
String = 43,
|
StringFragment = 42,
|
||||||
StringFragment = 44,
|
Interpolation = 43,
|
||||||
Interpolation = 45,
|
EscapeSeq = 44,
|
||||||
EscapeSeq = 46,
|
Boolean = 45,
|
||||||
Boolean = 47,
|
Null = 46,
|
||||||
Null = 48,
|
colon = 47,
|
||||||
colon = 49,
|
CatchExpr = 48,
|
||||||
CatchExpr = 50,
|
Block = 50,
|
||||||
Block = 52,
|
FinallyExpr = 51,
|
||||||
FinallyExpr = 53,
|
Underscore = 54,
|
||||||
Underscore = 56,
|
NamedArg = 55,
|
||||||
NamedArg = 57,
|
IfExpr = 56,
|
||||||
ElseIfExpr = 58,
|
FunctionCall = 58,
|
||||||
ElseExpr = 60,
|
ElseIfExpr = 59,
|
||||||
FunctionCallOrIdentifier = 61,
|
ElseExpr = 61,
|
||||||
BinOp = 62,
|
FunctionCallOrIdentifier = 62,
|
||||||
Regex = 63,
|
BinOp = 63,
|
||||||
Dict = 64,
|
Regex = 64,
|
||||||
Array = 65,
|
Dict = 65,
|
||||||
FunctionCallWithBlock = 66,
|
Array = 66,
|
||||||
TryExpr = 67,
|
FunctionCallWithBlock = 67,
|
||||||
Throw = 69,
|
TryExpr = 68,
|
||||||
CompoundAssign = 71,
|
Throw = 70,
|
||||||
Assign = 72
|
CompoundAssign = 72,
|
||||||
|
Assign = 73
|
||||||
|
|
|
||||||
|
|
@ -4,24 +4,24 @@ import {operatorTokenizer} from "./operatorTokenizer"
|
||||||
import {tokenizer, specializeKeyword} from "./tokenizer"
|
import {tokenizer, specializeKeyword} from "./tokenizer"
|
||||||
import {trackScope} from "./parserScopeContext"
|
import {trackScope} from "./parserScopeContext"
|
||||||
import {highlighting} from "./highlight"
|
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, null:92, catch:98, finally:104, end:106, if:114, else:120, try:138, throw:142}
|
||||||
export const parser = LRParser.deserialize({
|
export const parser = LRParser.deserialize({
|
||||||
version: 14,
|
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/RO<TQcO1G/RO<[QcO1G/RO<cQcO1G/ROOQa1G/S1G/SOOQ`-E7}-E7}O<jQQO1G/tOOQa1G/u1G/uO<uQbO1G/uOOQO'#EQ'#EQO<jQQO1G/tOOQa1G/t1G/tOOQ`'#ER'#ERO<uQbO1G/uO=PQbO1G/|O=kQbO1G/{O>VQbO'#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<<Hz<<HzOOQa<<H{<<H{OOQ`,5:i,5:iOOQ`-E7{-E7{OBgQQO,59zO4]QbO,59}OOQ`<<H|<<H|OBlQbO<<H|OOQ`<<Ha<<HaOBqQbO<<HaOBvQbO<<HaOCOQbO<<HaOOQ`'#EO'#EOOCZQbO<<HZOCcQbO'#DjOOQ`<<HZ<<HZOCkQbO<<HZOOQ`<<HV<<HVOOQ`<<H}<<H}OCpQbO<<H}O4]QbO1G/fOOQ`1G/i1G/iOOQ`AN>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`<<Ht<<Ht",
|
states: "<OQYQbOOO!dOpO'#DOO!iOSO'#DVO$wQcO'#DlO'[QcO'#E[OOQ`'#Ej'#EjO'uQRO'#DmO)[QcO'#EYO)lQbO'#C|OOQa'#Do'#DoO+qQbO'#DpOOQa'#E['#E[O+xQcO'#E[O,cQcO'#EZO-`QcO'#EYO-jQRO'#DvOOQ`'#EY'#EYO.OQbO'#EYO.VQQO'#EXOOQ`'#EX'#EXOOQ`'#Dx'#DxQYQbOOO.bQbO'#DRO.mQbO'#DfO/bQbO'#CyO0VQQO'#DrO/bQbO'#DtO0[ObO,59jO0gQbO'#DXO0oQWO'#DYOOOO'#Eb'#EbOOOO'#D}'#D}O1TOSO,59qOOQa,59q,59qOOQ`'#DQ'#DQO1cQbO'#DeOOQ`'#E`'#E`OOQ`'#EQ'#EQO1mQbO,5:SOOQa'#EZ'#EZO/bQbO,5:XO/bQbO,5:XO/bQbO,5:XO/bQbO,59gO/bQbO,59gO/bQbO,59gOOQ`'#Dz'#DzO)lQbO,59hO2gQcO'#DlO2nQcO'#E[O3ZQRO,59hO3bQQO,59hO3gQQO,59hO3oQQO,59hO4xQRO,59hO5PQRO,59hO5bQQO'#CwO5gQbO,5:[O5nQQO,5:ZOOQa,5:[,5:[O5yQbO,5:[O6TQbO,5:cO6TQbO,5:bO7[QbO,5:]O7cQbO,59cOOQ`,5:s,5:sO6TQbO'#DyOOQ`-E7v-E7vOOQ`'#D{'#D{O7}QbO'#DSO8YQbO'#DTOOQO'#D|'#D|O8QQQO'#DSO8hQQO,59mO8mQcO'#EZO9gQRO'#EiO:^QRO'#EiOOQO'#Ei'#EiO:eQQO,5:QO:jQRO,59eO:qQRO,59eO7[QbO,5:^O:|QcO,5:`O<UQcO,5:`O<fQcO,5:`OOQa1G/U1G/UOOOO,59s,59sOOOO,59t,59tOOOO-E7{-E7{OOQa1G/]1G/]OOQ`,5:P,5:POOQ`-E8O-E8OOOQa1G/s1G/sO=eQcO1G/sO=oQcO1G/sO=yQcO1G/sOOQa1G/R1G/RO?uQcO1G/RO?|QcO1G/RO@TQcO1G/ROOQ`-E7x-E7xO@[QRO1G/SO@cQQO1G/SO@hQQO1G/SO@pQQO1G/SO@{QRO1G/SOASQRO1G/SOAeQbO,59iOAoQQO1G/SOOQa1G/S1G/SOAwQQO1G/uOOQa1G/v1G/vOBSQbO1G/vOOQO'#ES'#ESOAwQQO1G/uOOQa1G/u1G/uOOQ`'#ET'#ETOBSQbO1G/vOB^QbO1G/}OBxQbO1G/|OCdQbO'#D`OCuQbO'#D`ODYQbO1G/wOOQ`-E7w-E7wOOQ`,5:e,5:eOOQ`-E7y-E7yODeQQO,59nOOQO,59o,59oOOQO-E7z-E7zODmQbO1G/XO7[QbO1G/lO7[QbO1G/PODtQbO1G/xOEPQQO7+$nOOQa7+$n7+$nOEXQQO1G/TOEaQQO7+%aOOQa7+%a7+%aOElQbO7+%bOOQa7+%b7+%bOOQO-E8Q-E8QOOQ`-E8R-E8ROOQ`'#EO'#EOOEvQQO'#EOOFOQbO'#EhOOQ`,59z,59zOFcQbO'#D^OFhQQO'#DaOOQ`7+%c7+%cOFmQbO7+%cOFrQbO7+%cOFzQbO7+$sOGYQbO7+$sOGjQbO7+%WOGrQbO7+$kOOQ`7+%d7+%dOGwQbO7+%dOG|QbO7+%dOOQa<<HY<<HYOHUQbO7+$oOHcQQO7+$oOOQa<<H{<<H{OOQa<<H|<<H|OOQ`,5:j,5:jOOQ`-E7|-E7|OHkQQO,59xO7[QbO,59{OOQ`<<H}<<H}OHpQbO<<H}OOQ`<<H_<<H_OHuQbO<<H_OHzQbO<<H_OISQbO<<H_OOQ`'#ER'#EROI_QbO<<HrOIgQbO'#DkOOQ`<<Hr<<HrOIoQbO<<HrOOQ`<<HV<<HVOOQ`<<IO<<IOOItQbO<<IOOOQO,5:k,5:kOIyQbO<<HZOOQO-E7}-E7}O7[QbO1G/dOOQ`1G/g1G/gOOQ`AN>iAN>iOOQ`AN=yAN=yOJWQbOAN=yOJ]QbOAN=yOOQ`-E8P-E8POOQ`AN>^AN>^OJeQbOAN>^O.mQbO,5:TO7[QbO,5:VOOQ`AN>jAN>jPAeQbO'#DzOOQ`7+%O7+%OOOQ`G23eG23eOJjQbOG23ePIjQbO'#DiOOQ`G23xG23xOJoQQO1G/oOOQ`1G/q1G/qOOQ`LD)PLD)PO7[QbO7+%ZOOQ`<<Hu<<Hu",
|
||||||
stateData: "Dk~O!xOSiOS~OdROe_OfZOgPOhfOnhOrgOuZO!PZO!QZO!aZO!fiO!hjO!}WO#RQO#YcO#^XO#_YO~O#PkO~O|nO#RqO#TlO#UmO~OdwOfZOgPOhfOuZOzsO!PZO!QZO!YrO!aZO!}WO#RQO#^XO#_YOT!{XU!{XW!{XX!{XY!{XZ!{X[!{X]!{X~OP!{XQ!{XR!{XS!{X^!{Xl!_X!R!_X#Y!_X#a!_X#]!_X!T!_X!W!_X!X!_X!]!_X~P!wOP!|XQ!|XR!|XS!|XT!|XU!|XW!|XX!|XY!|XZ!|X[!|X]!|X^!|Xl!|X#Y!|X#a!|X#]!|X!T!|X!W!|X!X!|X!]!|X~OdwOfZOgPOhfOuZOzsO!PZO!QZO!YrO!aZO!}WO#RQO#^XO#_YO!R!|X~P%_OPyOQyORzOSzOT|OU}OW{OX{OY{OZ{O[{O]{O^xO~Ol!zX#Y!zX#a!zX!T!zX!W!zX!X!zX#]!zX!]!zX~OPyOQyORzOSzO~P(pOdROe_OfZOgPOhfOnhOrgOuZO!PZO!QZO!aZO!fiO!hjO!}WO#RQO#^XO#_YO~OdwOfZOgPOuZOzsO!PZO!QZO!aZO!}WO#RQO#Y!UO#^XO#_YO~O#`!XO~P*sOV!ZO~P%_OP!{XQ!{XR!{XS!{XT!{XU!{XW!{XX!{XY!{XZ!{X[!{X]!{X^!{X~P(pOT|OU}O~P(pOV!ZO_![O`![Oa![Ob![Oc![O~O!R!]O~P(pOl!`O#Y!_O#a!_O~Od!bOz!dO!RxP~Od!hOfZOgPOuZO!PZO!QZO!aZO!}WO#RQO#^XO#_YO~OdwOfZOgPOuZO!PZO!QZO!aZO!}WO#RQO#^XO#_YO~O!R!oO~Od!sOu!sO!}WO~Od!tO!}WO~O#R!uO#T!uO#U!uO#V!uO#W!uO#X!uO~O|nO#R!wO#TlO#UmO~OhfO!Y!xO~P.{OhfOzsO!YrOlsa!Rsa#Ysa#asa#]sa!Tsa!Wsa!Xsa!]sa~P.{OPyOQyORzOSzO#]#SOl!zX~O!R!]O#]#SOl!zX~O#]#SOP!{XQ!{XR!{XS!{X^!{Xl!zX~P#sOT|OU}O#]#SOl!zX~Ol!`O~O#`#VO~P*sOzsO#Y#XO#`#ZO~O#Y#[O#`#VO~P.{O#Y#aO~P)lOl!`O#Yka#aka#]ka!Tka!Wka!Xka!]ka~Od!bOz!dO!RxX~Ou#gO!P#gO!Q#gO#RQO~O!R#iO~O!R!{X~P!wOT|OU}O!R#OX~OT|OU}OW{OX{OY{OZ{O[{O]{O~O!R#OX~P6QO!R#jO~O!R#kO~P6QOT|OU}O!R#kO~Ol!ga#Y!ga#a!ga!T!ga!W!ga!X!ga#]!ga!]!ga~P'uOl!ga#Y!ga#a!ga!T!ga!W!ga!X!ga#]!ga!]!ga~OPyOQyORzOSzO~P7xOT|OU}O~P7xO^xOR!`iS!`il!`i#Y!`i#a!`i#]!`i!T!`i!W!`i!X!`i!]!`i~OP!`iQ!`i~P9OOPyOQyO~P9OOPyOQyOR!`iS!`il!`i#Y!`i#a!`i#]!`i!T!`i!W!`i!X!`i!]!`i~OW{OX{OY{OZ{O[{O]{OToiloi#Yoi#aoi#]oi!Roi!Toi!Woi!Xoi!]oi~OU}O~P;POU}O~P;cOUoi~P;POzsO#Y#XO#`#nO~O#Y#[O#`#pO~P.{Ol!`O#Y!ji#a!ji!T!ji!W!ji!X!ji#]!ji!]!ji~Ol!`O#Y!ii#a!ii!T!ii!W!ii!X!ii#]!ii!]!ii~Ol!`O!T!UX!W!UX!X!UX!]!UX~O#Y#sO!T#ZP!W#ZP!X#ZP!]#ZP~P)lO!T#wO!W#xO!X#yO~Oz!dO!Rxa~O#Y#}O~P)lO!T#wO!W#xO!X$QO~OzsO#Y#XO#`$TO~O#Y#[O#`$UO~P.{Ol!`O#Y$VO~O#Y#sO!T#ZX!W#ZX!X#ZX!]#ZX~P)lOd$XO~O!R$YO~O!X$ZO~O!W#xO!X$ZO~Ol!`O!T#wO!W#xO!X$]O~O#Y#sO!T#ZP!W#ZP!X#ZP~P)lO!X$dO!]$cO~O!X$fO~O!X$gO~O!W#xO!X$gO~O!R$iO~O!X$kO~O!X$lO~O!W#xO!X$lO~O!T#wO!W#xO!X$lO~O!X$pO!]$cO~Or$rO!R$sO~O!X$pO~O!X$tO~O!X$vO~O!W#xO!X$vO~O!X$yO~O!X$|O~Or$rO~O!R$}O~Ou!a~",
|
stateData: "Jw~O!zOSiOS~OdROe_OfZOgPOhfOnhOsZO}ZO!OZO!ZgO!bZO!giO!ijO#PWO#QcO#TQO#`XO#aYO~O#RkO~OznO#TqO#VlO#WmO~OdwOfZOgPOhfOsZOxsO}ZO!OZO!WrO!bZO#PWO#TQO#`XO#aYOP!}XQ!}XR!}XS!}XT!}XU!}XW!}XX!}XY!}XZ!}X[!}X]!}X^!}Xl!`X!P!`X#_!`X~O#Q!`X#c!`X!R!`X!U!`X!V!`X!^!`X~P!wOdwOfZOgPOhfOsZOxsO}ZO!OZO!WrO!bZO#PWO#TQO#`XO#aYOP#OXQ#OXR#OXS#OXT#OXU#OXW#OXX#OXY#OXZ#OX[#OX]#OX^#OXl#OX#_#OX~O#Q#OX#c#OX!P#OX!R#OX!U#OX!V#OX!^#OX~P%_OPyOQyORzOSzOT|OU}OW{OX{OY{OZ{O[{O]{O^xO~Ol!|X#Q!|X#c!|X!R!|X!U!|X!V!|X#_!|X!^!|X~OPyOQyORzOSzO~P(pOd!QOe_OfZOgPOhfOnhOsZO}ZO!OZO!ZgO!bZO!giO!ijO#PWO#Q!OO#TQO#`XO#aYO~OdwOfZOgPOsZOxsO}ZO!OZO!bZO#PWO#Q!OO#TQO#`XO#aYO~O#b!]O~P*vOV!_O#Q#OX#c#OX!R#OX!U#OX!V#OX!^#OX~P&ZOP!}XQ!}XR!}XS!}XT!}XU!}XW!}XX!}XY!}XZ!}X[!}X]!}X^!}X~P(pOT|OU}O~P(pOV!_O_!`O`!`Oa!`Ob!`Oc!`O~O!P!aO~P(pOl!dO#Q!cO#c!cO~Od!fOx!hO!PvP~Od!lOfZOgPOsZO}ZO!OZO!bZO#PWO#TQO#`XO#aYO~OdwOfZOgPOsZO}ZO!OZO!bZO#PWO#TQO#`XO#aYO~O!P!sO~Od!wOs!wO#PWO~Od!xO#PWO~O#T!yO#V!yO#W!yO#X!yO#Y!yO#Z!yO~OznO#T!{O#VlO#WmO~OhfO!W!|O~P/bOhfOxsO!WrOl![a!P![a#Q![a#c![a#_![a!R![a!U![a!V![a!^![a~P/bO#Q!OO~P!wO#Q!OO~P%_OPyOQyORzOSzO#Q!OOl!|X~O#_#aO~P2uO#_#aO~O#_#aOl!|X~O!P!aO#_#aOl!|X~OP!}XQ!}XR!}XS!}XT!}XU!}XW!}XX!}XY!}XZ!}X[!}X]!}X^!}Xl!|X~O#_#aO~P3zOT|OU}O#Q!OO#_#aOl!|X~Ol!dO~O#b#cO~P*vOxsO#Q#eO#b#gO~O#Q#hO#b#cO~P/bOdROe_OfZOgPOhfOnhOsZO}ZO!OZO!ZgO!bZO!giO!ijO#PWO#TQO#`XO#aYO~O#Q#mO~P6TOl!dO#Qka#cka#_ka!Rka!Uka!Vka!^ka~Od!fOx!hO!PvX~Os#sO}#sO!O#sO#TQO~O!P#uO~OhfOxsO!WrOT!}XU!}XW!}XX!}XY!}XZ!}X[!}X]!}X!P!}X~P/bOT|OU}O!P#]X~OT|OU}OW{OX{OY{OZ{O[{O]{O~O!P#]X~P9rO!P#vO~O!P#wO~P9rOT|OU}O!P#wO~Ol!ha#Q!ha#c!ha!R!ha!U!ha!V!ha#_!ha!^!ha~P'uOl!ha#Q!ha#c!ha!R!ha!U!ha!V!ha#_!ha!^!ha~OPyOQyORzOSzO~P;jOT|OU}O~P;jO^xOR!aiS!ail!ai#Q!ai#c!ai#_!ai!R!ai!U!ai!V!ai!^!ai~OP!aiQ!ai~P<pOPyOQyO~P<pOPyOQyOR!aiS!ail!ai#Q!ai#c!ai#_!ai!R!ai!U!ai!V!ai!^!ai~OW{OX{OY{OZ{O[{O]{OToiloi#Qoi#coi#_oi!Poi!Roi!Uoi!Voi!^oi~OU}O~P>qOU}O~P?TOUoi~P>qO#_#zO~P2uO#_#zO~O#_#zOl!|X~O!P!aO#_#zOl!|X~O#_#zO~P3zOT|OU}O#Q!OO#_#zOl!|X~OhfO!WrO~P*vO#Q!OO#_#zO~OxsO#Q#eO#b#}O~O#Q#hO#b$PO~P/bOl!dO#Q!ki#c!ki!R!ki!U!ki!V!ki#_!ki!^!ki~Ol!dO#Q!ji#c!ji!R!ji!U!ji!V!ji#_!ji!^!ji~Ol!dO!R!SX!U!SX!V!SX!^!SX~O#Q$SO!R#[P!U#[P!V#[P!^#[P~P6TO!R$WO!U$XO!V$YO~Ox!hO!Pva~O#Q$^O~P6TO!R$WO!U$XO!V$aO~O#Q!OO#_$dO~O#Q!OO#_qi~OxsO#Q#eO#b$gO~O#Q#hO#b$hO~P/bOl!dO#Q$iO~O#Q$SO!R#[X!U#[X!V#[X!^#[X~P6TOd$kO~O!P$lO~O!V$mO~O!U$XO!V$mO~Ol!dO!R$WO!U$XO!V$oO~O#Q$SO!R#[P!U#[P!V#[P~P6TO!V$vO!^$uO~O!V$xO~O!V$yO~O!U$XO!V$yO~OhfO!WrO#_qq~P*vO#Q!OO#_qq~O!P%OO~O!V%QO~O!V%RO~O!U$XO!V%RO~O!R$WO!U$XO!V%RO~O!V%VO!^$uO~O!P%YO!Z%XO~O!V%VO~O!V%ZO~OhfO!WrO#_qy~P*vO!V%^O~O!U$XO!V%^O~O!V%aO~O!V%dO~O!P%eO~Os!b~",
|
||||||
goto: "4l#]PPPPPPPPPPPPPPPPPPPPPPPPPPP#^P#tP$Y%Q#^P&T&mP'l'r(c(fP(lP)j)jPPP)nP)z*dPPP*z+^P+b+h+|P,m-h#t#tP#tP#t#t.e.k.w/P/V/a/g/n/t/z0UPPP0`0d1W2oP3nP3tP3zPPPPPP4O4Ur`Oe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}R!PWu`OWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}r^Oe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}Q!SWS!ig$rQ!nhQ!rjQ#O}R#Q|xSOWeg!Z![!]!`!o#a#i#j#k#u#}$Y$i$r$s$}vZRSYhjsvxyz{|}!V!Y!h#W#]#oQ!skR!tltTOWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}T!kg$rtROWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}vwRSYhjsvxyz{|}!V!Y!h#W#]#oT!hg$rXtRSv!hr`Oe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}WrRSv!hQ!PWR!xsR!gfX!ef!c!f#f!pZORSWYeghjsvxyz{|}!V!Y!Z![!]!`!h!o#W#]#a#i#j#k#o#u#}$Y$i$r$s$}R#g!dTnQpQ#{#bQ$S#lQ$_#|R$n$`Q#b!]Q#l!oQ$O#jQ$P#kQ$j$YQ$u$iQ${$sR%O$}Q#z#bQ$R#lQ$[#{Q$^#|Q$h$SS$m$_$`R$w$nWtRSv!hQ!WYQ#U!VX#X!W#U#Y#mT$a$O$bQ$e$OR$q$buTOWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}rVOe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}Q!OWQ!qjQ!zyR!}z!qZORSWYeghjsvxyz{|}!V!Y!Z![!]!`!h!o#W#]#a#i#j#k#o#u#}$Y$i$r$s$}zZRSYghjsvxyz{|}!V!Y!h#W#]#o$ru[OWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}QeOR!ae^!^b!T#^#_#`#t#|R#c!^UvRS!hR!yvQ!cfR#e!cQ!ffQ#f!cT#h!f#fQpQR!vpS#u#a#}R$W#uQ$b$OR$o$bQ!VYR#T!VQ#Y!WQ#m#UT#q#Y#mQ#]!YQ#o#WT#r#]#oTdOeSbOeQ!TWQ#^!ZQ#_![`#`!]!o#j#k$Y$i$s$}Q#d!`U#t#a#u#}R#|#itUOWe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}WrRSv!hQ!YYS!jg$rQ!mhQ!pjQ!xsQ!zxQ!{yQ!|zQ#O{Q#P|Q#R}Q#W!VX#[!Y#W#]#or]Oe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}zwRSYghjsvxyz{|}!V!Y!h#W#]#o$rR!RWQ!lgR$z$rXuRSv!hToQpQ#v#aR$`#}raOe!Z![!]!`!o#a#i#j#k#u#}$Y$i$s$}R!QW",
|
goto: "7t#_PPPPPPPPPPPPPPPPPPPPPPPPPPP#`P#yP$`%Z&g&mP'u(R({)OP)UP*Z*ZPPP*_P*k+TPPP+k#`P,T,nP,r,x-_P.R/T#y#yP#yP#y#y0X0_0k1_1e1o1u1|2S2^2d2nPPP2x2|3q5aPPP6iP6yPPPPP6}7T7Zr`Oe!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%eQ!UWR#Z!Pw`OWe!P!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%er^Oe!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%eQ!XWS!mg%XQ!rhQ!vjQ#S}Q#U|R#^!PvSOeg!_!`!a!d!s#m#u#v#w$U$^$l%O%X%Y%e!SZRSYhjsvxyz{|}!Q!R!Z!^!l#_#d#i$O$e$|%[S!RW!PQ!wkR!xlQ!TWR#Y!PrROe!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%e!SwRSYhjsvxyz{|}!Q!R!Z!^!l#_#d#i$O$e$|%[S!QW!PT!lg%XetRSv!Q!R!l#_$e$|%[r`Oe!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%edrRSv!Q!R!l#_$e$|%[Q!UWQ!|sR#Z!PR!kfX!if!g!j#r#OZORSWYeghjsvxyz{|}!P!Q!R!Z!^!_!`!a!d!l!s#_#d#i#m#u#v#w$O$U$^$e$l$|%O%X%Y%[%eR#s!hTnQpQ$[#nQ$c#xQ$q$]R%T$rQ#n!aQ#x!sQ$_#vQ$`#wQ%P$lQ%]%OQ%c%YR%f%eQ$Z#nQ$b#xQ$n$[Q$p$]Q$z$cS%S$q$rR%_%TdtRSv!Q!R!l#_$e$|%[Q![YQ#b!ZX#e![#b#f#|vTOWe!P!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%eT!og%XT$s$_$tQ$w$_R%W$twTOWe!P!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%erVOe!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%eQ!SWQ!ujQ#OyQ#RzR#X!P#PZORSWYeghjsvxyz{|}!P!Q!R!Z!^!_!`!a!d!l!s#_#d#i#m#u#v#w$O$U$^$e$l$|%O%X%Y%[%e!WZRSYghjsvxyz{|}!Q!R!Z!^!l#_#d#i$O$e$|%X%[w[OWe!P!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%eQeOR!ee^!bb!Y#j#k#l$T$]R#o!bQ!PWQ!ZY`#W!P!Z#_#`#y$e$|%[S#_!Q!RS#`!S!XS#y#X#^Q$e#{R$|$fQ!gfR#q!gQ!jfQ#r!gT#t!j#rQpQR!zpS$U#m$^R$j$UQ$f#{R$}$fYvRS!Q!R!lR!}vQ$t$_R%U$tQ#f![Q#|#bT$Q#f#|Q#i!^Q$O#dT$R#i$OTdOeSbOeS!YW!PQ#j!_Q#k!``#l!a!s#v#w$l%O%Y%eQ#p!dU$T#m$U$^R$]#uvUOWe!P!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%edrRSv!Q!R!l#_$e$|%[Q!^YS!ng%XQ!qhQ!tjQ!|sQ#OxQ#PyQ#QzQ#S{Q#T|Q#V}Q#d!ZX#h!^#d#i$Or]Oe!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%e!WwRSYghjsvxyz{|}!Q!R!Z!^!l#_#d#i$O$e$|%X%[Q!WWR#]!P[uRSv!Q!R!lQ#{#_V${$e$|%[ToQpQ$V#mR$r$^Q!pgR%b%XraOe!_!`!a!d!s#m#u#v#w$U$^$l%O%Y%eQ!VWR#[!P",
|
||||||
nodeNames: "⚠ Star Slash Plus Minus And Or Eq EqEq Neq Lt Lte Gt Gte Modulo PlusEq MinusEq StarEq SlashEq ModuloEq Identifier AssignableIdentifier Word IdentifierBeforeDot Do Comment Program PipeExpr operator WhileExpr keyword ConditionalOp ParenExpr IfExpr keyword FunctionCall DotGet Number PositionalArg FunctionDef Params NamedParam NamedArgPrefix String StringFragment Interpolation EscapeSeq Boolean Null colon CatchExpr keyword Block FinallyExpr keyword keyword Underscore NamedArg ElseIfExpr keyword ElseExpr FunctionCallOrIdentifier BinOp Regex Dict Array FunctionCallWithBlock TryExpr keyword Throw keyword CompoundAssign Assign",
|
nodeNames: "⚠ Star Slash Plus Minus And Or Eq EqEq Neq Lt Lte Gt Gte Modulo PlusEq MinusEq StarEq SlashEq ModuloEq Identifier AssignableIdentifier Word IdentifierBeforeDot Do Comment Program PipeExpr operator WhileExpr keyword ConditionalOp ParenExpr FunctionCall DotGet Number PositionalArg FunctionDef Params NamedParam NamedArgPrefix String StringFragment Interpolation EscapeSeq Boolean Null colon CatchExpr keyword Block FinallyExpr keyword keyword Underscore NamedArg IfExpr keyword FunctionCall ElseIfExpr keyword ElseExpr FunctionCallOrIdentifier BinOp Regex Dict Array FunctionCallWithBlock TryExpr keyword Throw keyword CompoundAssign Assign",
|
||||||
maxTerm: 109,
|
maxTerm: 111,
|
||||||
context: trackScope,
|
context: trackScope,
|
||||||
nodeProps: [
|
nodeProps: [
|
||||||
["closedBy", 49,"end"]
|
["closedBy", 47,"end"]
|
||||||
],
|
],
|
||||||
propSources: [highlighting],
|
propSources: [highlighting],
|
||||||
skippedNodes: [0,25],
|
skippedNodes: [0,25],
|
||||||
repeatNodeCount: 11,
|
repeatNodeCount: 12,
|
||||||
tokenData: "Gw~R}OX$OXY$mYZ%WZp$Opq$mqs$Ost%qtu'Yuw$Owx'_xy'dyz'}z{$O{|(h|}$O}!O/n!O!P$O!P!Q2W!Q!R)Y!R![+k![!]:s!]!^%W!^!}$O!}#O;^#O#P=S#P#Q=X#Q#R$O#R#S=r#S#T$O#T#Y0r#Y#Z>]#Z#b0r#b#cCZ#c#f0r#f#gDW#g#h0r#h#iET#i#o0r#o#p$O#p#qGX#q;'S$O;'S;=`$g<%l~$O~O$O~~GrS$TU|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OS$jP;=`<%l$O^$tU|S!xYOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU%_U|S#YQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O^%xZiY|SOY%qYZ$OZt%qtu&kuw%qwx&kx#O%q#O#P&k#P;'S%q;'S;=`'S<%lO%qY&pSiYOY&kZ;'S&k;'S;=`&|<%lO&kY'PP;=`<%l&k^'VP;=`<%l%q~'_O#T~~'dO#R~U'kU|S!}QOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(UU|S#]QOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(mX|SOt$Ouw$Ox!Q$O!Q!R)Y!R![+k![#O$O#P;'S$O;'S;=`$g<%lO$OU)a^|SuQOt$Ouw$Ox!O$O!O!P*]!P!Q$O!Q![+k![#O$O#P#U$O#U#V,b#V#l$O#l#m-v#m;'S$O;'S;=`$g<%lO$OU*bW|SOt$Ouw$Ox!Q$O!Q![*z![#O$O#P;'S$O;'S;=`$g<%lO$OU+RW|SuQOt$Ouw$Ox!Q$O!Q![*z![#O$O#P;'S$O;'S;=`$g<%lO$OU+rY|SuQOt$Ouw$Ox!O$O!O!P*]!P!Q$O!Q![+k![#O$O#P;'S$O;'S;=`$g<%lO$OU,gX|SOt$Ouw$Ox!Q$O!Q!R-S!R!S-S!S#O$O#P;'S$O;'S;=`$g<%lO$OU-ZX|SuQOt$Ouw$Ox!Q$O!Q!R-S!R!S-S!S#O$O#P;'S$O;'S;=`$g<%lO$OU-{[|SOt$Ouw$Ox!Q$O!Q![.q![!c$O!c!i.q!i#O$O#P#T$O#T#Z.q#Z;'S$O;'S;=`$g<%lO$OU.x[|SuQOt$Ouw$Ox!Q$O!Q![.q![!c$O!c!i.q!i#O$O#P#T$O#T#Z.q#Z;'S$O;'S;=`$g<%lO$OU/s_|SOt$Ouw$Ox}$O}!O0r!O!Q$O!Q!R)Y!R![+k![!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$OU0w[|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$OU1tUzQ|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU2]W|SOt$Ouw$Ox!P$O!P!Q2u!Q#O$O#P;'S$O;'S;=`$g<%lO$OU2z^|SOY3vYZ$OZt3vtu4yuw3vwx4yx!P3v!P!Q$O!Q!}3v!}#O9l#O#P7X#P;'S3v;'S;=`:m<%lO3vU3}^|S!aQOY3vYZ$OZt3vtu4yuw3vwx4yx!P3v!P!Q7n!Q!}3v!}#O9l#O#P7X#P;'S3v;'S;=`:m<%lO3vQ5OX!aQOY4yZ!P4y!P!Q5k!Q!}4y!}#O6Y#O#P7X#P;'S4y;'S;=`7h<%lO4yQ5nP!P!Q5qQ5vU!aQ#Z#[5q#]#^5q#a#b5q#g#h5q#i#j5q#m#n5qQ6]VOY6YZ#O6Y#O#P6r#P#Q4y#Q;'S6Y;'S;=`7R<%lO6YQ6uSOY6YZ;'S6Y;'S;=`7R<%lO6YQ7UP;=`<%l6YQ7[SOY4yZ;'S4y;'S;=`7h<%lO4yQ7kP;=`<%l4yU7sW|SOt$Ouw$Ox!P$O!P!Q8]!Q#O$O#P;'S$O;'S;=`$g<%lO$OU8db|S!aQOt$Ouw$Ox#O$O#P#Z$O#Z#[8]#[#]$O#]#^8]#^#a$O#a#b8]#b#g$O#g#h8]#h#i$O#i#j8]#j#m$O#m#n8]#n;'S$O;'S;=`$g<%lO$OU9q[|SOY9lYZ$OZt9ltu6Yuw9lwx6Yx#O9l#O#P6r#P#Q3v#Q;'S9l;'S;=`:g<%lO9lU:jP;=`<%l9lU:pP;=`<%l3vU:zU|S!RQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU;eW#_Q|SOt$Ouw$Ox!_$O!_!`;}!`#O$O#P;'S$O;'S;=`$g<%lO$OU<SV|SOt$Ouw$Ox#O$O#P#Q<i#Q;'S$O;'S;=`$g<%lO$OU<pU#^Q|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~=XO#U~U=`U#`Q|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU=yU|S!YQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU>b]|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#U?Z#U#o0r#o;'S$O;'S;=`$g<%lO$OU?`^|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#`0r#`#a@[#a#o0r#o;'S$O;'S;=`$g<%lO$OU@a^|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#g0r#g#hA]#h#o0r#o;'S$O;'S;=`$g<%lO$OUAb^|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#X0r#X#YB^#Y#o0r#o;'S$O;'S;=`$g<%lO$OUBe[!PQ|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$O^Cb[#VW|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$O^D_[#XW|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#o0r#o;'S$O;'S;=`$g<%lO$O^E[^#WW|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#f0r#f#gFW#g#o0r#o;'S$O;'S;=`$g<%lO$OUF]^|SOt$Ouw$Ox}$O}!O0r!O!_$O!_!`1m!`#O$O#P#T$O#T#i0r#i#jA]#j#o0r#o;'S$O;'S;=`$g<%lO$OUG`UlQ|SOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~GwO#a~",
|
tokenData: "IS~R}OX$OXY$mYZ%WZp$Opq$mqs$Ost%qtu'Yuw$Owx'_xy'dyz'}z{$O{|(h|}$O}!O(h!O!P$O!P!Q0o!Q!R)Y!R![+w![!]9[!]!^%W!^!}$O!}#O9u#O#P;k#P#Q;p#Q#R$O#R#S<Z#S#T$O#T#Y<t#Y#Z>`#Z#b<t#b#cC|#c#f<t#f#gEP#g#h<t#h#iFS#i#o<t#o#p$O#p#qHd#q;'S$O;'S;=`$g<%l~$O~O$O~~H}S$TUzSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OS$jP;=`<%l$O^$tUzS!zYOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU%_UzS#QQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O^%xZiYzSOY%qYZ$OZt%qtu&kuw%qwx&kx#O%q#O#P&k#P;'S%q;'S;=`'S<%lO%qY&pSiYOY&kZ;'S&k;'S;=`&|<%lO&kY'PP;=`<%l&k^'VP;=`<%l%q~'_O#V~~'dO#T~U'kUzS#PQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(UUzS#_QOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU(mXzSOt$Ouw$Ox!Q$O!Q!R)Y!R![+w![#O$O#P;'S$O;'S;=`$g<%lO$OU)a`zSsQOt$Ouw$Ox!O$O!O!P*c!P!Q$O!Q![+w![#O$O#P#R$O#R#S,t#S#U$O#U#V-c#V#l$O#l#m.w#m;'S$O;'S;=`$g<%lO$OU*hWzSOt$Ouw$Ox!Q$O!Q![+Q![#O$O#P;'S$O;'S;=`$g<%lO$OU+XYzSsQOt$Ouw$Ox!Q$O!Q![+Q![#O$O#P#R$O#R#S*c#S;'S$O;'S;=`$g<%lO$OU,O[zSsQOt$Ouw$Ox!O$O!O!P*c!P!Q$O!Q![+w![#O$O#P#R$O#R#S,t#S;'S$O;'S;=`$g<%lO$OU,yWzSOt$Ouw$Ox!Q$O!Q![+w![#O$O#P;'S$O;'S;=`$g<%lO$OU-hXzSOt$Ouw$Ox!Q$O!Q!R.T!R!S.T!S#O$O#P;'S$O;'S;=`$g<%lO$OU.[XzSsQOt$Ouw$Ox!Q$O!Q!R.T!R!S.T!S#O$O#P;'S$O;'S;=`$g<%lO$OU.|[zSOt$Ouw$Ox!Q$O!Q![/r![!c$O!c!i/r!i#O$O#P#T$O#T#Z/r#Z;'S$O;'S;=`$g<%lO$OU/y[zSsQOt$Ouw$Ox!Q$O!Q![/r![!c$O!c!i/r!i#O$O#P#T$O#T#Z/r#Z;'S$O;'S;=`$g<%lO$OU0tWzSOt$Ouw$Ox!P$O!P!Q1^!Q#O$O#P;'S$O;'S;=`$g<%lO$OU1c^zSOY2_YZ$OZt2_tu3buw2_wx3bx!P2_!P!Q$O!Q!}2_!}#O8T#O#P5p#P;'S2_;'S;=`9U<%lO2_U2f^zS!bQOY2_YZ$OZt2_tu3buw2_wx3bx!P2_!P!Q6V!Q!}2_!}#O8T#O#P5p#P;'S2_;'S;=`9U<%lO2_Q3gX!bQOY3bZ!P3b!P!Q4S!Q!}3b!}#O4q#O#P5p#P;'S3b;'S;=`6P<%lO3bQ4VP!P!Q4YQ4_U!bQ#Z#[4Y#]#^4Y#a#b4Y#g#h4Y#i#j4Y#m#n4YQ4tVOY4qZ#O4q#O#P5Z#P#Q3b#Q;'S4q;'S;=`5j<%lO4qQ5^SOY4qZ;'S4q;'S;=`5j<%lO4qQ5mP;=`<%l4qQ5sSOY3bZ;'S3b;'S;=`6P<%lO3bQ6SP;=`<%l3bU6[WzSOt$Ouw$Ox!P$O!P!Q6t!Q#O$O#P;'S$O;'S;=`$g<%lO$OU6{bzS!bQOt$Ouw$Ox#O$O#P#Z$O#Z#[6t#[#]$O#]#^6t#^#a$O#a#b6t#b#g$O#g#h6t#h#i$O#i#j6t#j#m$O#m#n6t#n;'S$O;'S;=`$g<%lO$OU8Y[zSOY8TYZ$OZt8Ttu4quw8Twx4qx#O8T#O#P5Z#P#Q2_#Q;'S8T;'S;=`9O<%lO8TU9RP;=`<%l8TU9XP;=`<%l2_U9cUzS!PQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU9|W#aQzSOt$Ouw$Ox!_$O!_!`:f!`#O$O#P;'S$O;'S;=`$g<%lO$OU:kVzSOt$Ouw$Ox#O$O#P#Q;Q#Q;'S$O;'S;=`$g<%lO$OU;XU#`QzSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~;pO#W~U;wU#bQzSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU<bUzS!WQOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU<y^zSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$OU=|UxQzSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$OU>e_zSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#U?d#U#o<t#o;'S$O;'S;=`$g<%lO$OU?i`zSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#`<t#`#a@k#a#o<t#o;'S$O;'S;=`$g<%lO$OU@p`zSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#g<t#g#hAr#h#o<t#o;'S$O;'S;=`$g<%lO$OUAw`zSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#X<t#X#YBy#Y#o<t#o;'S$O;'S;=`$g<%lO$OUCQ^}QzSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^DT^#XWzSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^EW^#ZWzSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#o<t#o;'S$O;'S;=`$g<%lO$O^FZ`#YWzSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#f<t#f#gG]#g#o<t#o;'S$O;'S;=`$g<%lO$OUGb`zSOt$Ouw$Ox}$O}!O<t!O!Q$O!Q![<t![!_$O!_!`=u!`#O$O#P#T$O#T#i<t#i#jAr#j#o<t#o;'S$O;'S;=`$g<%lO$OUHkUlQzSOt$Ouw$Ox#O$O#P;'S$O;'S;=`$g<%lO$O~ISO#c~",
|
||||||
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO#P~~", 11)],
|
tokenizers: [operatorTokenizer, 1, 2, 3, tokenizer, new LocalTokenGroup("[~RP!O!PU~ZO#R~~", 11)],
|
||||||
topRules: {"Program":[0,26]},
|
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}],
|
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: 1922
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -368,6 +368,118 @@ describe('Parentheses', () => {
|
||||||
PositionalArg
|
PositionalArg
|
||||||
Number 3`)
|
Number 3`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('function call with named args on multiple lines in parens', () => {
|
||||||
|
expect(`(tail
|
||||||
|
arg1=true
|
||||||
|
arg2=30
|
||||||
|
)`).toMatchTree(`
|
||||||
|
ParenExpr
|
||||||
|
FunctionCall
|
||||||
|
Identifier tail
|
||||||
|
NamedArg
|
||||||
|
NamedArgPrefix arg1=
|
||||||
|
Boolean true
|
||||||
|
NamedArg
|
||||||
|
NamedArgPrefix arg2=
|
||||||
|
Number 30
|
||||||
|
`)
|
||||||
|
|
||||||
|
expect(`(
|
||||||
|
tail
|
||||||
|
arg1=true
|
||||||
|
arg2=30
|
||||||
|
)`).toMatchTree(`
|
||||||
|
ParenExpr
|
||||||
|
FunctionCall
|
||||||
|
Identifier tail
|
||||||
|
NamedArg
|
||||||
|
NamedArgPrefix arg1=
|
||||||
|
Boolean true
|
||||||
|
NamedArg
|
||||||
|
NamedArgPrefix arg2=
|
||||||
|
Number 30
|
||||||
|
`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('binop with newlines in parens', () => {
|
||||||
|
expect(`(
|
||||||
|
1 + 2
|
||||||
|
)`).toMatchTree(`
|
||||||
|
ParenExpr
|
||||||
|
BinOp
|
||||||
|
Number 1
|
||||||
|
Plus +
|
||||||
|
Number 2`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('comparison with newlines in parens', () => {
|
||||||
|
expect(`(
|
||||||
|
1 < 2
|
||||||
|
)`).toMatchTree(`
|
||||||
|
ParenExpr
|
||||||
|
ConditionalOp
|
||||||
|
Number 1
|
||||||
|
Lt <
|
||||||
|
Number 2`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('function call with multiple identifiers on separate lines in parens', () => {
|
||||||
|
expect(`(echo
|
||||||
|
arg1
|
||||||
|
arg2
|
||||||
|
arg3
|
||||||
|
)`).toMatchTree(`
|
||||||
|
ParenExpr
|
||||||
|
FunctionCall
|
||||||
|
Identifier echo
|
||||||
|
PositionalArg
|
||||||
|
Identifier arg1
|
||||||
|
PositionalArg
|
||||||
|
Identifier arg2
|
||||||
|
PositionalArg
|
||||||
|
Identifier arg3`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('Number literals', () => {
|
||||||
|
test('allows underscores in integer literals', () => {
|
||||||
|
expect('10_000').toMatchTree(`Number 10_000`)
|
||||||
|
expect('1_000_000').toMatchTree(`Number 1_000_000`)
|
||||||
|
expect('100_000').toMatchTree(`Number 100_000`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('allows underscores in decimal literals', () => {
|
||||||
|
expect('3.14_159').toMatchTree(`Number 3.14_159`)
|
||||||
|
expect('1_000.50').toMatchTree(`Number 1_000.50`)
|
||||||
|
expect('0.000_001').toMatchTree(`Number 0.000_001`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('allows underscores in negative numbers', () => {
|
||||||
|
expect('-10_000').toMatchTree(`Number -10_000`)
|
||||||
|
expect('-3.14_159').toMatchTree(`Number -3.14_159`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('allows underscores in positive numbers with explicit sign', () => {
|
||||||
|
expect('+10_000').toMatchTree(`Number +10_000`)
|
||||||
|
expect('+3.14_159').toMatchTree(`Number +3.14_159`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('works in expressions', () => {
|
||||||
|
expect('1_000 + 2_000').toMatchTree(`
|
||||||
|
BinOp
|
||||||
|
Number 1_000
|
||||||
|
Plus +
|
||||||
|
Number 2_000`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('works in function calls', () => {
|
||||||
|
expect('echo 10_000').toMatchTree(`
|
||||||
|
FunctionCall
|
||||||
|
Identifier echo
|
||||||
|
PositionalArg
|
||||||
|
Number 10_000`)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('BinOp', () => {
|
describe('BinOp', () => {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import {
|
||||||
} from 'reefvm'
|
} from 'reefvm'
|
||||||
|
|
||||||
import { dict } from './dict'
|
import { dict } from './dict'
|
||||||
|
import { json } from './json'
|
||||||
import { load } from './load'
|
import { load } from './load'
|
||||||
import { list } from './list'
|
import { list } from './list'
|
||||||
import { math } from './math'
|
import { math } from './math'
|
||||||
|
|
@ -13,6 +14,7 @@ import { str } from './str'
|
||||||
|
|
||||||
export const globals = {
|
export const globals = {
|
||||||
dict,
|
dict,
|
||||||
|
json,
|
||||||
load,
|
load,
|
||||||
list,
|
list,
|
||||||
math,
|
math,
|
||||||
|
|
@ -40,6 +42,7 @@ export const globals = {
|
||||||
'var?': function (this: VM, v: string) {
|
'var?': function (this: VM, v: string) {
|
||||||
return typeof v !== 'string' || this.scope.has(v)
|
return typeof v !== 'string' || this.scope.has(v)
|
||||||
},
|
},
|
||||||
|
ref: (fn: Function) => fn,
|
||||||
|
|
||||||
// env
|
// env
|
||||||
args: Bun.argv.slice(1),
|
args: Bun.argv.slice(1),
|
||||||
|
|
|
||||||
7
src/prelude/json.ts
Normal file
7
src/prelude/json.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
export const json = {
|
||||||
|
encode: (s: any) => JSON.stringify(s),
|
||||||
|
decode: (s: string) => JSON.parse(s),
|
||||||
|
}
|
||||||
|
|
||||||
|
; (json as any).parse = json.decode
|
||||||
|
; (json as any).stringify = json.encode
|
||||||
|
|
@ -73,6 +73,13 @@ export const list = {
|
||||||
const realItems = items.map(item => item.value)
|
const realItems = items.map(item => item.value)
|
||||||
return toValue(realList.splice(realStart, realDeleteCount, ...realItems))
|
return toValue(realList.splice(realStart, realDeleteCount, ...realItems))
|
||||||
},
|
},
|
||||||
|
insert: (list: Value, index: Value, item: Value) => {
|
||||||
|
if (list.type !== 'array') return toNull()
|
||||||
|
const realList = list.value as any[]
|
||||||
|
const realIndex = index.value as number
|
||||||
|
realList.splice(realIndex, 0, item)
|
||||||
|
return toValue(realList.length)
|
||||||
|
},
|
||||||
|
|
||||||
// sequence operations
|
// sequence operations
|
||||||
reverse: (list: any[]) => list.slice().reverse(),
|
reverse: (list: any[]) => list.slice().reverse(),
|
||||||
|
|
@ -143,3 +150,4 @@ export const list = {
|
||||||
; (list.pop as any).raw = true
|
; (list.pop as any).raw = true
|
||||||
; (list.shift as any).raw = true
|
; (list.shift as any).raw = true
|
||||||
; (list.unshift as any).raw = true
|
; (list.unshift as any).raw = true
|
||||||
|
; (list.insert as any).raw = true
|
||||||
|
|
@ -91,3 +91,15 @@ describe('environment', () => {
|
||||||
await expect(`list.first args | str.ends-with? 'shrimp.test.ts'`).toEvaluateTo(true)
|
await expect(`list.first args | str.ends-with? 'shrimp.test.ts'`).toEvaluateTo(true)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('ref', () => {
|
||||||
|
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')
|
||||||
|
})
|
||||||
|
|
|
||||||
84
src/prelude/tests/json.test.ts
Normal file
84
src/prelude/tests/json.test.ts
Normal file
|
|
@ -0,0 +1,84 @@
|
||||||
|
import { expect, describe, test } from 'bun:test'
|
||||||
|
|
||||||
|
describe('json', () => {
|
||||||
|
test('json.decode', () => {
|
||||||
|
expect(`json.decode '[1,2,3]'`).toEvaluateTo([1, 2, 3])
|
||||||
|
expect(`json.decode '"heya"'`).toEvaluateTo('heya')
|
||||||
|
expect(`json.decode '[true, false, null]'`).toEvaluateTo([true, false, null])
|
||||||
|
expect(`json.decode '{"a": true, "b": false, "c": "yeah"}'`).toEvaluateTo({ a: true, b: false, c: "yeah" })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('json.encode', () => {
|
||||||
|
expect(`json.encode [1 2 3]`).toEvaluateTo('[1,2,3]')
|
||||||
|
expect(`json.encode 'heya'`).toEvaluateTo('"heya"')
|
||||||
|
expect(`json.encode [true false null]`).toEvaluateTo('[true,false,null]')
|
||||||
|
expect(`json.encode [a=true b=false c='yeah'] | json.decode`).toEvaluateTo({ a: true, b: false, c: "yeah" })
|
||||||
|
})
|
||||||
|
|
||||||
|
test('edge cases - empty structures', () => {
|
||||||
|
expect(`json.decode '[]'`).toEvaluateTo([])
|
||||||
|
expect(`json.decode '{}'`).toEvaluateTo({})
|
||||||
|
expect(`json.encode []`).toEvaluateTo('[]')
|
||||||
|
expect(`json.encode [=]`).toEvaluateTo('{}')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('edge cases - special characters in strings', () => {
|
||||||
|
expect(`json.decode '"hello\\\\nworld"'`).toEvaluateTo('hello\nworld')
|
||||||
|
expect(`json.decode '"tab\\\\there"'`).toEvaluateTo('tab\there')
|
||||||
|
expect(`json.decode '"forward/slash"'`).toEvaluateTo('forward/slash')
|
||||||
|
expect(`json.decode '"with\\\\\\\\backslash"'`).toEvaluateTo('with\\backslash')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('numbers - integers and floats', () => {
|
||||||
|
expect(`json.decode '42'`).toEvaluateTo(42)
|
||||||
|
expect(`json.decode '0'`).toEvaluateTo(0)
|
||||||
|
expect(`json.decode '-17'`).toEvaluateTo(-17)
|
||||||
|
expect(`json.decode '3.14159'`).toEvaluateTo(3.14159)
|
||||||
|
expect(`json.decode '-0.5'`).toEvaluateTo(-0.5)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('numbers - scientific notation', () => {
|
||||||
|
expect(`json.decode '1e10'`).toEvaluateTo(1e10)
|
||||||
|
expect(`json.decode '2.5e-3'`).toEvaluateTo(2.5e-3)
|
||||||
|
expect(`json.decode '1.23E+5'`).toEvaluateTo(1.23e5)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('unicode - emoji and special characters', () => {
|
||||||
|
expect(`json.decode '"hello 👋"'`).toEvaluateTo('hello 👋')
|
||||||
|
expect(`json.decode '"🎉🚀✨"'`).toEvaluateTo('🎉🚀✨')
|
||||||
|
expect(`json.encode '你好'`).toEvaluateTo('"你好"')
|
||||||
|
expect(`json.encode 'café'`).toEvaluateTo('"café"')
|
||||||
|
})
|
||||||
|
|
||||||
|
test('nested structures - arrays', () => {
|
||||||
|
expect(`json.decode '[[1,2],[3,4],[5,6]]'`).toEvaluateTo([[1, 2], [3, 4], [5, 6]])
|
||||||
|
expect(`json.decode '[1,[2,[3,[4]]]]'`).toEvaluateTo([1, [2, [3, [4]]]])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('nested structures - objects', () => {
|
||||||
|
expect(`json.decode '{"user":{"name":"Alice","age":30}}'`).toEvaluateTo({
|
||||||
|
user: { name: 'Alice', age: 30 }
|
||||||
|
})
|
||||||
|
expect(`json.decode '{"a":{"b":{"c":"deep"}}}'`).toEvaluateTo({
|
||||||
|
a: { b: { c: 'deep' } }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('nested structures - mixed arrays and objects', () => {
|
||||||
|
expect(`json.decode '[{"id":1,"tags":["a","b"]},{"id":2,"tags":["c"]}]'`).toEvaluateTo([
|
||||||
|
{ id: 1, tags: ['a', 'b'] },
|
||||||
|
{ id: 2, tags: ['c'] }
|
||||||
|
])
|
||||||
|
expect(`json.decode '{"items":[1,2,3],"meta":{"count":3}}'`).toEvaluateTo({
|
||||||
|
items: [1, 2, 3],
|
||||||
|
meta: { count: 3 }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
test('error handling - invalid json', () => {
|
||||||
|
expect(`json.decode '{invalid}'`).toFailEvaluation()
|
||||||
|
expect(`json.decode '[1,2,3'`).toFailEvaluation()
|
||||||
|
expect(`json.decode 'undefined'`).toFailEvaluation()
|
||||||
|
expect(`json.decode ''`).toFailEvaluation()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -349,6 +349,22 @@ describe('collections', () => {
|
||||||
await expect(`arr = [1 2 3 4 5]; list.splice arr 3 2; arr`).toEvaluateTo([1, 2, 3])
|
await expect(`arr = [1 2 3 4 5]; list.splice arr 3 2; arr`).toEvaluateTo([1, 2, 3])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('list.insert adds element at index and mutates array', async () => {
|
||||||
|
await expect(`arr = [1 2 4 5]; list.insert arr 2 3; arr`).toEvaluateTo([1, 2, 3, 4, 5])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('list.insert returns array length', async () => {
|
||||||
|
await expect(`list.insert [1 2 4] 2 3`).toEvaluateTo(4)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('list.insert at start', async () => {
|
||||||
|
await expect(`arr = [2 3]; list.insert arr 0 1; arr`).toEvaluateTo([1, 2, 3])
|
||||||
|
})
|
||||||
|
|
||||||
|
test('list.insert at end', async () => {
|
||||||
|
await expect(`arr = [1 2]; list.insert arr 2 99; arr`).toEvaluateTo([1, 2, 99])
|
||||||
|
})
|
||||||
|
|
||||||
test('list.sort with no callback sorts ascending', async () => {
|
test('list.sort with no callback sorts ascending', async () => {
|
||||||
await expect(`list.sort [3 1 4 1 5] null`).toEvaluateTo([1, 1, 3, 4, 5])
|
await expect(`list.sort [3 1 4 1 5] null`).toEvaluateTo([1, 1, 3, 4, 5])
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user