Compare commits
2 Commits
99a5aa5312
...
cf09f51380
| Author | SHA1 | Date | |
|---|---|---|---|
| cf09f51380 | |||
| 3c6d0913c0 |
4
bun.lock
4
bun.lock
|
|
@ -62,11 +62,11 @@
|
||||||
|
|
||||||
"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#bffb83a5280a4d74e424c4e0f4fbd46f790227a3", { "peerDependencies": { "typescript": "^5" } }, "bffb83a5280a4d74e424c4e0f4fbd46f790227a3"],
|
"reefvm": ["reefvm@git+https://git.nose.space/defunkt/reefvm#15884ac239b7ab2310e0f87b82f9f1af485c28c7", { "peerDependencies": { "typescript": "^5" } }, "15884ac239b7ab2310e0f87b82f9f1af485c28c7"],
|
||||||
|
|
||||||
"style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="],
|
"style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="],
|
||||||
|
|
||||||
"tailwindcss": ["tailwindcss@4.1.16", "", {}, "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA=="],
|
"tailwindcss": ["tailwindcss@4.1.17", "", {}, "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q=="],
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
"typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
@ -31,4 +31,4 @@
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
"printWidth": 100
|
"printWidth": 100
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -232,6 +232,24 @@ export class Compiler {
|
||||||
case '%':
|
case '%':
|
||||||
instructions.push(['MOD'])
|
instructions.push(['MOD'])
|
||||||
break
|
break
|
||||||
|
case 'band':
|
||||||
|
instructions.push(['BIT_AND'])
|
||||||
|
break
|
||||||
|
case 'bor':
|
||||||
|
instructions.push(['BIT_OR'])
|
||||||
|
break
|
||||||
|
case 'bxor':
|
||||||
|
instructions.push(['BIT_XOR'])
|
||||||
|
break
|
||||||
|
case '<<':
|
||||||
|
instructions.push(['BIT_SHL'])
|
||||||
|
break
|
||||||
|
case '>>':
|
||||||
|
instructions.push(['BIT_SHR'])
|
||||||
|
break
|
||||||
|
case '>>>':
|
||||||
|
instructions.push(['BIT_USHR'])
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
throw new CompilerError(`Unsupported binary operator: ${opValue}`, op.from, op.to)
|
throw new CompilerError(`Unsupported binary operator: ${opValue}`, op.from, op.to)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
178
src/compiler/tests/bitwise.test.ts
Normal file
178
src/compiler/tests/bitwise.test.ts
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
import { expect, describe, test } from 'bun:test'
|
||||||
|
|
||||||
|
describe('bitwise operators', () => {
|
||||||
|
describe('band (bitwise AND)', () => {
|
||||||
|
test('basic AND operation', () => {
|
||||||
|
expect('5 band 3').toEvaluateTo(1)
|
||||||
|
// 5 = 0101, 3 = 0011, result = 0001 = 1
|
||||||
|
})
|
||||||
|
|
||||||
|
test('AND with zero', () => {
|
||||||
|
expect('5 band 0').toEvaluateTo(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('AND with all bits set', () => {
|
||||||
|
expect('15 band 7').toEvaluateTo(7)
|
||||||
|
// 15 = 1111, 7 = 0111, result = 0111 = 7
|
||||||
|
})
|
||||||
|
|
||||||
|
test('AND in assignment', () => {
|
||||||
|
expect('x = 12 band 10').toEvaluateTo(8)
|
||||||
|
// 12 = 1100, 10 = 1010, result = 1000 = 8
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('bor (bitwise OR)', () => {
|
||||||
|
test('basic OR operation', () => {
|
||||||
|
expect('5 bor 3').toEvaluateTo(7)
|
||||||
|
// 5 = 0101, 3 = 0011, result = 0111 = 7
|
||||||
|
})
|
||||||
|
|
||||||
|
test('OR with zero', () => {
|
||||||
|
expect('5 bor 0').toEvaluateTo(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('OR with all bits set', () => {
|
||||||
|
expect('8 bor 4').toEvaluateTo(12)
|
||||||
|
// 8 = 1000, 4 = 0100, result = 1100 = 12
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('bxor (bitwise XOR)', () => {
|
||||||
|
test('basic XOR operation', () => {
|
||||||
|
expect('5 bxor 3').toEvaluateTo(6)
|
||||||
|
// 5 = 0101, 3 = 0011, result = 0110 = 6
|
||||||
|
})
|
||||||
|
|
||||||
|
test('XOR with itself returns zero', () => {
|
||||||
|
expect('5 bxor 5').toEvaluateTo(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('XOR with zero returns same value', () => {
|
||||||
|
expect('7 bxor 0').toEvaluateTo(7)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('XOR in assignment', () => {
|
||||||
|
expect('result = 8 bxor 12').toEvaluateTo(4)
|
||||||
|
// 8 = 1000, 12 = 1100, result = 0100 = 4
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('bnot (bitwise NOT)', () => {
|
||||||
|
test('NOT of positive number', () => {
|
||||||
|
expect('bnot 5').toEvaluateTo(-6)
|
||||||
|
// ~5 = -6 (two\'s complement)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('NOT of zero', () => {
|
||||||
|
expect('bnot 0').toEvaluateTo(-1)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('NOT of negative number', () => {
|
||||||
|
expect('bnot -1').toEvaluateTo(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('double NOT returns original', () => {
|
||||||
|
expect('bnot (bnot 5)').toEvaluateTo(5)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('<< (left shift)', () => {
|
||||||
|
test('basic left shift', () => {
|
||||||
|
expect('5 << 2').toEvaluateTo(20)
|
||||||
|
// 5 << 2 = 20
|
||||||
|
})
|
||||||
|
|
||||||
|
test('shift by zero', () => {
|
||||||
|
expect('5 << 0').toEvaluateTo(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('shift by one', () => {
|
||||||
|
expect('3 << 1').toEvaluateTo(6)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('large shift', () => {
|
||||||
|
expect('1 << 10').toEvaluateTo(1024)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('>> (signed right shift)', () => {
|
||||||
|
test('basic right shift', () => {
|
||||||
|
expect('20 >> 2').toEvaluateTo(5)
|
||||||
|
// 20 >> 2 = 5
|
||||||
|
})
|
||||||
|
|
||||||
|
test('shift by zero', () => {
|
||||||
|
expect('20 >> 0').toEvaluateTo(20)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('preserves sign for negative numbers', () => {
|
||||||
|
expect('-20 >> 2').toEvaluateTo(-5)
|
||||||
|
// Sign is preserved
|
||||||
|
})
|
||||||
|
|
||||||
|
test('negative number right shift', () => {
|
||||||
|
expect('-8 >> 1').toEvaluateTo(-4)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('>>> (unsigned right shift)', () => {
|
||||||
|
test('basic unsigned right shift', () => {
|
||||||
|
expect('20 >>> 2').toEvaluateTo(5)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('unsigned shift of -1', () => {
|
||||||
|
expect('-1 >>> 1').toEvaluateTo(2147483647)
|
||||||
|
// -1 >>> 1 = 2147483647 (unsigned, no sign extension)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('unsigned shift of negative number', () => {
|
||||||
|
expect('-8 >>> 1').toEvaluateTo(2147483644)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('compound expressions', () => {
|
||||||
|
test('multiple bitwise operations', () => {
|
||||||
|
expect('(5 band 3) bor (8 bxor 12)').toEvaluateTo(5)
|
||||||
|
// (5 & 3) | (8 ^ 12) = 1 | 4 = 5
|
||||||
|
})
|
||||||
|
|
||||||
|
test('bitwise with variables', () => {
|
||||||
|
expect(`
|
||||||
|
a = 5
|
||||||
|
b = 3
|
||||||
|
a bor b
|
||||||
|
`).toEvaluateTo(7)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('shift operations with variables', () => {
|
||||||
|
expect(`
|
||||||
|
x = 16
|
||||||
|
y = 2
|
||||||
|
x >> y
|
||||||
|
`).toEvaluateTo(4)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('mixing shifts and bitwise', () => {
|
||||||
|
expect('(8 << 1) band 15').toEvaluateTo(0)
|
||||||
|
// (8 << 1) & 15 = 16 & 15 = 0
|
||||||
|
})
|
||||||
|
|
||||||
|
test('mixing shifts and bitwise 2', () => {
|
||||||
|
expect('(7 << 1) band 15').toEvaluateTo(14)
|
||||||
|
// (7 << 1) & 15 = 14 & 15 = 14
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('precedence', () => {
|
||||||
|
test('bitwise has correct precedence with arithmetic', () => {
|
||||||
|
expect('1 + 2 band 3').toEvaluateTo(3)
|
||||||
|
// (1 + 2) & 3 = 3 & 3 = 3
|
||||||
|
})
|
||||||
|
|
||||||
|
test('shift has correct precedence', () => {
|
||||||
|
expect('4 + 8 << 1').toEvaluateTo(24)
|
||||||
|
// (4 + 8) << 1 = 12 << 1 = 24
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -5,6 +5,12 @@ type Operator = { str: string; tokenName: keyof typeof terms }
|
||||||
const operators: Array<Operator> = [
|
const operators: Array<Operator> = [
|
||||||
{ str: 'and', tokenName: 'And' },
|
{ str: 'and', tokenName: 'And' },
|
||||||
{ str: 'or', tokenName: 'Or' },
|
{ str: 'or', tokenName: 'Or' },
|
||||||
|
{ str: 'band', tokenName: 'Band' },
|
||||||
|
{ str: 'bor', tokenName: 'Bor' },
|
||||||
|
{ str: 'bxor', tokenName: 'Bxor' },
|
||||||
|
{ str: '>>>', tokenName: 'Ushr' }, // Must come before >>
|
||||||
|
{ str: '>>', tokenName: 'Shr' },
|
||||||
|
{ str: '<<', tokenName: 'Shl' },
|
||||||
{ str: '>=', tokenName: 'Gte' },
|
{ str: '>=', tokenName: 'Gte' },
|
||||||
{ str: '<=', tokenName: 'Lte' },
|
{ str: '<=', tokenName: 'Lte' },
|
||||||
{ str: '!=', tokenName: 'Neq' },
|
{ str: '!=', tokenName: 'Neq' },
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
@top Program { item* }
|
@top Program { item* }
|
||||||
|
|
||||||
@external tokens operatorTokenizer from "./operatorTokenizer" { Star, Slash, Plus, Minus, And, Or, Eq, EqEq, Neq, Lt, Lte, Gt, Gte, Modulo, PlusEq, MinusEq, StarEq, SlashEq, ModuloEq }
|
@external tokens operatorTokenizer from "./operatorTokenizer" { Star, Slash, Plus, Minus, And, Or, Eq, EqEq, Neq, Lt, Lte, Gt, Gte, Modulo, PlusEq, MinusEq, StarEq, SlashEq, ModuloEq, Band, Bor, Bxor, Shl, Shr, Ushr }
|
||||||
|
|
||||||
@tokens {
|
@tokens {
|
||||||
@precedence { Number Regex }
|
@precedence { Number Regex }
|
||||||
|
|
@ -47,6 +47,7 @@ null { @specialize[@name=Null]<Identifier, "null"> }
|
||||||
comparison @left,
|
comparison @left,
|
||||||
multiplicative @left,
|
multiplicative @left,
|
||||||
additive @left,
|
additive @left,
|
||||||
|
bitwise @left,
|
||||||
call
|
call
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -184,7 +185,13 @@ BinOp {
|
||||||
(expression | BinOp) !multiplicative Star (expression | BinOp) |
|
(expression | BinOp) !multiplicative Star (expression | BinOp) |
|
||||||
(expression | BinOp) !multiplicative Slash (expression | BinOp) |
|
(expression | BinOp) !multiplicative Slash (expression | BinOp) |
|
||||||
(expression | BinOp) !additive Plus (expression | BinOp) |
|
(expression | BinOp) !additive Plus (expression | BinOp) |
|
||||||
(expression | BinOp) !additive Minus (expression | BinOp)
|
(expression | BinOp) !additive Minus (expression | BinOp) |
|
||||||
|
(expression | BinOp) !bitwise Band (expression | BinOp) |
|
||||||
|
(expression | BinOp) !bitwise Bor (expression | BinOp) |
|
||||||
|
(expression | BinOp) !bitwise Bxor (expression | BinOp) |
|
||||||
|
(expression | BinOp) !bitwise Shl (expression | BinOp) |
|
||||||
|
(expression | BinOp) !bitwise Shr (expression | BinOp) |
|
||||||
|
(expression | BinOp) !bitwise Ushr (expression | BinOp)
|
||||||
}
|
}
|
||||||
|
|
||||||
ParenExpr {
|
ParenExpr {
|
||||||
|
|
|
||||||
|
|
@ -19,48 +19,54 @@ export const
|
||||||
StarEq = 17,
|
StarEq = 17,
|
||||||
SlashEq = 18,
|
SlashEq = 18,
|
||||||
ModuloEq = 19,
|
ModuloEq = 19,
|
||||||
Identifier = 20,
|
Band = 20,
|
||||||
AssignableIdentifier = 21,
|
Bor = 21,
|
||||||
Word = 22,
|
Bxor = 22,
|
||||||
IdentifierBeforeDot = 23,
|
Shl = 23,
|
||||||
Do = 24,
|
Shr = 24,
|
||||||
Comment = 25,
|
Ushr = 25,
|
||||||
Program = 26,
|
Identifier = 26,
|
||||||
PipeExpr = 27,
|
AssignableIdentifier = 27,
|
||||||
WhileExpr = 29,
|
Word = 28,
|
||||||
keyword = 70,
|
IdentifierBeforeDot = 29,
|
||||||
ConditionalOp = 31,
|
Do = 30,
|
||||||
ParenExpr = 32,
|
Comment = 31,
|
||||||
IfExpr = 33,
|
Program = 32,
|
||||||
FunctionCall = 35,
|
PipeExpr = 33,
|
||||||
DotGet = 36,
|
WhileExpr = 35,
|
||||||
Number = 37,
|
keyword = 76,
|
||||||
PositionalArg = 38,
|
ConditionalOp = 37,
|
||||||
FunctionDef = 39,
|
ParenExpr = 38,
|
||||||
Params = 40,
|
IfExpr = 39,
|
||||||
NamedParam = 41,
|
FunctionCall = 41,
|
||||||
NamedArgPrefix = 42,
|
DotGet = 42,
|
||||||
String = 43,
|
Number = 43,
|
||||||
StringFragment = 44,
|
PositionalArg = 44,
|
||||||
Interpolation = 45,
|
FunctionDef = 45,
|
||||||
EscapeSeq = 46,
|
Params = 46,
|
||||||
Boolean = 47,
|
NamedParam = 47,
|
||||||
Null = 48,
|
NamedArgPrefix = 48,
|
||||||
colon = 49,
|
String = 49,
|
||||||
CatchExpr = 50,
|
StringFragment = 50,
|
||||||
Block = 52,
|
Interpolation = 51,
|
||||||
FinallyExpr = 53,
|
EscapeSeq = 52,
|
||||||
Underscore = 56,
|
Boolean = 53,
|
||||||
NamedArg = 57,
|
Null = 54,
|
||||||
ElseIfExpr = 58,
|
colon = 55,
|
||||||
ElseExpr = 60,
|
CatchExpr = 56,
|
||||||
FunctionCallOrIdentifier = 61,
|
Block = 58,
|
||||||
BinOp = 62,
|
FinallyExpr = 59,
|
||||||
Regex = 63,
|
Underscore = 62,
|
||||||
Dict = 64,
|
NamedArg = 63,
|
||||||
Array = 65,
|
ElseIfExpr = 64,
|
||||||
FunctionCallWithBlock = 66,
|
ElseExpr = 66,
|
||||||
TryExpr = 67,
|
FunctionCallOrIdentifier = 67,
|
||||||
Throw = 69,
|
BinOp = 68,
|
||||||
CompoundAssign = 71,
|
Regex = 69,
|
||||||
Assign = 72
|
Dict = 70,
|
||||||
|
Array = 71,
|
||||||
|
FunctionCallWithBlock = 72,
|
||||||
|
TryExpr = 73,
|
||||||
|
Throw = 75,
|
||||||
|
CompoundAssign = 77,
|
||||||
|
Assign = 78
|
||||||
|
|
|
||||||
|
|
@ -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:72, if:80, null:108, catch:114, finally:120, end:122, else:130, try:148, throw:152}
|
||||||
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: "9hQYQbOOO!dOpO'#DWO!iOSO'#D_O$_QcO'#DqO'hQcO'#E`OOQ`'#En'#EnO(kQRO'#DrO*mQcO'#E^O+WQbO'#DSOOQa'#Dt'#DtO-YQbO'#DuOOQa'#E`'#E`O-aQcO'#E`O.xQcO'#E_O/}QcO'#E^O0XQRO'#D{OOQ`'#E^'#E^O0mQbO'#E^O0tQQO'#E]OOQ`'#E]'#E]OOQ`'#D}'#D}QYQbOOO1PQbO'#DZO1[QbO'#DTO2PQbO'#DPO2tQQO'#DwO2PQbO'#DyO2yObO,59rO3UQbO'#DaO3^QWO'#DbOOOO'#Ef'#EfOOOO'#ES'#ESO3rOSO,59yOOQa,59y,59yOOQ`'#DY'#DYO4QQbO'#DmOOQ`'#Ed'#EdOOQ`'#EP'#EPO4[QbO,59qOOQa'#E_'#E_O2PQbO,5:^O2PQbO,5:^O2PQbO,5:^O2PQbO,5:^O2PQbO,59mO2PQbO,59mO2PQbO,59mO5UQRO,59nO5]QQO,59nO5eQQO,59nO5pQRO,59nO5wQRO,59nO6VQQO'#C}OOQ`'#EV'#EVO6[QbO,5:aO6cQQO,5:`OOQa,5:a,5:aO6nQbO,5:aO+WQbO,5:hO+WQbO,5:gO6xQbO,5:bO7PQbO,59iOOQ`,5:w,5:wO+WQbO'#EOOOQ`-E7{-E7{OOQ`'#EQ'#EQO7kQbO'#D[O7vQbO'#D]OOQO'#ER'#ERO7nQQO'#D[O8UQQO,59uO8ZQcO'#E_O8bQRO'#EbO9XQRO'#EbOOQO'#Eb'#EbO9`QQO,59oO9eQRO,59kO9lQRO,59kO6xQbO,5:cO9wQcO,5:eO;PQcO,5:eO;sQcO,5:eOOQa1G/^1G/^OOOO,59{,59{OOOO,59|,59|OOOO-E8Q-E8QOOQa1G/e1G/eOOQ`,5:X,5:XOOQ`-E7}-E7}OOQa1G/x1G/xO=UQcO1G/xO=`QcO1G/xO>nQcO1G/xO>xQcO1G/xO?VQcO1G/xOOQa1G/X1G/XO@eQcO1G/XO@lQcO1G/XO@sQcO1G/XOOQa1G/Y1G/YOOQ`-E8T-E8TO@zQQO1G/zOOQa1G/{1G/{OAVQbO1G/{OOQO'#EW'#EWO@zQQO1G/zOOQa1G/z1G/zOOQ`'#EX'#EXOAVQbO1G/{OAaQbO1G0SOA{QbO1G0ROBgQbO'#DhOBxQbO'#DhOC]QbO1G/|OOQ`-E7|-E7|OOQ`,5:j,5:jOOQ`-E8O-E8OOChQQO,59vOOQO,59w,59wOOQO-E8P-E8POCpQbO1G/aO6xQbO1G/ZO6xQbO1G/VOCwQbO1G/}ODSQQO7+%fOOQa7+%f7+%fOD_QbO7+%gOOQa7+%g7+%gOOQO-E8U-E8UOOQ`-E8V-E8VOOQ`'#ET'#ETODiQQO'#ETODqQbO'#EmOOQ`,5:S,5:SOEUQbO'#DfOEZQQO'#DiOOQ`7+%h7+%hOE`QbO7+%hOEeQbO7+%hOEmQbO7+${OE{QbO7+${OF]QbO7+$uOFeQbO7+$qOOQ`7+%i7+%iOFjQbO7+%iOFoQbO7+%iOOQa<<IQ<<IQOOQa<<IR<<IROOQ`,5:o,5:oOOQ`-E8R-E8ROFwQQO,5:QO6xQbO,5:TOOQ`<<IS<<ISOF|QbO<<ISOOQ`<<Hg<<HgOGRQbO<<HgOGWQbO<<HgOG`QbO<<HgOOQ`'#EU'#EUOGkQbO<<HaOGsQbO'#DpOOQ`<<Ha<<HaOG{QbO<<HaOOQ`<<H]<<H]OOQ`<<IT<<ITOHQQbO<<ITO6xQbO1G/lOOQ`1G/o1G/oOOQ`AN>nAN>nOOQ`AN>RAN>ROHVQbOAN>ROH[QbOAN>ROOQ`-E8S-E8SOOQ`AN={AN={OHdQbOAN={O1[QbO,5:YO6xQbO,5:[OOQ`AN>oAN>oOOQ`7+%W7+%WOOQ`G23mG23mOHiQbOG23mPHnQbO'#DnOOQ`G23gG23gOHsQQO1G/tOOQ`1G/v1G/vOOQ`LD)XLD)XO6xQbO7+%`OOQ`<<Hz<<Hz",
|
||||||
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: "H{~O#OOSoOS~OjROk_OlZOmPOnfOthOxgO{ZO!VZO!WZO!gZO!liO!njO#TWO#XQO#`cO#dXO#eYO~O#VkO~O!SnO#XqO#ZlO#[mO~OjwOlZOmPOnfO{ZO!QsO!VZO!WZO!`rO!gZO#TWO#XQO#dXO#eYOT#RXU#RXW#RXX#RXY#RXZ#RX[#RX]#RX~OP#RXQ#RXR#RXS#RX^#RXd#RXe#RXf#RXg#RXh#RXi#RXr!eX!X!eX#`!eX#g!eX#c!eX!Z!eX!^!eX!_!eX!c!eX~P!wOP#SXQ#SXR#SXS#SXT#SXU#SXW#SXX#SXY#SXZ#SX[#SX]#SX^#SXd#SXe#SXf#SXg#SXh#SXi#SXr#SX#`#SX#g#SX#c#SX!Z#SX!^#SX!_#SX!c#SX~OjwOlZOmPOnfO{ZO!QsO!VZO!WZO!`rO!gZO#TWO#XQO#dXO#eYO!X#SX~P%qOPyOQyORzOSzOT}OU!OOW|OX|OY|OZ|O[|O]|O^xOd{Oe{Of{Og{Oh{Oi{O~OPyOQyORzOSzOd{Oe{Of{Og{Oh{Oi{Or#QX~O#`#QX#g#QX!Z#QX!^#QX!_#QX#c#QX!c#QX~P)xOjROk_OlZOmPOnfOthOxgO{ZO!VZO!WZO!gZO!liO!njO#TWO#XQO#dXO#eYO~OjwOlZOmPO{ZO!QsO!VZO!WZO!gZO#TWO#XQO#`!VO#dXO#eYO~O#f!YO~P,_OV![O~P%qOP#RXQ#RXR#RXS#RXT#RXU#RXW#RXX#RXY#RXZ#RX[#RX]#RX^#RXd#RXe#RXf#RXg#RXh#RXi#RXr#QX~O#`#QX#g#QX!Z#QX!^#QX!_#QX#c#QX!c#QX~P-hOr#QX#`#QX#g#QX!Z#QX!^#QX!_#QX#c#QX!c#QX~OT}OU!OO~P/cOV![O_!]O`!]Oa!]Ob!]Oc!]O~O!X!^O~P/cOr!aO#`!`O#g!`O~Oj!cO!Q!eO!X!OP~Oj!iOlZOmPO{ZO!VZO!WZO!gZO#TWO#XQO#dXO#eYO~OjwOlZOmPO{ZO!VZO!WZO!gZO#TWO#XQO#dXO#eYO~O!X!pO~Oj!tO{!tO#TWO~Oj!uO#TWO~O#X!vO#Z!vO#[!vO#]!vO#^!vO#_!vO~O!SnO#X!xO#ZlO#[mO~OnfO!`!yO~P2POnfO!QsO!`rOrya!Xya#`ya#gya#cya!Zya!^ya!_ya!cya~P2PO#c#VO~P)xO#c#VOr#QX~O!X!^O#c#VOr#QX~O#c#VO~P-hOT}OU!OO#c#VOr#QX~Or!aO~O#f#YO~P,_O!QsO#`#[O#f#^O~O#`#_O#f#YO~P2PO#`#dO~P+WOr!aO#`qa#gqa#cqa!Zqa!^qa!_qa!cqa~Oj!cO!Q!eO!X!OX~O{#jO!V#jO!W#jO#XQO~O!X#lO~O!X#RX~P!wOT}OU!OO!X#UX~OT}OU!OOW|OX|OY|OZ|O[|O]|O~O!X#UX~P8mO!X#mO~O!X#nO~P8mOT}OU!OO!X#nO~Or!ma#`!ma#g!ma!Z!ma!^!ma!_!ma#c!ma!c!ma~P(kOr!ma#`!ma#g!ma!Z!ma!^!ma!_!ma#c!ma!c!ma~OPyOQyORzOSzOd{Oe{Of{Og{Oh{Oi{O~P:eOT}OU!OO~P:eO^xOR!fiS!fid!fie!fif!fig!fih!fii!fir!fi#`!fi#g!fi#c!fi!Z!fi!^!fi!_!fi!c!fi~OP!fiQ!fi~P;}OPyOQyO~P;}OPyOQyOd!fie!fif!fig!fih!fii!fir!fi#`!fi#g!fi#c!fi!Z!fi!^!fi!_!fi!c!fi~OR!fiS!fi~P=jORzOSzO^xO~P=jORzOSzO~P=jOW|OX|OY|OZ|O[|O]|OTuirui#`ui#gui#cui!Xui!Zui!^ui!_ui!cui~OU!OO~P?aOU!OO~P?sOUui~P?aO!QsO#`#[O#f#qO~O#`#_O#f#sO~P2POr!aO#`!pi#g!pi!Z!pi!^!pi!_!pi#c!pi!c!pi~Or!aO#`!oi#g!oi!Z!oi!^!oi!_!oi#c!oi!c!oi~Or!aO!Z![X!^![X!_![X!c![X~O#`#vO!Z#aP!^#aP!_#aP!c#aP~P+WO!Z#zO!^#{O!_#|O~O!Q!eO!X!Oa~O#`$QO~P+WO!Z#zO!^#{O!_$TO~O!QsO#`#[O#f$WO~O#`#_O#f$XO~P2POr!aO#`$YO~O#`#vO!Z#aX!^#aX!_#aX!c#aX~P+WOj$[O~O!X$]O~O!_$^O~O!^#{O!_$^O~Or!aO!Z#zO!^#{O!_$`O~O#`#vO!Z#aP!^#aP!_#aP~P+WO!_$gO!c$fO~O!_$iO~O!_$jO~O!^#{O!_$jO~O!X$lO~O!_$nO~O!_$oO~O!^#{O!_$oO~O!Z#zO!^#{O!_$oO~O!_$sO!c$fO~Ox$uO!X$vO~O!_$sO~O!_$wO~O!_$yO~O!^#{O!_$yO~O!_$|O~O!_%PO~Ox$uO~O!X%QO~O{!g~",
|
||||||
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: "5O#cPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP#dP#zP$`%W#dP&[&tP't'z(k(nP(tP)s)sPPP)wP*T*mPPP+T+gP+k+q,VP,y-u#z#zP#zP#z#z.s.y/V/_/e/o/u/|0S0Y0dPPP0n0r1f3QP4QP4WP4^PPPPPP4b4hr`Oe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QR!QWu`OWe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%Qr^Oe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QQ!TWS!jg$uQ!ohQ!sjQ#R!OR#T}xSOWeg![!]!^!a!p#d#l#m#n#x$Q$]$l$u$v%QxZRSYhjsvxyz{|}!O!W!Z!i#Z#`#rQ!tkR!ultTOWe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QT!lg$utROWe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QxwRSYhjsvxyz{|}!O!W!Z!i#Z#`#rT!ig$uXtRSv!ir`Oe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QWrRSv!iQ!QWR!ysR!hfX!ff!d!g#i!rZORSWYeghjsvxyz{|}!O!W!Z![!]!^!a!i!p#Z#`#d#l#m#n#r#x$Q$]$l$u$v%QR#j!eTnQpQ$O#eQ$V#oQ$b$PR$q$cQ#e!^Q#o!pQ$R#mQ$S#nQ$m$]Q$x$lQ%O$vR%R%QQ#}#eQ$U#oQ$_$OQ$a$PQ$k$VS$p$b$cR$z$qWtRSv!iQ!XYQ#X!WX#[!X#X#]#pT$d$R$eQ$h$RR$t$euTOWe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QrVOe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QQ!PWQ!rjQ!{yQ#OzR#Q{!sZORSWYeghjsvxyz{|}!O!W!Z![!]!^!a!i!p#Z#`#d#l#m#n#r#x$Q$]$l$u$v%Q|ZRSYghjsvxyz{|}!O!W!Z!i#Z#`#r$uu[OWe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QQeOR!be^!_b!U#a#b#c#w$PR#f!_UvRS!iR!zvQ!dfR#h!dQ!gfQ#i!dT#k!g#iQpQR!wpS#x#d$QR$Z#xQ$e$RR$r$eQ!WYR#W!WQ#]!XQ#p#XT#t#]#pQ#`!ZQ#r#ZT#u#`#rTdOeSbOeQ!UWQ#a![Q#b!]`#c!^!p#m#n$]$l$v%QQ#g!aU#w#d#x$QR$P#ltUOWe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QWrRSv!iQ!ZYS!kg$uQ!nhQ!qjQ!ysQ!{xQ!|yQ!}zQ#P{Q#R|Q#S}Q#U!OQ#Z!WX#_!Z#Z#`#rr]Oe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%Q|wRSYghjsvxyz{|}!O!W!Z!i#Z#`#r$uR!SWQ!mgR$}$uXuRSv!iToQpQ#y#dR$c$QraOe![!]!^!a!p#d#l#m#n#x$Q$]$l$v%QR!RW",
|
||||||
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 Band Bor Bxor Shl Shr Ushr 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",
|
||||||
maxTerm: 109,
|
maxTerm: 115,
|
||||||
context: trackScope,
|
context: trackScope,
|
||||||
nodeProps: [
|
nodeProps: [
|
||||||
["closedBy", 49,"end"]
|
["closedBy", 55,"end"]
|
||||||
],
|
],
|
||||||
propSources: [highlighting],
|
propSources: [highlighting],
|
||||||
skippedNodes: [0,25],
|
skippedNodes: [0,31],
|
||||||
repeatNodeCount: 11,
|
repeatNodeCount: 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!xYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[U|S#YQOt#{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#T~~(OO#R~U(VU|S!}QOt#{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#_Q|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#U~U9eU#`Q|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#`#a<a#a#o,w#o;'S#{;'S;=`$d<%lO#{U<f^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#g,w#g#h=b#h#o,w#o;'S#{;'S;=`$d<%lO#{U=g^|SOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#X,w#X#Y>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~",
|
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!SSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{S$gP;=`<%l#{^$qU!SS#OYOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U%[U!SS#`QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^%sW!SSOp#{pq&]qt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{^&dZoY!SSOY&]YZ#{Zt&]tu'Vuw&]wx'Vx#O&]#O#P'V#P;'S&];'S;=`'n<%lO&]Y'[SoYOY'VZ;'S'V;'S;=`'h<%lO'VY'kP;=`<%l'V^'qP;=`<%l&]~'yO#Z~~(OO#X~U(VU!SS#TQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U(pU!SS#cQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U)XW!SSOt#{uw#{x!Q#{!Q![)q![#O#{#P;'S#{;'S;=`$d<%lO#{U)xY!SS{QOt#{uw#{x!O#{!O!P*h!P!Q#{!Q![)q![#O#{#P;'S#{;'S;=`$d<%lO#{U*mW!SSOt#{uw#{x!Q#{!Q![+V![#O#{#P;'S#{;'S;=`$d<%lO#{U+^W!SS{QOt#{uw#{x!Q#{!Q![+V![#O#{#P;'S#{;'S;=`$d<%lO#{U+{^!SSOt#{uw#{x}#{}!O,w!O!Q#{!Q![)q![!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{U,|[!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{U-yU!QQ!SSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U.bW!SSOt#{uw#{x!P#{!P!Q.z!Q#O#{#P;'S#{;'S;=`$d<%lO#{U/P^!SSOY/{YZ#{Zt/{tu1Ouw/{wx1Ox!P/{!P!Q#{!Q!}/{!}#O5q#O#P3^#P;'S/{;'S;=`6r<%lO/{U0S^!SS!gQOY/{YZ#{Zt/{tu1Ouw/{wx1Ox!P/{!P!Q3s!Q!}/{!}#O5q#O#P3^#P;'S/{;'S;=`6r<%lO/{Q1TX!gQOY1OZ!P1O!P!Q1p!Q!}1O!}#O2_#O#P3^#P;'S1O;'S;=`3m<%lO1OQ1sP!P!Q1vQ1{U!gQ#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!SSOt#{uw#{x!P#{!P!Q4b!Q#O#{#P;'S#{;'S;=`$d<%lO#{U4ib!SS!gQOt#{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[!SSOY5qYZ#{Zt5qtu2_uw5qwx2_x#O5q#O#P2w#P#Q/{#Q;'S5q;'S;=`6l<%lO5qU6oP;=`<%l5qU6uP;=`<%l/{U7PU!SS!XQOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U7jW#eQ!SSOt#{uw#{x!_#{!_!`8S!`#O#{#P;'S#{;'S;=`$d<%lO#{U8XV!SSOt#{uw#{x#O#{#P#Q8n#Q;'S#{;'S;=`$d<%lO#{U8uU#dQ!SSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~9^O#[~U9eU#fQ!SSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U:OU!SS!`QOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{U:g]!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#U;`#U#o,w#o;'S#{;'S;=`$d<%lO#{U;e^!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#`,w#`#a<a#a#o,w#o;'S#{;'S;=`$d<%lO#{U<f^!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#g,w#g#h=b#h#o,w#o;'S#{;'S;=`$d<%lO#{U=g^!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#X,w#X#Y>c#Y#o,w#o;'S#{;'S;=`$d<%lO#{U>j[!VQ!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^?g[#]W!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^@d[#_W!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#o,w#o;'S#{;'S;=`$d<%lO#{^Aa^#^W!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#f,w#f#gB]#g#o,w#o;'S#{;'S;=`$d<%lO#{UBb^!SSOt#{uw#{x}#{}!O,w!O!_#{!_!`-r!`#O#{#P#T#{#T#i,w#i#j=b#j#o,w#o;'S#{;'S;=`$d<%lO#{UCeUrQ!SSOt#{uw#{x#O#{#P;'S#{;'S;=`$d<%lO#{~C|O#g~",
|
||||||
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#V~~", 11)],
|
||||||
topRules: {"Program":[0,26]},
|
topRules: {"Program":[0,32]},
|
||||||
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: 26, get: (value: any, stack: any) => (specializeKeyword(value, stack) << 1), external: specializeKeyword},{term: 26, get: (value: keyof typeof spec_Identifier) => spec_Identifier[value] || -1}],
|
||||||
tokenPrec: 1634
|
tokenPrec: 1834
|
||||||
})
|
})
|
||||||
|
|
|
||||||
72
src/parser/tests/bitwise.test.ts
Normal file
72
src/parser/tests/bitwise.test.ts
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { expect, describe, test } from 'bun:test'
|
||||||
|
|
||||||
|
import '../shrimp.grammar' // Importing this so changes cause it to retest!
|
||||||
|
|
||||||
|
describe('bitwise operators - grammar', () => {
|
||||||
|
test('parses band (bitwise AND)', () => {
|
||||||
|
expect('5 band 3').toMatchTree(`
|
||||||
|
BinOp
|
||||||
|
Number 5
|
||||||
|
Band band
|
||||||
|
Number 3`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('parses bor (bitwise OR)', () => {
|
||||||
|
expect('5 bor 3').toMatchTree(`
|
||||||
|
BinOp
|
||||||
|
Number 5
|
||||||
|
Bor bor
|
||||||
|
Number 3`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('parses bxor (bitwise XOR)', () => {
|
||||||
|
expect('5 bxor 3').toMatchTree(`
|
||||||
|
BinOp
|
||||||
|
Number 5
|
||||||
|
Bxor bxor
|
||||||
|
Number 3`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('parses << (left shift)', () => {
|
||||||
|
expect('5 << 2').toMatchTree(`
|
||||||
|
BinOp
|
||||||
|
Number 5
|
||||||
|
Shl <<
|
||||||
|
Number 2`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('parses >> (signed right shift)', () => {
|
||||||
|
expect('20 >> 2').toMatchTree(`
|
||||||
|
BinOp
|
||||||
|
Number 20
|
||||||
|
Shr >>
|
||||||
|
Number 2`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('parses >>> (unsigned right shift)', () => {
|
||||||
|
expect('-1 >>> 1').toMatchTree(`
|
||||||
|
BinOp
|
||||||
|
Number -1
|
||||||
|
Ushr >>>
|
||||||
|
Number 1`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('parses bnot (bitwise NOT) as function call', () => {
|
||||||
|
expect('bnot 5').toMatchTree(`
|
||||||
|
FunctionCall
|
||||||
|
Identifier bnot
|
||||||
|
PositionalArg
|
||||||
|
Number 5`)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('bitwise operators work in expressions', () => {
|
||||||
|
expect('x = 5 band 3').toMatchTree(`
|
||||||
|
Assign
|
||||||
|
AssignableIdentifier x
|
||||||
|
Eq =
|
||||||
|
BinOp
|
||||||
|
Number 5
|
||||||
|
Band band
|
||||||
|
Number 3`)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -56,6 +56,7 @@ export const globals = {
|
||||||
|
|
||||||
// boolean/logic
|
// boolean/logic
|
||||||
not: (v: any) => !v,
|
not: (v: any) => !v,
|
||||||
|
bnot: (n: number) => ~(n | 0),
|
||||||
|
|
||||||
// utilities
|
// utilities
|
||||||
inc: (n: number) => n + 1,
|
inc: (n: number) => n + 1,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user