diff --git a/.cspell.json b/.cspell.json index b38edf2f..0045e03c 100644 --- a/.cspell.json +++ b/.cspell.json @@ -76,6 +76,7 @@ "gotchas", "greaterthan", "greaterthanorequal", + "groth", "hardcodes", "hash", "hashoutputs", diff --git a/docs/function-call-convention.md b/docs/function-call-convention.md new file mode 100644 index 00000000..6eb0883b --- /dev/null +++ b/docs/function-call-convention.md @@ -0,0 +1,88 @@ +# The user-function calling convention and its op-cost + +This note documents the argument-staging convention for user-defined function calls +(`OP_DEFINE`/`OP_INVOKE`), why the original upstream convention caused a measurable op-cost +regression on call-dense contracts, and the fix (`d0409c2`). It is written against the +`feat/multi-returns` branch. + +## The regression + +After porting the zk-verifier contracts from the old `feat/library-support` fork to this branch, +every byte-scored benchmark entry improved, but the BN254 op-bound multi-input families regressed ++1.3–2.3%. Per-stage decomposition localised the loss to *unrolled, call-dense* bodies (the lazy +tower's fused-miller and final-exp stages: thousands of small multi-return calls per chunk), while +*loop-shaped* stages improved. Constant hoisting and inlining were ruled out by direct measurement; +disassembly of the same Miller chunk under both compilers showed the new one emitting smaller +bytecode but executing ~5% more instructions. + +## The cause + +**The argument-staging convention at `OP_INVOKE` call sites.** The compiler expected the *last* +parameter on top of the stack at function entry ("like builtin functions"). Arguments are staged by +bringing each one to the top of the stack in turn — so staging them left-to-right leaves the last +argument on top, which sounds like a match. But the staging ops themselves are what cost: for the +overwhelmingly common call shape — variables passed in declaration order, e.g. `fp2Sub(a0, a1, b0, +b1)` over locals laid out `[a0, a1, b0, b1]` (first on top) — building the *reversed* layout costs +real reversal instructions at **every call site**: + +``` +convention: last param on top convention: first param on top +-------------------------------- -------------------------------- + OP_SWAP OP_0 OP_INVOKE OP_0 OP_INVOKE +OP_2DUP OP_SWAP OP_0 OP_INVOKE OP_2DUP OP_0 OP_INVOKE +``` + +(2-argument call, measured; with 4–6 arguments the reversal grows into `OP_SWAP OP_2SWAP OP_SWAP` +chains.) The old fork compiled bodies against a **first-parameter-on-top** entry layout and staged +arguments **right-to-left**: each argument is still brought to the top in turn, but in reverse +order, so for declaration-order variable arguments the emitted ` OP_ROLL` pairs cancel to +nothing in the peephole optimiser. A typical call costs **zero staging instructions**. + +The overhead was ~1–3 executed instructions per call depending on arity. On the BN254 lazy tower +(~12–14k executed calls per proof) that multiplied to ~+2.9M op-cost on the residue pipeline and +~+5M on groth16-chunked — and for op-bound contracts, whose unlocking scripts are zero-padded until +`(41 + length) × 800` covers the op budget, every 800 op-cost is one more mandatory padding byte. + +## The fix + +`GenerateTargetTraversal` now: + +1. **Seeds function bodies with the first parameter on top** (`compileGlobalFunctionBody` visits + parameters in declaration order; `visitParameter` pushes to the stack bottom). +2. **Stages user-function call arguments right-to-left** (`stageUserFunctionArguments`), so the + first argument lands on top, matching the body layout. Built-in functions keep natural + left-to-right evaluation. +3. **Guards ROLL under reversed emission**: evaluating arguments right-to-left breaks the textual + final-use order that the `opRolls` analysis assumes, so within a call's argument tree a variable + may only be ROLLed if it appears exactly once across the whole (possibly nested) tree + (`ArgIdentifierCounter`; see the `isOpRoll` guard). Everything else stays a PICK; leftover + originals are cleaned up once at the end of the spend path. + +Output is byte-identical to the old fork on representative multi-return call patterns (2-arg and +4-arg, including argument reuse and nested calls). + +## Static size vs executed cost + +The two conventions sit at different points on a per-call vs per-spend spectrum, so **static +bytecode size can grow while executed op-cost drops**: + +- reversal staging (removed) was paid in bytes *and* executed instructions at **every call site**; +- PICK-instead-of-ROLL residue and end-of-spend cleanup (`OP_NIP`/`OP_2DROP` chains) are paid in + bytes but executed **once per spend**. + +Measured on real contracts: loop-shaped `vkx.cash` improves on both axes (−8 bytes, −14 static +ops); unrolled `miller_00.cash` grows +111 static bytes while executed instructions drop (the old +fork's equivalent chunk was +425 bytes static and ~5% cheaper dynamically). Op-bound contracts +price executed cost, so this is the right default trade. If the small static give-back ever matters +for a byte-scored, call-dense contract, per-call staging could be resurrected behind +`optimizeFor: 'size'` — deliberately not done now to avoid conventions diverging without a +demonstrated need. + +## Interaction with the rest of the pipeline + +- **Inlining** is unaffected: an inlined body is compiled against the same staged-arguments layout + and spliced where the arguments sit. +- **Multi-return values** still leave the last-declared value on top; destructuring is unchanged. +- **Debug frames** pin the body bytecode, which changed shape under the new layout — the pinned + generation and BitAuth-script fixtures were updated accordingly. +- **Recursion** still falls back to `OP_DEFINE`/`OP_INVOKE` via the invoked-functions guard. diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index af1f2814..f18740dd 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -3,6 +3,7 @@ import { IdentifierNode, ImportNode, FunctionDefinitionNode, + ConstantDefinitionNode, VariableDefinitionNode, ParameterNode, Node, @@ -22,6 +23,7 @@ import { ExpressionNode, SliceNode, IntLiteralNode, + TupleAssignmentNode, } from './ast/AST.js'; import { Symbol, SymbolType } from './ast/SymbolTable.js'; import { Location } from './ast/Location.js'; @@ -84,6 +86,32 @@ export class FunctionRedefinitionError extends RedefinitionError { } } +export class ConstantDefinitionError extends CashScriptError { + constructor( + public node: ConstantDefinitionNode, + message: string, + ) { + super(node, message); + } +} + +export class ConstantRedefinitionError extends RedefinitionError { + constructor( + public node: ConstantDefinitionNode, + ) { + super(node, `Redefinition of constant ${node.name}`); + } +} + +export class ConstantNameCollisionError extends CashScriptError { + constructor( + node: Node, + name: string, + ) { + super(node, `Identifier '${name}' collides with a global constant of the same name`); + } +} + export class MissingContractError extends Error { constructor() { super('Source file does not contain a contract definition'); @@ -198,6 +226,35 @@ export class ReturnTypeError extends TypeError { } } +export class ReturnCountError extends CashScriptError { + constructor( + node: Node, + actual: number, + expected: number, + ) { + super(node, `Function returns ${actual} value(s) but ${expected} were declared`); + } +} + +export class TupleArityError extends CashScriptError { + constructor( + node: Node, + targetCount: number, + valueCount: number, + ) { + super(node, `Cannot destructure ${valueCount} value(s) into ${targetCount} variable(s)`); + } +} + +export class MultiReturnDestructureError extends CashScriptError { + constructor( + node: FunctionCallNode, + count: number, + ) { + super(node, `Function '${node.identifier.name}' returns ${count} values and must be destructured into ${count} variables`); + } +} + export class InvalidParameterTypeError extends TypeError { constructor( node: FunctionCallNode | RequireNode | InstantiationNode, @@ -280,6 +337,23 @@ export class TupleAssignmentError extends CashScriptError { } } +export class DuplicateTupleTargetError extends CashScriptError { + constructor( + node: TupleAssignmentNode, + name: string, + ) { + super(node, `Duplicate target '${name}' in tuple destructuring`); + } +} + +export class TupleTargetOrderError extends CashScriptError { + constructor( + node: TupleAssignmentNode, + ) { + super(node, 'Declaration targets must come before all reassignment targets in a tuple destructuring'); + } +} + export class ConstantConditionError extends CashScriptError { constructor( node: BranchNode | RequireNode, @@ -297,6 +371,8 @@ export class ConstantModificationError extends CashScriptError { } } +export class InvalidModifierError extends CashScriptError {} + export class ArrayElementError extends CashScriptError { constructor( node: ArrayNode, diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index 645b319c..a455ada0 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -35,6 +35,7 @@ export class SourceFileNode extends Node { public functions: FunctionDefinitionNode[] = [], public imports: ImportNode[] = [], public pragmas: string[] = [], + public constants: ConstantDefinitionNode[] = [], ) { super(); } @@ -44,6 +45,23 @@ export class SourceFileNode extends Node { } } +// A compile-time constant (file top level). Its initializer is folded to a literal and inlined at +// every use site by the constant-inlining pass, after which this node is discarded — it is never +// visited by an AstVisitor. +export class ConstantDefinitionNode extends Node implements Named, Typed { + constructor( + public type: Type, + public name: string, + public expression: ExpressionNode, + ) { + super(); + } + + accept(): T { + throw new Error('ConstantDefinitionNode must be inlined before AST traversal'); + } +} + export class ImportNode extends Node { constructor( public path: string, @@ -85,7 +103,7 @@ export class FunctionDefinitionNode extends Node implements Named { public name: string, public parameters: ParameterNode[], public body: BlockNode, - public returnType?: Type, + public returnTypes?: Type[], ) { super(); } @@ -99,6 +117,9 @@ export class ParameterNode extends Node implements Named, Typed { constructor( public type: Type, public name: string, + // Declaration modifiers (e.g. `unused`, which exempts the parameter from the unused-variable + // check — useful for padding bytes that buy a larger compute budget without being referenced). + public modifiers: string[] = [], ) { super(); } @@ -127,11 +148,20 @@ export class VariableDefinitionNode extends NonControlStatementNode implements N } } +export interface TupleTarget { + name: string; + // For a fresh-declaration target (`int x`) this is the declared type. For a reassignment target + // (`x`, no type) it is undefined at parse time and filled in from the existing variable's symbol + // during SymbolTableTraversal. + type?: Type; + // True for a reassignment of an already-declared variable (no `typeName` in source). + isReassignment?: boolean; +} + export class TupleAssignmentNode extends NonControlStatementNode { constructor( - // TODO: Use an IdentifierNode instead of a custom type - public left: { name: string, type: Type }, - public right: { name: string, type: Type }, + // TODO: Use IdentifierNodes instead of a custom type + public targets: TupleTarget[], public tuple: ExpressionNode, ) { super(); @@ -211,7 +241,7 @@ export class FunctionCallStatementNode extends NonControlStatementNode { export class ReturnNode extends NonControlStatementNode { constructor( - public expression: ExpressionNode, + public expressions: ExpressionNode[], ) { super(); } diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index a88c186b..2b20ef5a 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -9,6 +9,7 @@ import { ParameterNode, VariableDefinitionNode, FunctionDefinitionNode, + ConstantDefinitionNode, FunctionKind, AssignNode, IdentifierNode, @@ -47,6 +48,7 @@ import type { ContractDefinitionContext, ContractFunctionDefinitionContext, GlobalFunctionDefinitionContext, + ConstantDefinitionContext, ReturnStatementContext, FunctionCallStatementContext, VariableDefinitionContext, @@ -117,11 +119,14 @@ export default class AstBuilder const imports = ctx.importDirective_list().map((directive) => this.visit(directive) as ImportNode); const functions: FunctionDefinitionNode[] = []; + const constants: ConstantDefinitionNode[] = []; let contract: ContractNode | undefined; ctx.topLevelDefinition_list().forEach((def) => { if (def.globalFunctionDefinition()) { functions.push(this.visit(def.globalFunctionDefinition()) as FunctionDefinitionNode); + } else if (def.constantDefinition()) { + constants.push(this.visitConstantDefinition(def.constantDefinition())); } else if (def.contractDefinition()) { if (contract) { throw new ParseError('A source file may define at most one contract', Location.fromCtx(def.contractDefinition())); @@ -130,11 +135,20 @@ export default class AstBuilder } }); - const sourceFileNode = new SourceFileNode(contract, functions, imports, pragmas); + const sourceFileNode = new SourceFileNode(contract, functions, imports, pragmas, constants); sourceFileNode.location = Location.fromCtx(ctx); return sourceFileNode; } + visitConstantDefinition(ctx: ConstantDefinitionContext): ConstantDefinitionNode { + const type = parseType(ctx.typeName().getText()); + const name = ctx.Identifier().getText(); + const expression = this.visit(ctx.expression()) as ExpressionNode; + const node = new ConstantDefinitionNode(type, name, expression); + node.location = Location.fromCtx(ctx); + return node; + } + visitImportDirective(ctx: ImportDirectiveContext): ImportNode { const raw = ctx.StringLiteral().getText(); const importNode = new ImportNode(raw.substring(1, raw.length - 1)); @@ -167,19 +181,22 @@ export default class AstBuilder } visitGlobalFunctionDefinition(ctx: GlobalFunctionDefinitionContext): FunctionDefinitionNode { - const returnType = ctx.typeName() ? parseType(ctx.typeName().getText()) : undefined; - return this.buildFunctionDefinition(ctx, FunctionKind.GLOBAL, returnType); + // A missing `returns` clause yields undefined (void); an empty list is impossible per the grammar. + const returnTypes = ctx.typeName_list().length > 0 + ? ctx.typeName_list().map((typeName) => parseType(typeName.getText())) + : undefined; + return this.buildFunctionDefinition(ctx, FunctionKind.GLOBAL, returnTypes); } private buildFunctionDefinition( ctx: ContractFunctionDefinitionContext | GlobalFunctionDefinitionContext, kind: FunctionKind, - returnType?: Type, + returnTypes?: Type[], ): FunctionDefinitionNode { const name = ctx.Identifier().getText(); const parameters = ctx.parameterList().parameter_list().map((p) => this.visit(p) as ParameterNode); const body = this.visit(ctx.functionBody()) as BlockNode; - const functionDefinition = new FunctionDefinitionNode(kind, name, parameters, body, returnType); + const functionDefinition = new FunctionDefinitionNode(kind, name, parameters, body, returnTypes); functionDefinition.location = Location.fromCtx(ctx); return functionDefinition; } @@ -193,8 +210,9 @@ export default class AstBuilder visitParameter(ctx: ParameterContext): ParameterNode { const type = parseType(ctx.typeName().getText()); + const modifiers = ctx.modifier_list().map((modifier) => modifier.getText()); const name = ctx.Identifier().getText(); - const parameter = new ParameterNode(type, name); + const parameter = new ParameterNode(type, name, modifiers); parameter.location = Location.fromCtx(ctx); return parameter; } @@ -231,13 +249,18 @@ export default class AstBuilder visitTupleAssignment(ctx: TupleAssignmentContext): TupleAssignmentNode { const expression = this.visit(ctx.expression()); - const names = ctx.Identifier_list(); - const types = ctx.typeName_list(); - const [var1, var2] = names.map((name, i) => ({ - name: name.getText(), - type: parseType(types[i].getText()), - })); - const tupleAssignment = new TupleAssignmentNode(var1, var2, expression); + // Each target is either `typeName Identifier` (fresh declaration) or `Identifier` (reassignment + // of an existing variable). A reassignment target has no type at parse time; SymbolTableTraversal + // fills it in from the existing variable's symbol. + const targets = ctx.tupleTarget_list().map((target) => { + const typeName = target.typeName(); + return { + name: target.Identifier().getText(), + type: typeName ? parseType(typeName.getText()) : undefined, + isReassignment: typeName === null, + }; + }); + const tupleAssignment = new TupleAssignmentNode(targets, expression); tupleAssignment.location = Location.fromCtx(ctx); return tupleAssignment; } @@ -295,8 +318,8 @@ export default class AstBuilder } visitReturnStatement(ctx: ReturnStatementContext): ReturnNode { - const expression = this.visit(ctx.expression()); - const returnNode = new ReturnNode(expression); + const expressions = ctx.expression_list().map((expression) => this.visit(expression) as ExpressionNode); + const returnNode = new ReturnNode(expressions); returnNode.location = Location.fromCtx(ctx); return returnNode; } diff --git a/packages/cashc/src/ast/AstTraversal.ts b/packages/cashc/src/ast/AstTraversal.ts index bd428132..65a4c3b7 100644 --- a/packages/cashc/src/ast/AstTraversal.ts +++ b/packages/cashc/src/ast/AstTraversal.ts @@ -91,7 +91,7 @@ export default class AstTraversal extends AstVisitor { } visitReturn(node: ReturnNode): Node { - node.expression = this.visit(node.expression); + node.expressions = this.visitList(node.expressions); return node; } diff --git a/packages/cashc/src/ast/Globals.ts b/packages/cashc/src/ast/Globals.ts index 878475c6..70c7b429 100644 --- a/packages/cashc/src/ast/Globals.ts +++ b/packages/cashc/src/ast/Globals.ts @@ -44,6 +44,7 @@ export enum Class { export enum Modifier { CONSTANT = 'constant', + UNUSED = 'unused', } export const GLOBAL_SYMBOL_TABLE = new SymbolTable(); diff --git a/packages/cashc/src/ast/SymbolTable.ts b/packages/cashc/src/ast/SymbolTable.ts index 36a25525..4574f352 100644 --- a/packages/cashc/src/ast/SymbolTable.ts +++ b/packages/cashc/src/ast/SymbolTable.ts @@ -9,6 +9,13 @@ import { export class Symbol { references: IdentifierNode[] = []; + // When true, this symbol is exempt from the unused-variable check (set for a variable or parameter + // declared with the `unused` modifier). + ignoreUnused: boolean = false; + + // For functions, the full ordered list of return types (empty for void). `type` mirrors the first + // (or VOID) so single-value call sites are unchanged; multi-return call sites read `returnTypes`. + returnTypes: Type[] = []; private constructor( public name: string, @@ -29,13 +36,16 @@ export class Symbol { } static builtinFunction(name: string, returnType: Type, parameters: Type[], bytecode: Script): Symbol { - return new Symbol(name, returnType, SymbolType.FUNCTION, undefined, parameters, bytecode); + const symbol = new Symbol(name, returnType, SymbolType.FUNCTION, undefined, parameters, bytecode); + symbol.returnTypes = returnType === PrimitiveType.VOID ? [] : [returnType]; + return symbol; } static userFunction(node: FunctionDefinitionNode, functionId: number): Symbol { const parameterTypes = node.parameters.map((parameter) => parameter.type); - const returnType = node.returnType ?? PrimitiveType.VOID; - const symbol = new Symbol(node.name, returnType, SymbolType.FUNCTION, node, parameterTypes); + const returnTypes = node.returnTypes ?? []; + const symbol = new Symbol(node.name, returnTypes[0] ?? PrimitiveType.VOID, SymbolType.FUNCTION, node, parameterTypes); + symbol.returnTypes = returnTypes; symbol.setFunctionId(functionId); return symbol; } @@ -90,6 +100,7 @@ export class SymbolTable { unusedSymbols(): Symbol[] { return Array.from(this.symbols) .map((e) => e[1]) + .filter((s) => !s.ignoreUnused) .filter((s) => s.references.length === 0); } } diff --git a/packages/cashc/src/cashc-cli.ts b/packages/cashc/src/cashc-cli.ts index 997b0a3e..e263eba9 100644 --- a/packages/cashc/src/cashc-cli.ts +++ b/packages/cashc/src/cashc-cli.ts @@ -27,6 +27,10 @@ program .option('-s, --size', 'Display the size in bytes of the compiled bytecode.') .option('-S, --skip-enforce-function-parameter-types', 'Do not enforce function parameter types.') .option('-L, --skip-enforce-locktime-guard', 'Do not inject a tx.time guard when tx.locktime is used.') + .addOption( + new Option('-O, --optimize-for ', 'Optimisation objective: minimise bytecode size or executed op-cost (default).') + .choices(['size', 'opcost']), + ) .addOption( new Option('-f, --format ', 'Specify the format of the output.') .choices(['json', 'ts']) @@ -53,6 +57,7 @@ function run(): void { const compilerOptions: CompilerOptions = { enforceFunctionParameterTypes: !opts.skipEnforceFunctionParameterTypes, enforceLocktimeGuard: !opts.skipEnforceLocktimeGuard, + ...(opts.optimizeFor ? { optimizeFor: opts.optimizeFor } : {}), }; try { diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index a46a4fa0..41b61771 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -26,6 +26,8 @@ import { ImportResolver, resolveDependencies, } from './dependency-resolution.js'; +import { inlineConstants } from './constant-folding.js'; +import { hoistRepeatedConstants } from './constant-hoisting.js'; import GenerateTargetTraversal from './generation/GenerateTargetTraversal.js'; import SymbolTableTraversal from './semantic/SymbolTableTraversal.js'; import TypeCheckTraversal from './semantic/TypeCheckTraversal.js'; @@ -37,8 +39,15 @@ import DeadCodeEliminationTraversal from './semantic/DeadCodeEliminationTraversa export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + // recorded explicitly so artifacts always state the objective they were compiled under + // (see CompilerOptions in @cashscript/utils for the size/opcost trade-off) + optimizeFor: 'opcost', }; +// Above this unoptimised op-count the legacy-optimiser cross-check is skipped automatically +// (its quadratic cost would dominate compile time on large generated contracts). +const OPTIMISATION_CROSS_CHECK_MAX_OPS = 10_000; + export interface CompileOptions extends CompilerOptions { errorListener?: CashScriptErrorListener; } @@ -91,6 +100,15 @@ function compileCode( checkVersionConstraints(ast.pragmas); ast = resolveDependencies(ast, resolver, errorListener) as Ast; + + // Fold top-level constants to literals and inline them at every use site + ast = inlineConstants(ast) as Ast; + + // Under the 'size' objective, bind repeated in-body literals to locals (see CompilerOptions) + if (mergedCompilerOptions.optimizeFor === 'size') { + ast = hoistRepeatedConstants(ast) as Ast; + } + if (!ast.contract) throw new MissingContractError(); const constructorParamLength = ast.contract.parameters.length; @@ -112,7 +130,6 @@ function compileCode( ast = ast.accept(traversal) as Ast; // Bytecode optimisation - const optimisedBytecodeOld = optimiseBytecodeOld(traversal.output); const optimisationResult = optimiseBytecode( traversal.output, sourceMapToLocationData(traversal.sourceMap), @@ -122,10 +139,18 @@ function compileCode( constructorParamLength, ); - if (scriptToAsm(optimisedBytecodeOld) !== scriptToAsm(optimisationResult.script)) { - console.error(scriptToAsm(optimisedBytecodeOld)); - console.error(scriptToAsm(optimisationResult.script)); - throw new Error('New bytecode optimisation is not backwards compatible, please report this issue to the CashScript team'); + // Backwards-compat cross-check against the legacy ASM-regex optimiser. That optimiser is + // O(runs × size²) (it re-stringifies the whole script per replacement), so on large generated + // contracts (tens of KB) the check would dominate compile time — skip it there; the new + // optimiser is exercised by the full test suite either way. Skippable explicitly via the + // disableOptimisationCrossCheck compiler option. + if (!mergedCompilerOptions.disableOptimisationCrossCheck && traversal.output.length <= OPTIMISATION_CROSS_CHECK_MAX_OPS) { + const optimisedBytecodeOld = optimiseBytecodeOld(traversal.output); + if (scriptToAsm(optimisedBytecodeOld) !== scriptToAsm(optimisationResult.script)) { + console.error(scriptToAsm(optimisedBytecodeOld)); + console.error(scriptToAsm(optimisationResult.script)); + throw new Error('New bytecode optimisation is not backwards compatible, please report this issue to the CashScript team'); + } } // Attach debug information diff --git a/packages/cashc/src/constant-folding.ts b/packages/cashc/src/constant-folding.ts new file mode 100644 index 00000000..7819aa1f --- /dev/null +++ b/packages/cashc/src/constant-folding.ts @@ -0,0 +1,232 @@ +import { implicitlyCastable } from '@cashscript/utils'; +import { + SourceFileNode, + ConstantDefinitionNode, + ContractNode, + FunctionDefinitionNode, + ExpressionNode, + IdentifierNode, + LiteralNode, + IntLiteralNode, + BoolLiteralNode, + StringLiteralNode, + HexLiteralNode, + UnaryOpNode, + BinaryOpNode, + CastNode, + FunctionCallNode, + InstantiationNode, + ParameterNode, + VariableDefinitionNode, + TupleAssignmentNode, + AssignNode, + Node, +} from './ast/AST.js'; +import AstTraversal from './ast/AstTraversal.js'; +import { BinaryOperator, UnaryOperator } from './ast/Operator.js'; +import { + ConstantDefinitionError, + ConstantRedefinitionError, + ConstantNameCollisionError, +} from './Errors.js'; + +// Folds every top-level constant to a literal and inlines it at each use site (in the contract and +// in global function bodies). Runs after dependency resolution and before semantic analysis, so the +// rest of the pipeline only ever sees plain literals. +export function inlineConstants(ast: SourceFileNode): SourceFileNode { + if (ast.constants.length === 0) return ast; + + const values = new Map(); + for (const definition of ast.constants) { + if (values.has(definition.name)) throw new ConstantRedefinitionError(definition); + const value = evaluateConstant(definition.expression, values, definition); + assertMatchesDeclaredType(definition, value); + values.set(definition.name, value); + } + + ast.functions.forEach((func) => { + if (values.has(func.name)) throw new ConstantNameCollisionError(func, func.name); + }); + + const inliner = new ConstantInliner(values); + ast.functions = ast.functions.map((func) => inliner.visit(func) as FunctionDefinitionNode); + if (ast.contract) ast.contract = inliner.visit(ast.contract) as ContractNode; + ast.constants = []; + + return ast; +} + +// Folds a constant initializer to a literal node. Supports literals, references to previously defined +// constants, and arithmetic/logical/comparison operators over them. Anything that depends on +// runtime/introspection values is rejected (constants must be known at compile time). +function evaluateConstant( + expression: ExpressionNode, + known: Map, + definition: ConstantDefinitionNode, +): LiteralNode { + if (expression instanceof IntLiteralNode) return new IntLiteralNode(expression.value); + if (expression instanceof BoolLiteralNode) return new BoolLiteralNode(expression.value); + if (expression instanceof HexLiteralNode) return new HexLiteralNode(expression.value); + if (expression instanceof StringLiteralNode) return new StringLiteralNode(expression.value, expression.quote); + + if (expression instanceof IdentifierNode) { + const value = known.get(expression.name); + if (!value) { + throw new ConstantDefinitionError( + definition, + `Constant '${definition.name}' references '${expression.name}', which is not a known constant`, + ); + } + return cloneLiteral(value); + } + + if (expression instanceof UnaryOpNode) { + const operand = evaluateConstant(expression.expression, known, definition); + return foldUnary(expression.operator, operand, definition); + } + + if (expression instanceof BinaryOpNode) { + const left = evaluateConstant(expression.left, known, definition); + const right = evaluateConstant(expression.right, known, definition); + return foldBinary(expression.operator, left, right, definition); + } + + if (expression instanceof CastNode) { + // Allow trivial numeric casts of constant expressions (e.g. int(...)); the value is unchanged. + return evaluateConstant(expression.expression, known, definition); + } + + throw new ConstantDefinitionError( + definition, + `Constant '${definition.name}' must be a compile-time constant expression (no introspection or runtime values)`, + ); +} + +function foldUnary(operator: UnaryOperator, operand: LiteralNode, definition: ConstantDefinitionNode): LiteralNode { + if (operator === UnaryOperator.NEGATE && operand instanceof IntLiteralNode) { + return new IntLiteralNode(-operand.value); + } + if (operator === UnaryOperator.NOT && operand instanceof BoolLiteralNode) { + return new BoolLiteralNode(!operand.value); + } + throw new ConstantDefinitionError( + definition, + `Constant '${definition.name}' uses operator '${operator}' on an unsupported constant operand`, + ); +} + +function foldBinary( + operator: BinaryOperator, + left: LiteralNode, + right: LiteralNode, + definition: ConstantDefinitionNode, +): LiteralNode { + if (left instanceof IntLiteralNode && right instanceof IntLiteralNode) { + const a = left.value; + const b = right.value; + switch (operator) { + case BinaryOperator.PLUS: return new IntLiteralNode(a + b); + case BinaryOperator.MINUS: return new IntLiteralNode(a - b); + case BinaryOperator.MUL: return new IntLiteralNode(a * b); + case BinaryOperator.DIV: return new IntLiteralNode(a / b); + case BinaryOperator.MOD: return new IntLiteralNode(a % b); + case BinaryOperator.LT: return new BoolLiteralNode(a < b); + case BinaryOperator.LE: return new BoolLiteralNode(a <= b); + case BinaryOperator.GT: return new BoolLiteralNode(a > b); + case BinaryOperator.GE: return new BoolLiteralNode(a >= b); + case BinaryOperator.EQ: return new BoolLiteralNode(a === b); + case BinaryOperator.NE: return new BoolLiteralNode(a !== b); + default: break; + } + } + + if (left instanceof BoolLiteralNode && right instanceof BoolLiteralNode) { + switch (operator) { + case BinaryOperator.AND: return new BoolLiteralNode(left.value && right.value); + case BinaryOperator.OR: return new BoolLiteralNode(left.value || right.value); + case BinaryOperator.EQ: return new BoolLiteralNode(left.value === right.value); + case BinaryOperator.NE: return new BoolLiteralNode(left.value !== right.value); + default: break; + } + } + + throw new ConstantDefinitionError( + definition, + `Constant '${definition.name}' uses operator '${operator}' on unsupported constant operands`, + ); +} + +// The folded value must fit the declared type (e.g. `bytes32 constant X` requires a 32-byte literal). +function assertMatchesDeclaredType(definition: ConstantDefinitionNode, value: LiteralNode): void { + if (!implicitlyCastable(value.type, definition.type)) { + throw new ConstantDefinitionError( + definition, + `Constant '${definition.name}' has declared type ${definition.type} but its value has type ${value.type}`, + ); + } +} + +function cloneLiteral(literal: LiteralNode): LiteralNode { + if (literal instanceof IntLiteralNode) return new IntLiteralNode(literal.value); + if (literal instanceof BoolLiteralNode) return new BoolLiteralNode(literal.value); + if (literal instanceof HexLiteralNode) return new HexLiteralNode(literal.value); + if (literal instanceof StringLiteralNode) return new StringLiteralNode(literal.value, literal.quote); + throw new Error(`Cannot clone literal of type ${literal.type}`); // Shouldn't happen +} + +// Replaces every identifier that names a constant with a clone of the constant's literal value. +// Callee identifiers (function/instantiation names) are left untouched, and any local that shadows a +// constant name is rejected (it would silently break inlining). +class ConstantInliner extends AstTraversal { + constructor(private constants: Map) { + super(); + } + + visitIdentifier(node: IdentifierNode): Node { + const value = this.constants.get(node.name); + if (value) { + // The inlined literal takes the use site's source location (a folded constant value may have + // none of its own), so source-map generation always has a valid location to point at. + const literal = cloneLiteral(value); + literal.location = node.location; + return literal; + } + return node; + } + + visitFunctionCall(node: FunctionCallNode): Node { + // Do NOT inline the callee identifier (it is a function name, not a value). + node.parameters = this.visitList(node.parameters); + return node; + } + + visitInstantiation(node: InstantiationNode): Node { + node.parameters = this.visitList(node.parameters); + return node; + } + + visitParameter(node: ParameterNode): Node { + this.assertNotConstant(node.name, node); + return node; + } + + visitVariableDefinition(node: VariableDefinitionNode): Node { + this.assertNotConstant(node.name, node); + return super.visitVariableDefinition(node); + } + + visitTupleAssignment(node: TupleAssignmentNode): Node { + node.targets.forEach((target) => this.assertNotConstant(target.name, node)); + return super.visitTupleAssignment(node); + } + + visitAssign(node: AssignNode): Node { + this.assertNotConstant(node.identifier.name, node); + node.expression = this.visit(node.expression); + return node; + } + + private assertNotConstant(name: string, node: Node): void { + if (this.constants.has(name)) throw new ConstantNameCollisionError(node, name); + } +} diff --git a/packages/cashc/src/constant-hoisting.ts b/packages/cashc/src/constant-hoisting.ts new file mode 100644 index 00000000..146df361 --- /dev/null +++ b/packages/cashc/src/constant-hoisting.ts @@ -0,0 +1,158 @@ +import { binToHex } from '@bitauth/libauth'; +import { encodeInt, scriptToBytecode } from '@cashscript/utils'; +import { + SourceFileNode, + FunctionDefinitionNode, + BlockNode, + LiteralNode, + IntLiteralNode, + HexLiteralNode, + IdentifierNode, + VariableDefinitionNode, + ParameterNode, + TupleAssignmentNode, + Node, +} from './ast/AST.js'; +import AstTraversal from './ast/AstTraversal.js'; + +// Byte-size optimisation with an op-cost trade-off, so gated behind `optimizeFor: 'size'`: +// a literal that occurs two or more times within one function body is bound to a local at the +// top of the body when that is cheaper by exact byte accounting, and the occurrences become +// identifier references. The second and later uses then cost a stack pick instead of re-pushing +// the literal (~-30 bytes per duplicate of a 32-byte field prime), at the price of a couple of +// extra ops per call for the binding and cleanup. +// +// That trade is right for size-scored contracts and wrong for op-bound ones (where unlocking +// scripts are zero-padded to buy op budget, byte savings are free anyway and the extra ops +// translate directly into more padding) — hence the default 'opcost' objective skips it. +// +// Runs after constant folding (so uses of top-level constants are already literals here) and +// before semantic analysis (so the introduced locals get symbols like any other variable). + +export function hoistRepeatedConstants(ast: SourceFileNode): SourceFileNode { + ast.functions.forEach((func) => hoistInBody(func.body)); + ast.contract?.functions.forEach((func: FunctionDefinitionNode) => hoistInBody(func.body)); + return ast; +} + +// Exact byte accounting: replacing each duplicate push with an identifier access costs about +// 2 bytes (depth + OP_PICK; the declaration itself re-uses the first push) plus ~1 byte of +// end-of-scope cleanup, so hoisting pays when the duplicates' push bytes beat that overhead. +const worthHoisting = (pushBytes: number, count: number): boolean => (count - 1) * pushBytes > 2 * (count - 1) + 1; + +function hoistInBody(body: BlockNode): void { + if (!body.statements || body.statements.length === 0) return; + + const counter = new LiteralCounter(); + counter.visit(body); + + const hoisted = [...counter.literals.values()] + .filter(({ pushBytes, count }) => worthHoisting(pushBytes, count)); + if (hoisted.length === 0) return; + + // Fresh local names that collide with nothing already named in the body. + const names = new Map(); + let n = 0; + for (const { key } of hoisted) { + while (counter.usedNames.has(`hc${n}`)) n += 1; + names.set(key, `hc${n}`); + n += 1; + } + + new LiteralReplacer(names).visit(body); + + // Declarations go at the very top of the body; source locations borrow from the first + // statement so source-map generation always has a valid location to point at. + const location = body.statements[0].location; + const declarations = hoisted.map(({ key, template }) => { + const literal = cloneLiteral(template); + literal.location = location; + const definition = new VariableDefinitionNode(template.type!, [], names.get(key)!, literal); + definition.location = location; + return definition; + }); + body.statements.unshift(...declarations); +} + +type Hoistable = IntLiteralNode | HexLiteralNode; + +const literalKey = (node: Hoistable): string => ( + node instanceof IntLiteralNode ? `i${node.value}` : `x${binToHex(node.value)}` +); + +const literalPushBytes = (node: Hoistable): number => ( + scriptToBytecode([node instanceof IntLiteralNode ? encodeInt(node.value) : node.value]).length +); + +function cloneLiteral(node: Hoistable): LiteralNode { + return node instanceof IntLiteralNode ? new IntLiteralNode(node.value) : new HexLiteralNode(node.value); +} + +// Counts hoistable literals by value and records every name already used in the body +// (identifiers, parameters, definitions, tuple targets), so the introduced locals cannot +// shadow or be shadowed by anything. +class LiteralCounter extends AstTraversal { + literals = new Map(); + usedNames = new Set(); + + private countLiteral(node: Hoistable): void { + const key = literalKey(node); + const entry = this.literals.get(key); + if (entry) entry.count += 1; + else this.literals.set(key, { key, template: node, pushBytes: literalPushBytes(node), count: 1 }); + } + + visitIntLiteral(node: IntLiteralNode): Node { + this.countLiteral(node); + return node; + } + + visitHexLiteral(node: HexLiteralNode): Node { + this.countLiteral(node); + return node; + } + + visitIdentifier(node: IdentifierNode): Node { + this.usedNames.add(node.name); + return node; + } + + visitParameter(node: ParameterNode): Node { + this.usedNames.add(node.name); + return node; + } + + visitVariableDefinition(node: VariableDefinitionNode): Node { + this.usedNames.add(node.name); + return super.visitVariableDefinition(node); + } + + visitTupleAssignment(node: TupleAssignmentNode): Node { + node.targets.forEach((target) => this.usedNames.add(target.name)); + return super.visitTupleAssignment(node); + } +} + +// Swaps each hoisted literal occurrence for a reference to its local. The identifier takes +// the literal's source location (same convention as constant inlining, in reverse). +class LiteralReplacer extends AstTraversal { + constructor(private names: Map) { + super(); + } + + private replace(node: Hoistable): Node { + const name = this.names.get(literalKey(node)); + if (name === undefined) return node; + const identifier = new IdentifierNode(name); + identifier.location = node.location; + return identifier; + } + + visitIntLiteral(node: IntLiteralNode): Node { + return this.replace(node); + } + + visitHexLiteral(node: HexLiteralNode): Node { + return this.replace(node); + } +} diff --git a/packages/cashc/src/dependency-resolution.ts b/packages/cashc/src/dependency-resolution.ts index 5c8b96e2..516c82ca 100644 --- a/packages/cashc/src/dependency-resolution.ts +++ b/packages/cashc/src/dependency-resolution.ts @@ -1,6 +1,8 @@ import fs from 'fs'; import path from 'path'; -import { SourceFileNode, FunctionDefinitionNode, ImportNode } from './ast/AST.js'; +import { + SourceFileNode, FunctionDefinitionNode, ConstantDefinitionNode, ImportNode, +} from './ast/AST.js'; import { checkVersionConstraints } from './ast/Pragma.js'; import type { CashScriptErrorListener } from './ast/error-listeners.js'; import { ImportResolutionError } from './Errors.js'; @@ -62,25 +64,31 @@ export function resolveDependencies( ); } - const importedFunctions = collectImports(ast.imports, resolver, errorListener); - ast.functions = [...importedFunctions, ...ast.functions]; + const imported = collectImports(ast.imports, resolver, errorListener); + ast.functions = [...imported.functions, ...ast.functions]; + ast.constants = [...imported.constants, ...ast.constants]; ast.imports = []; return ast; } -// Depth-first walk of the import graph, returning every global function it reaches. `visitedPaths` is -// internal bookkeeping that de-duplicates files by canonical path — collapsing diamonds (a file reached -// through two paths is read once) and guaranteeing termination for mutual or cyclic imports — so this -// function stays pure with respect to its arguments. +interface ImportedDefinitions { + functions: FunctionDefinitionNode[]; + constants: ConstantDefinitionNode[]; +} + +// Depth-first walk of the import graph, returning every global function and constant it reaches. +// `visitedPaths` is internal bookkeeping that de-duplicates files by canonical path — collapsing +// diamonds (a file reached through two paths is read once) and guaranteeing termination for mutual +// or cyclic imports — so this function stays pure with respect to its arguments. function collectImports( imports: ImportNode[], resolver: ImportResolver, errorListener?: CashScriptErrorListener, -): FunctionDefinitionNode[] { +): ImportedDefinitions { const visitedPaths = new Set(); - const collect = (currentImports: ImportNode[], currentDir: string): FunctionDefinitionNode[] => + const collect = (currentImports: ImportNode[], currentDir: string): ImportedDefinitions[] => currentImports.flatMap((importNode) => { const canonicalPath = resolver.resolve(currentDir, importNode.path); if (visitedPaths.has(canonicalPath)) return []; @@ -103,8 +111,15 @@ function collectImports( func.sourceFile = resolver.sourceName(canonicalPath); }); - return [...collect(importedAst.imports, resolver.dirname(canonicalPath)), ...importedAst.functions]; + return [ + ...collect(importedAst.imports, resolver.dirname(canonicalPath)), + { functions: importedAst.functions, constants: importedAst.constants }, + ]; }); - return collect(imports, resolver.rootDir); + const collected = collect(imports, resolver.rootDir); + return { + functions: collected.flatMap((definitions) => definitions.functions), + constants: collected.flatMap((definitions) => definitions.constants), + }; } diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index 07654a0c..2eb066cd 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -11,6 +11,7 @@ import { scriptToAsm, scriptToBytecode, optimiseBytecode, + OptimiseBytecodeResult, generateSourceMap, generateSourceTags, FullLocationData, @@ -22,6 +23,7 @@ import { StackItem, BytesType, CompilerOptions, + OptimizationTarget, SourceTagEntry, SourceTagKind, } from '@cashscript/utils'; @@ -60,6 +62,7 @@ import { ForNode, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; +import { Symbol } from '../ast/SymbolTable.js'; import { GlobalFunction, Class } from '../ast/Globals.js'; import { BinaryOperator } from '../ast/Operator.js'; import { @@ -71,6 +74,12 @@ import { } from './utils.js'; import { isNumericType } from '../utils.js'; +// The optimised body of a function chosen for inlining, including its frame-local debug info +// (location data, logs, requires, source tags) so call sites can splice that too. +interface InlinedFunction extends OptimiseBytecodeResult { + sourceFile?: string; // originating file for imported functions; absent means the contract's own file +} + export default class GenerateTargetTraversal extends AstTraversal { private locationData: FullLocationData = []; // detailed location data needed for sourcemap creation sourceMap: string; @@ -85,6 +94,20 @@ export default class GenerateTargetTraversal extends AstTraversal { private scopeDepth = 0; private currentFunction: FunctionDefinitionNode; private constructorParameterCount: number; + // Optimised bodies of global functions chosen for inlining: call sites splice these instead of + // emitting OP_INVOKE, and they get no OP_DEFINE. Shared with body sub-traversals so an inlined + // callee is spliced into its callers too. + inlinedFunctionBodies: Map = new Map(); + // Global functions emitted as an OP_INVOKE (so they need an OP_DEFINE and cannot be inlined). Only + // populated for recursive/cyclic calls, where the callee is still being compiled when its call is + // emitted. Shared with body sub-traversals. + invokedFunctions: Set = new Set(); + // Depth of nested user-function-call argument staging (see stageUserFunctionArguments). + private userCallArgDepth = 0; + // Per-variable occurrence counts across the outermost call's whole argument tree. Names appearing + // 2+ times stay OP_PICK (a ROLL under reversed emission would consume them too early). Populated + // when userCallArgDepth goes 0 -> 1 and cleared when it returns to 0. + private callArgNameCounts: Map | null = null; constructor(private compilerOptions: CompilerOptions) { super(); @@ -152,27 +175,76 @@ export default class GenerateTargetTraversal extends AstTraversal { } private defineGlobalFunctions(node: SourceFileNode): void { + const functionsByName = new Map(node.functions.map((func) => [func.name, func])); + const inliningEnabled = !this.compilerOptions.disableInlining; + const loopExcluded = collectLoopExcludedFunctions(node, functionsByName); + const definedBodies = new Map(); + + // Compile and decide in callee-first order so an inlined callee's body is available to splice into + // its callers (a spliced callee then counts towards its caller's body size). A function already + // emitted as an OP_INVOKE (recursion) must stay shared via OP_DEFINE. + calleesFirst(node.functions, functionsByName).forEach((func) => { + const symbol = node.symbolTable!.getFromThis(func.name)!; + const optimisedBody = this.compileGlobalFunctionBody(func); + // Tiny bodies (<= 2 script elements) are exempt from the loop exclusion: inlined they step + // no more opcodes than the 2-op invoke site even when skipped, execute fewer when taken, + // and save the define/invoke bytes — strictly dominant on every axis. + if ( + inliningEnabled + && (!loopExcluded.has(func.name) || optimisedBody.script.length <= 2) + && isWorthInlining(symbol, optimisedBody.script, this.compilerOptions.optimizeFor) + && !this.invokedFunctions.has(func.name) + ) { + this.inlinedFunctionBodies.set(func.name, { ...optimisedBody, sourceFile: func.sourceFile }); + } else { + definedBodies.set(func.name, optimisedBody); + } + }); + + // Emit OP_DEFINEs in declaration order so output is stable regardless of the compile order above. + // Only defined functions get a debug frame: an inlined body never executes via OP_INVOKE, so its + // debug info is spliced into the caller at each call site instead (see spliceInlinedFunction). node.functions.forEach((func) => { + const optimisedBody = definedBodies.get(func.name); + if (optimisedBody === undefined) return; // inlined: no OP_DEFINE const { functionId } = node.symbolTable!.getFromThis(func.name)!; - const bodyBytecode = this.compileGlobalFunctionBody(func, functionId!); - + this.pushDebugFrame(func, optimisedBody, functionId!); const locationData = { location: func.location, positionHint: PositionHint.START }; - this.emit(bodyBytecode, locationData); // + this.emit(scriptToBytecode(optimisedBody.script), locationData); // this.emit(encodeInt(BigInt(functionId!)), locationData); // this.emit(Op.OP_DEFINE, { ...locationData, positionHint: PositionHint.END }); }); } - private compileGlobalFunctionBody(node: FunctionDefinitionNode, functionId: number): Uint8Array { + private pushDebugFrame(node: FunctionDefinitionNode, optimised: OptimiseBytecodeResult, functionId: number): void { + const sourceTags = generateSourceTags(optimised.sourceTags); + + this.frames.push({ + id: functionId, + name: node.name, + inputs: node.parameters.map((parameter) => ({ name: parameter.name, type: parameter.type.toString() })), + bytecode: binToHex(scriptToBytecode(optimised.script)), + sourceMap: generateSourceMap(optimised.locationData), + ...(sourceTags ? { sourceTags } : {}), + ...(node.sourceCode !== undefined ? { source: node.sourceCode } : {}), + ...(node.sourceFile !== undefined ? { sourceFile: node.sourceFile } : {}), + logs: optimised.logs, + requires: optimised.requires, + }); + } + + private compileGlobalFunctionBody(node: FunctionDefinitionNode): OptimiseBytecodeResult { const bodyTraversal = new GenerateTargetTraversal(this.compilerOptions); bodyTraversal.currentFunction = node; bodyTraversal.constructorParameterCount = 0; + // Share the inline tables so a body splices its already-inlined callees (and records OP_INVOKEs). + bodyTraversal.inlinedFunctionBodies = this.inlinedFunctionBodies; + bodyTraversal.invokedFunctions = this.invokedFunctions; - // Seed the stack with parameters in reverse order so the last parameter is on top - // (similar to how builtin functions work) - for (let i = node.parameters.length - 1; i >= 0; i -= 1) { - bodyTraversal.visit(node.parameters[i]); - } + // Seed the stack with the parameters (visitParameter pushes them to the stack bottom in order, + // so the first parameter ends up on top) — matching the right-to-left argument staging at call + // sites, where declaration-order variable arguments then need no reordering at all. + node.parameters.forEach((parameter) => bodyTraversal.visit(parameter)); bodyTraversal.visit(node.body); bodyTraversal.cleanGlobalFunctionStack(node); @@ -186,30 +258,15 @@ export default class GenerateTargetTraversal extends AstTraversal { 0, ); - const bodyBytecode = scriptToBytecode(optimised.script); - const sourceTags = generateSourceTags(optimised.sourceTags); - - this.frames.push({ - id: functionId, - name: node.name, - inputs: node.parameters.map((parameter) => ({ name: parameter.name, type: parameter.type.toString() })), - bytecode: binToHex(bodyBytecode), - sourceMap: generateSourceMap(optimised.locationData), - ...(sourceTags ? { sourceTags } : {}), - ...(node.sourceCode !== undefined ? { source: node.sourceCode } : {}), - ...(node.sourceFile !== undefined ? { sourceFile: node.sourceFile } : {}), - logs: optimised.logs, - requires: optimised.requires, - }); - - return bodyBytecode; + return optimised; } cleanGlobalFunctionStack(node: FunctionDefinitionNode): void { - if (node.returnType === undefined) { + const returnCount = node.returnTypes?.length ?? 0; + if (returnCount === 0) { this.removeScopedVariables(0, node.body); // void: drop the entire frame } else { - this.cleanStack(node.body); // value: OP_NIP everything below the return value on top + this.cleanStack(node.body, returnCount); // value(s): drop everything below the N results on top } } @@ -319,13 +376,46 @@ export default class GenerateTargetTraversal extends AstTraversal { } } - cleanStack(functionBodyNode: Node): void { - // Keep final verification value, OP_NIP the other stack values + cleanStack(functionBodyNode: Node, keepCount: number = 1): void { + // Keep the top `keepCount` values (a contract function's verification value, or a global + // function's return values), dropping everything below them while preserving their order. + // Chooses per-item dropping (OP_NIP, or OP_ROLL OP_DROP) or the altstack form + // (k× OP_TOALTSTACK, OP_2DROP pairs, k× OP_FROMALTSTACK — fixed 2k-op overhead, ~1 op per + // 2 drops) by op/byte estimate on the active objective. A just-pushed constant verification + // value stays on the NIP path: the peephole already rewrites `OP_1 OP_NIP…` to + // `OP_2DROP… OP_1`, which beats the altstack round-trip. const tagStartIndex = this.output.length; - const stackSize = this.stack.length; - for (let i = 0; i < stackSize - 1; i += 1) { - this.emit(Op.OP_NIP, { location: functionBodyNode.location, positionHint: PositionHint.END }); - this.nipFromStack(); + const locationData = { location: functionBodyNode.location, positionHint: PositionHint.END }; + const dropCount = this.stack.length - keepCount; + const pairDrops = Math.floor(dropCount / 2) + (dropCount % 2); + const perItemOps = keepCount === 1 ? dropCount * 100 : dropCount * (301 + keepCount); + const altOps = 200 * keepCount + 100 * pairDrops; + const perItemBytes = keepCount === 1 ? dropCount : dropCount * 3; + const altBytes = 2 * keepCount + pairDrops; + const topIsFreshConstant = keepCount === 1 && isConstantPushElement(this.output[this.output.length - 1]); + const useAltstack = !topIsFreshConstant && (this.compilerOptions.optimizeFor === 'size' + ? altBytes < perItemBytes + : altOps < perItemOps); + if (useAltstack) { + for (let i = 0; i < keepCount; i += 1) this.emit(Op.OP_TOALTSTACK, locationData); + for (let i = 0; i + 1 < dropCount; i += 2) this.emit(Op.OP_2DROP, locationData); + if (dropCount % 2 === 1) this.emit(Op.OP_DROP, locationData); + for (let i = 0; i < keepCount; i += 1) this.emit(Op.OP_FROMALTSTACK, locationData); + for (let i = 0; i < dropCount; i += 1) this.removeFromStack(keepCount); + } else { + for (let i = 0; i < dropCount; i += 1) { + if (keepCount === 1) { + // OP_NIP drops the item directly below the top value (1 byte, cheaper than ROLL + DROP). + this.emit(Op.OP_NIP, locationData); + this.nipFromStack(); + } else { + // The next item to drop sits just below the top `keepCount` values: roll it up and drop it. + this.emit(encodeInt(BigInt(keepCount)), locationData); + this.emit(Op.OP_ROLL, locationData); + this.emit(Op.OP_DROP, locationData); + this.removeFromStack(keepCount); + } + } } this.tagScopeCleanup(tagStartIndex); } @@ -388,10 +478,39 @@ export default class GenerateTargetTraversal extends AstTraversal { } visitTupleAssignment(node: TupleAssignmentNode): Node { + // The RHS leaves N values on the stack, last on top (as `.split` and multi-return calls do). node.tuple = this.visit(node.tuple); - this.popFromStack(2); - this.pushToStack(node.left.name); - this.pushToStack(node.right.name); + const n = node.targets.length; + + // Outside a loop/branch, binding is a pure rename: the result entries take the target names, and + // a reassigned variable's old slot becomes a dead duplicate cleaned up at end of scope. + const scopedReassign = this.scopeDepth > 0 && node.targets.some((target) => target.isReassignment); + if (!scopedReassign) { + this.popFromStack(n); + node.targets.forEach((target) => this.pushToStack(target.name)); + return node; + } + + // In a loop/branch the stack layout must be preserved, so reassignments are folded in place. This + // requires declarations to form a contiguous block below all reassignments (the natural layout of + // a multi-return: fresh values, then updated accumulators). SymbolTableTraversal enforces this + // ordering for every tuple destructuring (TupleTargetOrderError), so the check here is an + // internal invariant only. + const firstReassign = node.targets.findIndex((target) => target.isReassignment); + const lastDeclaration = node.targets.reduce((acc, target, i) => (target.isReassignment ? acc : i), -1); + if (lastDeclaration > firstReassign) { + throw new Error('Declaration targets must come before all reassignment targets in a scoped tuple destructuring'); + } + + // Fold the trailing reassignment block into the existing slots top-down (each target's value is on + // top when processed), then rename the leading declaration values in place (no opcodes). + for (let i = n - 1; i >= firstReassign; i -= 1) { + this.emitReplace(this.getStackIndex(node.targets[i].name), node); + this.popFromStack(); + } + for (let s = 0; s < firstReassign; s += 1) { + this.stack[s] = node.targets[firstReassign - 1 - s].name; + } return node; } @@ -662,14 +781,91 @@ export default class GenerateTargetTraversal extends AstTraversal { } const symbol = node.identifier.symbol!; - node.parameters = this.visitList(node.parameters); - this.emit(symbol.bytecode!, { location: node.location, positionHint: PositionHint.END }); + + // User-defined function arguments are staged right-to-left (first argument on top, matching the + // body's parameter layout); built-in functions keep natural left-to-right evaluation. + if (symbol.functionId !== undefined) { + this.stageUserFunctionArguments(node); + } else { + node.parameters = this.visitList(node.parameters); + } + + // An inlined function is spliced in place of ` OP_INVOKE`. Its optimised body was compiled + // with the arguments staged on top of the stack (the exact state here), so it runs identically: + // consuming the arguments and leaving its N return values on top. + const inlined = this.inlinedFunctionBodies.get(node.identifier.name); + if (inlined !== undefined) { + this.spliceInlinedFunction(node, inlined); + } else { + this.emit(symbol.bytecode!, { location: node.location, positionHint: PositionHint.END }); + if (symbol.functionId !== undefined) this.invokedFunctions.add(node.identifier.name); + } this.popFromStack(node.parameters.length); - if (symbol.type !== PrimitiveType.VOID) this.pushToStack('(value)'); + + // The call leaves one value per declared return type (none for a void function); a multi-return + // function's values are subsequently bound by visitTupleAssignment. + for (let i = 0; i < symbol.returnTypes.length; i += 1) this.pushToStack('(value)'); return node; } + // Stages user-function call arguments right-to-left, so the first argument ends up on top of the + // stack — the layout the function body is compiled against. With arguments that are variables in + // declaration order (the common case), the emitted ROLLs then cancel to nothing in the optimiser, + // so a typical call costs zero staging instructions. Reversed emission breaks the textual + // final-use order, so at the outermost call each variable's occurrences are counted across the + // whole (possibly nested) argument tree: only names used exactly once may ROLL (see isOpRoll); + // everything else stays a PICK. + private stageUserFunctionArguments(node: FunctionCallNode): void { + const isOutermostCall = this.userCallArgDepth === 0; + if (isOutermostCall) { + const counter = new ArgIdentifierCounter(); + node.parameters.forEach((argument) => counter.visit(argument)); + this.callArgNameCounts = counter.counts; + } + + this.userCallArgDepth += 1; + for (let i = node.parameters.length - 1; i >= 0; i -= 1) { + node.parameters[i] = this.visit(node.parameters[i]); + } + this.userCallArgDepth -= 1; + + if (isOutermostCall) this.callArgNameCounts = null; + } + + // Splices an inlined body together with its frame-local debug info (ip-shifted), so logs and + // requires inside it keep working without a debug frame. A same-file body keeps its own source + // locations; a body from another file is attributed to the call site instead, since a source map + // can only reference its own frame's source file. + private spliceInlinedFunction(node: FunctionCallNode, inlined: InlinedFunction): void { + const callSiteLocation = { location: node.location, positionHint: PositionHint.END }; + const callSiteLine = node.location.start.line; + const sameFile = inlined.sourceFile === this.currentFunction?.sourceFile; + const ipOffset = this.output.length + this.constructorParameterCount; + const tagOffset = this.output.length; + + inlined.script.forEach((op, i) => this.emit(op, sameFile ? inlined.locationData[i] : callSiteLocation)); + + this.requires.push(...inlined.requires.map((entry) => ({ + ...entry, + ip: entry.ip + ipOffset, + ...(sameFile ? {} : { line: callSiteLine }), + }))); + + this.consoleLogs.push(...inlined.logs.map((entry) => ({ + ...entry, + ip: entry.ip + ipOffset, + ...(sameFile ? {} : { line: callSiteLine }), + data: entry.data.map((item) => (typeof item === 'string' ? item : { ...item, ip: item.ip + ipOffset })), + }))); + + this.sourceTags.push(...inlined.sourceTags.map((entry) => ({ + ...entry, + startIndex: entry.startIndex + tagOffset, + endIndex: entry.endIndex + tagOffset, + }))); + } + visitMultiSig(node: FunctionCallNode): Node { this.emit(encodeBool(false), { location: node.location, positionHint: PositionHint.START }); this.pushToStack('(value)'); @@ -863,7 +1059,12 @@ export default class GenerateTargetTraversal extends AstTraversal { } isOpRoll(node: IdentifierNode): boolean { - return this.currentFunction.opRolls.get(node.name) === node && this.scopeDepth === 0; + // Must be the variable's final use (opRolls site) and not inside an if/loop scope. + if (this.currentFunction.opRolls.get(node.name) !== node || this.scopeDepth !== 0) return false; + // Inside a user-function-call argument list, ROLL is only safe when this variable appears exactly + // once across the whole argument tree; otherwise reversed emission would consume it too early. + if (this.userCallArgDepth > 0) return this.callArgNameCounts?.get(node.name) === 1; + return true; } visitBoolLiteral(node: BoolLiteralNode): Node { @@ -890,3 +1091,159 @@ export default class GenerateTargetTraversal extends AstTraversal { return node; } } + +// Counts identifier reads across a user-function call's whole argument tree, used to decide whether +// a final-use variable in the argument list is safe to OP_ROLL: a name referenced exactly once has +// no other use that the reversed-emission ROLL could consume early. Function/instantiation callee +// identifiers are not stack-variable reads, so they are skipped (only the call arguments are counted). +class ArgIdentifierCounter extends AstTraversal { + counts: Map = new Map(); + + visitIdentifier(node: IdentifierNode): Node { + this.counts.set(node.name, (this.counts.get(node.name) ?? 0) + 1); + return node; + } + + visitFunctionCall(node: FunctionCallNode): Node { + node.parameters = this.visitList(node.parameters); + return node; + } + + visitInstantiation(node: InstantiationNode): Node { + node.parameters = this.visitList(node.parameters); + return node; + } +} + +// Under the 'opcost' objective (the default), a small body is inlined regardless of use count, +// even when OP_DEFINE would be smaller: every invocation costs ~2 executed instructions (funcid +// push + OP_INVOKE) that splicing a tiny body avoids, and for op-bound contracts the byte cost is +// free anyway (their unlocking scripts are zero-padded to buy op budget, so extra ops translate +// directly into more padding while locking bytes do not). +const OPCOST_INLINE_MAX_BODY_BYTES = 6; + +// A script element that pushes a constant: raw push data, or one of the small-integer push +// opcodes. Used to spot a `require`-style body whose verification value was just pushed. +function isConstantPushElement(element: OpOrData | undefined): boolean { + if (element === undefined) return false; + if (element instanceof Uint8Array) return true; + return element === Op.OP_0 || element === Op.OP_1NEGATE || (element >= Op.OP_1 && element <= Op.OP_16); +} + +// Byte-exact comparison: defining costs the body once (as a push) plus OP_DEFINE, and +// OP_INVOKE per call site; inlining costs the body at every call site. A tie favours +// inlining (frees the function id and skips the OP_INVOKE round-trip at runtime). +function isWorthInlining(symbol: Symbol, bodyScript: Script, optimizeFor?: OptimizationTarget): boolean { + const useCount = symbol.references.length; + const bodyBytes = scriptToBytecode(bodyScript).length; + if (optimizeFor !== 'size' && bodyBytes <= OPCOST_INLINE_MAX_BODY_BYTES) return true; + const bodyPushBytes = scriptToBytecode([scriptToBytecode(bodyScript)]).length; + const idBytes = scriptToBytecode([encodeInt(BigInt(symbol.functionId!))]).length; + const definedCost = bodyPushBytes + idBytes + 1 + useCount * (idBytes + 1); + return useCount * bodyBytes <= definedCost; +} + +// Orders functions so every callee precedes its callers (post-order over the call graph), so an +// inlined callee's compiled body is available to splice into its callers. A cycle (recursion) is +// broken by the visited guard; those functions fall back to OP_DEFINE/OP_INVOKE. +function calleesFirst( + functions: FunctionDefinitionNode[], + functionsByName: Map, +): FunctionDefinitionNode[] { + const ordered: FunctionDefinitionNode[] = []; + const visited = new Set(); + + const visit = (func: FunctionDefinitionNode): void => { + if (visited.has(func.name)) return; + visited.add(func.name); + calledFunctionNames(func, functionsByName).forEach((name) => visit(functionsByName.get(name)!)); + ordered.push(func); + }; + + functions.forEach(visit); + return ordered; +} + +// The names of the global functions called anywhere within a function's body. +function calledFunctionNames( + func: FunctionDefinitionNode, + functionsByName: Map, +): Set { + const names = new Set(); + const collector = new class extends AstTraversal { + visitFunctionCall(node: FunctionCallNode): Node { + if (functionsByName.has(node.identifier.name)) names.add(node.identifier.name); + node.parameters = this.visitList(node.parameters); + return node; + } + }(); + collector.visit(func.body); + return names; +} + +// Functions that must stay OP_DEFINE'd because a call site sits inside a loop — directly, or via +// the callee chain of such a function. Splicing a body into a loop makes every iteration step over +// it, and the VM charges per-opcode cost even for opcodes in an untaken branch, so a small byte +// saving multiplies into a large op-cost regression (measured ~2.8x on sparse-input double-and-add +// loops, where the group-law body sits in a rarely-taken `if`). With OP_DEFINE the skipped call +// site costs 2 stepped opcodes instead of the whole body. +// +// The callee closure protects callees on CONDITIONAL paths inside a loop-resident caller: the +// caller's defined body is stepped end-to-end on every invoke, so a callee inlined into one of its +// untaken branches would be stepped per invocation too. A callee on the caller's always-path is +// stepped ≈ executed either way, so excluding it over-approximates — but the residual cost is only +// ~2 ops + ~5 bytes per function, so the closure is kept coarse rather than branch-aware. Same +// deliberate imprecision for always-executed call sites directly in loops: inlining there would +// actually save the 2 invoke ops per iteration, but the asymmetry (2 ops/iteration sacrificed vs +// ~100×body-size/iteration protected) makes conservative the right default. (A branch-aware +// variant was measured at ±0 op-cost on real codebases — every hot call site is if-guarded — +// and rejected as not worth the complexity.) +function collectLoopExcludedFunctions( + node: SourceFileNode, + functionsByName: Map, +): Set { + const excluded = new Set(); + let loopDepth = 0; + const collector = new class extends AstTraversal { + visitWhile(n: WhileNode): Node { + loopDepth += 1; + const result = super.visitWhile(n); + loopDepth -= 1; + return result; + } + + visitDoWhile(n: DoWhileNode): Node { + loopDepth += 1; + const result = super.visitDoWhile(n); + loopDepth -= 1; + return result; + } + + visitFor(n: ForNode): Node { + loopDepth += 1; + const result = super.visitFor(n); + loopDepth -= 1; + return result; + } + + visitFunctionCall(n: FunctionCallNode): Node { + if (loopDepth > 0 && functionsByName.has(n.identifier.name)) excluded.add(n.identifier.name); + return super.visitFunctionCall(n); + } + }(); + node.functions.forEach((func) => collector.visit(func.body)); + if (node.contract) collector.visit(node.contract); + + const queue = [...excluded]; + while (queue.length > 0) { + const func = functionsByName.get(queue.shift()!); + if (func === undefined) continue; + calledFunctionNames(func, functionsByName).forEach((name) => { + if (!excluded.has(name)) { + excluded.add(name); + queue.push(name); + } + }); + } + return excluded; +} diff --git a/packages/cashc/src/grammar/CashScript.g4 b/packages/cashc/src/grammar/CashScript.g4 index c221b077..ec5f98e6 100644 --- a/packages/cashc/src/grammar/CashScript.g4 +++ b/packages/cashc/src/grammar/CashScript.g4 @@ -30,11 +30,18 @@ importDirective topLevelDefinition : globalFunctionDefinition + | constantDefinition | contractDefinition ; +// A compile-time constant, folded to a literal and inlined at every use site before semantic +// analysis. The initializer must be a constant expression (no introspection / runtime values). +constantDefinition + : typeName 'constant' Identifier '=' expression ';' + ; + globalFunctionDefinition - : 'function' Identifier parameterList ('returns' '(' typeName ')')? functionBody + : 'function' Identifier parameterList ('returns' '(' typeName (',' typeName)* ')')? functionBody ; contractDefinition @@ -54,7 +61,7 @@ parameterList ; parameter - : typeName Identifier + : typeName modifier* Identifier ; block @@ -83,7 +90,7 @@ functionCallStatement ; returnStatement - : 'return' expression + : 'return' expression (',' expression)* ; controlStatement @@ -96,7 +103,16 @@ variableDefinition ; tupleAssignment - : typeName Identifier ',' typeName Identifier '=' expression + : tupleTarget (',' tupleTarget)+ '=' expression + | '(' tupleTarget (',' tupleTarget)+ ')' '=' expression + ; + +// A destructuring target is either a fresh declaration (`int x`) or an existing variable to +// reassign (`x`, no type). Reassigning existing variables avoids the fresh-temp + per-element +// rebind workaround; the code generator lowers a top-level reassignment to a stack rename. +tupleTarget + : typeName Identifier + | Identifier ; assignStatement @@ -194,6 +210,7 @@ expression modifier : 'constant' + | 'unused' ; literal diff --git a/packages/cashc/src/grammar/CashScript.interp b/packages/cashc/src/grammar/CashScript.interp index 30fbbbcd..229dd09f 100644 --- a/packages/cashc/src/grammar/CashScript.interp +++ b/packages/cashc/src/grammar/CashScript.interp @@ -11,14 +11,15 @@ null '<=' '=' 'import' +'constant' 'function' 'returns' '(' +',' ')' 'contract' '{' '}' -',' 'return' '+=' '-=' @@ -63,7 +64,7 @@ null '|' '&&' '||' -'constant' +'unused' null null null @@ -151,6 +152,7 @@ null null null null +null VersionLiteral BooleanLiteral NumberUnit @@ -181,6 +183,7 @@ versionConstraint versionOperator importDirective topLevelDefinition +constantDefinition globalFunctionDefinition contractDefinition contractFunctionDefinition @@ -195,6 +198,7 @@ returnStatement controlStatement variableDefinition tupleAssignment +tupleTarget assignStatement timeOpStatement requireStatement @@ -219,4 +223,4 @@ typeCast atn: -[4, 1, 84, 481, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 1, 0, 5, 0, 88, 8, 0, 10, 0, 12, 0, 91, 9, 0, 1, 0, 5, 0, 94, 8, 0, 10, 0, 12, 0, 97, 9, 0, 1, 0, 5, 0, 100, 8, 0, 10, 0, 12, 0, 103, 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 3, 3, 116, 8, 3, 1, 4, 3, 4, 119, 8, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 3, 7, 131, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 3, 8, 141, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 5, 9, 150, 8, 9, 10, 9, 12, 9, 153, 9, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 5, 11, 164, 8, 11, 10, 11, 12, 11, 167, 9, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 175, 8, 12, 10, 12, 12, 12, 178, 9, 12, 1, 12, 3, 12, 181, 8, 12, 3, 12, 183, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 192, 8, 14, 10, 14, 12, 14, 195, 9, 14, 1, 14, 1, 14, 3, 14, 199, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 205, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 215, 8, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 3, 19, 224, 8, 19, 1, 20, 1, 20, 5, 20, 228, 8, 20, 10, 20, 12, 20, 231, 9, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 250, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 259, 8, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 268, 8, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 3, 26, 282, 8, 26, 1, 27, 1, 27, 1, 27, 3, 27, 287, 8, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 3, 31, 315, 8, 31, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 321, 8, 33, 1, 34, 1, 34, 1, 34, 1, 34, 5, 34, 327, 8, 34, 10, 34, 12, 34, 330, 9, 34, 1, 34, 3, 34, 333, 8, 34, 3, 34, 335, 8, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 346, 8, 36, 10, 36, 12, 36, 349, 9, 36, 1, 36, 3, 36, 352, 8, 36, 3, 36, 354, 8, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 367, 8, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 393, 8, 37, 10, 37, 12, 37, 396, 9, 37, 1, 37, 3, 37, 399, 8, 37, 3, 37, 401, 8, 37, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 407, 8, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 459, 8, 37, 10, 37, 12, 37, 462, 9, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 471, 8, 39, 1, 40, 1, 40, 3, 40, 475, 8, 40, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 0, 1, 74, 43, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 0, 14, 1, 0, 4, 10, 2, 0, 10, 10, 21, 22, 1, 0, 23, 24, 1, 0, 36, 40, 2, 0, 36, 40, 42, 45, 2, 0, 5, 5, 50, 51, 1, 0, 52, 54, 2, 0, 51, 51, 55, 55, 1, 0, 56, 57, 1, 0, 6, 9, 1, 0, 58, 59, 1, 0, 46, 47, 1, 0, 71, 73, 2, 0, 71, 72, 79, 79, 508, 0, 89, 1, 0, 0, 0, 2, 106, 1, 0, 0, 0, 4, 111, 1, 0, 0, 0, 6, 113, 1, 0, 0, 0, 8, 118, 1, 0, 0, 0, 10, 122, 1, 0, 0, 0, 12, 124, 1, 0, 0, 0, 14, 130, 1, 0, 0, 0, 16, 132, 1, 0, 0, 0, 18, 144, 1, 0, 0, 0, 20, 156, 1, 0, 0, 0, 22, 161, 1, 0, 0, 0, 24, 170, 1, 0, 0, 0, 26, 186, 1, 0, 0, 0, 28, 198, 1, 0, 0, 0, 30, 204, 1, 0, 0, 0, 32, 214, 1, 0, 0, 0, 34, 216, 1, 0, 0, 0, 36, 218, 1, 0, 0, 0, 38, 223, 1, 0, 0, 0, 40, 225, 1, 0, 0, 0, 42, 236, 1, 0, 0, 0, 44, 249, 1, 0, 0, 0, 46, 251, 1, 0, 0, 0, 48, 262, 1, 0, 0, 0, 50, 271, 1, 0, 0, 0, 52, 274, 1, 0, 0, 0, 54, 286, 1, 0, 0, 0, 56, 288, 1, 0, 0, 0, 58, 296, 1, 0, 0, 0, 60, 302, 1, 0, 0, 0, 62, 314, 1, 0, 0, 0, 64, 316, 1, 0, 0, 0, 66, 320, 1, 0, 0, 0, 68, 322, 1, 0, 0, 0, 70, 338, 1, 0, 0, 0, 72, 341, 1, 0, 0, 0, 74, 406, 1, 0, 0, 0, 76, 463, 1, 0, 0, 0, 78, 470, 1, 0, 0, 0, 80, 472, 1, 0, 0, 0, 82, 476, 1, 0, 0, 0, 84, 478, 1, 0, 0, 0, 86, 88, 3, 2, 1, 0, 87, 86, 1, 0, 0, 0, 88, 91, 1, 0, 0, 0, 89, 87, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 95, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 92, 94, 3, 12, 6, 0, 93, 92, 1, 0, 0, 0, 94, 97, 1, 0, 0, 0, 95, 93, 1, 0, 0, 0, 95, 96, 1, 0, 0, 0, 96, 101, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 98, 100, 3, 14, 7, 0, 99, 98, 1, 0, 0, 0, 100, 103, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 101, 102, 1, 0, 0, 0, 102, 104, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 104, 105, 5, 0, 0, 1, 105, 1, 1, 0, 0, 0, 106, 107, 5, 1, 0, 0, 107, 108, 3, 4, 2, 0, 108, 109, 3, 6, 3, 0, 109, 110, 5, 2, 0, 0, 110, 3, 1, 0, 0, 0, 111, 112, 5, 3, 0, 0, 112, 5, 1, 0, 0, 0, 113, 115, 3, 8, 4, 0, 114, 116, 3, 8, 4, 0, 115, 114, 1, 0, 0, 0, 115, 116, 1, 0, 0, 0, 116, 7, 1, 0, 0, 0, 117, 119, 3, 10, 5, 0, 118, 117, 1, 0, 0, 0, 118, 119, 1, 0, 0, 0, 119, 120, 1, 0, 0, 0, 120, 121, 5, 65, 0, 0, 121, 9, 1, 0, 0, 0, 122, 123, 7, 0, 0, 0, 123, 11, 1, 0, 0, 0, 124, 125, 5, 11, 0, 0, 125, 126, 5, 75, 0, 0, 126, 127, 5, 2, 0, 0, 127, 13, 1, 0, 0, 0, 128, 131, 3, 16, 8, 0, 129, 131, 3, 18, 9, 0, 130, 128, 1, 0, 0, 0, 130, 129, 1, 0, 0, 0, 131, 15, 1, 0, 0, 0, 132, 133, 5, 12, 0, 0, 133, 134, 5, 81, 0, 0, 134, 140, 3, 24, 12, 0, 135, 136, 5, 13, 0, 0, 136, 137, 5, 14, 0, 0, 137, 138, 3, 82, 41, 0, 138, 139, 5, 15, 0, 0, 139, 141, 1, 0, 0, 0, 140, 135, 1, 0, 0, 0, 140, 141, 1, 0, 0, 0, 141, 142, 1, 0, 0, 0, 142, 143, 3, 22, 11, 0, 143, 17, 1, 0, 0, 0, 144, 145, 5, 16, 0, 0, 145, 146, 5, 81, 0, 0, 146, 147, 3, 24, 12, 0, 147, 151, 5, 17, 0, 0, 148, 150, 3, 20, 10, 0, 149, 148, 1, 0, 0, 0, 150, 153, 1, 0, 0, 0, 151, 149, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 154, 1, 0, 0, 0, 153, 151, 1, 0, 0, 0, 154, 155, 5, 18, 0, 0, 155, 19, 1, 0, 0, 0, 156, 157, 5, 12, 0, 0, 157, 158, 5, 81, 0, 0, 158, 159, 3, 24, 12, 0, 159, 160, 3, 22, 11, 0, 160, 21, 1, 0, 0, 0, 161, 165, 5, 17, 0, 0, 162, 164, 3, 30, 15, 0, 163, 162, 1, 0, 0, 0, 164, 167, 1, 0, 0, 0, 165, 163, 1, 0, 0, 0, 165, 166, 1, 0, 0, 0, 166, 168, 1, 0, 0, 0, 167, 165, 1, 0, 0, 0, 168, 169, 5, 18, 0, 0, 169, 23, 1, 0, 0, 0, 170, 182, 5, 14, 0, 0, 171, 176, 3, 26, 13, 0, 172, 173, 5, 19, 0, 0, 173, 175, 3, 26, 13, 0, 174, 172, 1, 0, 0, 0, 175, 178, 1, 0, 0, 0, 176, 174, 1, 0, 0, 0, 176, 177, 1, 0, 0, 0, 177, 180, 1, 0, 0, 0, 178, 176, 1, 0, 0, 0, 179, 181, 5, 19, 0, 0, 180, 179, 1, 0, 0, 0, 180, 181, 1, 0, 0, 0, 181, 183, 1, 0, 0, 0, 182, 171, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 185, 5, 15, 0, 0, 185, 25, 1, 0, 0, 0, 186, 187, 3, 82, 41, 0, 187, 188, 5, 81, 0, 0, 188, 27, 1, 0, 0, 0, 189, 193, 5, 17, 0, 0, 190, 192, 3, 30, 15, 0, 191, 190, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 196, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 199, 5, 18, 0, 0, 197, 199, 3, 30, 15, 0, 198, 189, 1, 0, 0, 0, 198, 197, 1, 0, 0, 0, 199, 29, 1, 0, 0, 0, 200, 205, 3, 38, 19, 0, 201, 202, 3, 32, 16, 0, 202, 203, 5, 2, 0, 0, 203, 205, 1, 0, 0, 0, 204, 200, 1, 0, 0, 0, 204, 201, 1, 0, 0, 0, 205, 31, 1, 0, 0, 0, 206, 215, 3, 40, 20, 0, 207, 215, 3, 42, 21, 0, 208, 215, 3, 44, 22, 0, 209, 215, 3, 46, 23, 0, 210, 215, 3, 48, 24, 0, 211, 215, 3, 34, 17, 0, 212, 215, 3, 50, 25, 0, 213, 215, 3, 36, 18, 0, 214, 206, 1, 0, 0, 0, 214, 207, 1, 0, 0, 0, 214, 208, 1, 0, 0, 0, 214, 209, 1, 0, 0, 0, 214, 210, 1, 0, 0, 0, 214, 211, 1, 0, 0, 0, 214, 212, 1, 0, 0, 0, 214, 213, 1, 0, 0, 0, 215, 33, 1, 0, 0, 0, 216, 217, 3, 70, 35, 0, 217, 35, 1, 0, 0, 0, 218, 219, 5, 20, 0, 0, 219, 220, 3, 74, 37, 0, 220, 37, 1, 0, 0, 0, 221, 224, 3, 52, 26, 0, 222, 224, 3, 54, 27, 0, 223, 221, 1, 0, 0, 0, 223, 222, 1, 0, 0, 0, 224, 39, 1, 0, 0, 0, 225, 229, 3, 82, 41, 0, 226, 228, 3, 76, 38, 0, 227, 226, 1, 0, 0, 0, 228, 231, 1, 0, 0, 0, 229, 227, 1, 0, 0, 0, 229, 230, 1, 0, 0, 0, 230, 232, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 232, 233, 5, 81, 0, 0, 233, 234, 5, 10, 0, 0, 234, 235, 3, 74, 37, 0, 235, 41, 1, 0, 0, 0, 236, 237, 3, 82, 41, 0, 237, 238, 5, 81, 0, 0, 238, 239, 5, 19, 0, 0, 239, 240, 3, 82, 41, 0, 240, 241, 5, 81, 0, 0, 241, 242, 5, 10, 0, 0, 242, 243, 3, 74, 37, 0, 243, 43, 1, 0, 0, 0, 244, 245, 5, 81, 0, 0, 245, 246, 7, 1, 0, 0, 246, 250, 3, 74, 37, 0, 247, 248, 5, 81, 0, 0, 248, 250, 7, 2, 0, 0, 249, 244, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 45, 1, 0, 0, 0, 251, 252, 5, 25, 0, 0, 252, 253, 5, 14, 0, 0, 253, 254, 5, 78, 0, 0, 254, 255, 5, 6, 0, 0, 255, 258, 3, 74, 37, 0, 256, 257, 5, 19, 0, 0, 257, 259, 3, 64, 32, 0, 258, 256, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 1, 0, 0, 0, 260, 261, 5, 15, 0, 0, 261, 47, 1, 0, 0, 0, 262, 263, 5, 25, 0, 0, 263, 264, 5, 14, 0, 0, 264, 267, 3, 74, 37, 0, 265, 266, 5, 19, 0, 0, 266, 268, 3, 64, 32, 0, 267, 265, 1, 0, 0, 0, 267, 268, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 270, 5, 15, 0, 0, 270, 49, 1, 0, 0, 0, 271, 272, 5, 26, 0, 0, 272, 273, 3, 68, 34, 0, 273, 51, 1, 0, 0, 0, 274, 275, 5, 27, 0, 0, 275, 276, 5, 14, 0, 0, 276, 277, 3, 74, 37, 0, 277, 278, 5, 15, 0, 0, 278, 281, 3, 28, 14, 0, 279, 280, 5, 28, 0, 0, 280, 282, 3, 28, 14, 0, 281, 279, 1, 0, 0, 0, 281, 282, 1, 0, 0, 0, 282, 53, 1, 0, 0, 0, 283, 287, 3, 56, 28, 0, 284, 287, 3, 58, 29, 0, 285, 287, 3, 60, 30, 0, 286, 283, 1, 0, 0, 0, 286, 284, 1, 0, 0, 0, 286, 285, 1, 0, 0, 0, 287, 55, 1, 0, 0, 0, 288, 289, 5, 29, 0, 0, 289, 290, 3, 28, 14, 0, 290, 291, 5, 30, 0, 0, 291, 292, 5, 14, 0, 0, 292, 293, 3, 74, 37, 0, 293, 294, 5, 15, 0, 0, 294, 295, 5, 2, 0, 0, 295, 57, 1, 0, 0, 0, 296, 297, 5, 30, 0, 0, 297, 298, 5, 14, 0, 0, 298, 299, 3, 74, 37, 0, 299, 300, 5, 15, 0, 0, 300, 301, 3, 28, 14, 0, 301, 59, 1, 0, 0, 0, 302, 303, 5, 31, 0, 0, 303, 304, 5, 14, 0, 0, 304, 305, 3, 62, 31, 0, 305, 306, 5, 2, 0, 0, 306, 307, 3, 74, 37, 0, 307, 308, 5, 2, 0, 0, 308, 309, 3, 44, 22, 0, 309, 310, 5, 15, 0, 0, 310, 311, 3, 28, 14, 0, 311, 61, 1, 0, 0, 0, 312, 315, 3, 40, 20, 0, 313, 315, 3, 44, 22, 0, 314, 312, 1, 0, 0, 0, 314, 313, 1, 0, 0, 0, 315, 63, 1, 0, 0, 0, 316, 317, 5, 75, 0, 0, 317, 65, 1, 0, 0, 0, 318, 321, 5, 81, 0, 0, 319, 321, 3, 78, 39, 0, 320, 318, 1, 0, 0, 0, 320, 319, 1, 0, 0, 0, 321, 67, 1, 0, 0, 0, 322, 334, 5, 14, 0, 0, 323, 328, 3, 66, 33, 0, 324, 325, 5, 19, 0, 0, 325, 327, 3, 66, 33, 0, 326, 324, 1, 0, 0, 0, 327, 330, 1, 0, 0, 0, 328, 326, 1, 0, 0, 0, 328, 329, 1, 0, 0, 0, 329, 332, 1, 0, 0, 0, 330, 328, 1, 0, 0, 0, 331, 333, 5, 19, 0, 0, 332, 331, 1, 0, 0, 0, 332, 333, 1, 0, 0, 0, 333, 335, 1, 0, 0, 0, 334, 323, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, 335, 336, 1, 0, 0, 0, 336, 337, 5, 15, 0, 0, 337, 69, 1, 0, 0, 0, 338, 339, 5, 81, 0, 0, 339, 340, 3, 72, 36, 0, 340, 71, 1, 0, 0, 0, 341, 353, 5, 14, 0, 0, 342, 347, 3, 74, 37, 0, 343, 344, 5, 19, 0, 0, 344, 346, 3, 74, 37, 0, 345, 343, 1, 0, 0, 0, 346, 349, 1, 0, 0, 0, 347, 345, 1, 0, 0, 0, 347, 348, 1, 0, 0, 0, 348, 351, 1, 0, 0, 0, 349, 347, 1, 0, 0, 0, 350, 352, 5, 19, 0, 0, 351, 350, 1, 0, 0, 0, 351, 352, 1, 0, 0, 0, 352, 354, 1, 0, 0, 0, 353, 342, 1, 0, 0, 0, 353, 354, 1, 0, 0, 0, 354, 355, 1, 0, 0, 0, 355, 356, 5, 15, 0, 0, 356, 73, 1, 0, 0, 0, 357, 358, 6, 37, -1, 0, 358, 359, 5, 14, 0, 0, 359, 360, 3, 74, 37, 0, 360, 361, 5, 15, 0, 0, 361, 407, 1, 0, 0, 0, 362, 363, 3, 84, 42, 0, 363, 364, 5, 14, 0, 0, 364, 366, 3, 74, 37, 0, 365, 367, 5, 19, 0, 0, 366, 365, 1, 0, 0, 0, 366, 367, 1, 0, 0, 0, 367, 368, 1, 0, 0, 0, 368, 369, 5, 15, 0, 0, 369, 407, 1, 0, 0, 0, 370, 407, 3, 70, 35, 0, 371, 372, 5, 32, 0, 0, 372, 373, 5, 81, 0, 0, 373, 407, 3, 72, 36, 0, 374, 375, 5, 35, 0, 0, 375, 376, 5, 33, 0, 0, 376, 377, 3, 74, 37, 0, 377, 378, 5, 34, 0, 0, 378, 379, 7, 3, 0, 0, 379, 407, 1, 0, 0, 0, 380, 381, 5, 41, 0, 0, 381, 382, 5, 33, 0, 0, 382, 383, 3, 74, 37, 0, 383, 384, 5, 34, 0, 0, 384, 385, 7, 4, 0, 0, 385, 407, 1, 0, 0, 0, 386, 387, 7, 5, 0, 0, 387, 407, 3, 74, 37, 15, 388, 400, 5, 33, 0, 0, 389, 394, 3, 74, 37, 0, 390, 391, 5, 19, 0, 0, 391, 393, 3, 74, 37, 0, 392, 390, 1, 0, 0, 0, 393, 396, 1, 0, 0, 0, 394, 392, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 398, 1, 0, 0, 0, 396, 394, 1, 0, 0, 0, 397, 399, 5, 19, 0, 0, 398, 397, 1, 0, 0, 0, 398, 399, 1, 0, 0, 0, 399, 401, 1, 0, 0, 0, 400, 389, 1, 0, 0, 0, 400, 401, 1, 0, 0, 0, 401, 402, 1, 0, 0, 0, 402, 407, 5, 34, 0, 0, 403, 407, 5, 80, 0, 0, 404, 407, 5, 81, 0, 0, 405, 407, 3, 78, 39, 0, 406, 357, 1, 0, 0, 0, 406, 362, 1, 0, 0, 0, 406, 370, 1, 0, 0, 0, 406, 371, 1, 0, 0, 0, 406, 374, 1, 0, 0, 0, 406, 380, 1, 0, 0, 0, 406, 386, 1, 0, 0, 0, 406, 388, 1, 0, 0, 0, 406, 403, 1, 0, 0, 0, 406, 404, 1, 0, 0, 0, 406, 405, 1, 0, 0, 0, 407, 460, 1, 0, 0, 0, 408, 409, 10, 14, 0, 0, 409, 410, 7, 6, 0, 0, 410, 459, 3, 74, 37, 15, 411, 412, 10, 13, 0, 0, 412, 413, 7, 7, 0, 0, 413, 459, 3, 74, 37, 14, 414, 415, 10, 12, 0, 0, 415, 416, 7, 8, 0, 0, 416, 459, 3, 74, 37, 13, 417, 418, 10, 11, 0, 0, 418, 419, 7, 9, 0, 0, 419, 459, 3, 74, 37, 12, 420, 421, 10, 10, 0, 0, 421, 422, 7, 10, 0, 0, 422, 459, 3, 74, 37, 11, 423, 424, 10, 9, 0, 0, 424, 425, 5, 60, 0, 0, 425, 459, 3, 74, 37, 10, 426, 427, 10, 8, 0, 0, 427, 428, 5, 4, 0, 0, 428, 459, 3, 74, 37, 9, 429, 430, 10, 7, 0, 0, 430, 431, 5, 61, 0, 0, 431, 459, 3, 74, 37, 8, 432, 433, 10, 6, 0, 0, 433, 434, 5, 62, 0, 0, 434, 459, 3, 74, 37, 7, 435, 436, 10, 5, 0, 0, 436, 437, 5, 63, 0, 0, 437, 459, 3, 74, 37, 6, 438, 439, 10, 21, 0, 0, 439, 440, 5, 33, 0, 0, 440, 441, 5, 68, 0, 0, 441, 459, 5, 34, 0, 0, 442, 443, 10, 18, 0, 0, 443, 459, 7, 11, 0, 0, 444, 445, 10, 17, 0, 0, 445, 446, 5, 48, 0, 0, 446, 447, 5, 14, 0, 0, 447, 448, 3, 74, 37, 0, 448, 449, 5, 15, 0, 0, 449, 459, 1, 0, 0, 0, 450, 451, 10, 16, 0, 0, 451, 452, 5, 49, 0, 0, 452, 453, 5, 14, 0, 0, 453, 454, 3, 74, 37, 0, 454, 455, 5, 19, 0, 0, 455, 456, 3, 74, 37, 0, 456, 457, 5, 15, 0, 0, 457, 459, 1, 0, 0, 0, 458, 408, 1, 0, 0, 0, 458, 411, 1, 0, 0, 0, 458, 414, 1, 0, 0, 0, 458, 417, 1, 0, 0, 0, 458, 420, 1, 0, 0, 0, 458, 423, 1, 0, 0, 0, 458, 426, 1, 0, 0, 0, 458, 429, 1, 0, 0, 0, 458, 432, 1, 0, 0, 0, 458, 435, 1, 0, 0, 0, 458, 438, 1, 0, 0, 0, 458, 442, 1, 0, 0, 0, 458, 444, 1, 0, 0, 0, 458, 450, 1, 0, 0, 0, 459, 462, 1, 0, 0, 0, 460, 458, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 75, 1, 0, 0, 0, 462, 460, 1, 0, 0, 0, 463, 464, 5, 64, 0, 0, 464, 77, 1, 0, 0, 0, 465, 471, 5, 66, 0, 0, 466, 471, 3, 80, 40, 0, 467, 471, 5, 75, 0, 0, 468, 471, 5, 76, 0, 0, 469, 471, 5, 77, 0, 0, 470, 465, 1, 0, 0, 0, 470, 466, 1, 0, 0, 0, 470, 467, 1, 0, 0, 0, 470, 468, 1, 0, 0, 0, 470, 469, 1, 0, 0, 0, 471, 79, 1, 0, 0, 0, 472, 474, 5, 68, 0, 0, 473, 475, 5, 67, 0, 0, 474, 473, 1, 0, 0, 0, 474, 475, 1, 0, 0, 0, 475, 81, 1, 0, 0, 0, 476, 477, 7, 12, 0, 0, 477, 83, 1, 0, 0, 0, 478, 479, 7, 13, 0, 0, 479, 85, 1, 0, 0, 0, 40, 89, 95, 101, 115, 118, 130, 140, 151, 165, 176, 180, 182, 193, 198, 204, 214, 223, 229, 249, 258, 267, 281, 286, 314, 320, 328, 332, 334, 347, 351, 353, 366, 394, 398, 400, 406, 458, 460, 470, 474] \ No newline at end of file +[4, 1, 85, 534, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 1, 0, 5, 0, 92, 8, 0, 10, 0, 12, 0, 95, 9, 0, 1, 0, 5, 0, 98, 8, 0, 10, 0, 12, 0, 101, 9, 0, 1, 0, 5, 0, 104, 8, 0, 10, 0, 12, 0, 107, 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 3, 3, 120, 8, 3, 1, 4, 3, 4, 123, 8, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 3, 7, 136, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 5, 9, 153, 8, 9, 10, 9, 12, 9, 156, 9, 9, 1, 9, 1, 9, 3, 9, 160, 8, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 169, 8, 10, 10, 10, 12, 10, 172, 9, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 5, 12, 183, 8, 12, 10, 12, 12, 12, 186, 9, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 194, 8, 13, 10, 13, 12, 13, 197, 9, 13, 1, 13, 3, 13, 200, 8, 13, 3, 13, 202, 8, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 208, 8, 14, 10, 14, 12, 14, 211, 9, 14, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 217, 8, 15, 10, 15, 12, 15, 220, 9, 15, 1, 15, 1, 15, 3, 15, 224, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 230, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 240, 8, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 248, 8, 19, 10, 19, 12, 19, 251, 9, 19, 1, 20, 1, 20, 3, 20, 255, 8, 20, 1, 21, 1, 21, 5, 21, 259, 8, 21, 10, 21, 12, 21, 262, 9, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 4, 22, 271, 8, 22, 11, 22, 12, 22, 272, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 4, 22, 282, 8, 22, 11, 22, 12, 22, 283, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 290, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 296, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 303, 8, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 312, 8, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 3, 26, 321, 8, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 3, 28, 335, 8, 28, 1, 29, 1, 29, 1, 29, 3, 29, 340, 8, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 368, 8, 33, 1, 34, 1, 34, 1, 35, 1, 35, 3, 35, 374, 8, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 380, 8, 36, 10, 36, 12, 36, 383, 9, 36, 1, 36, 3, 36, 386, 8, 36, 3, 36, 388, 8, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 399, 8, 38, 10, 38, 12, 38, 402, 9, 38, 1, 38, 3, 38, 405, 8, 38, 3, 38, 407, 8, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 420, 8, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 5, 39, 446, 8, 39, 10, 39, 12, 39, 449, 9, 39, 1, 39, 3, 39, 452, 8, 39, 3, 39, 454, 8, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 460, 8, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 5, 39, 512, 8, 39, 10, 39, 12, 39, 515, 9, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 524, 8, 41, 1, 42, 1, 42, 3, 42, 528, 8, 42, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 0, 1, 78, 45, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 0, 15, 1, 0, 4, 10, 2, 0, 10, 10, 22, 23, 1, 0, 24, 25, 1, 0, 37, 41, 2, 0, 37, 41, 43, 46, 2, 0, 5, 5, 51, 52, 1, 0, 53, 55, 2, 0, 52, 52, 56, 56, 1, 0, 57, 58, 1, 0, 6, 9, 1, 0, 59, 60, 1, 0, 47, 48, 2, 0, 12, 12, 65, 65, 1, 0, 72, 74, 2, 0, 72, 73, 80, 80, 567, 0, 93, 1, 0, 0, 0, 2, 110, 1, 0, 0, 0, 4, 115, 1, 0, 0, 0, 6, 117, 1, 0, 0, 0, 8, 122, 1, 0, 0, 0, 10, 126, 1, 0, 0, 0, 12, 128, 1, 0, 0, 0, 14, 135, 1, 0, 0, 0, 16, 137, 1, 0, 0, 0, 18, 144, 1, 0, 0, 0, 20, 163, 1, 0, 0, 0, 22, 175, 1, 0, 0, 0, 24, 180, 1, 0, 0, 0, 26, 189, 1, 0, 0, 0, 28, 205, 1, 0, 0, 0, 30, 223, 1, 0, 0, 0, 32, 229, 1, 0, 0, 0, 34, 239, 1, 0, 0, 0, 36, 241, 1, 0, 0, 0, 38, 243, 1, 0, 0, 0, 40, 254, 1, 0, 0, 0, 42, 256, 1, 0, 0, 0, 44, 289, 1, 0, 0, 0, 46, 295, 1, 0, 0, 0, 48, 302, 1, 0, 0, 0, 50, 304, 1, 0, 0, 0, 52, 315, 1, 0, 0, 0, 54, 324, 1, 0, 0, 0, 56, 327, 1, 0, 0, 0, 58, 339, 1, 0, 0, 0, 60, 341, 1, 0, 0, 0, 62, 349, 1, 0, 0, 0, 64, 355, 1, 0, 0, 0, 66, 367, 1, 0, 0, 0, 68, 369, 1, 0, 0, 0, 70, 373, 1, 0, 0, 0, 72, 375, 1, 0, 0, 0, 74, 391, 1, 0, 0, 0, 76, 394, 1, 0, 0, 0, 78, 459, 1, 0, 0, 0, 80, 516, 1, 0, 0, 0, 82, 523, 1, 0, 0, 0, 84, 525, 1, 0, 0, 0, 86, 529, 1, 0, 0, 0, 88, 531, 1, 0, 0, 0, 90, 92, 3, 2, 1, 0, 91, 90, 1, 0, 0, 0, 92, 95, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 93, 94, 1, 0, 0, 0, 94, 99, 1, 0, 0, 0, 95, 93, 1, 0, 0, 0, 96, 98, 3, 12, 6, 0, 97, 96, 1, 0, 0, 0, 98, 101, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 99, 100, 1, 0, 0, 0, 100, 105, 1, 0, 0, 0, 101, 99, 1, 0, 0, 0, 102, 104, 3, 14, 7, 0, 103, 102, 1, 0, 0, 0, 104, 107, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 105, 106, 1, 0, 0, 0, 106, 108, 1, 0, 0, 0, 107, 105, 1, 0, 0, 0, 108, 109, 5, 0, 0, 1, 109, 1, 1, 0, 0, 0, 110, 111, 5, 1, 0, 0, 111, 112, 3, 4, 2, 0, 112, 113, 3, 6, 3, 0, 113, 114, 5, 2, 0, 0, 114, 3, 1, 0, 0, 0, 115, 116, 5, 3, 0, 0, 116, 5, 1, 0, 0, 0, 117, 119, 3, 8, 4, 0, 118, 120, 3, 8, 4, 0, 119, 118, 1, 0, 0, 0, 119, 120, 1, 0, 0, 0, 120, 7, 1, 0, 0, 0, 121, 123, 3, 10, 5, 0, 122, 121, 1, 0, 0, 0, 122, 123, 1, 0, 0, 0, 123, 124, 1, 0, 0, 0, 124, 125, 5, 66, 0, 0, 125, 9, 1, 0, 0, 0, 126, 127, 7, 0, 0, 0, 127, 11, 1, 0, 0, 0, 128, 129, 5, 11, 0, 0, 129, 130, 5, 76, 0, 0, 130, 131, 5, 2, 0, 0, 131, 13, 1, 0, 0, 0, 132, 136, 3, 18, 9, 0, 133, 136, 3, 16, 8, 0, 134, 136, 3, 20, 10, 0, 135, 132, 1, 0, 0, 0, 135, 133, 1, 0, 0, 0, 135, 134, 1, 0, 0, 0, 136, 15, 1, 0, 0, 0, 137, 138, 3, 86, 43, 0, 138, 139, 5, 12, 0, 0, 139, 140, 5, 82, 0, 0, 140, 141, 5, 10, 0, 0, 141, 142, 3, 78, 39, 0, 142, 143, 5, 2, 0, 0, 143, 17, 1, 0, 0, 0, 144, 145, 5, 13, 0, 0, 145, 146, 5, 82, 0, 0, 146, 159, 3, 26, 13, 0, 147, 148, 5, 14, 0, 0, 148, 149, 5, 15, 0, 0, 149, 154, 3, 86, 43, 0, 150, 151, 5, 16, 0, 0, 151, 153, 3, 86, 43, 0, 152, 150, 1, 0, 0, 0, 153, 156, 1, 0, 0, 0, 154, 152, 1, 0, 0, 0, 154, 155, 1, 0, 0, 0, 155, 157, 1, 0, 0, 0, 156, 154, 1, 0, 0, 0, 157, 158, 5, 17, 0, 0, 158, 160, 1, 0, 0, 0, 159, 147, 1, 0, 0, 0, 159, 160, 1, 0, 0, 0, 160, 161, 1, 0, 0, 0, 161, 162, 3, 24, 12, 0, 162, 19, 1, 0, 0, 0, 163, 164, 5, 18, 0, 0, 164, 165, 5, 82, 0, 0, 165, 166, 3, 26, 13, 0, 166, 170, 5, 19, 0, 0, 167, 169, 3, 22, 11, 0, 168, 167, 1, 0, 0, 0, 169, 172, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 170, 171, 1, 0, 0, 0, 171, 173, 1, 0, 0, 0, 172, 170, 1, 0, 0, 0, 173, 174, 5, 20, 0, 0, 174, 21, 1, 0, 0, 0, 175, 176, 5, 13, 0, 0, 176, 177, 5, 82, 0, 0, 177, 178, 3, 26, 13, 0, 178, 179, 3, 24, 12, 0, 179, 23, 1, 0, 0, 0, 180, 184, 5, 19, 0, 0, 181, 183, 3, 32, 16, 0, 182, 181, 1, 0, 0, 0, 183, 186, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 184, 185, 1, 0, 0, 0, 185, 187, 1, 0, 0, 0, 186, 184, 1, 0, 0, 0, 187, 188, 5, 20, 0, 0, 188, 25, 1, 0, 0, 0, 189, 201, 5, 15, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 16, 0, 0, 192, 194, 3, 28, 14, 0, 193, 191, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 199, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 198, 200, 5, 16, 0, 0, 199, 198, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 202, 1, 0, 0, 0, 201, 190, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 203, 1, 0, 0, 0, 203, 204, 5, 17, 0, 0, 204, 27, 1, 0, 0, 0, 205, 209, 3, 86, 43, 0, 206, 208, 3, 80, 40, 0, 207, 206, 1, 0, 0, 0, 208, 211, 1, 0, 0, 0, 209, 207, 1, 0, 0, 0, 209, 210, 1, 0, 0, 0, 210, 212, 1, 0, 0, 0, 211, 209, 1, 0, 0, 0, 212, 213, 5, 82, 0, 0, 213, 29, 1, 0, 0, 0, 214, 218, 5, 19, 0, 0, 215, 217, 3, 32, 16, 0, 216, 215, 1, 0, 0, 0, 217, 220, 1, 0, 0, 0, 218, 216, 1, 0, 0, 0, 218, 219, 1, 0, 0, 0, 219, 221, 1, 0, 0, 0, 220, 218, 1, 0, 0, 0, 221, 224, 5, 20, 0, 0, 222, 224, 3, 32, 16, 0, 223, 214, 1, 0, 0, 0, 223, 222, 1, 0, 0, 0, 224, 31, 1, 0, 0, 0, 225, 230, 3, 40, 20, 0, 226, 227, 3, 34, 17, 0, 227, 228, 5, 2, 0, 0, 228, 230, 1, 0, 0, 0, 229, 225, 1, 0, 0, 0, 229, 226, 1, 0, 0, 0, 230, 33, 1, 0, 0, 0, 231, 240, 3, 42, 21, 0, 232, 240, 3, 44, 22, 0, 233, 240, 3, 48, 24, 0, 234, 240, 3, 50, 25, 0, 235, 240, 3, 52, 26, 0, 236, 240, 3, 36, 18, 0, 237, 240, 3, 54, 27, 0, 238, 240, 3, 38, 19, 0, 239, 231, 1, 0, 0, 0, 239, 232, 1, 0, 0, 0, 239, 233, 1, 0, 0, 0, 239, 234, 1, 0, 0, 0, 239, 235, 1, 0, 0, 0, 239, 236, 1, 0, 0, 0, 239, 237, 1, 0, 0, 0, 239, 238, 1, 0, 0, 0, 240, 35, 1, 0, 0, 0, 241, 242, 3, 74, 37, 0, 242, 37, 1, 0, 0, 0, 243, 244, 5, 21, 0, 0, 244, 249, 3, 78, 39, 0, 245, 246, 5, 16, 0, 0, 246, 248, 3, 78, 39, 0, 247, 245, 1, 0, 0, 0, 248, 251, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 249, 250, 1, 0, 0, 0, 250, 39, 1, 0, 0, 0, 251, 249, 1, 0, 0, 0, 252, 255, 3, 56, 28, 0, 253, 255, 3, 58, 29, 0, 254, 252, 1, 0, 0, 0, 254, 253, 1, 0, 0, 0, 255, 41, 1, 0, 0, 0, 256, 260, 3, 86, 43, 0, 257, 259, 3, 80, 40, 0, 258, 257, 1, 0, 0, 0, 259, 262, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 260, 261, 1, 0, 0, 0, 261, 263, 1, 0, 0, 0, 262, 260, 1, 0, 0, 0, 263, 264, 5, 82, 0, 0, 264, 265, 5, 10, 0, 0, 265, 266, 3, 78, 39, 0, 266, 43, 1, 0, 0, 0, 267, 270, 3, 46, 23, 0, 268, 269, 5, 16, 0, 0, 269, 271, 3, 46, 23, 0, 270, 268, 1, 0, 0, 0, 271, 272, 1, 0, 0, 0, 272, 270, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 5, 10, 0, 0, 275, 276, 3, 78, 39, 0, 276, 290, 1, 0, 0, 0, 277, 278, 5, 15, 0, 0, 278, 281, 3, 46, 23, 0, 279, 280, 5, 16, 0, 0, 280, 282, 3, 46, 23, 0, 281, 279, 1, 0, 0, 0, 282, 283, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, 283, 284, 1, 0, 0, 0, 284, 285, 1, 0, 0, 0, 285, 286, 5, 17, 0, 0, 286, 287, 5, 10, 0, 0, 287, 288, 3, 78, 39, 0, 288, 290, 1, 0, 0, 0, 289, 267, 1, 0, 0, 0, 289, 277, 1, 0, 0, 0, 290, 45, 1, 0, 0, 0, 291, 292, 3, 86, 43, 0, 292, 293, 5, 82, 0, 0, 293, 296, 1, 0, 0, 0, 294, 296, 5, 82, 0, 0, 295, 291, 1, 0, 0, 0, 295, 294, 1, 0, 0, 0, 296, 47, 1, 0, 0, 0, 297, 298, 5, 82, 0, 0, 298, 299, 7, 1, 0, 0, 299, 303, 3, 78, 39, 0, 300, 301, 5, 82, 0, 0, 301, 303, 7, 2, 0, 0, 302, 297, 1, 0, 0, 0, 302, 300, 1, 0, 0, 0, 303, 49, 1, 0, 0, 0, 304, 305, 5, 26, 0, 0, 305, 306, 5, 15, 0, 0, 306, 307, 5, 79, 0, 0, 307, 308, 5, 6, 0, 0, 308, 311, 3, 78, 39, 0, 309, 310, 5, 16, 0, 0, 310, 312, 3, 68, 34, 0, 311, 309, 1, 0, 0, 0, 311, 312, 1, 0, 0, 0, 312, 313, 1, 0, 0, 0, 313, 314, 5, 17, 0, 0, 314, 51, 1, 0, 0, 0, 315, 316, 5, 26, 0, 0, 316, 317, 5, 15, 0, 0, 317, 320, 3, 78, 39, 0, 318, 319, 5, 16, 0, 0, 319, 321, 3, 68, 34, 0, 320, 318, 1, 0, 0, 0, 320, 321, 1, 0, 0, 0, 321, 322, 1, 0, 0, 0, 322, 323, 5, 17, 0, 0, 323, 53, 1, 0, 0, 0, 324, 325, 5, 27, 0, 0, 325, 326, 3, 72, 36, 0, 326, 55, 1, 0, 0, 0, 327, 328, 5, 28, 0, 0, 328, 329, 5, 15, 0, 0, 329, 330, 3, 78, 39, 0, 330, 331, 5, 17, 0, 0, 331, 334, 3, 30, 15, 0, 332, 333, 5, 29, 0, 0, 333, 335, 3, 30, 15, 0, 334, 332, 1, 0, 0, 0, 334, 335, 1, 0, 0, 0, 335, 57, 1, 0, 0, 0, 336, 340, 3, 60, 30, 0, 337, 340, 3, 62, 31, 0, 338, 340, 3, 64, 32, 0, 339, 336, 1, 0, 0, 0, 339, 337, 1, 0, 0, 0, 339, 338, 1, 0, 0, 0, 340, 59, 1, 0, 0, 0, 341, 342, 5, 30, 0, 0, 342, 343, 3, 30, 15, 0, 343, 344, 5, 31, 0, 0, 344, 345, 5, 15, 0, 0, 345, 346, 3, 78, 39, 0, 346, 347, 5, 17, 0, 0, 347, 348, 5, 2, 0, 0, 348, 61, 1, 0, 0, 0, 349, 350, 5, 31, 0, 0, 350, 351, 5, 15, 0, 0, 351, 352, 3, 78, 39, 0, 352, 353, 5, 17, 0, 0, 353, 354, 3, 30, 15, 0, 354, 63, 1, 0, 0, 0, 355, 356, 5, 32, 0, 0, 356, 357, 5, 15, 0, 0, 357, 358, 3, 66, 33, 0, 358, 359, 5, 2, 0, 0, 359, 360, 3, 78, 39, 0, 360, 361, 5, 2, 0, 0, 361, 362, 3, 48, 24, 0, 362, 363, 5, 17, 0, 0, 363, 364, 3, 30, 15, 0, 364, 65, 1, 0, 0, 0, 365, 368, 3, 42, 21, 0, 366, 368, 3, 48, 24, 0, 367, 365, 1, 0, 0, 0, 367, 366, 1, 0, 0, 0, 368, 67, 1, 0, 0, 0, 369, 370, 5, 76, 0, 0, 370, 69, 1, 0, 0, 0, 371, 374, 5, 82, 0, 0, 372, 374, 3, 82, 41, 0, 373, 371, 1, 0, 0, 0, 373, 372, 1, 0, 0, 0, 374, 71, 1, 0, 0, 0, 375, 387, 5, 15, 0, 0, 376, 381, 3, 70, 35, 0, 377, 378, 5, 16, 0, 0, 378, 380, 3, 70, 35, 0, 379, 377, 1, 0, 0, 0, 380, 383, 1, 0, 0, 0, 381, 379, 1, 0, 0, 0, 381, 382, 1, 0, 0, 0, 382, 385, 1, 0, 0, 0, 383, 381, 1, 0, 0, 0, 384, 386, 5, 16, 0, 0, 385, 384, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 388, 1, 0, 0, 0, 387, 376, 1, 0, 0, 0, 387, 388, 1, 0, 0, 0, 388, 389, 1, 0, 0, 0, 389, 390, 5, 17, 0, 0, 390, 73, 1, 0, 0, 0, 391, 392, 5, 82, 0, 0, 392, 393, 3, 76, 38, 0, 393, 75, 1, 0, 0, 0, 394, 406, 5, 15, 0, 0, 395, 400, 3, 78, 39, 0, 396, 397, 5, 16, 0, 0, 397, 399, 3, 78, 39, 0, 398, 396, 1, 0, 0, 0, 399, 402, 1, 0, 0, 0, 400, 398, 1, 0, 0, 0, 400, 401, 1, 0, 0, 0, 401, 404, 1, 0, 0, 0, 402, 400, 1, 0, 0, 0, 403, 405, 5, 16, 0, 0, 404, 403, 1, 0, 0, 0, 404, 405, 1, 0, 0, 0, 405, 407, 1, 0, 0, 0, 406, 395, 1, 0, 0, 0, 406, 407, 1, 0, 0, 0, 407, 408, 1, 0, 0, 0, 408, 409, 5, 17, 0, 0, 409, 77, 1, 0, 0, 0, 410, 411, 6, 39, -1, 0, 411, 412, 5, 15, 0, 0, 412, 413, 3, 78, 39, 0, 413, 414, 5, 17, 0, 0, 414, 460, 1, 0, 0, 0, 415, 416, 3, 88, 44, 0, 416, 417, 5, 15, 0, 0, 417, 419, 3, 78, 39, 0, 418, 420, 5, 16, 0, 0, 419, 418, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 420, 421, 1, 0, 0, 0, 421, 422, 5, 17, 0, 0, 422, 460, 1, 0, 0, 0, 423, 460, 3, 74, 37, 0, 424, 425, 5, 33, 0, 0, 425, 426, 5, 82, 0, 0, 426, 460, 3, 76, 38, 0, 427, 428, 5, 36, 0, 0, 428, 429, 5, 34, 0, 0, 429, 430, 3, 78, 39, 0, 430, 431, 5, 35, 0, 0, 431, 432, 7, 3, 0, 0, 432, 460, 1, 0, 0, 0, 433, 434, 5, 42, 0, 0, 434, 435, 5, 34, 0, 0, 435, 436, 3, 78, 39, 0, 436, 437, 5, 35, 0, 0, 437, 438, 7, 4, 0, 0, 438, 460, 1, 0, 0, 0, 439, 440, 7, 5, 0, 0, 440, 460, 3, 78, 39, 15, 441, 453, 5, 34, 0, 0, 442, 447, 3, 78, 39, 0, 443, 444, 5, 16, 0, 0, 444, 446, 3, 78, 39, 0, 445, 443, 1, 0, 0, 0, 446, 449, 1, 0, 0, 0, 447, 445, 1, 0, 0, 0, 447, 448, 1, 0, 0, 0, 448, 451, 1, 0, 0, 0, 449, 447, 1, 0, 0, 0, 450, 452, 5, 16, 0, 0, 451, 450, 1, 0, 0, 0, 451, 452, 1, 0, 0, 0, 452, 454, 1, 0, 0, 0, 453, 442, 1, 0, 0, 0, 453, 454, 1, 0, 0, 0, 454, 455, 1, 0, 0, 0, 455, 460, 5, 35, 0, 0, 456, 460, 5, 81, 0, 0, 457, 460, 5, 82, 0, 0, 458, 460, 3, 82, 41, 0, 459, 410, 1, 0, 0, 0, 459, 415, 1, 0, 0, 0, 459, 423, 1, 0, 0, 0, 459, 424, 1, 0, 0, 0, 459, 427, 1, 0, 0, 0, 459, 433, 1, 0, 0, 0, 459, 439, 1, 0, 0, 0, 459, 441, 1, 0, 0, 0, 459, 456, 1, 0, 0, 0, 459, 457, 1, 0, 0, 0, 459, 458, 1, 0, 0, 0, 460, 513, 1, 0, 0, 0, 461, 462, 10, 14, 0, 0, 462, 463, 7, 6, 0, 0, 463, 512, 3, 78, 39, 15, 464, 465, 10, 13, 0, 0, 465, 466, 7, 7, 0, 0, 466, 512, 3, 78, 39, 14, 467, 468, 10, 12, 0, 0, 468, 469, 7, 8, 0, 0, 469, 512, 3, 78, 39, 13, 470, 471, 10, 11, 0, 0, 471, 472, 7, 9, 0, 0, 472, 512, 3, 78, 39, 12, 473, 474, 10, 10, 0, 0, 474, 475, 7, 10, 0, 0, 475, 512, 3, 78, 39, 11, 476, 477, 10, 9, 0, 0, 477, 478, 5, 61, 0, 0, 478, 512, 3, 78, 39, 10, 479, 480, 10, 8, 0, 0, 480, 481, 5, 4, 0, 0, 481, 512, 3, 78, 39, 9, 482, 483, 10, 7, 0, 0, 483, 484, 5, 62, 0, 0, 484, 512, 3, 78, 39, 8, 485, 486, 10, 6, 0, 0, 486, 487, 5, 63, 0, 0, 487, 512, 3, 78, 39, 7, 488, 489, 10, 5, 0, 0, 489, 490, 5, 64, 0, 0, 490, 512, 3, 78, 39, 6, 491, 492, 10, 21, 0, 0, 492, 493, 5, 34, 0, 0, 493, 494, 5, 69, 0, 0, 494, 512, 5, 35, 0, 0, 495, 496, 10, 18, 0, 0, 496, 512, 7, 11, 0, 0, 497, 498, 10, 17, 0, 0, 498, 499, 5, 49, 0, 0, 499, 500, 5, 15, 0, 0, 500, 501, 3, 78, 39, 0, 501, 502, 5, 17, 0, 0, 502, 512, 1, 0, 0, 0, 503, 504, 10, 16, 0, 0, 504, 505, 5, 50, 0, 0, 505, 506, 5, 15, 0, 0, 506, 507, 3, 78, 39, 0, 507, 508, 5, 16, 0, 0, 508, 509, 3, 78, 39, 0, 509, 510, 5, 17, 0, 0, 510, 512, 1, 0, 0, 0, 511, 461, 1, 0, 0, 0, 511, 464, 1, 0, 0, 0, 511, 467, 1, 0, 0, 0, 511, 470, 1, 0, 0, 0, 511, 473, 1, 0, 0, 0, 511, 476, 1, 0, 0, 0, 511, 479, 1, 0, 0, 0, 511, 482, 1, 0, 0, 0, 511, 485, 1, 0, 0, 0, 511, 488, 1, 0, 0, 0, 511, 491, 1, 0, 0, 0, 511, 495, 1, 0, 0, 0, 511, 497, 1, 0, 0, 0, 511, 503, 1, 0, 0, 0, 512, 515, 1, 0, 0, 0, 513, 511, 1, 0, 0, 0, 513, 514, 1, 0, 0, 0, 514, 79, 1, 0, 0, 0, 515, 513, 1, 0, 0, 0, 516, 517, 7, 12, 0, 0, 517, 81, 1, 0, 0, 0, 518, 524, 5, 67, 0, 0, 519, 524, 3, 84, 42, 0, 520, 524, 5, 76, 0, 0, 521, 524, 5, 77, 0, 0, 522, 524, 5, 78, 0, 0, 523, 518, 1, 0, 0, 0, 523, 519, 1, 0, 0, 0, 523, 520, 1, 0, 0, 0, 523, 521, 1, 0, 0, 0, 523, 522, 1, 0, 0, 0, 524, 83, 1, 0, 0, 0, 525, 527, 5, 69, 0, 0, 526, 528, 5, 68, 0, 0, 527, 526, 1, 0, 0, 0, 527, 528, 1, 0, 0, 0, 528, 85, 1, 0, 0, 0, 529, 530, 7, 13, 0, 0, 530, 87, 1, 0, 0, 0, 531, 532, 7, 14, 0, 0, 532, 89, 1, 0, 0, 0, 47, 93, 99, 105, 119, 122, 135, 154, 159, 170, 184, 195, 199, 201, 209, 218, 223, 229, 239, 249, 254, 260, 272, 283, 289, 295, 302, 311, 320, 334, 339, 367, 373, 381, 385, 387, 400, 404, 406, 419, 447, 451, 453, 459, 511, 513, 523, 527] \ No newline at end of file diff --git a/packages/cashc/src/grammar/CashScript.tokens b/packages/cashc/src/grammar/CashScript.tokens index 16dc361d..7f8aef36 100644 --- a/packages/cashc/src/grammar/CashScript.tokens +++ b/packages/cashc/src/grammar/CashScript.tokens @@ -62,26 +62,27 @@ T__60=61 T__61=62 T__62=63 T__63=64 -VersionLiteral=65 -BooleanLiteral=66 -NumberUnit=67 -NumberLiteral=68 -NumberPart=69 -ExponentPart=70 -PrimitiveType=71 -UnboundedBytes=72 -BoundedBytes=73 -Bound=74 -StringLiteral=75 -DateLiteral=76 -HexLiteral=77 -TxVar=78 -UnsafeCast=79 -NullaryOp=80 -Identifier=81 -WHITESPACE=82 -COMMENT=83 -LINE_COMMENT=84 +T__64=65 +VersionLiteral=66 +BooleanLiteral=67 +NumberUnit=68 +NumberLiteral=69 +NumberPart=70 +ExponentPart=71 +PrimitiveType=72 +UnboundedBytes=73 +BoundedBytes=74 +Bound=75 +StringLiteral=76 +DateLiteral=77 +HexLiteral=78 +TxVar=79 +UnsafeCast=80 +NullaryOp=81 +Identifier=82 +WHITESPACE=83 +COMMENT=84 +LINE_COMMENT=85 'pragma'=1 ';'=2 'cashscript'=3 @@ -93,57 +94,58 @@ LINE_COMMENT=84 '<='=9 '='=10 'import'=11 -'function'=12 -'returns'=13 -'('=14 -')'=15 -'contract'=16 -'{'=17 -'}'=18 -','=19 -'return'=20 -'+='=21 -'-='=22 -'++'=23 -'--'=24 -'require'=25 -'console.log'=26 -'if'=27 -'else'=28 -'do'=29 -'while'=30 -'for'=31 -'new'=32 -'['=33 -']'=34 -'tx.outputs'=35 -'.value'=36 -'.lockingBytecode'=37 -'.tokenCategory'=38 -'.nftCommitment'=39 -'.tokenAmount'=40 -'tx.inputs'=41 -'.outpointTransactionHash'=42 -'.outpointIndex'=43 -'.unlockingBytecode'=44 -'.sequenceNumber'=45 -'.reverse()'=46 -'.length'=47 -'.split'=48 -'.slice'=49 -'!'=50 -'-'=51 -'*'=52 -'/'=53 -'%'=54 -'+'=55 -'>>'=56 -'<<'=57 -'=='=58 -'!='=59 -'&'=60 -'|'=61 -'&&'=62 -'||'=63 -'constant'=64 -'bytes'=72 +'constant'=12 +'function'=13 +'returns'=14 +'('=15 +','=16 +')'=17 +'contract'=18 +'{'=19 +'}'=20 +'return'=21 +'+='=22 +'-='=23 +'++'=24 +'--'=25 +'require'=26 +'console.log'=27 +'if'=28 +'else'=29 +'do'=30 +'while'=31 +'for'=32 +'new'=33 +'['=34 +']'=35 +'tx.outputs'=36 +'.value'=37 +'.lockingBytecode'=38 +'.tokenCategory'=39 +'.nftCommitment'=40 +'.tokenAmount'=41 +'tx.inputs'=42 +'.outpointTransactionHash'=43 +'.outpointIndex'=44 +'.unlockingBytecode'=45 +'.sequenceNumber'=46 +'.reverse()'=47 +'.length'=48 +'.split'=49 +'.slice'=50 +'!'=51 +'-'=52 +'*'=53 +'/'=54 +'%'=55 +'+'=56 +'>>'=57 +'<<'=58 +'=='=59 +'!='=60 +'&'=61 +'|'=62 +'&&'=63 +'||'=64 +'unused'=65 +'bytes'=73 diff --git a/packages/cashc/src/grammar/CashScriptLexer.interp b/packages/cashc/src/grammar/CashScriptLexer.interp index d394bd0e..b3ac7b16 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.interp +++ b/packages/cashc/src/grammar/CashScriptLexer.interp @@ -11,14 +11,15 @@ null '<=' '=' 'import' +'constant' 'function' 'returns' '(' +',' ')' 'contract' '{' '}' -',' 'return' '+=' '-=' @@ -63,7 +64,7 @@ null '|' '&&' '||' -'constant' +'unused' null null null @@ -151,6 +152,7 @@ null null null null +null VersionLiteral BooleanLiteral NumberUnit @@ -237,6 +239,7 @@ T__60 T__61 T__62 T__63 +T__64 VersionLiteral BooleanLiteral NumberUnit @@ -266,4 +269,4 @@ mode names: DEFAULT_MODE atn: -[4, 0, 84, 966, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 4, 64, 557, 8, 64, 11, 64, 12, 64, 558, 1, 64, 1, 64, 4, 64, 563, 8, 64, 11, 64, 12, 64, 564, 1, 64, 1, 64, 4, 64, 569, 8, 64, 11, 64, 12, 64, 570, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 582, 8, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 3, 66, 641, 8, 66, 1, 67, 3, 67, 644, 8, 67, 1, 67, 1, 67, 3, 67, 648, 8, 67, 1, 68, 4, 68, 651, 8, 68, 11, 68, 12, 68, 652, 1, 68, 1, 68, 4, 68, 657, 8, 68, 11, 68, 12, 68, 658, 5, 68, 661, 8, 68, 10, 68, 12, 68, 664, 9, 68, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 3, 70, 698, 8, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 3, 72, 717, 8, 72, 1, 73, 1, 73, 5, 73, 721, 8, 73, 10, 73, 12, 73, 724, 9, 73, 1, 74, 1, 74, 1, 74, 1, 74, 5, 74, 730, 8, 74, 10, 74, 12, 74, 733, 9, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 5, 74, 740, 8, 74, 10, 74, 12, 74, 743, 9, 74, 1, 74, 3, 74, 746, 8, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 5, 76, 760, 8, 76, 10, 76, 12, 76, 763, 9, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 1, 77, 3, 77, 780, 8, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 3, 78, 817, 8, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 3, 78, 830, 8, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 3, 79, 926, 8, 79, 1, 80, 1, 80, 5, 80, 930, 8, 80, 10, 80, 12, 80, 933, 9, 80, 1, 81, 4, 81, 936, 8, 81, 11, 81, 12, 81, 937, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 5, 82, 946, 8, 82, 10, 82, 12, 82, 949, 9, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 5, 83, 960, 8, 83, 10, 83, 12, 83, 963, 9, 83, 1, 83, 1, 83, 3, 731, 741, 947, 0, 84, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, 97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, 54, 109, 55, 111, 56, 113, 57, 115, 58, 117, 59, 119, 60, 121, 61, 123, 62, 125, 63, 127, 64, 129, 65, 131, 66, 133, 67, 135, 68, 137, 69, 139, 70, 141, 71, 143, 72, 145, 73, 147, 74, 149, 75, 151, 76, 153, 77, 155, 78, 157, 79, 159, 80, 161, 81, 163, 82, 165, 83, 167, 84, 1, 0, 11, 1, 0, 48, 57, 2, 0, 69, 69, 101, 101, 1, 0, 49, 57, 3, 0, 10, 10, 13, 13, 34, 34, 3, 0, 10, 10, 13, 13, 39, 39, 2, 0, 88, 88, 120, 120, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 65, 90, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 12, 13, 32, 32, 2, 0, 10, 10, 13, 13, 1010, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, 0, 0, 0, 145, 1, 0, 0, 0, 0, 147, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, 153, 1, 0, 0, 0, 0, 155, 1, 0, 0, 0, 0, 157, 1, 0, 0, 0, 0, 159, 1, 0, 0, 0, 0, 161, 1, 0, 0, 0, 0, 163, 1, 0, 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1, 0, 0, 0, 1, 169, 1, 0, 0, 0, 3, 176, 1, 0, 0, 0, 5, 178, 1, 0, 0, 0, 7, 189, 1, 0, 0, 0, 9, 191, 1, 0, 0, 0, 11, 193, 1, 0, 0, 0, 13, 196, 1, 0, 0, 0, 15, 198, 1, 0, 0, 0, 17, 200, 1, 0, 0, 0, 19, 203, 1, 0, 0, 0, 21, 205, 1, 0, 0, 0, 23, 212, 1, 0, 0, 0, 25, 221, 1, 0, 0, 0, 27, 229, 1, 0, 0, 0, 29, 231, 1, 0, 0, 0, 31, 233, 1, 0, 0, 0, 33, 242, 1, 0, 0, 0, 35, 244, 1, 0, 0, 0, 37, 246, 1, 0, 0, 0, 39, 248, 1, 0, 0, 0, 41, 255, 1, 0, 0, 0, 43, 258, 1, 0, 0, 0, 45, 261, 1, 0, 0, 0, 47, 264, 1, 0, 0, 0, 49, 267, 1, 0, 0, 0, 51, 275, 1, 0, 0, 0, 53, 287, 1, 0, 0, 0, 55, 290, 1, 0, 0, 0, 57, 295, 1, 0, 0, 0, 59, 298, 1, 0, 0, 0, 61, 304, 1, 0, 0, 0, 63, 308, 1, 0, 0, 0, 65, 312, 1, 0, 0, 0, 67, 314, 1, 0, 0, 0, 69, 316, 1, 0, 0, 0, 71, 327, 1, 0, 0, 0, 73, 334, 1, 0, 0, 0, 75, 351, 1, 0, 0, 0, 77, 366, 1, 0, 0, 0, 79, 381, 1, 0, 0, 0, 81, 394, 1, 0, 0, 0, 83, 404, 1, 0, 0, 0, 85, 429, 1, 0, 0, 0, 87, 444, 1, 0, 0, 0, 89, 463, 1, 0, 0, 0, 91, 479, 1, 0, 0, 0, 93, 490, 1, 0, 0, 0, 95, 498, 1, 0, 0, 0, 97, 505, 1, 0, 0, 0, 99, 512, 1, 0, 0, 0, 101, 514, 1, 0, 0, 0, 103, 516, 1, 0, 0, 0, 105, 518, 1, 0, 0, 0, 107, 520, 1, 0, 0, 0, 109, 522, 1, 0, 0, 0, 111, 524, 1, 0, 0, 0, 113, 527, 1, 0, 0, 0, 115, 530, 1, 0, 0, 0, 117, 533, 1, 0, 0, 0, 119, 536, 1, 0, 0, 0, 121, 538, 1, 0, 0, 0, 123, 540, 1, 0, 0, 0, 125, 543, 1, 0, 0, 0, 127, 546, 1, 0, 0, 0, 129, 556, 1, 0, 0, 0, 131, 581, 1, 0, 0, 0, 133, 640, 1, 0, 0, 0, 135, 643, 1, 0, 0, 0, 137, 650, 1, 0, 0, 0, 139, 665, 1, 0, 0, 0, 141, 697, 1, 0, 0, 0, 143, 699, 1, 0, 0, 0, 145, 716, 1, 0, 0, 0, 147, 718, 1, 0, 0, 0, 149, 745, 1, 0, 0, 0, 151, 747, 1, 0, 0, 0, 153, 756, 1, 0, 0, 0, 155, 779, 1, 0, 0, 0, 157, 829, 1, 0, 0, 0, 159, 925, 1, 0, 0, 0, 161, 927, 1, 0, 0, 0, 163, 935, 1, 0, 0, 0, 165, 941, 1, 0, 0, 0, 167, 955, 1, 0, 0, 0, 169, 170, 5, 112, 0, 0, 170, 171, 5, 114, 0, 0, 171, 172, 5, 97, 0, 0, 172, 173, 5, 103, 0, 0, 173, 174, 5, 109, 0, 0, 174, 175, 5, 97, 0, 0, 175, 2, 1, 0, 0, 0, 176, 177, 5, 59, 0, 0, 177, 4, 1, 0, 0, 0, 178, 179, 5, 99, 0, 0, 179, 180, 5, 97, 0, 0, 180, 181, 5, 115, 0, 0, 181, 182, 5, 104, 0, 0, 182, 183, 5, 115, 0, 0, 183, 184, 5, 99, 0, 0, 184, 185, 5, 114, 0, 0, 185, 186, 5, 105, 0, 0, 186, 187, 5, 112, 0, 0, 187, 188, 5, 116, 0, 0, 188, 6, 1, 0, 0, 0, 189, 190, 5, 94, 0, 0, 190, 8, 1, 0, 0, 0, 191, 192, 5, 126, 0, 0, 192, 10, 1, 0, 0, 0, 193, 194, 5, 62, 0, 0, 194, 195, 5, 61, 0, 0, 195, 12, 1, 0, 0, 0, 196, 197, 5, 62, 0, 0, 197, 14, 1, 0, 0, 0, 198, 199, 5, 60, 0, 0, 199, 16, 1, 0, 0, 0, 200, 201, 5, 60, 0, 0, 201, 202, 5, 61, 0, 0, 202, 18, 1, 0, 0, 0, 203, 204, 5, 61, 0, 0, 204, 20, 1, 0, 0, 0, 205, 206, 5, 105, 0, 0, 206, 207, 5, 109, 0, 0, 207, 208, 5, 112, 0, 0, 208, 209, 5, 111, 0, 0, 209, 210, 5, 114, 0, 0, 210, 211, 5, 116, 0, 0, 211, 22, 1, 0, 0, 0, 212, 213, 5, 102, 0, 0, 213, 214, 5, 117, 0, 0, 214, 215, 5, 110, 0, 0, 215, 216, 5, 99, 0, 0, 216, 217, 5, 116, 0, 0, 217, 218, 5, 105, 0, 0, 218, 219, 5, 111, 0, 0, 219, 220, 5, 110, 0, 0, 220, 24, 1, 0, 0, 0, 221, 222, 5, 114, 0, 0, 222, 223, 5, 101, 0, 0, 223, 224, 5, 116, 0, 0, 224, 225, 5, 117, 0, 0, 225, 226, 5, 114, 0, 0, 226, 227, 5, 110, 0, 0, 227, 228, 5, 115, 0, 0, 228, 26, 1, 0, 0, 0, 229, 230, 5, 40, 0, 0, 230, 28, 1, 0, 0, 0, 231, 232, 5, 41, 0, 0, 232, 30, 1, 0, 0, 0, 233, 234, 5, 99, 0, 0, 234, 235, 5, 111, 0, 0, 235, 236, 5, 110, 0, 0, 236, 237, 5, 116, 0, 0, 237, 238, 5, 114, 0, 0, 238, 239, 5, 97, 0, 0, 239, 240, 5, 99, 0, 0, 240, 241, 5, 116, 0, 0, 241, 32, 1, 0, 0, 0, 242, 243, 5, 123, 0, 0, 243, 34, 1, 0, 0, 0, 244, 245, 5, 125, 0, 0, 245, 36, 1, 0, 0, 0, 246, 247, 5, 44, 0, 0, 247, 38, 1, 0, 0, 0, 248, 249, 5, 114, 0, 0, 249, 250, 5, 101, 0, 0, 250, 251, 5, 116, 0, 0, 251, 252, 5, 117, 0, 0, 252, 253, 5, 114, 0, 0, 253, 254, 5, 110, 0, 0, 254, 40, 1, 0, 0, 0, 255, 256, 5, 43, 0, 0, 256, 257, 5, 61, 0, 0, 257, 42, 1, 0, 0, 0, 258, 259, 5, 45, 0, 0, 259, 260, 5, 61, 0, 0, 260, 44, 1, 0, 0, 0, 261, 262, 5, 43, 0, 0, 262, 263, 5, 43, 0, 0, 263, 46, 1, 0, 0, 0, 264, 265, 5, 45, 0, 0, 265, 266, 5, 45, 0, 0, 266, 48, 1, 0, 0, 0, 267, 268, 5, 114, 0, 0, 268, 269, 5, 101, 0, 0, 269, 270, 5, 113, 0, 0, 270, 271, 5, 117, 0, 0, 271, 272, 5, 105, 0, 0, 272, 273, 5, 114, 0, 0, 273, 274, 5, 101, 0, 0, 274, 50, 1, 0, 0, 0, 275, 276, 5, 99, 0, 0, 276, 277, 5, 111, 0, 0, 277, 278, 5, 110, 0, 0, 278, 279, 5, 115, 0, 0, 279, 280, 5, 111, 0, 0, 280, 281, 5, 108, 0, 0, 281, 282, 5, 101, 0, 0, 282, 283, 5, 46, 0, 0, 283, 284, 5, 108, 0, 0, 284, 285, 5, 111, 0, 0, 285, 286, 5, 103, 0, 0, 286, 52, 1, 0, 0, 0, 287, 288, 5, 105, 0, 0, 288, 289, 5, 102, 0, 0, 289, 54, 1, 0, 0, 0, 290, 291, 5, 101, 0, 0, 291, 292, 5, 108, 0, 0, 292, 293, 5, 115, 0, 0, 293, 294, 5, 101, 0, 0, 294, 56, 1, 0, 0, 0, 295, 296, 5, 100, 0, 0, 296, 297, 5, 111, 0, 0, 297, 58, 1, 0, 0, 0, 298, 299, 5, 119, 0, 0, 299, 300, 5, 104, 0, 0, 300, 301, 5, 105, 0, 0, 301, 302, 5, 108, 0, 0, 302, 303, 5, 101, 0, 0, 303, 60, 1, 0, 0, 0, 304, 305, 5, 102, 0, 0, 305, 306, 5, 111, 0, 0, 306, 307, 5, 114, 0, 0, 307, 62, 1, 0, 0, 0, 308, 309, 5, 110, 0, 0, 309, 310, 5, 101, 0, 0, 310, 311, 5, 119, 0, 0, 311, 64, 1, 0, 0, 0, 312, 313, 5, 91, 0, 0, 313, 66, 1, 0, 0, 0, 314, 315, 5, 93, 0, 0, 315, 68, 1, 0, 0, 0, 316, 317, 5, 116, 0, 0, 317, 318, 5, 120, 0, 0, 318, 319, 5, 46, 0, 0, 319, 320, 5, 111, 0, 0, 320, 321, 5, 117, 0, 0, 321, 322, 5, 116, 0, 0, 322, 323, 5, 112, 0, 0, 323, 324, 5, 117, 0, 0, 324, 325, 5, 116, 0, 0, 325, 326, 5, 115, 0, 0, 326, 70, 1, 0, 0, 0, 327, 328, 5, 46, 0, 0, 328, 329, 5, 118, 0, 0, 329, 330, 5, 97, 0, 0, 330, 331, 5, 108, 0, 0, 331, 332, 5, 117, 0, 0, 332, 333, 5, 101, 0, 0, 333, 72, 1, 0, 0, 0, 334, 335, 5, 46, 0, 0, 335, 336, 5, 108, 0, 0, 336, 337, 5, 111, 0, 0, 337, 338, 5, 99, 0, 0, 338, 339, 5, 107, 0, 0, 339, 340, 5, 105, 0, 0, 340, 341, 5, 110, 0, 0, 341, 342, 5, 103, 0, 0, 342, 343, 5, 66, 0, 0, 343, 344, 5, 121, 0, 0, 344, 345, 5, 116, 0, 0, 345, 346, 5, 101, 0, 0, 346, 347, 5, 99, 0, 0, 347, 348, 5, 111, 0, 0, 348, 349, 5, 100, 0, 0, 349, 350, 5, 101, 0, 0, 350, 74, 1, 0, 0, 0, 351, 352, 5, 46, 0, 0, 352, 353, 5, 116, 0, 0, 353, 354, 5, 111, 0, 0, 354, 355, 5, 107, 0, 0, 355, 356, 5, 101, 0, 0, 356, 357, 5, 110, 0, 0, 357, 358, 5, 67, 0, 0, 358, 359, 5, 97, 0, 0, 359, 360, 5, 116, 0, 0, 360, 361, 5, 101, 0, 0, 361, 362, 5, 103, 0, 0, 362, 363, 5, 111, 0, 0, 363, 364, 5, 114, 0, 0, 364, 365, 5, 121, 0, 0, 365, 76, 1, 0, 0, 0, 366, 367, 5, 46, 0, 0, 367, 368, 5, 110, 0, 0, 368, 369, 5, 102, 0, 0, 369, 370, 5, 116, 0, 0, 370, 371, 5, 67, 0, 0, 371, 372, 5, 111, 0, 0, 372, 373, 5, 109, 0, 0, 373, 374, 5, 109, 0, 0, 374, 375, 5, 105, 0, 0, 375, 376, 5, 116, 0, 0, 376, 377, 5, 109, 0, 0, 377, 378, 5, 101, 0, 0, 378, 379, 5, 110, 0, 0, 379, 380, 5, 116, 0, 0, 380, 78, 1, 0, 0, 0, 381, 382, 5, 46, 0, 0, 382, 383, 5, 116, 0, 0, 383, 384, 5, 111, 0, 0, 384, 385, 5, 107, 0, 0, 385, 386, 5, 101, 0, 0, 386, 387, 5, 110, 0, 0, 387, 388, 5, 65, 0, 0, 388, 389, 5, 109, 0, 0, 389, 390, 5, 111, 0, 0, 390, 391, 5, 117, 0, 0, 391, 392, 5, 110, 0, 0, 392, 393, 5, 116, 0, 0, 393, 80, 1, 0, 0, 0, 394, 395, 5, 116, 0, 0, 395, 396, 5, 120, 0, 0, 396, 397, 5, 46, 0, 0, 397, 398, 5, 105, 0, 0, 398, 399, 5, 110, 0, 0, 399, 400, 5, 112, 0, 0, 400, 401, 5, 117, 0, 0, 401, 402, 5, 116, 0, 0, 402, 403, 5, 115, 0, 0, 403, 82, 1, 0, 0, 0, 404, 405, 5, 46, 0, 0, 405, 406, 5, 111, 0, 0, 406, 407, 5, 117, 0, 0, 407, 408, 5, 116, 0, 0, 408, 409, 5, 112, 0, 0, 409, 410, 5, 111, 0, 0, 410, 411, 5, 105, 0, 0, 411, 412, 5, 110, 0, 0, 412, 413, 5, 116, 0, 0, 413, 414, 5, 84, 0, 0, 414, 415, 5, 114, 0, 0, 415, 416, 5, 97, 0, 0, 416, 417, 5, 110, 0, 0, 417, 418, 5, 115, 0, 0, 418, 419, 5, 97, 0, 0, 419, 420, 5, 99, 0, 0, 420, 421, 5, 116, 0, 0, 421, 422, 5, 105, 0, 0, 422, 423, 5, 111, 0, 0, 423, 424, 5, 110, 0, 0, 424, 425, 5, 72, 0, 0, 425, 426, 5, 97, 0, 0, 426, 427, 5, 115, 0, 0, 427, 428, 5, 104, 0, 0, 428, 84, 1, 0, 0, 0, 429, 430, 5, 46, 0, 0, 430, 431, 5, 111, 0, 0, 431, 432, 5, 117, 0, 0, 432, 433, 5, 116, 0, 0, 433, 434, 5, 112, 0, 0, 434, 435, 5, 111, 0, 0, 435, 436, 5, 105, 0, 0, 436, 437, 5, 110, 0, 0, 437, 438, 5, 116, 0, 0, 438, 439, 5, 73, 0, 0, 439, 440, 5, 110, 0, 0, 440, 441, 5, 100, 0, 0, 441, 442, 5, 101, 0, 0, 442, 443, 5, 120, 0, 0, 443, 86, 1, 0, 0, 0, 444, 445, 5, 46, 0, 0, 445, 446, 5, 117, 0, 0, 446, 447, 5, 110, 0, 0, 447, 448, 5, 108, 0, 0, 448, 449, 5, 111, 0, 0, 449, 450, 5, 99, 0, 0, 450, 451, 5, 107, 0, 0, 451, 452, 5, 105, 0, 0, 452, 453, 5, 110, 0, 0, 453, 454, 5, 103, 0, 0, 454, 455, 5, 66, 0, 0, 455, 456, 5, 121, 0, 0, 456, 457, 5, 116, 0, 0, 457, 458, 5, 101, 0, 0, 458, 459, 5, 99, 0, 0, 459, 460, 5, 111, 0, 0, 460, 461, 5, 100, 0, 0, 461, 462, 5, 101, 0, 0, 462, 88, 1, 0, 0, 0, 463, 464, 5, 46, 0, 0, 464, 465, 5, 115, 0, 0, 465, 466, 5, 101, 0, 0, 466, 467, 5, 113, 0, 0, 467, 468, 5, 117, 0, 0, 468, 469, 5, 101, 0, 0, 469, 470, 5, 110, 0, 0, 470, 471, 5, 99, 0, 0, 471, 472, 5, 101, 0, 0, 472, 473, 5, 78, 0, 0, 473, 474, 5, 117, 0, 0, 474, 475, 5, 109, 0, 0, 475, 476, 5, 98, 0, 0, 476, 477, 5, 101, 0, 0, 477, 478, 5, 114, 0, 0, 478, 90, 1, 0, 0, 0, 479, 480, 5, 46, 0, 0, 480, 481, 5, 114, 0, 0, 481, 482, 5, 101, 0, 0, 482, 483, 5, 118, 0, 0, 483, 484, 5, 101, 0, 0, 484, 485, 5, 114, 0, 0, 485, 486, 5, 115, 0, 0, 486, 487, 5, 101, 0, 0, 487, 488, 5, 40, 0, 0, 488, 489, 5, 41, 0, 0, 489, 92, 1, 0, 0, 0, 490, 491, 5, 46, 0, 0, 491, 492, 5, 108, 0, 0, 492, 493, 5, 101, 0, 0, 493, 494, 5, 110, 0, 0, 494, 495, 5, 103, 0, 0, 495, 496, 5, 116, 0, 0, 496, 497, 5, 104, 0, 0, 497, 94, 1, 0, 0, 0, 498, 499, 5, 46, 0, 0, 499, 500, 5, 115, 0, 0, 500, 501, 5, 112, 0, 0, 501, 502, 5, 108, 0, 0, 502, 503, 5, 105, 0, 0, 503, 504, 5, 116, 0, 0, 504, 96, 1, 0, 0, 0, 505, 506, 5, 46, 0, 0, 506, 507, 5, 115, 0, 0, 507, 508, 5, 108, 0, 0, 508, 509, 5, 105, 0, 0, 509, 510, 5, 99, 0, 0, 510, 511, 5, 101, 0, 0, 511, 98, 1, 0, 0, 0, 512, 513, 5, 33, 0, 0, 513, 100, 1, 0, 0, 0, 514, 515, 5, 45, 0, 0, 515, 102, 1, 0, 0, 0, 516, 517, 5, 42, 0, 0, 517, 104, 1, 0, 0, 0, 518, 519, 5, 47, 0, 0, 519, 106, 1, 0, 0, 0, 520, 521, 5, 37, 0, 0, 521, 108, 1, 0, 0, 0, 522, 523, 5, 43, 0, 0, 523, 110, 1, 0, 0, 0, 524, 525, 5, 62, 0, 0, 525, 526, 5, 62, 0, 0, 526, 112, 1, 0, 0, 0, 527, 528, 5, 60, 0, 0, 528, 529, 5, 60, 0, 0, 529, 114, 1, 0, 0, 0, 530, 531, 5, 61, 0, 0, 531, 532, 5, 61, 0, 0, 532, 116, 1, 0, 0, 0, 533, 534, 5, 33, 0, 0, 534, 535, 5, 61, 0, 0, 535, 118, 1, 0, 0, 0, 536, 537, 5, 38, 0, 0, 537, 120, 1, 0, 0, 0, 538, 539, 5, 124, 0, 0, 539, 122, 1, 0, 0, 0, 540, 541, 5, 38, 0, 0, 541, 542, 5, 38, 0, 0, 542, 124, 1, 0, 0, 0, 543, 544, 5, 124, 0, 0, 544, 545, 5, 124, 0, 0, 545, 126, 1, 0, 0, 0, 546, 547, 5, 99, 0, 0, 547, 548, 5, 111, 0, 0, 548, 549, 5, 110, 0, 0, 549, 550, 5, 115, 0, 0, 550, 551, 5, 116, 0, 0, 551, 552, 5, 97, 0, 0, 552, 553, 5, 110, 0, 0, 553, 554, 5, 116, 0, 0, 554, 128, 1, 0, 0, 0, 555, 557, 7, 0, 0, 0, 556, 555, 1, 0, 0, 0, 557, 558, 1, 0, 0, 0, 558, 556, 1, 0, 0, 0, 558, 559, 1, 0, 0, 0, 559, 560, 1, 0, 0, 0, 560, 562, 5, 46, 0, 0, 561, 563, 7, 0, 0, 0, 562, 561, 1, 0, 0, 0, 563, 564, 1, 0, 0, 0, 564, 562, 1, 0, 0, 0, 564, 565, 1, 0, 0, 0, 565, 566, 1, 0, 0, 0, 566, 568, 5, 46, 0, 0, 567, 569, 7, 0, 0, 0, 568, 567, 1, 0, 0, 0, 569, 570, 1, 0, 0, 0, 570, 568, 1, 0, 0, 0, 570, 571, 1, 0, 0, 0, 571, 130, 1, 0, 0, 0, 572, 573, 5, 116, 0, 0, 573, 574, 5, 114, 0, 0, 574, 575, 5, 117, 0, 0, 575, 582, 5, 101, 0, 0, 576, 577, 5, 102, 0, 0, 577, 578, 5, 97, 0, 0, 578, 579, 5, 108, 0, 0, 579, 580, 5, 115, 0, 0, 580, 582, 5, 101, 0, 0, 581, 572, 1, 0, 0, 0, 581, 576, 1, 0, 0, 0, 582, 132, 1, 0, 0, 0, 583, 584, 5, 115, 0, 0, 584, 585, 5, 97, 0, 0, 585, 586, 5, 116, 0, 0, 586, 587, 5, 111, 0, 0, 587, 588, 5, 115, 0, 0, 588, 589, 5, 104, 0, 0, 589, 590, 5, 105, 0, 0, 590, 641, 5, 115, 0, 0, 591, 592, 5, 115, 0, 0, 592, 593, 5, 97, 0, 0, 593, 594, 5, 116, 0, 0, 594, 641, 5, 115, 0, 0, 595, 596, 5, 102, 0, 0, 596, 597, 5, 105, 0, 0, 597, 598, 5, 110, 0, 0, 598, 599, 5, 110, 0, 0, 599, 600, 5, 101, 0, 0, 600, 641, 5, 121, 0, 0, 601, 602, 5, 98, 0, 0, 602, 603, 5, 105, 0, 0, 603, 604, 5, 116, 0, 0, 604, 641, 5, 115, 0, 0, 605, 606, 5, 98, 0, 0, 606, 607, 5, 105, 0, 0, 607, 608, 5, 116, 0, 0, 608, 609, 5, 99, 0, 0, 609, 610, 5, 111, 0, 0, 610, 611, 5, 105, 0, 0, 611, 641, 5, 110, 0, 0, 612, 613, 5, 115, 0, 0, 613, 614, 5, 101, 0, 0, 614, 615, 5, 99, 0, 0, 615, 616, 5, 111, 0, 0, 616, 617, 5, 110, 0, 0, 617, 618, 5, 100, 0, 0, 618, 641, 5, 115, 0, 0, 619, 620, 5, 109, 0, 0, 620, 621, 5, 105, 0, 0, 621, 622, 5, 110, 0, 0, 622, 623, 5, 117, 0, 0, 623, 624, 5, 116, 0, 0, 624, 625, 5, 101, 0, 0, 625, 641, 5, 115, 0, 0, 626, 627, 5, 104, 0, 0, 627, 628, 5, 111, 0, 0, 628, 629, 5, 117, 0, 0, 629, 630, 5, 114, 0, 0, 630, 641, 5, 115, 0, 0, 631, 632, 5, 100, 0, 0, 632, 633, 5, 97, 0, 0, 633, 634, 5, 121, 0, 0, 634, 641, 5, 115, 0, 0, 635, 636, 5, 119, 0, 0, 636, 637, 5, 101, 0, 0, 637, 638, 5, 101, 0, 0, 638, 639, 5, 107, 0, 0, 639, 641, 5, 115, 0, 0, 640, 583, 1, 0, 0, 0, 640, 591, 1, 0, 0, 0, 640, 595, 1, 0, 0, 0, 640, 601, 1, 0, 0, 0, 640, 605, 1, 0, 0, 0, 640, 612, 1, 0, 0, 0, 640, 619, 1, 0, 0, 0, 640, 626, 1, 0, 0, 0, 640, 631, 1, 0, 0, 0, 640, 635, 1, 0, 0, 0, 641, 134, 1, 0, 0, 0, 642, 644, 5, 45, 0, 0, 643, 642, 1, 0, 0, 0, 643, 644, 1, 0, 0, 0, 644, 645, 1, 0, 0, 0, 645, 647, 3, 137, 68, 0, 646, 648, 3, 139, 69, 0, 647, 646, 1, 0, 0, 0, 647, 648, 1, 0, 0, 0, 648, 136, 1, 0, 0, 0, 649, 651, 7, 0, 0, 0, 650, 649, 1, 0, 0, 0, 651, 652, 1, 0, 0, 0, 652, 650, 1, 0, 0, 0, 652, 653, 1, 0, 0, 0, 653, 662, 1, 0, 0, 0, 654, 656, 5, 95, 0, 0, 655, 657, 7, 0, 0, 0, 656, 655, 1, 0, 0, 0, 657, 658, 1, 0, 0, 0, 658, 656, 1, 0, 0, 0, 658, 659, 1, 0, 0, 0, 659, 661, 1, 0, 0, 0, 660, 654, 1, 0, 0, 0, 661, 664, 1, 0, 0, 0, 662, 660, 1, 0, 0, 0, 662, 663, 1, 0, 0, 0, 663, 138, 1, 0, 0, 0, 664, 662, 1, 0, 0, 0, 665, 666, 7, 1, 0, 0, 666, 667, 3, 137, 68, 0, 667, 140, 1, 0, 0, 0, 668, 669, 5, 105, 0, 0, 669, 670, 5, 110, 0, 0, 670, 698, 5, 116, 0, 0, 671, 672, 5, 98, 0, 0, 672, 673, 5, 111, 0, 0, 673, 674, 5, 111, 0, 0, 674, 698, 5, 108, 0, 0, 675, 676, 5, 115, 0, 0, 676, 677, 5, 116, 0, 0, 677, 678, 5, 114, 0, 0, 678, 679, 5, 105, 0, 0, 679, 680, 5, 110, 0, 0, 680, 698, 5, 103, 0, 0, 681, 682, 5, 112, 0, 0, 682, 683, 5, 117, 0, 0, 683, 684, 5, 98, 0, 0, 684, 685, 5, 107, 0, 0, 685, 686, 5, 101, 0, 0, 686, 698, 5, 121, 0, 0, 687, 688, 5, 115, 0, 0, 688, 689, 5, 105, 0, 0, 689, 698, 5, 103, 0, 0, 690, 691, 5, 100, 0, 0, 691, 692, 5, 97, 0, 0, 692, 693, 5, 116, 0, 0, 693, 694, 5, 97, 0, 0, 694, 695, 5, 115, 0, 0, 695, 696, 5, 105, 0, 0, 696, 698, 5, 103, 0, 0, 697, 668, 1, 0, 0, 0, 697, 671, 1, 0, 0, 0, 697, 675, 1, 0, 0, 0, 697, 681, 1, 0, 0, 0, 697, 687, 1, 0, 0, 0, 697, 690, 1, 0, 0, 0, 698, 142, 1, 0, 0, 0, 699, 700, 5, 98, 0, 0, 700, 701, 5, 121, 0, 0, 701, 702, 5, 116, 0, 0, 702, 703, 5, 101, 0, 0, 703, 704, 5, 115, 0, 0, 704, 144, 1, 0, 0, 0, 705, 706, 5, 98, 0, 0, 706, 707, 5, 121, 0, 0, 707, 708, 5, 116, 0, 0, 708, 709, 5, 101, 0, 0, 709, 710, 5, 115, 0, 0, 710, 711, 1, 0, 0, 0, 711, 717, 3, 147, 73, 0, 712, 713, 5, 98, 0, 0, 713, 714, 5, 121, 0, 0, 714, 715, 5, 116, 0, 0, 715, 717, 5, 101, 0, 0, 716, 705, 1, 0, 0, 0, 716, 712, 1, 0, 0, 0, 717, 146, 1, 0, 0, 0, 718, 722, 7, 2, 0, 0, 719, 721, 7, 0, 0, 0, 720, 719, 1, 0, 0, 0, 721, 724, 1, 0, 0, 0, 722, 720, 1, 0, 0, 0, 722, 723, 1, 0, 0, 0, 723, 148, 1, 0, 0, 0, 724, 722, 1, 0, 0, 0, 725, 731, 5, 34, 0, 0, 726, 727, 5, 92, 0, 0, 727, 730, 5, 34, 0, 0, 728, 730, 8, 3, 0, 0, 729, 726, 1, 0, 0, 0, 729, 728, 1, 0, 0, 0, 730, 733, 1, 0, 0, 0, 731, 732, 1, 0, 0, 0, 731, 729, 1, 0, 0, 0, 732, 734, 1, 0, 0, 0, 733, 731, 1, 0, 0, 0, 734, 746, 5, 34, 0, 0, 735, 741, 5, 39, 0, 0, 736, 737, 5, 92, 0, 0, 737, 740, 5, 39, 0, 0, 738, 740, 8, 4, 0, 0, 739, 736, 1, 0, 0, 0, 739, 738, 1, 0, 0, 0, 740, 743, 1, 0, 0, 0, 741, 742, 1, 0, 0, 0, 741, 739, 1, 0, 0, 0, 742, 744, 1, 0, 0, 0, 743, 741, 1, 0, 0, 0, 744, 746, 5, 39, 0, 0, 745, 725, 1, 0, 0, 0, 745, 735, 1, 0, 0, 0, 746, 150, 1, 0, 0, 0, 747, 748, 5, 100, 0, 0, 748, 749, 5, 97, 0, 0, 749, 750, 5, 116, 0, 0, 750, 751, 5, 101, 0, 0, 751, 752, 5, 40, 0, 0, 752, 753, 1, 0, 0, 0, 753, 754, 3, 149, 74, 0, 754, 755, 5, 41, 0, 0, 755, 152, 1, 0, 0, 0, 756, 757, 5, 48, 0, 0, 757, 761, 7, 5, 0, 0, 758, 760, 7, 6, 0, 0, 759, 758, 1, 0, 0, 0, 760, 763, 1, 0, 0, 0, 761, 759, 1, 0, 0, 0, 761, 762, 1, 0, 0, 0, 762, 154, 1, 0, 0, 0, 763, 761, 1, 0, 0, 0, 764, 765, 5, 116, 0, 0, 765, 766, 5, 104, 0, 0, 766, 767, 5, 105, 0, 0, 767, 768, 5, 115, 0, 0, 768, 769, 5, 46, 0, 0, 769, 770, 5, 97, 0, 0, 770, 771, 5, 103, 0, 0, 771, 780, 5, 101, 0, 0, 772, 773, 5, 116, 0, 0, 773, 774, 5, 120, 0, 0, 774, 775, 5, 46, 0, 0, 775, 776, 5, 116, 0, 0, 776, 777, 5, 105, 0, 0, 777, 778, 5, 109, 0, 0, 778, 780, 5, 101, 0, 0, 779, 764, 1, 0, 0, 0, 779, 772, 1, 0, 0, 0, 780, 156, 1, 0, 0, 0, 781, 782, 5, 117, 0, 0, 782, 783, 5, 110, 0, 0, 783, 784, 5, 115, 0, 0, 784, 785, 5, 97, 0, 0, 785, 786, 5, 102, 0, 0, 786, 787, 5, 101, 0, 0, 787, 788, 5, 95, 0, 0, 788, 789, 5, 105, 0, 0, 789, 790, 5, 110, 0, 0, 790, 830, 5, 116, 0, 0, 791, 792, 5, 117, 0, 0, 792, 793, 5, 110, 0, 0, 793, 794, 5, 115, 0, 0, 794, 795, 5, 97, 0, 0, 795, 796, 5, 102, 0, 0, 796, 797, 5, 101, 0, 0, 797, 798, 5, 95, 0, 0, 798, 799, 5, 98, 0, 0, 799, 800, 5, 111, 0, 0, 800, 801, 5, 111, 0, 0, 801, 830, 5, 108, 0, 0, 802, 803, 5, 117, 0, 0, 803, 804, 5, 110, 0, 0, 804, 805, 5, 115, 0, 0, 805, 806, 5, 97, 0, 0, 806, 807, 5, 102, 0, 0, 807, 808, 5, 101, 0, 0, 808, 809, 5, 95, 0, 0, 809, 810, 5, 98, 0, 0, 810, 811, 5, 121, 0, 0, 811, 812, 5, 116, 0, 0, 812, 813, 5, 101, 0, 0, 813, 814, 5, 115, 0, 0, 814, 816, 1, 0, 0, 0, 815, 817, 3, 147, 73, 0, 816, 815, 1, 0, 0, 0, 816, 817, 1, 0, 0, 0, 817, 830, 1, 0, 0, 0, 818, 819, 5, 117, 0, 0, 819, 820, 5, 110, 0, 0, 820, 821, 5, 115, 0, 0, 821, 822, 5, 97, 0, 0, 822, 823, 5, 102, 0, 0, 823, 824, 5, 101, 0, 0, 824, 825, 5, 95, 0, 0, 825, 826, 5, 98, 0, 0, 826, 827, 5, 121, 0, 0, 827, 828, 5, 116, 0, 0, 828, 830, 5, 101, 0, 0, 829, 781, 1, 0, 0, 0, 829, 791, 1, 0, 0, 0, 829, 802, 1, 0, 0, 0, 829, 818, 1, 0, 0, 0, 830, 158, 1, 0, 0, 0, 831, 832, 5, 116, 0, 0, 832, 833, 5, 104, 0, 0, 833, 834, 5, 105, 0, 0, 834, 835, 5, 115, 0, 0, 835, 836, 5, 46, 0, 0, 836, 837, 5, 97, 0, 0, 837, 838, 5, 99, 0, 0, 838, 839, 5, 116, 0, 0, 839, 840, 5, 105, 0, 0, 840, 841, 5, 118, 0, 0, 841, 842, 5, 101, 0, 0, 842, 843, 5, 73, 0, 0, 843, 844, 5, 110, 0, 0, 844, 845, 5, 112, 0, 0, 845, 846, 5, 117, 0, 0, 846, 847, 5, 116, 0, 0, 847, 848, 5, 73, 0, 0, 848, 849, 5, 110, 0, 0, 849, 850, 5, 100, 0, 0, 850, 851, 5, 101, 0, 0, 851, 926, 5, 120, 0, 0, 852, 853, 5, 116, 0, 0, 853, 854, 5, 104, 0, 0, 854, 855, 5, 105, 0, 0, 855, 856, 5, 115, 0, 0, 856, 857, 5, 46, 0, 0, 857, 858, 5, 97, 0, 0, 858, 859, 5, 99, 0, 0, 859, 860, 5, 116, 0, 0, 860, 861, 5, 105, 0, 0, 861, 862, 5, 118, 0, 0, 862, 863, 5, 101, 0, 0, 863, 864, 5, 66, 0, 0, 864, 865, 5, 121, 0, 0, 865, 866, 5, 116, 0, 0, 866, 867, 5, 101, 0, 0, 867, 868, 5, 99, 0, 0, 868, 869, 5, 111, 0, 0, 869, 870, 5, 100, 0, 0, 870, 926, 5, 101, 0, 0, 871, 872, 5, 116, 0, 0, 872, 873, 5, 120, 0, 0, 873, 874, 5, 46, 0, 0, 874, 875, 5, 105, 0, 0, 875, 876, 5, 110, 0, 0, 876, 877, 5, 112, 0, 0, 877, 878, 5, 117, 0, 0, 878, 879, 5, 116, 0, 0, 879, 880, 5, 115, 0, 0, 880, 881, 5, 46, 0, 0, 881, 882, 5, 108, 0, 0, 882, 883, 5, 101, 0, 0, 883, 884, 5, 110, 0, 0, 884, 885, 5, 103, 0, 0, 885, 886, 5, 116, 0, 0, 886, 926, 5, 104, 0, 0, 887, 888, 5, 116, 0, 0, 888, 889, 5, 120, 0, 0, 889, 890, 5, 46, 0, 0, 890, 891, 5, 111, 0, 0, 891, 892, 5, 117, 0, 0, 892, 893, 5, 116, 0, 0, 893, 894, 5, 112, 0, 0, 894, 895, 5, 117, 0, 0, 895, 896, 5, 116, 0, 0, 896, 897, 5, 115, 0, 0, 897, 898, 5, 46, 0, 0, 898, 899, 5, 108, 0, 0, 899, 900, 5, 101, 0, 0, 900, 901, 5, 110, 0, 0, 901, 902, 5, 103, 0, 0, 902, 903, 5, 116, 0, 0, 903, 926, 5, 104, 0, 0, 904, 905, 5, 116, 0, 0, 905, 906, 5, 120, 0, 0, 906, 907, 5, 46, 0, 0, 907, 908, 5, 118, 0, 0, 908, 909, 5, 101, 0, 0, 909, 910, 5, 114, 0, 0, 910, 911, 5, 115, 0, 0, 911, 912, 5, 105, 0, 0, 912, 913, 5, 111, 0, 0, 913, 926, 5, 110, 0, 0, 914, 915, 5, 116, 0, 0, 915, 916, 5, 120, 0, 0, 916, 917, 5, 46, 0, 0, 917, 918, 5, 108, 0, 0, 918, 919, 5, 111, 0, 0, 919, 920, 5, 99, 0, 0, 920, 921, 5, 107, 0, 0, 921, 922, 5, 116, 0, 0, 922, 923, 5, 105, 0, 0, 923, 924, 5, 109, 0, 0, 924, 926, 5, 101, 0, 0, 925, 831, 1, 0, 0, 0, 925, 852, 1, 0, 0, 0, 925, 871, 1, 0, 0, 0, 925, 887, 1, 0, 0, 0, 925, 904, 1, 0, 0, 0, 925, 914, 1, 0, 0, 0, 926, 160, 1, 0, 0, 0, 927, 931, 7, 7, 0, 0, 928, 930, 7, 8, 0, 0, 929, 928, 1, 0, 0, 0, 930, 933, 1, 0, 0, 0, 931, 929, 1, 0, 0, 0, 931, 932, 1, 0, 0, 0, 932, 162, 1, 0, 0, 0, 933, 931, 1, 0, 0, 0, 934, 936, 7, 9, 0, 0, 935, 934, 1, 0, 0, 0, 936, 937, 1, 0, 0, 0, 937, 935, 1, 0, 0, 0, 937, 938, 1, 0, 0, 0, 938, 939, 1, 0, 0, 0, 939, 940, 6, 81, 0, 0, 940, 164, 1, 0, 0, 0, 941, 942, 5, 47, 0, 0, 942, 943, 5, 42, 0, 0, 943, 947, 1, 0, 0, 0, 944, 946, 9, 0, 0, 0, 945, 944, 1, 0, 0, 0, 946, 949, 1, 0, 0, 0, 947, 948, 1, 0, 0, 0, 947, 945, 1, 0, 0, 0, 948, 950, 1, 0, 0, 0, 949, 947, 1, 0, 0, 0, 950, 951, 5, 42, 0, 0, 951, 952, 5, 47, 0, 0, 952, 953, 1, 0, 0, 0, 953, 954, 6, 82, 1, 0, 954, 166, 1, 0, 0, 0, 955, 956, 5, 47, 0, 0, 956, 957, 5, 47, 0, 0, 957, 961, 1, 0, 0, 0, 958, 960, 8, 10, 0, 0, 959, 958, 1, 0, 0, 0, 960, 963, 1, 0, 0, 0, 961, 959, 1, 0, 0, 0, 961, 962, 1, 0, 0, 0, 962, 964, 1, 0, 0, 0, 963, 961, 1, 0, 0, 0, 964, 965, 6, 83, 1, 0, 965, 168, 1, 0, 0, 0, 28, 0, 558, 564, 570, 581, 640, 643, 647, 652, 658, 662, 697, 716, 722, 729, 731, 739, 741, 745, 761, 779, 816, 829, 925, 931, 937, 947, 961, 2, 6, 0, 0, 0, 1, 0] \ No newline at end of file +[4, 0, 85, 975, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 52, 1, 52, 1, 53, 1, 53, 1, 54, 1, 54, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 4, 65, 566, 8, 65, 11, 65, 12, 65, 567, 1, 65, 1, 65, 4, 65, 572, 8, 65, 11, 65, 12, 65, 573, 1, 65, 1, 65, 4, 65, 578, 8, 65, 11, 65, 12, 65, 579, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 1, 66, 3, 66, 591, 8, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 1, 67, 3, 67, 650, 8, 67, 1, 68, 3, 68, 653, 8, 68, 1, 68, 1, 68, 3, 68, 657, 8, 68, 1, 69, 4, 69, 660, 8, 69, 11, 69, 12, 69, 661, 1, 69, 1, 69, 4, 69, 666, 8, 69, 11, 69, 12, 69, 667, 5, 69, 670, 8, 69, 10, 69, 12, 69, 673, 9, 69, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 3, 71, 707, 8, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 1, 73, 3, 73, 726, 8, 73, 1, 74, 1, 74, 5, 74, 730, 8, 74, 10, 74, 12, 74, 733, 9, 74, 1, 75, 1, 75, 1, 75, 1, 75, 5, 75, 739, 8, 75, 10, 75, 12, 75, 742, 9, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 5, 75, 749, 8, 75, 10, 75, 12, 75, 752, 9, 75, 1, 75, 3, 75, 755, 8, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 5, 77, 769, 8, 77, 10, 77, 12, 77, 772, 9, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 1, 78, 3, 78, 789, 8, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 3, 79, 826, 8, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 3, 79, 839, 8, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 1, 80, 3, 80, 935, 8, 80, 1, 81, 1, 81, 5, 81, 939, 8, 81, 10, 81, 12, 81, 942, 9, 81, 1, 82, 4, 82, 945, 8, 82, 11, 82, 12, 82, 946, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 5, 83, 955, 8, 83, 10, 83, 12, 83, 958, 9, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 5, 84, 969, 8, 84, 10, 84, 12, 84, 972, 9, 84, 1, 84, 1, 84, 3, 740, 750, 956, 0, 85, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, 97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, 54, 109, 55, 111, 56, 113, 57, 115, 58, 117, 59, 119, 60, 121, 61, 123, 62, 125, 63, 127, 64, 129, 65, 131, 66, 133, 67, 135, 68, 137, 69, 139, 70, 141, 71, 143, 72, 145, 73, 147, 74, 149, 75, 151, 76, 153, 77, 155, 78, 157, 79, 159, 80, 161, 81, 163, 82, 165, 83, 167, 84, 169, 85, 1, 0, 11, 1, 0, 48, 57, 2, 0, 69, 69, 101, 101, 1, 0, 49, 57, 3, 0, 10, 10, 13, 13, 34, 34, 3, 0, 10, 10, 13, 13, 39, 39, 2, 0, 88, 88, 120, 120, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 65, 90, 97, 122, 4, 0, 48, 57, 65, 90, 95, 95, 97, 122, 3, 0, 9, 10, 12, 13, 32, 32, 2, 0, 10, 10, 13, 13, 1019, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103, 1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0, 0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 115, 1, 0, 0, 0, 0, 117, 1, 0, 0, 0, 0, 119, 1, 0, 0, 0, 0, 121, 1, 0, 0, 0, 0, 123, 1, 0, 0, 0, 0, 125, 1, 0, 0, 0, 0, 127, 1, 0, 0, 0, 0, 129, 1, 0, 0, 0, 0, 131, 1, 0, 0, 0, 0, 133, 1, 0, 0, 0, 0, 135, 1, 0, 0, 0, 0, 137, 1, 0, 0, 0, 0, 139, 1, 0, 0, 0, 0, 141, 1, 0, 0, 0, 0, 143, 1, 0, 0, 0, 0, 145, 1, 0, 0, 0, 0, 147, 1, 0, 0, 0, 0, 149, 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, 153, 1, 0, 0, 0, 0, 155, 1, 0, 0, 0, 0, 157, 1, 0, 0, 0, 0, 159, 1, 0, 0, 0, 0, 161, 1, 0, 0, 0, 0, 163, 1, 0, 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1, 0, 0, 0, 0, 169, 1, 0, 0, 0, 1, 171, 1, 0, 0, 0, 3, 178, 1, 0, 0, 0, 5, 180, 1, 0, 0, 0, 7, 191, 1, 0, 0, 0, 9, 193, 1, 0, 0, 0, 11, 195, 1, 0, 0, 0, 13, 198, 1, 0, 0, 0, 15, 200, 1, 0, 0, 0, 17, 202, 1, 0, 0, 0, 19, 205, 1, 0, 0, 0, 21, 207, 1, 0, 0, 0, 23, 214, 1, 0, 0, 0, 25, 223, 1, 0, 0, 0, 27, 232, 1, 0, 0, 0, 29, 240, 1, 0, 0, 0, 31, 242, 1, 0, 0, 0, 33, 244, 1, 0, 0, 0, 35, 246, 1, 0, 0, 0, 37, 255, 1, 0, 0, 0, 39, 257, 1, 0, 0, 0, 41, 259, 1, 0, 0, 0, 43, 266, 1, 0, 0, 0, 45, 269, 1, 0, 0, 0, 47, 272, 1, 0, 0, 0, 49, 275, 1, 0, 0, 0, 51, 278, 1, 0, 0, 0, 53, 286, 1, 0, 0, 0, 55, 298, 1, 0, 0, 0, 57, 301, 1, 0, 0, 0, 59, 306, 1, 0, 0, 0, 61, 309, 1, 0, 0, 0, 63, 315, 1, 0, 0, 0, 65, 319, 1, 0, 0, 0, 67, 323, 1, 0, 0, 0, 69, 325, 1, 0, 0, 0, 71, 327, 1, 0, 0, 0, 73, 338, 1, 0, 0, 0, 75, 345, 1, 0, 0, 0, 77, 362, 1, 0, 0, 0, 79, 377, 1, 0, 0, 0, 81, 392, 1, 0, 0, 0, 83, 405, 1, 0, 0, 0, 85, 415, 1, 0, 0, 0, 87, 440, 1, 0, 0, 0, 89, 455, 1, 0, 0, 0, 91, 474, 1, 0, 0, 0, 93, 490, 1, 0, 0, 0, 95, 501, 1, 0, 0, 0, 97, 509, 1, 0, 0, 0, 99, 516, 1, 0, 0, 0, 101, 523, 1, 0, 0, 0, 103, 525, 1, 0, 0, 0, 105, 527, 1, 0, 0, 0, 107, 529, 1, 0, 0, 0, 109, 531, 1, 0, 0, 0, 111, 533, 1, 0, 0, 0, 113, 535, 1, 0, 0, 0, 115, 538, 1, 0, 0, 0, 117, 541, 1, 0, 0, 0, 119, 544, 1, 0, 0, 0, 121, 547, 1, 0, 0, 0, 123, 549, 1, 0, 0, 0, 125, 551, 1, 0, 0, 0, 127, 554, 1, 0, 0, 0, 129, 557, 1, 0, 0, 0, 131, 565, 1, 0, 0, 0, 133, 590, 1, 0, 0, 0, 135, 649, 1, 0, 0, 0, 137, 652, 1, 0, 0, 0, 139, 659, 1, 0, 0, 0, 141, 674, 1, 0, 0, 0, 143, 706, 1, 0, 0, 0, 145, 708, 1, 0, 0, 0, 147, 725, 1, 0, 0, 0, 149, 727, 1, 0, 0, 0, 151, 754, 1, 0, 0, 0, 153, 756, 1, 0, 0, 0, 155, 765, 1, 0, 0, 0, 157, 788, 1, 0, 0, 0, 159, 838, 1, 0, 0, 0, 161, 934, 1, 0, 0, 0, 163, 936, 1, 0, 0, 0, 165, 944, 1, 0, 0, 0, 167, 950, 1, 0, 0, 0, 169, 964, 1, 0, 0, 0, 171, 172, 5, 112, 0, 0, 172, 173, 5, 114, 0, 0, 173, 174, 5, 97, 0, 0, 174, 175, 5, 103, 0, 0, 175, 176, 5, 109, 0, 0, 176, 177, 5, 97, 0, 0, 177, 2, 1, 0, 0, 0, 178, 179, 5, 59, 0, 0, 179, 4, 1, 0, 0, 0, 180, 181, 5, 99, 0, 0, 181, 182, 5, 97, 0, 0, 182, 183, 5, 115, 0, 0, 183, 184, 5, 104, 0, 0, 184, 185, 5, 115, 0, 0, 185, 186, 5, 99, 0, 0, 186, 187, 5, 114, 0, 0, 187, 188, 5, 105, 0, 0, 188, 189, 5, 112, 0, 0, 189, 190, 5, 116, 0, 0, 190, 6, 1, 0, 0, 0, 191, 192, 5, 94, 0, 0, 192, 8, 1, 0, 0, 0, 193, 194, 5, 126, 0, 0, 194, 10, 1, 0, 0, 0, 195, 196, 5, 62, 0, 0, 196, 197, 5, 61, 0, 0, 197, 12, 1, 0, 0, 0, 198, 199, 5, 62, 0, 0, 199, 14, 1, 0, 0, 0, 200, 201, 5, 60, 0, 0, 201, 16, 1, 0, 0, 0, 202, 203, 5, 60, 0, 0, 203, 204, 5, 61, 0, 0, 204, 18, 1, 0, 0, 0, 205, 206, 5, 61, 0, 0, 206, 20, 1, 0, 0, 0, 207, 208, 5, 105, 0, 0, 208, 209, 5, 109, 0, 0, 209, 210, 5, 112, 0, 0, 210, 211, 5, 111, 0, 0, 211, 212, 5, 114, 0, 0, 212, 213, 5, 116, 0, 0, 213, 22, 1, 0, 0, 0, 214, 215, 5, 99, 0, 0, 215, 216, 5, 111, 0, 0, 216, 217, 5, 110, 0, 0, 217, 218, 5, 115, 0, 0, 218, 219, 5, 116, 0, 0, 219, 220, 5, 97, 0, 0, 220, 221, 5, 110, 0, 0, 221, 222, 5, 116, 0, 0, 222, 24, 1, 0, 0, 0, 223, 224, 5, 102, 0, 0, 224, 225, 5, 117, 0, 0, 225, 226, 5, 110, 0, 0, 226, 227, 5, 99, 0, 0, 227, 228, 5, 116, 0, 0, 228, 229, 5, 105, 0, 0, 229, 230, 5, 111, 0, 0, 230, 231, 5, 110, 0, 0, 231, 26, 1, 0, 0, 0, 232, 233, 5, 114, 0, 0, 233, 234, 5, 101, 0, 0, 234, 235, 5, 116, 0, 0, 235, 236, 5, 117, 0, 0, 236, 237, 5, 114, 0, 0, 237, 238, 5, 110, 0, 0, 238, 239, 5, 115, 0, 0, 239, 28, 1, 0, 0, 0, 240, 241, 5, 40, 0, 0, 241, 30, 1, 0, 0, 0, 242, 243, 5, 44, 0, 0, 243, 32, 1, 0, 0, 0, 244, 245, 5, 41, 0, 0, 245, 34, 1, 0, 0, 0, 246, 247, 5, 99, 0, 0, 247, 248, 5, 111, 0, 0, 248, 249, 5, 110, 0, 0, 249, 250, 5, 116, 0, 0, 250, 251, 5, 114, 0, 0, 251, 252, 5, 97, 0, 0, 252, 253, 5, 99, 0, 0, 253, 254, 5, 116, 0, 0, 254, 36, 1, 0, 0, 0, 255, 256, 5, 123, 0, 0, 256, 38, 1, 0, 0, 0, 257, 258, 5, 125, 0, 0, 258, 40, 1, 0, 0, 0, 259, 260, 5, 114, 0, 0, 260, 261, 5, 101, 0, 0, 261, 262, 5, 116, 0, 0, 262, 263, 5, 117, 0, 0, 263, 264, 5, 114, 0, 0, 264, 265, 5, 110, 0, 0, 265, 42, 1, 0, 0, 0, 266, 267, 5, 43, 0, 0, 267, 268, 5, 61, 0, 0, 268, 44, 1, 0, 0, 0, 269, 270, 5, 45, 0, 0, 270, 271, 5, 61, 0, 0, 271, 46, 1, 0, 0, 0, 272, 273, 5, 43, 0, 0, 273, 274, 5, 43, 0, 0, 274, 48, 1, 0, 0, 0, 275, 276, 5, 45, 0, 0, 276, 277, 5, 45, 0, 0, 277, 50, 1, 0, 0, 0, 278, 279, 5, 114, 0, 0, 279, 280, 5, 101, 0, 0, 280, 281, 5, 113, 0, 0, 281, 282, 5, 117, 0, 0, 282, 283, 5, 105, 0, 0, 283, 284, 5, 114, 0, 0, 284, 285, 5, 101, 0, 0, 285, 52, 1, 0, 0, 0, 286, 287, 5, 99, 0, 0, 287, 288, 5, 111, 0, 0, 288, 289, 5, 110, 0, 0, 289, 290, 5, 115, 0, 0, 290, 291, 5, 111, 0, 0, 291, 292, 5, 108, 0, 0, 292, 293, 5, 101, 0, 0, 293, 294, 5, 46, 0, 0, 294, 295, 5, 108, 0, 0, 295, 296, 5, 111, 0, 0, 296, 297, 5, 103, 0, 0, 297, 54, 1, 0, 0, 0, 298, 299, 5, 105, 0, 0, 299, 300, 5, 102, 0, 0, 300, 56, 1, 0, 0, 0, 301, 302, 5, 101, 0, 0, 302, 303, 5, 108, 0, 0, 303, 304, 5, 115, 0, 0, 304, 305, 5, 101, 0, 0, 305, 58, 1, 0, 0, 0, 306, 307, 5, 100, 0, 0, 307, 308, 5, 111, 0, 0, 308, 60, 1, 0, 0, 0, 309, 310, 5, 119, 0, 0, 310, 311, 5, 104, 0, 0, 311, 312, 5, 105, 0, 0, 312, 313, 5, 108, 0, 0, 313, 314, 5, 101, 0, 0, 314, 62, 1, 0, 0, 0, 315, 316, 5, 102, 0, 0, 316, 317, 5, 111, 0, 0, 317, 318, 5, 114, 0, 0, 318, 64, 1, 0, 0, 0, 319, 320, 5, 110, 0, 0, 320, 321, 5, 101, 0, 0, 321, 322, 5, 119, 0, 0, 322, 66, 1, 0, 0, 0, 323, 324, 5, 91, 0, 0, 324, 68, 1, 0, 0, 0, 325, 326, 5, 93, 0, 0, 326, 70, 1, 0, 0, 0, 327, 328, 5, 116, 0, 0, 328, 329, 5, 120, 0, 0, 329, 330, 5, 46, 0, 0, 330, 331, 5, 111, 0, 0, 331, 332, 5, 117, 0, 0, 332, 333, 5, 116, 0, 0, 333, 334, 5, 112, 0, 0, 334, 335, 5, 117, 0, 0, 335, 336, 5, 116, 0, 0, 336, 337, 5, 115, 0, 0, 337, 72, 1, 0, 0, 0, 338, 339, 5, 46, 0, 0, 339, 340, 5, 118, 0, 0, 340, 341, 5, 97, 0, 0, 341, 342, 5, 108, 0, 0, 342, 343, 5, 117, 0, 0, 343, 344, 5, 101, 0, 0, 344, 74, 1, 0, 0, 0, 345, 346, 5, 46, 0, 0, 346, 347, 5, 108, 0, 0, 347, 348, 5, 111, 0, 0, 348, 349, 5, 99, 0, 0, 349, 350, 5, 107, 0, 0, 350, 351, 5, 105, 0, 0, 351, 352, 5, 110, 0, 0, 352, 353, 5, 103, 0, 0, 353, 354, 5, 66, 0, 0, 354, 355, 5, 121, 0, 0, 355, 356, 5, 116, 0, 0, 356, 357, 5, 101, 0, 0, 357, 358, 5, 99, 0, 0, 358, 359, 5, 111, 0, 0, 359, 360, 5, 100, 0, 0, 360, 361, 5, 101, 0, 0, 361, 76, 1, 0, 0, 0, 362, 363, 5, 46, 0, 0, 363, 364, 5, 116, 0, 0, 364, 365, 5, 111, 0, 0, 365, 366, 5, 107, 0, 0, 366, 367, 5, 101, 0, 0, 367, 368, 5, 110, 0, 0, 368, 369, 5, 67, 0, 0, 369, 370, 5, 97, 0, 0, 370, 371, 5, 116, 0, 0, 371, 372, 5, 101, 0, 0, 372, 373, 5, 103, 0, 0, 373, 374, 5, 111, 0, 0, 374, 375, 5, 114, 0, 0, 375, 376, 5, 121, 0, 0, 376, 78, 1, 0, 0, 0, 377, 378, 5, 46, 0, 0, 378, 379, 5, 110, 0, 0, 379, 380, 5, 102, 0, 0, 380, 381, 5, 116, 0, 0, 381, 382, 5, 67, 0, 0, 382, 383, 5, 111, 0, 0, 383, 384, 5, 109, 0, 0, 384, 385, 5, 109, 0, 0, 385, 386, 5, 105, 0, 0, 386, 387, 5, 116, 0, 0, 387, 388, 5, 109, 0, 0, 388, 389, 5, 101, 0, 0, 389, 390, 5, 110, 0, 0, 390, 391, 5, 116, 0, 0, 391, 80, 1, 0, 0, 0, 392, 393, 5, 46, 0, 0, 393, 394, 5, 116, 0, 0, 394, 395, 5, 111, 0, 0, 395, 396, 5, 107, 0, 0, 396, 397, 5, 101, 0, 0, 397, 398, 5, 110, 0, 0, 398, 399, 5, 65, 0, 0, 399, 400, 5, 109, 0, 0, 400, 401, 5, 111, 0, 0, 401, 402, 5, 117, 0, 0, 402, 403, 5, 110, 0, 0, 403, 404, 5, 116, 0, 0, 404, 82, 1, 0, 0, 0, 405, 406, 5, 116, 0, 0, 406, 407, 5, 120, 0, 0, 407, 408, 5, 46, 0, 0, 408, 409, 5, 105, 0, 0, 409, 410, 5, 110, 0, 0, 410, 411, 5, 112, 0, 0, 411, 412, 5, 117, 0, 0, 412, 413, 5, 116, 0, 0, 413, 414, 5, 115, 0, 0, 414, 84, 1, 0, 0, 0, 415, 416, 5, 46, 0, 0, 416, 417, 5, 111, 0, 0, 417, 418, 5, 117, 0, 0, 418, 419, 5, 116, 0, 0, 419, 420, 5, 112, 0, 0, 420, 421, 5, 111, 0, 0, 421, 422, 5, 105, 0, 0, 422, 423, 5, 110, 0, 0, 423, 424, 5, 116, 0, 0, 424, 425, 5, 84, 0, 0, 425, 426, 5, 114, 0, 0, 426, 427, 5, 97, 0, 0, 427, 428, 5, 110, 0, 0, 428, 429, 5, 115, 0, 0, 429, 430, 5, 97, 0, 0, 430, 431, 5, 99, 0, 0, 431, 432, 5, 116, 0, 0, 432, 433, 5, 105, 0, 0, 433, 434, 5, 111, 0, 0, 434, 435, 5, 110, 0, 0, 435, 436, 5, 72, 0, 0, 436, 437, 5, 97, 0, 0, 437, 438, 5, 115, 0, 0, 438, 439, 5, 104, 0, 0, 439, 86, 1, 0, 0, 0, 440, 441, 5, 46, 0, 0, 441, 442, 5, 111, 0, 0, 442, 443, 5, 117, 0, 0, 443, 444, 5, 116, 0, 0, 444, 445, 5, 112, 0, 0, 445, 446, 5, 111, 0, 0, 446, 447, 5, 105, 0, 0, 447, 448, 5, 110, 0, 0, 448, 449, 5, 116, 0, 0, 449, 450, 5, 73, 0, 0, 450, 451, 5, 110, 0, 0, 451, 452, 5, 100, 0, 0, 452, 453, 5, 101, 0, 0, 453, 454, 5, 120, 0, 0, 454, 88, 1, 0, 0, 0, 455, 456, 5, 46, 0, 0, 456, 457, 5, 117, 0, 0, 457, 458, 5, 110, 0, 0, 458, 459, 5, 108, 0, 0, 459, 460, 5, 111, 0, 0, 460, 461, 5, 99, 0, 0, 461, 462, 5, 107, 0, 0, 462, 463, 5, 105, 0, 0, 463, 464, 5, 110, 0, 0, 464, 465, 5, 103, 0, 0, 465, 466, 5, 66, 0, 0, 466, 467, 5, 121, 0, 0, 467, 468, 5, 116, 0, 0, 468, 469, 5, 101, 0, 0, 469, 470, 5, 99, 0, 0, 470, 471, 5, 111, 0, 0, 471, 472, 5, 100, 0, 0, 472, 473, 5, 101, 0, 0, 473, 90, 1, 0, 0, 0, 474, 475, 5, 46, 0, 0, 475, 476, 5, 115, 0, 0, 476, 477, 5, 101, 0, 0, 477, 478, 5, 113, 0, 0, 478, 479, 5, 117, 0, 0, 479, 480, 5, 101, 0, 0, 480, 481, 5, 110, 0, 0, 481, 482, 5, 99, 0, 0, 482, 483, 5, 101, 0, 0, 483, 484, 5, 78, 0, 0, 484, 485, 5, 117, 0, 0, 485, 486, 5, 109, 0, 0, 486, 487, 5, 98, 0, 0, 487, 488, 5, 101, 0, 0, 488, 489, 5, 114, 0, 0, 489, 92, 1, 0, 0, 0, 490, 491, 5, 46, 0, 0, 491, 492, 5, 114, 0, 0, 492, 493, 5, 101, 0, 0, 493, 494, 5, 118, 0, 0, 494, 495, 5, 101, 0, 0, 495, 496, 5, 114, 0, 0, 496, 497, 5, 115, 0, 0, 497, 498, 5, 101, 0, 0, 498, 499, 5, 40, 0, 0, 499, 500, 5, 41, 0, 0, 500, 94, 1, 0, 0, 0, 501, 502, 5, 46, 0, 0, 502, 503, 5, 108, 0, 0, 503, 504, 5, 101, 0, 0, 504, 505, 5, 110, 0, 0, 505, 506, 5, 103, 0, 0, 506, 507, 5, 116, 0, 0, 507, 508, 5, 104, 0, 0, 508, 96, 1, 0, 0, 0, 509, 510, 5, 46, 0, 0, 510, 511, 5, 115, 0, 0, 511, 512, 5, 112, 0, 0, 512, 513, 5, 108, 0, 0, 513, 514, 5, 105, 0, 0, 514, 515, 5, 116, 0, 0, 515, 98, 1, 0, 0, 0, 516, 517, 5, 46, 0, 0, 517, 518, 5, 115, 0, 0, 518, 519, 5, 108, 0, 0, 519, 520, 5, 105, 0, 0, 520, 521, 5, 99, 0, 0, 521, 522, 5, 101, 0, 0, 522, 100, 1, 0, 0, 0, 523, 524, 5, 33, 0, 0, 524, 102, 1, 0, 0, 0, 525, 526, 5, 45, 0, 0, 526, 104, 1, 0, 0, 0, 527, 528, 5, 42, 0, 0, 528, 106, 1, 0, 0, 0, 529, 530, 5, 47, 0, 0, 530, 108, 1, 0, 0, 0, 531, 532, 5, 37, 0, 0, 532, 110, 1, 0, 0, 0, 533, 534, 5, 43, 0, 0, 534, 112, 1, 0, 0, 0, 535, 536, 5, 62, 0, 0, 536, 537, 5, 62, 0, 0, 537, 114, 1, 0, 0, 0, 538, 539, 5, 60, 0, 0, 539, 540, 5, 60, 0, 0, 540, 116, 1, 0, 0, 0, 541, 542, 5, 61, 0, 0, 542, 543, 5, 61, 0, 0, 543, 118, 1, 0, 0, 0, 544, 545, 5, 33, 0, 0, 545, 546, 5, 61, 0, 0, 546, 120, 1, 0, 0, 0, 547, 548, 5, 38, 0, 0, 548, 122, 1, 0, 0, 0, 549, 550, 5, 124, 0, 0, 550, 124, 1, 0, 0, 0, 551, 552, 5, 38, 0, 0, 552, 553, 5, 38, 0, 0, 553, 126, 1, 0, 0, 0, 554, 555, 5, 124, 0, 0, 555, 556, 5, 124, 0, 0, 556, 128, 1, 0, 0, 0, 557, 558, 5, 117, 0, 0, 558, 559, 5, 110, 0, 0, 559, 560, 5, 117, 0, 0, 560, 561, 5, 115, 0, 0, 561, 562, 5, 101, 0, 0, 562, 563, 5, 100, 0, 0, 563, 130, 1, 0, 0, 0, 564, 566, 7, 0, 0, 0, 565, 564, 1, 0, 0, 0, 566, 567, 1, 0, 0, 0, 567, 565, 1, 0, 0, 0, 567, 568, 1, 0, 0, 0, 568, 569, 1, 0, 0, 0, 569, 571, 5, 46, 0, 0, 570, 572, 7, 0, 0, 0, 571, 570, 1, 0, 0, 0, 572, 573, 1, 0, 0, 0, 573, 571, 1, 0, 0, 0, 573, 574, 1, 0, 0, 0, 574, 575, 1, 0, 0, 0, 575, 577, 5, 46, 0, 0, 576, 578, 7, 0, 0, 0, 577, 576, 1, 0, 0, 0, 578, 579, 1, 0, 0, 0, 579, 577, 1, 0, 0, 0, 579, 580, 1, 0, 0, 0, 580, 132, 1, 0, 0, 0, 581, 582, 5, 116, 0, 0, 582, 583, 5, 114, 0, 0, 583, 584, 5, 117, 0, 0, 584, 591, 5, 101, 0, 0, 585, 586, 5, 102, 0, 0, 586, 587, 5, 97, 0, 0, 587, 588, 5, 108, 0, 0, 588, 589, 5, 115, 0, 0, 589, 591, 5, 101, 0, 0, 590, 581, 1, 0, 0, 0, 590, 585, 1, 0, 0, 0, 591, 134, 1, 0, 0, 0, 592, 593, 5, 115, 0, 0, 593, 594, 5, 97, 0, 0, 594, 595, 5, 116, 0, 0, 595, 596, 5, 111, 0, 0, 596, 597, 5, 115, 0, 0, 597, 598, 5, 104, 0, 0, 598, 599, 5, 105, 0, 0, 599, 650, 5, 115, 0, 0, 600, 601, 5, 115, 0, 0, 601, 602, 5, 97, 0, 0, 602, 603, 5, 116, 0, 0, 603, 650, 5, 115, 0, 0, 604, 605, 5, 102, 0, 0, 605, 606, 5, 105, 0, 0, 606, 607, 5, 110, 0, 0, 607, 608, 5, 110, 0, 0, 608, 609, 5, 101, 0, 0, 609, 650, 5, 121, 0, 0, 610, 611, 5, 98, 0, 0, 611, 612, 5, 105, 0, 0, 612, 613, 5, 116, 0, 0, 613, 650, 5, 115, 0, 0, 614, 615, 5, 98, 0, 0, 615, 616, 5, 105, 0, 0, 616, 617, 5, 116, 0, 0, 617, 618, 5, 99, 0, 0, 618, 619, 5, 111, 0, 0, 619, 620, 5, 105, 0, 0, 620, 650, 5, 110, 0, 0, 621, 622, 5, 115, 0, 0, 622, 623, 5, 101, 0, 0, 623, 624, 5, 99, 0, 0, 624, 625, 5, 111, 0, 0, 625, 626, 5, 110, 0, 0, 626, 627, 5, 100, 0, 0, 627, 650, 5, 115, 0, 0, 628, 629, 5, 109, 0, 0, 629, 630, 5, 105, 0, 0, 630, 631, 5, 110, 0, 0, 631, 632, 5, 117, 0, 0, 632, 633, 5, 116, 0, 0, 633, 634, 5, 101, 0, 0, 634, 650, 5, 115, 0, 0, 635, 636, 5, 104, 0, 0, 636, 637, 5, 111, 0, 0, 637, 638, 5, 117, 0, 0, 638, 639, 5, 114, 0, 0, 639, 650, 5, 115, 0, 0, 640, 641, 5, 100, 0, 0, 641, 642, 5, 97, 0, 0, 642, 643, 5, 121, 0, 0, 643, 650, 5, 115, 0, 0, 644, 645, 5, 119, 0, 0, 645, 646, 5, 101, 0, 0, 646, 647, 5, 101, 0, 0, 647, 648, 5, 107, 0, 0, 648, 650, 5, 115, 0, 0, 649, 592, 1, 0, 0, 0, 649, 600, 1, 0, 0, 0, 649, 604, 1, 0, 0, 0, 649, 610, 1, 0, 0, 0, 649, 614, 1, 0, 0, 0, 649, 621, 1, 0, 0, 0, 649, 628, 1, 0, 0, 0, 649, 635, 1, 0, 0, 0, 649, 640, 1, 0, 0, 0, 649, 644, 1, 0, 0, 0, 650, 136, 1, 0, 0, 0, 651, 653, 5, 45, 0, 0, 652, 651, 1, 0, 0, 0, 652, 653, 1, 0, 0, 0, 653, 654, 1, 0, 0, 0, 654, 656, 3, 139, 69, 0, 655, 657, 3, 141, 70, 0, 656, 655, 1, 0, 0, 0, 656, 657, 1, 0, 0, 0, 657, 138, 1, 0, 0, 0, 658, 660, 7, 0, 0, 0, 659, 658, 1, 0, 0, 0, 660, 661, 1, 0, 0, 0, 661, 659, 1, 0, 0, 0, 661, 662, 1, 0, 0, 0, 662, 671, 1, 0, 0, 0, 663, 665, 5, 95, 0, 0, 664, 666, 7, 0, 0, 0, 665, 664, 1, 0, 0, 0, 666, 667, 1, 0, 0, 0, 667, 665, 1, 0, 0, 0, 667, 668, 1, 0, 0, 0, 668, 670, 1, 0, 0, 0, 669, 663, 1, 0, 0, 0, 670, 673, 1, 0, 0, 0, 671, 669, 1, 0, 0, 0, 671, 672, 1, 0, 0, 0, 672, 140, 1, 0, 0, 0, 673, 671, 1, 0, 0, 0, 674, 675, 7, 1, 0, 0, 675, 676, 3, 139, 69, 0, 676, 142, 1, 0, 0, 0, 677, 678, 5, 105, 0, 0, 678, 679, 5, 110, 0, 0, 679, 707, 5, 116, 0, 0, 680, 681, 5, 98, 0, 0, 681, 682, 5, 111, 0, 0, 682, 683, 5, 111, 0, 0, 683, 707, 5, 108, 0, 0, 684, 685, 5, 115, 0, 0, 685, 686, 5, 116, 0, 0, 686, 687, 5, 114, 0, 0, 687, 688, 5, 105, 0, 0, 688, 689, 5, 110, 0, 0, 689, 707, 5, 103, 0, 0, 690, 691, 5, 112, 0, 0, 691, 692, 5, 117, 0, 0, 692, 693, 5, 98, 0, 0, 693, 694, 5, 107, 0, 0, 694, 695, 5, 101, 0, 0, 695, 707, 5, 121, 0, 0, 696, 697, 5, 115, 0, 0, 697, 698, 5, 105, 0, 0, 698, 707, 5, 103, 0, 0, 699, 700, 5, 100, 0, 0, 700, 701, 5, 97, 0, 0, 701, 702, 5, 116, 0, 0, 702, 703, 5, 97, 0, 0, 703, 704, 5, 115, 0, 0, 704, 705, 5, 105, 0, 0, 705, 707, 5, 103, 0, 0, 706, 677, 1, 0, 0, 0, 706, 680, 1, 0, 0, 0, 706, 684, 1, 0, 0, 0, 706, 690, 1, 0, 0, 0, 706, 696, 1, 0, 0, 0, 706, 699, 1, 0, 0, 0, 707, 144, 1, 0, 0, 0, 708, 709, 5, 98, 0, 0, 709, 710, 5, 121, 0, 0, 710, 711, 5, 116, 0, 0, 711, 712, 5, 101, 0, 0, 712, 713, 5, 115, 0, 0, 713, 146, 1, 0, 0, 0, 714, 715, 5, 98, 0, 0, 715, 716, 5, 121, 0, 0, 716, 717, 5, 116, 0, 0, 717, 718, 5, 101, 0, 0, 718, 719, 5, 115, 0, 0, 719, 720, 1, 0, 0, 0, 720, 726, 3, 149, 74, 0, 721, 722, 5, 98, 0, 0, 722, 723, 5, 121, 0, 0, 723, 724, 5, 116, 0, 0, 724, 726, 5, 101, 0, 0, 725, 714, 1, 0, 0, 0, 725, 721, 1, 0, 0, 0, 726, 148, 1, 0, 0, 0, 727, 731, 7, 2, 0, 0, 728, 730, 7, 0, 0, 0, 729, 728, 1, 0, 0, 0, 730, 733, 1, 0, 0, 0, 731, 729, 1, 0, 0, 0, 731, 732, 1, 0, 0, 0, 732, 150, 1, 0, 0, 0, 733, 731, 1, 0, 0, 0, 734, 740, 5, 34, 0, 0, 735, 736, 5, 92, 0, 0, 736, 739, 5, 34, 0, 0, 737, 739, 8, 3, 0, 0, 738, 735, 1, 0, 0, 0, 738, 737, 1, 0, 0, 0, 739, 742, 1, 0, 0, 0, 740, 741, 1, 0, 0, 0, 740, 738, 1, 0, 0, 0, 741, 743, 1, 0, 0, 0, 742, 740, 1, 0, 0, 0, 743, 755, 5, 34, 0, 0, 744, 750, 5, 39, 0, 0, 745, 746, 5, 92, 0, 0, 746, 749, 5, 39, 0, 0, 747, 749, 8, 4, 0, 0, 748, 745, 1, 0, 0, 0, 748, 747, 1, 0, 0, 0, 749, 752, 1, 0, 0, 0, 750, 751, 1, 0, 0, 0, 750, 748, 1, 0, 0, 0, 751, 753, 1, 0, 0, 0, 752, 750, 1, 0, 0, 0, 753, 755, 5, 39, 0, 0, 754, 734, 1, 0, 0, 0, 754, 744, 1, 0, 0, 0, 755, 152, 1, 0, 0, 0, 756, 757, 5, 100, 0, 0, 757, 758, 5, 97, 0, 0, 758, 759, 5, 116, 0, 0, 759, 760, 5, 101, 0, 0, 760, 761, 5, 40, 0, 0, 761, 762, 1, 0, 0, 0, 762, 763, 3, 151, 75, 0, 763, 764, 5, 41, 0, 0, 764, 154, 1, 0, 0, 0, 765, 766, 5, 48, 0, 0, 766, 770, 7, 5, 0, 0, 767, 769, 7, 6, 0, 0, 768, 767, 1, 0, 0, 0, 769, 772, 1, 0, 0, 0, 770, 768, 1, 0, 0, 0, 770, 771, 1, 0, 0, 0, 771, 156, 1, 0, 0, 0, 772, 770, 1, 0, 0, 0, 773, 774, 5, 116, 0, 0, 774, 775, 5, 104, 0, 0, 775, 776, 5, 105, 0, 0, 776, 777, 5, 115, 0, 0, 777, 778, 5, 46, 0, 0, 778, 779, 5, 97, 0, 0, 779, 780, 5, 103, 0, 0, 780, 789, 5, 101, 0, 0, 781, 782, 5, 116, 0, 0, 782, 783, 5, 120, 0, 0, 783, 784, 5, 46, 0, 0, 784, 785, 5, 116, 0, 0, 785, 786, 5, 105, 0, 0, 786, 787, 5, 109, 0, 0, 787, 789, 5, 101, 0, 0, 788, 773, 1, 0, 0, 0, 788, 781, 1, 0, 0, 0, 789, 158, 1, 0, 0, 0, 790, 791, 5, 117, 0, 0, 791, 792, 5, 110, 0, 0, 792, 793, 5, 115, 0, 0, 793, 794, 5, 97, 0, 0, 794, 795, 5, 102, 0, 0, 795, 796, 5, 101, 0, 0, 796, 797, 5, 95, 0, 0, 797, 798, 5, 105, 0, 0, 798, 799, 5, 110, 0, 0, 799, 839, 5, 116, 0, 0, 800, 801, 5, 117, 0, 0, 801, 802, 5, 110, 0, 0, 802, 803, 5, 115, 0, 0, 803, 804, 5, 97, 0, 0, 804, 805, 5, 102, 0, 0, 805, 806, 5, 101, 0, 0, 806, 807, 5, 95, 0, 0, 807, 808, 5, 98, 0, 0, 808, 809, 5, 111, 0, 0, 809, 810, 5, 111, 0, 0, 810, 839, 5, 108, 0, 0, 811, 812, 5, 117, 0, 0, 812, 813, 5, 110, 0, 0, 813, 814, 5, 115, 0, 0, 814, 815, 5, 97, 0, 0, 815, 816, 5, 102, 0, 0, 816, 817, 5, 101, 0, 0, 817, 818, 5, 95, 0, 0, 818, 819, 5, 98, 0, 0, 819, 820, 5, 121, 0, 0, 820, 821, 5, 116, 0, 0, 821, 822, 5, 101, 0, 0, 822, 823, 5, 115, 0, 0, 823, 825, 1, 0, 0, 0, 824, 826, 3, 149, 74, 0, 825, 824, 1, 0, 0, 0, 825, 826, 1, 0, 0, 0, 826, 839, 1, 0, 0, 0, 827, 828, 5, 117, 0, 0, 828, 829, 5, 110, 0, 0, 829, 830, 5, 115, 0, 0, 830, 831, 5, 97, 0, 0, 831, 832, 5, 102, 0, 0, 832, 833, 5, 101, 0, 0, 833, 834, 5, 95, 0, 0, 834, 835, 5, 98, 0, 0, 835, 836, 5, 121, 0, 0, 836, 837, 5, 116, 0, 0, 837, 839, 5, 101, 0, 0, 838, 790, 1, 0, 0, 0, 838, 800, 1, 0, 0, 0, 838, 811, 1, 0, 0, 0, 838, 827, 1, 0, 0, 0, 839, 160, 1, 0, 0, 0, 840, 841, 5, 116, 0, 0, 841, 842, 5, 104, 0, 0, 842, 843, 5, 105, 0, 0, 843, 844, 5, 115, 0, 0, 844, 845, 5, 46, 0, 0, 845, 846, 5, 97, 0, 0, 846, 847, 5, 99, 0, 0, 847, 848, 5, 116, 0, 0, 848, 849, 5, 105, 0, 0, 849, 850, 5, 118, 0, 0, 850, 851, 5, 101, 0, 0, 851, 852, 5, 73, 0, 0, 852, 853, 5, 110, 0, 0, 853, 854, 5, 112, 0, 0, 854, 855, 5, 117, 0, 0, 855, 856, 5, 116, 0, 0, 856, 857, 5, 73, 0, 0, 857, 858, 5, 110, 0, 0, 858, 859, 5, 100, 0, 0, 859, 860, 5, 101, 0, 0, 860, 935, 5, 120, 0, 0, 861, 862, 5, 116, 0, 0, 862, 863, 5, 104, 0, 0, 863, 864, 5, 105, 0, 0, 864, 865, 5, 115, 0, 0, 865, 866, 5, 46, 0, 0, 866, 867, 5, 97, 0, 0, 867, 868, 5, 99, 0, 0, 868, 869, 5, 116, 0, 0, 869, 870, 5, 105, 0, 0, 870, 871, 5, 118, 0, 0, 871, 872, 5, 101, 0, 0, 872, 873, 5, 66, 0, 0, 873, 874, 5, 121, 0, 0, 874, 875, 5, 116, 0, 0, 875, 876, 5, 101, 0, 0, 876, 877, 5, 99, 0, 0, 877, 878, 5, 111, 0, 0, 878, 879, 5, 100, 0, 0, 879, 935, 5, 101, 0, 0, 880, 881, 5, 116, 0, 0, 881, 882, 5, 120, 0, 0, 882, 883, 5, 46, 0, 0, 883, 884, 5, 105, 0, 0, 884, 885, 5, 110, 0, 0, 885, 886, 5, 112, 0, 0, 886, 887, 5, 117, 0, 0, 887, 888, 5, 116, 0, 0, 888, 889, 5, 115, 0, 0, 889, 890, 5, 46, 0, 0, 890, 891, 5, 108, 0, 0, 891, 892, 5, 101, 0, 0, 892, 893, 5, 110, 0, 0, 893, 894, 5, 103, 0, 0, 894, 895, 5, 116, 0, 0, 895, 935, 5, 104, 0, 0, 896, 897, 5, 116, 0, 0, 897, 898, 5, 120, 0, 0, 898, 899, 5, 46, 0, 0, 899, 900, 5, 111, 0, 0, 900, 901, 5, 117, 0, 0, 901, 902, 5, 116, 0, 0, 902, 903, 5, 112, 0, 0, 903, 904, 5, 117, 0, 0, 904, 905, 5, 116, 0, 0, 905, 906, 5, 115, 0, 0, 906, 907, 5, 46, 0, 0, 907, 908, 5, 108, 0, 0, 908, 909, 5, 101, 0, 0, 909, 910, 5, 110, 0, 0, 910, 911, 5, 103, 0, 0, 911, 912, 5, 116, 0, 0, 912, 935, 5, 104, 0, 0, 913, 914, 5, 116, 0, 0, 914, 915, 5, 120, 0, 0, 915, 916, 5, 46, 0, 0, 916, 917, 5, 118, 0, 0, 917, 918, 5, 101, 0, 0, 918, 919, 5, 114, 0, 0, 919, 920, 5, 115, 0, 0, 920, 921, 5, 105, 0, 0, 921, 922, 5, 111, 0, 0, 922, 935, 5, 110, 0, 0, 923, 924, 5, 116, 0, 0, 924, 925, 5, 120, 0, 0, 925, 926, 5, 46, 0, 0, 926, 927, 5, 108, 0, 0, 927, 928, 5, 111, 0, 0, 928, 929, 5, 99, 0, 0, 929, 930, 5, 107, 0, 0, 930, 931, 5, 116, 0, 0, 931, 932, 5, 105, 0, 0, 932, 933, 5, 109, 0, 0, 933, 935, 5, 101, 0, 0, 934, 840, 1, 0, 0, 0, 934, 861, 1, 0, 0, 0, 934, 880, 1, 0, 0, 0, 934, 896, 1, 0, 0, 0, 934, 913, 1, 0, 0, 0, 934, 923, 1, 0, 0, 0, 935, 162, 1, 0, 0, 0, 936, 940, 7, 7, 0, 0, 937, 939, 7, 8, 0, 0, 938, 937, 1, 0, 0, 0, 939, 942, 1, 0, 0, 0, 940, 938, 1, 0, 0, 0, 940, 941, 1, 0, 0, 0, 941, 164, 1, 0, 0, 0, 942, 940, 1, 0, 0, 0, 943, 945, 7, 9, 0, 0, 944, 943, 1, 0, 0, 0, 945, 946, 1, 0, 0, 0, 946, 944, 1, 0, 0, 0, 946, 947, 1, 0, 0, 0, 947, 948, 1, 0, 0, 0, 948, 949, 6, 82, 0, 0, 949, 166, 1, 0, 0, 0, 950, 951, 5, 47, 0, 0, 951, 952, 5, 42, 0, 0, 952, 956, 1, 0, 0, 0, 953, 955, 9, 0, 0, 0, 954, 953, 1, 0, 0, 0, 955, 958, 1, 0, 0, 0, 956, 957, 1, 0, 0, 0, 956, 954, 1, 0, 0, 0, 957, 959, 1, 0, 0, 0, 958, 956, 1, 0, 0, 0, 959, 960, 5, 42, 0, 0, 960, 961, 5, 47, 0, 0, 961, 962, 1, 0, 0, 0, 962, 963, 6, 83, 1, 0, 963, 168, 1, 0, 0, 0, 964, 965, 5, 47, 0, 0, 965, 966, 5, 47, 0, 0, 966, 970, 1, 0, 0, 0, 967, 969, 8, 10, 0, 0, 968, 967, 1, 0, 0, 0, 969, 972, 1, 0, 0, 0, 970, 968, 1, 0, 0, 0, 970, 971, 1, 0, 0, 0, 971, 973, 1, 0, 0, 0, 972, 970, 1, 0, 0, 0, 973, 974, 6, 84, 1, 0, 974, 170, 1, 0, 0, 0, 28, 0, 567, 573, 579, 590, 649, 652, 656, 661, 667, 671, 706, 725, 731, 738, 740, 748, 750, 754, 770, 788, 825, 838, 934, 940, 946, 956, 970, 2, 6, 0, 0, 0, 1, 0] \ No newline at end of file diff --git a/packages/cashc/src/grammar/CashScriptLexer.tokens b/packages/cashc/src/grammar/CashScriptLexer.tokens index 16dc361d..7f8aef36 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.tokens +++ b/packages/cashc/src/grammar/CashScriptLexer.tokens @@ -62,26 +62,27 @@ T__60=61 T__61=62 T__62=63 T__63=64 -VersionLiteral=65 -BooleanLiteral=66 -NumberUnit=67 -NumberLiteral=68 -NumberPart=69 -ExponentPart=70 -PrimitiveType=71 -UnboundedBytes=72 -BoundedBytes=73 -Bound=74 -StringLiteral=75 -DateLiteral=76 -HexLiteral=77 -TxVar=78 -UnsafeCast=79 -NullaryOp=80 -Identifier=81 -WHITESPACE=82 -COMMENT=83 -LINE_COMMENT=84 +T__64=65 +VersionLiteral=66 +BooleanLiteral=67 +NumberUnit=68 +NumberLiteral=69 +NumberPart=70 +ExponentPart=71 +PrimitiveType=72 +UnboundedBytes=73 +BoundedBytes=74 +Bound=75 +StringLiteral=76 +DateLiteral=77 +HexLiteral=78 +TxVar=79 +UnsafeCast=80 +NullaryOp=81 +Identifier=82 +WHITESPACE=83 +COMMENT=84 +LINE_COMMENT=85 'pragma'=1 ';'=2 'cashscript'=3 @@ -93,57 +94,58 @@ LINE_COMMENT=84 '<='=9 '='=10 'import'=11 -'function'=12 -'returns'=13 -'('=14 -')'=15 -'contract'=16 -'{'=17 -'}'=18 -','=19 -'return'=20 -'+='=21 -'-='=22 -'++'=23 -'--'=24 -'require'=25 -'console.log'=26 -'if'=27 -'else'=28 -'do'=29 -'while'=30 -'for'=31 -'new'=32 -'['=33 -']'=34 -'tx.outputs'=35 -'.value'=36 -'.lockingBytecode'=37 -'.tokenCategory'=38 -'.nftCommitment'=39 -'.tokenAmount'=40 -'tx.inputs'=41 -'.outpointTransactionHash'=42 -'.outpointIndex'=43 -'.unlockingBytecode'=44 -'.sequenceNumber'=45 -'.reverse()'=46 -'.length'=47 -'.split'=48 -'.slice'=49 -'!'=50 -'-'=51 -'*'=52 -'/'=53 -'%'=54 -'+'=55 -'>>'=56 -'<<'=57 -'=='=58 -'!='=59 -'&'=60 -'|'=61 -'&&'=62 -'||'=63 -'constant'=64 -'bytes'=72 +'constant'=12 +'function'=13 +'returns'=14 +'('=15 +','=16 +')'=17 +'contract'=18 +'{'=19 +'}'=20 +'return'=21 +'+='=22 +'-='=23 +'++'=24 +'--'=25 +'require'=26 +'console.log'=27 +'if'=28 +'else'=29 +'do'=30 +'while'=31 +'for'=32 +'new'=33 +'['=34 +']'=35 +'tx.outputs'=36 +'.value'=37 +'.lockingBytecode'=38 +'.tokenCategory'=39 +'.nftCommitment'=40 +'.tokenAmount'=41 +'tx.inputs'=42 +'.outpointTransactionHash'=43 +'.outpointIndex'=44 +'.unlockingBytecode'=45 +'.sequenceNumber'=46 +'.reverse()'=47 +'.length'=48 +'.split'=49 +'.slice'=50 +'!'=51 +'-'=52 +'*'=53 +'/'=54 +'%'=55 +'+'=56 +'>>'=57 +'<<'=58 +'=='=59 +'!='=60 +'&'=61 +'|'=62 +'&&'=63 +'||'=64 +'unused'=65 +'bytes'=73 diff --git a/packages/cashc/src/grammar/CashScriptLexer.ts b/packages/cashc/src/grammar/CashScriptLexer.ts index 0300faed..22f916a6 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.ts +++ b/packages/cashc/src/grammar/CashScriptLexer.ts @@ -1,4 +1,4 @@ -// Generated from src/grammar/CashScript.g4 by ANTLR 4.13.1 +// Generated from CashScript.g4 by ANTLR 4.13.2 // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { ATN, @@ -76,26 +76,27 @@ export default class CashScriptLexer extends Lexer { public static readonly T__61 = 62; public static readonly T__62 = 63; public static readonly T__63 = 64; - public static readonly VersionLiteral = 65; - public static readonly BooleanLiteral = 66; - public static readonly NumberUnit = 67; - public static readonly NumberLiteral = 68; - public static readonly NumberPart = 69; - public static readonly ExponentPart = 70; - public static readonly PrimitiveType = 71; - public static readonly UnboundedBytes = 72; - public static readonly BoundedBytes = 73; - public static readonly Bound = 74; - public static readonly StringLiteral = 75; - public static readonly DateLiteral = 76; - public static readonly HexLiteral = 77; - public static readonly TxVar = 78; - public static readonly UnsafeCast = 79; - public static readonly NullaryOp = 80; - public static readonly Identifier = 81; - public static readonly WHITESPACE = 82; - public static readonly COMMENT = 83; - public static readonly LINE_COMMENT = 84; + public static readonly T__64 = 65; + public static readonly VersionLiteral = 66; + public static readonly BooleanLiteral = 67; + public static readonly NumberUnit = 68; + public static readonly NumberLiteral = 69; + public static readonly NumberPart = 70; + public static readonly ExponentPart = 71; + public static readonly PrimitiveType = 72; + public static readonly UnboundedBytes = 73; + public static readonly BoundedBytes = 74; + public static readonly Bound = 75; + public static readonly StringLiteral = 76; + public static readonly DateLiteral = 77; + public static readonly HexLiteral = 78; + public static readonly TxVar = 79; + public static readonly UnsafeCast = 80; + public static readonly NullaryOp = 81; + public static readonly Identifier = 82; + public static readonly WHITESPACE = 83; + public static readonly COMMENT = 84; + public static readonly LINE_COMMENT = 85; public static readonly EOF = Token.EOF; public static readonly channelNames: string[] = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ]; @@ -105,12 +106,13 @@ export default class CashScriptLexer extends Lexer { "'>='", "'>'", "'<'", "'<='", "'='", "'import'", + "'constant'", "'function'", "'returns'", - "'('", "')'", - "'contract'", + "'('", "','", + "')'", "'contract'", "'{'", "'}'", - "','", "'return'", + "'return'", "'+='", "'-='", "'++'", "'--'", "'require'", @@ -141,7 +143,7 @@ export default class CashScriptLexer extends Lexer { "'=='", "'!='", "'&'", "'|'", "'&&'", "'||'", - "'constant'", + "'unused'", null, null, null, null, null, null, @@ -178,7 +180,8 @@ export default class CashScriptLexer extends Lexer { null, null, null, null, null, null, - null, "VersionLiteral", + null, null, + "VersionLiteral", "BooleanLiteral", "NumberUnit", "NumberLiteral", @@ -206,11 +209,11 @@ export default class CashScriptLexer extends Lexer { "T__33", "T__34", "T__35", "T__36", "T__37", "T__38", "T__39", "T__40", "T__41", "T__42", "T__43", "T__44", "T__45", "T__46", "T__47", "T__48", "T__49", "T__50", "T__51", "T__52", "T__53", "T__54", "T__55", "T__56", - "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "VersionLiteral", - "BooleanLiteral", "NumberUnit", "NumberLiteral", "NumberPart", "ExponentPart", - "PrimitiveType", "UnboundedBytes", "BoundedBytes", "Bound", "StringLiteral", - "DateLiteral", "HexLiteral", "TxVar", "UnsafeCast", "NullaryOp", "Identifier", - "WHITESPACE", "COMMENT", "LINE_COMMENT", + "T__57", "T__58", "T__59", "T__60", "T__61", "T__62", "T__63", "T__64", + "VersionLiteral", "BooleanLiteral", "NumberUnit", "NumberLiteral", "NumberPart", + "ExponentPart", "PrimitiveType", "UnboundedBytes", "BoundedBytes", "Bound", + "StringLiteral", "DateLiteral", "HexLiteral", "TxVar", "UnsafeCast", "NullaryOp", + "Identifier", "WHITESPACE", "COMMENT", "LINE_COMMENT", ]; @@ -231,7 +234,7 @@ export default class CashScriptLexer extends Lexer { public get modeNames(): string[] { return CashScriptLexer.modeNames; } - public static readonly _serializedATN: number[] = [4,0,84,966,6,-1,2,0, + public static readonly _serializedATN: number[] = [4,0,85,975,6,-1,2,0, 7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9, 7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7, 16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23, @@ -243,312 +246,314 @@ export default class CashScriptLexer extends Lexer { 60,7,60,2,61,7,61,2,62,7,62,2,63,7,63,2,64,7,64,2,65,7,65,2,66,7,66,2,67, 7,67,2,68,7,68,2,69,7,69,2,70,7,70,2,71,7,71,2,72,7,72,2,73,7,73,2,74,7, 74,2,75,7,75,2,76,7,76,2,77,7,77,2,78,7,78,2,79,7,79,2,80,7,80,2,81,7,81, - 2,82,7,82,2,83,7,83,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,2,1,2,1,2,1,2, - 1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,5,1,6,1,6,1,7,1,7, - 1,8,1,8,1,8,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,11,1,11,1,11,1, - 11,1,11,1,11,1,11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,12,1,13, - 1,13,1,14,1,14,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,15,1,16,1,16,1, - 17,1,17,1,18,1,18,1,19,1,19,1,19,1,19,1,19,1,19,1,19,1,20,1,20,1,20,1,21, - 1,21,1,21,1,22,1,22,1,22,1,23,1,23,1,23,1,24,1,24,1,24,1,24,1,24,1,24,1, - 24,1,24,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,26, - 1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,28,1,28,1,28,1,29,1,29,1,29,1,29,1, - 29,1,29,1,30,1,30,1,30,1,30,1,31,1,31,1,31,1,31,1,32,1,32,1,33,1,33,1,34, - 1,34,1,34,1,34,1,34,1,34,1,34,1,34,1,34,1,34,1,34,1,35,1,35,1,35,1,35,1, - 35,1,35,1,35,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,36, - 1,36,1,36,1,36,1,36,1,36,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1, - 37,1,37,1,37,1,37,1,37,1,37,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38, - 1,38,1,38,1,38,1,38,1,38,1,38,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1, - 39,1,39,1,39,1,39,1,39,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40, - 1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1, - 41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,42,1,42,1,42,1,42, - 1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,43,1,43,1,43,1, - 43,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,43, - 1,43,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1, - 44,1,44,1,44,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,46, - 1,46,1,46,1,46,1,46,1,46,1,46,1,46,1,47,1,47,1,47,1,47,1,47,1,47,1,47,1, - 48,1,48,1,48,1,48,1,48,1,48,1,48,1,49,1,49,1,50,1,50,1,51,1,51,1,52,1,52, - 1,53,1,53,1,54,1,54,1,55,1,55,1,55,1,56,1,56,1,56,1,57,1,57,1,57,1,58,1, - 58,1,58,1,59,1,59,1,60,1,60,1,61,1,61,1,61,1,62,1,62,1,62,1,63,1,63,1,63, - 1,63,1,63,1,63,1,63,1,63,1,63,1,64,4,64,557,8,64,11,64,12,64,558,1,64,1, - 64,4,64,563,8,64,11,64,12,64,564,1,64,1,64,4,64,569,8,64,11,64,12,64,570, - 1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,1,65,3,65,582,8,65,1,66,1,66,1, - 66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66, - 1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1, - 66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66, - 1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,1,66,3,66,641,8,66,1, - 67,3,67,644,8,67,1,67,1,67,3,67,648,8,67,1,68,4,68,651,8,68,11,68,12,68, - 652,1,68,1,68,4,68,657,8,68,11,68,12,68,658,5,68,661,8,68,10,68,12,68,664, - 9,68,1,69,1,69,1,69,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1, - 70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70,1,70, - 1,70,1,70,1,70,1,70,3,70,698,8,70,1,71,1,71,1,71,1,71,1,71,1,71,1,72,1, - 72,1,72,1,72,1,72,1,72,1,72,1,72,1,72,1,72,1,72,3,72,717,8,72,1,73,1,73, - 5,73,721,8,73,10,73,12,73,724,9,73,1,74,1,74,1,74,1,74,5,74,730,8,74,10, - 74,12,74,733,9,74,1,74,1,74,1,74,1,74,1,74,5,74,740,8,74,10,74,12,74,743, - 9,74,1,74,3,74,746,8,74,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1, - 76,1,76,1,76,5,76,760,8,76,10,76,12,76,763,9,76,1,77,1,77,1,77,1,77,1,77, - 1,77,1,77,1,77,1,77,1,77,1,77,1,77,1,77,1,77,1,77,3,77,780,8,77,1,78,1, - 78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78, - 1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1, - 78,1,78,1,78,1,78,1,78,3,78,817,8,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78, - 1,78,1,78,1,78,1,78,3,78,830,8,78,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1, - 79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79, - 1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1, - 79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79, + 2,82,7,82,2,83,7,83,2,84,7,84,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,2,1, + 2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,3,1,3,1,4,1,4,1,5,1,5,1,5,1,6,1, + 6,1,7,1,7,1,8,1,8,1,8,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,10,1,10,1,11,1, + 11,1,11,1,11,1,11,1,11,1,11,1,11,1,11,1,12,1,12,1,12,1,12,1,12,1,12,1,12, + 1,12,1,12,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,13,1,14,1,14,1,15,1,15,1, + 16,1,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,18,1,18,1,19,1,19, + 1,20,1,20,1,20,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1,22,1,22,1,22,1,23,1, + 23,1,23,1,24,1,24,1,24,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,25,1,26,1,26, + 1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,26,1,27,1,27,1,27,1,28,1, + 28,1,28,1,28,1,28,1,29,1,29,1,29,1,30,1,30,1,30,1,30,1,30,1,30,1,31,1,31, + 1,31,1,31,1,32,1,32,1,32,1,32,1,33,1,33,1,34,1,34,1,35,1,35,1,35,1,35,1, + 35,1,35,1,35,1,35,1,35,1,35,1,35,1,36,1,36,1,36,1,36,1,36,1,36,1,36,1,37, + 1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1, + 37,1,37,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38, + 1,38,1,38,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1, + 39,1,39,1,39,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40,1,40, + 1,40,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,41,1,42,1,42,1,42,1, + 42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,42, + 1,42,1,42,1,42,1,42,1,42,1,42,1,42,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1, + 43,1,43,1,43,1,43,1,43,1,43,1,43,1,43,1,44,1,44,1,44,1,44,1,44,1,44,1,44, + 1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,44,1,45,1,45,1, + 45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,45,1,46, + 1,46,1,46,1,46,1,46,1,46,1,46,1,46,1,46,1,46,1,46,1,47,1,47,1,47,1,47,1, + 47,1,47,1,47,1,47,1,48,1,48,1,48,1,48,1,48,1,48,1,48,1,49,1,49,1,49,1,49, + 1,49,1,49,1,49,1,50,1,50,1,51,1,51,1,52,1,52,1,53,1,53,1,54,1,54,1,55,1, + 55,1,56,1,56,1,56,1,57,1,57,1,57,1,58,1,58,1,58,1,59,1,59,1,59,1,60,1,60, + 1,61,1,61,1,62,1,62,1,62,1,63,1,63,1,63,1,64,1,64,1,64,1,64,1,64,1,64,1, + 64,1,65,4,65,566,8,65,11,65,12,65,567,1,65,1,65,4,65,572,8,65,11,65,12, + 65,573,1,65,1,65,4,65,578,8,65,11,65,12,65,579,1,66,1,66,1,66,1,66,1,66, + 1,66,1,66,1,66,1,66,3,66,591,8,66,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1, + 67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67, + 1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1, + 67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67,1,67, + 1,67,1,67,1,67,1,67,1,67,1,67,3,67,650,8,67,1,68,3,68,653,8,68,1,68,1,68, + 3,68,657,8,68,1,69,4,69,660,8,69,11,69,12,69,661,1,69,1,69,4,69,666,8,69, + 11,69,12,69,667,5,69,670,8,69,10,69,12,69,673,9,69,1,70,1,70,1,70,1,71, + 1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1, + 71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,1,71,3,71, + 707,8,71,1,72,1,72,1,72,1,72,1,72,1,72,1,73,1,73,1,73,1,73,1,73,1,73,1, + 73,1,73,1,73,1,73,1,73,3,73,726,8,73,1,74,1,74,5,74,730,8,74,10,74,12,74, + 733,9,74,1,75,1,75,1,75,1,75,5,75,739,8,75,10,75,12,75,742,9,75,1,75,1, + 75,1,75,1,75,1,75,5,75,749,8,75,10,75,12,75,752,9,75,1,75,3,75,755,8,75, + 1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,77,1,77,1,77,5,77,769,8, + 77,10,77,12,77,772,9,77,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1,78,1, + 78,1,78,1,78,1,78,1,78,1,78,3,78,789,8,78,1,79,1,79,1,79,1,79,1,79,1,79, 1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1, 79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79, - 1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,3, - 79,926,8,79,1,80,1,80,5,80,930,8,80,10,80,12,80,933,9,80,1,81,4,81,936, - 8,81,11,81,12,81,937,1,81,1,81,1,82,1,82,1,82,1,82,5,82,946,8,82,10,82, - 12,82,949,9,82,1,82,1,82,1,82,1,82,1,82,1,83,1,83,1,83,1,83,5,83,960,8, - 83,10,83,12,83,963,9,83,1,83,1,83,3,731,741,947,0,84,1,1,3,2,5,3,7,4,9, - 5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,25,13,27,14,29,15,31,16,33,17,35, - 18,37,19,39,20,41,21,43,22,45,23,47,24,49,25,51,26,53,27,55,28,57,29,59, - 30,61,31,63,32,65,33,67,34,69,35,71,36,73,37,75,38,77,39,79,40,81,41,83, - 42,85,43,87,44,89,45,91,46,93,47,95,48,97,49,99,50,101,51,103,52,105,53, - 107,54,109,55,111,56,113,57,115,58,117,59,119,60,121,61,123,62,125,63,127, - 64,129,65,131,66,133,67,135,68,137,69,139,70,141,71,143,72,145,73,147,74, - 149,75,151,76,153,77,155,78,157,79,159,80,161,81,163,82,165,83,167,84,1, - 0,11,1,0,48,57,2,0,69,69,101,101,1,0,49,57,3,0,10,10,13,13,34,34,3,0,10, - 10,13,13,39,39,2,0,88,88,120,120,3,0,48,57,65,70,97,102,2,0,65,90,97,122, - 4,0,48,57,65,90,95,95,97,122,3,0,9,10,12,13,32,32,2,0,10,10,13,13,1010, - 0,1,1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0, - 0,0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23, - 1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0, - 0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45, - 1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0, - 0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67, - 1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0, - 0,0,79,1,0,0,0,0,81,1,0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89, - 1,0,0,0,0,91,1,0,0,0,0,93,1,0,0,0,0,95,1,0,0,0,0,97,1,0,0,0,0,99,1,0,0, - 0,0,101,1,0,0,0,0,103,1,0,0,0,0,105,1,0,0,0,0,107,1,0,0,0,0,109,1,0,0,0, - 0,111,1,0,0,0,0,113,1,0,0,0,0,115,1,0,0,0,0,117,1,0,0,0,0,119,1,0,0,0,0, - 121,1,0,0,0,0,123,1,0,0,0,0,125,1,0,0,0,0,127,1,0,0,0,0,129,1,0,0,0,0,131, - 1,0,0,0,0,133,1,0,0,0,0,135,1,0,0,0,0,137,1,0,0,0,0,139,1,0,0,0,0,141,1, - 0,0,0,0,143,1,0,0,0,0,145,1,0,0,0,0,147,1,0,0,0,0,149,1,0,0,0,0,151,1,0, - 0,0,0,153,1,0,0,0,0,155,1,0,0,0,0,157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0, - 0,0,163,1,0,0,0,0,165,1,0,0,0,0,167,1,0,0,0,1,169,1,0,0,0,3,176,1,0,0,0, - 5,178,1,0,0,0,7,189,1,0,0,0,9,191,1,0,0,0,11,193,1,0,0,0,13,196,1,0,0,0, - 15,198,1,0,0,0,17,200,1,0,0,0,19,203,1,0,0,0,21,205,1,0,0,0,23,212,1,0, - 0,0,25,221,1,0,0,0,27,229,1,0,0,0,29,231,1,0,0,0,31,233,1,0,0,0,33,242, - 1,0,0,0,35,244,1,0,0,0,37,246,1,0,0,0,39,248,1,0,0,0,41,255,1,0,0,0,43, - 258,1,0,0,0,45,261,1,0,0,0,47,264,1,0,0,0,49,267,1,0,0,0,51,275,1,0,0,0, - 53,287,1,0,0,0,55,290,1,0,0,0,57,295,1,0,0,0,59,298,1,0,0,0,61,304,1,0, - 0,0,63,308,1,0,0,0,65,312,1,0,0,0,67,314,1,0,0,0,69,316,1,0,0,0,71,327, - 1,0,0,0,73,334,1,0,0,0,75,351,1,0,0,0,77,366,1,0,0,0,79,381,1,0,0,0,81, - 394,1,0,0,0,83,404,1,0,0,0,85,429,1,0,0,0,87,444,1,0,0,0,89,463,1,0,0,0, - 91,479,1,0,0,0,93,490,1,0,0,0,95,498,1,0,0,0,97,505,1,0,0,0,99,512,1,0, - 0,0,101,514,1,0,0,0,103,516,1,0,0,0,105,518,1,0,0,0,107,520,1,0,0,0,109, - 522,1,0,0,0,111,524,1,0,0,0,113,527,1,0,0,0,115,530,1,0,0,0,117,533,1,0, - 0,0,119,536,1,0,0,0,121,538,1,0,0,0,123,540,1,0,0,0,125,543,1,0,0,0,127, - 546,1,0,0,0,129,556,1,0,0,0,131,581,1,0,0,0,133,640,1,0,0,0,135,643,1,0, - 0,0,137,650,1,0,0,0,139,665,1,0,0,0,141,697,1,0,0,0,143,699,1,0,0,0,145, - 716,1,0,0,0,147,718,1,0,0,0,149,745,1,0,0,0,151,747,1,0,0,0,153,756,1,0, - 0,0,155,779,1,0,0,0,157,829,1,0,0,0,159,925,1,0,0,0,161,927,1,0,0,0,163, - 935,1,0,0,0,165,941,1,0,0,0,167,955,1,0,0,0,169,170,5,112,0,0,170,171,5, - 114,0,0,171,172,5,97,0,0,172,173,5,103,0,0,173,174,5,109,0,0,174,175,5, - 97,0,0,175,2,1,0,0,0,176,177,5,59,0,0,177,4,1,0,0,0,178,179,5,99,0,0,179, - 180,5,97,0,0,180,181,5,115,0,0,181,182,5,104,0,0,182,183,5,115,0,0,183, - 184,5,99,0,0,184,185,5,114,0,0,185,186,5,105,0,0,186,187,5,112,0,0,187, - 188,5,116,0,0,188,6,1,0,0,0,189,190,5,94,0,0,190,8,1,0,0,0,191,192,5,126, - 0,0,192,10,1,0,0,0,193,194,5,62,0,0,194,195,5,61,0,0,195,12,1,0,0,0,196, - 197,5,62,0,0,197,14,1,0,0,0,198,199,5,60,0,0,199,16,1,0,0,0,200,201,5,60, - 0,0,201,202,5,61,0,0,202,18,1,0,0,0,203,204,5,61,0,0,204,20,1,0,0,0,205, - 206,5,105,0,0,206,207,5,109,0,0,207,208,5,112,0,0,208,209,5,111,0,0,209, - 210,5,114,0,0,210,211,5,116,0,0,211,22,1,0,0,0,212,213,5,102,0,0,213,214, - 5,117,0,0,214,215,5,110,0,0,215,216,5,99,0,0,216,217,5,116,0,0,217,218, - 5,105,0,0,218,219,5,111,0,0,219,220,5,110,0,0,220,24,1,0,0,0,221,222,5, - 114,0,0,222,223,5,101,0,0,223,224,5,116,0,0,224,225,5,117,0,0,225,226,5, - 114,0,0,226,227,5,110,0,0,227,228,5,115,0,0,228,26,1,0,0,0,229,230,5,40, - 0,0,230,28,1,0,0,0,231,232,5,41,0,0,232,30,1,0,0,0,233,234,5,99,0,0,234, - 235,5,111,0,0,235,236,5,110,0,0,236,237,5,116,0,0,237,238,5,114,0,0,238, - 239,5,97,0,0,239,240,5,99,0,0,240,241,5,116,0,0,241,32,1,0,0,0,242,243, - 5,123,0,0,243,34,1,0,0,0,244,245,5,125,0,0,245,36,1,0,0,0,246,247,5,44, - 0,0,247,38,1,0,0,0,248,249,5,114,0,0,249,250,5,101,0,0,250,251,5,116,0, - 0,251,252,5,117,0,0,252,253,5,114,0,0,253,254,5,110,0,0,254,40,1,0,0,0, - 255,256,5,43,0,0,256,257,5,61,0,0,257,42,1,0,0,0,258,259,5,45,0,0,259,260, - 5,61,0,0,260,44,1,0,0,0,261,262,5,43,0,0,262,263,5,43,0,0,263,46,1,0,0, - 0,264,265,5,45,0,0,265,266,5,45,0,0,266,48,1,0,0,0,267,268,5,114,0,0,268, - 269,5,101,0,0,269,270,5,113,0,0,270,271,5,117,0,0,271,272,5,105,0,0,272, - 273,5,114,0,0,273,274,5,101,0,0,274,50,1,0,0,0,275,276,5,99,0,0,276,277, - 5,111,0,0,277,278,5,110,0,0,278,279,5,115,0,0,279,280,5,111,0,0,280,281, - 5,108,0,0,281,282,5,101,0,0,282,283,5,46,0,0,283,284,5,108,0,0,284,285, - 5,111,0,0,285,286,5,103,0,0,286,52,1,0,0,0,287,288,5,105,0,0,288,289,5, - 102,0,0,289,54,1,0,0,0,290,291,5,101,0,0,291,292,5,108,0,0,292,293,5,115, - 0,0,293,294,5,101,0,0,294,56,1,0,0,0,295,296,5,100,0,0,296,297,5,111,0, - 0,297,58,1,0,0,0,298,299,5,119,0,0,299,300,5,104,0,0,300,301,5,105,0,0, - 301,302,5,108,0,0,302,303,5,101,0,0,303,60,1,0,0,0,304,305,5,102,0,0,305, - 306,5,111,0,0,306,307,5,114,0,0,307,62,1,0,0,0,308,309,5,110,0,0,309,310, - 5,101,0,0,310,311,5,119,0,0,311,64,1,0,0,0,312,313,5,91,0,0,313,66,1,0, - 0,0,314,315,5,93,0,0,315,68,1,0,0,0,316,317,5,116,0,0,317,318,5,120,0,0, - 318,319,5,46,0,0,319,320,5,111,0,0,320,321,5,117,0,0,321,322,5,116,0,0, - 322,323,5,112,0,0,323,324,5,117,0,0,324,325,5,116,0,0,325,326,5,115,0,0, - 326,70,1,0,0,0,327,328,5,46,0,0,328,329,5,118,0,0,329,330,5,97,0,0,330, - 331,5,108,0,0,331,332,5,117,0,0,332,333,5,101,0,0,333,72,1,0,0,0,334,335, - 5,46,0,0,335,336,5,108,0,0,336,337,5,111,0,0,337,338,5,99,0,0,338,339,5, - 107,0,0,339,340,5,105,0,0,340,341,5,110,0,0,341,342,5,103,0,0,342,343,5, - 66,0,0,343,344,5,121,0,0,344,345,5,116,0,0,345,346,5,101,0,0,346,347,5, - 99,0,0,347,348,5,111,0,0,348,349,5,100,0,0,349,350,5,101,0,0,350,74,1,0, - 0,0,351,352,5,46,0,0,352,353,5,116,0,0,353,354,5,111,0,0,354,355,5,107, - 0,0,355,356,5,101,0,0,356,357,5,110,0,0,357,358,5,67,0,0,358,359,5,97,0, - 0,359,360,5,116,0,0,360,361,5,101,0,0,361,362,5,103,0,0,362,363,5,111,0, - 0,363,364,5,114,0,0,364,365,5,121,0,0,365,76,1,0,0,0,366,367,5,46,0,0,367, - 368,5,110,0,0,368,369,5,102,0,0,369,370,5,116,0,0,370,371,5,67,0,0,371, - 372,5,111,0,0,372,373,5,109,0,0,373,374,5,109,0,0,374,375,5,105,0,0,375, - 376,5,116,0,0,376,377,5,109,0,0,377,378,5,101,0,0,378,379,5,110,0,0,379, - 380,5,116,0,0,380,78,1,0,0,0,381,382,5,46,0,0,382,383,5,116,0,0,383,384, - 5,111,0,0,384,385,5,107,0,0,385,386,5,101,0,0,386,387,5,110,0,0,387,388, - 5,65,0,0,388,389,5,109,0,0,389,390,5,111,0,0,390,391,5,117,0,0,391,392, - 5,110,0,0,392,393,5,116,0,0,393,80,1,0,0,0,394,395,5,116,0,0,395,396,5, - 120,0,0,396,397,5,46,0,0,397,398,5,105,0,0,398,399,5,110,0,0,399,400,5, - 112,0,0,400,401,5,117,0,0,401,402,5,116,0,0,402,403,5,115,0,0,403,82,1, - 0,0,0,404,405,5,46,0,0,405,406,5,111,0,0,406,407,5,117,0,0,407,408,5,116, - 0,0,408,409,5,112,0,0,409,410,5,111,0,0,410,411,5,105,0,0,411,412,5,110, - 0,0,412,413,5,116,0,0,413,414,5,84,0,0,414,415,5,114,0,0,415,416,5,97,0, - 0,416,417,5,110,0,0,417,418,5,115,0,0,418,419,5,97,0,0,419,420,5,99,0,0, - 420,421,5,116,0,0,421,422,5,105,0,0,422,423,5,111,0,0,423,424,5,110,0,0, - 424,425,5,72,0,0,425,426,5,97,0,0,426,427,5,115,0,0,427,428,5,104,0,0,428, - 84,1,0,0,0,429,430,5,46,0,0,430,431,5,111,0,0,431,432,5,117,0,0,432,433, - 5,116,0,0,433,434,5,112,0,0,434,435,5,111,0,0,435,436,5,105,0,0,436,437, - 5,110,0,0,437,438,5,116,0,0,438,439,5,73,0,0,439,440,5,110,0,0,440,441, - 5,100,0,0,441,442,5,101,0,0,442,443,5,120,0,0,443,86,1,0,0,0,444,445,5, - 46,0,0,445,446,5,117,0,0,446,447,5,110,0,0,447,448,5,108,0,0,448,449,5, - 111,0,0,449,450,5,99,0,0,450,451,5,107,0,0,451,452,5,105,0,0,452,453,5, - 110,0,0,453,454,5,103,0,0,454,455,5,66,0,0,455,456,5,121,0,0,456,457,5, - 116,0,0,457,458,5,101,0,0,458,459,5,99,0,0,459,460,5,111,0,0,460,461,5, - 100,0,0,461,462,5,101,0,0,462,88,1,0,0,0,463,464,5,46,0,0,464,465,5,115, - 0,0,465,466,5,101,0,0,466,467,5,113,0,0,467,468,5,117,0,0,468,469,5,101, - 0,0,469,470,5,110,0,0,470,471,5,99,0,0,471,472,5,101,0,0,472,473,5,78,0, - 0,473,474,5,117,0,0,474,475,5,109,0,0,475,476,5,98,0,0,476,477,5,101,0, - 0,477,478,5,114,0,0,478,90,1,0,0,0,479,480,5,46,0,0,480,481,5,114,0,0,481, - 482,5,101,0,0,482,483,5,118,0,0,483,484,5,101,0,0,484,485,5,114,0,0,485, - 486,5,115,0,0,486,487,5,101,0,0,487,488,5,40,0,0,488,489,5,41,0,0,489,92, - 1,0,0,0,490,491,5,46,0,0,491,492,5,108,0,0,492,493,5,101,0,0,493,494,5, - 110,0,0,494,495,5,103,0,0,495,496,5,116,0,0,496,497,5,104,0,0,497,94,1, - 0,0,0,498,499,5,46,0,0,499,500,5,115,0,0,500,501,5,112,0,0,501,502,5,108, - 0,0,502,503,5,105,0,0,503,504,5,116,0,0,504,96,1,0,0,0,505,506,5,46,0,0, - 506,507,5,115,0,0,507,508,5,108,0,0,508,509,5,105,0,0,509,510,5,99,0,0, - 510,511,5,101,0,0,511,98,1,0,0,0,512,513,5,33,0,0,513,100,1,0,0,0,514,515, - 5,45,0,0,515,102,1,0,0,0,516,517,5,42,0,0,517,104,1,0,0,0,518,519,5,47, - 0,0,519,106,1,0,0,0,520,521,5,37,0,0,521,108,1,0,0,0,522,523,5,43,0,0,523, - 110,1,0,0,0,524,525,5,62,0,0,525,526,5,62,0,0,526,112,1,0,0,0,527,528,5, - 60,0,0,528,529,5,60,0,0,529,114,1,0,0,0,530,531,5,61,0,0,531,532,5,61,0, - 0,532,116,1,0,0,0,533,534,5,33,0,0,534,535,5,61,0,0,535,118,1,0,0,0,536, - 537,5,38,0,0,537,120,1,0,0,0,538,539,5,124,0,0,539,122,1,0,0,0,540,541, - 5,38,0,0,541,542,5,38,0,0,542,124,1,0,0,0,543,544,5,124,0,0,544,545,5,124, - 0,0,545,126,1,0,0,0,546,547,5,99,0,0,547,548,5,111,0,0,548,549,5,110,0, - 0,549,550,5,115,0,0,550,551,5,116,0,0,551,552,5,97,0,0,552,553,5,110,0, - 0,553,554,5,116,0,0,554,128,1,0,0,0,555,557,7,0,0,0,556,555,1,0,0,0,557, - 558,1,0,0,0,558,556,1,0,0,0,558,559,1,0,0,0,559,560,1,0,0,0,560,562,5,46, - 0,0,561,563,7,0,0,0,562,561,1,0,0,0,563,564,1,0,0,0,564,562,1,0,0,0,564, - 565,1,0,0,0,565,566,1,0,0,0,566,568,5,46,0,0,567,569,7,0,0,0,568,567,1, - 0,0,0,569,570,1,0,0,0,570,568,1,0,0,0,570,571,1,0,0,0,571,130,1,0,0,0,572, - 573,5,116,0,0,573,574,5,114,0,0,574,575,5,117,0,0,575,582,5,101,0,0,576, - 577,5,102,0,0,577,578,5,97,0,0,578,579,5,108,0,0,579,580,5,115,0,0,580, - 582,5,101,0,0,581,572,1,0,0,0,581,576,1,0,0,0,582,132,1,0,0,0,583,584,5, - 115,0,0,584,585,5,97,0,0,585,586,5,116,0,0,586,587,5,111,0,0,587,588,5, - 115,0,0,588,589,5,104,0,0,589,590,5,105,0,0,590,641,5,115,0,0,591,592,5, - 115,0,0,592,593,5,97,0,0,593,594,5,116,0,0,594,641,5,115,0,0,595,596,5, - 102,0,0,596,597,5,105,0,0,597,598,5,110,0,0,598,599,5,110,0,0,599,600,5, - 101,0,0,600,641,5,121,0,0,601,602,5,98,0,0,602,603,5,105,0,0,603,604,5, - 116,0,0,604,641,5,115,0,0,605,606,5,98,0,0,606,607,5,105,0,0,607,608,5, - 116,0,0,608,609,5,99,0,0,609,610,5,111,0,0,610,611,5,105,0,0,611,641,5, - 110,0,0,612,613,5,115,0,0,613,614,5,101,0,0,614,615,5,99,0,0,615,616,5, - 111,0,0,616,617,5,110,0,0,617,618,5,100,0,0,618,641,5,115,0,0,619,620,5, - 109,0,0,620,621,5,105,0,0,621,622,5,110,0,0,622,623,5,117,0,0,623,624,5, - 116,0,0,624,625,5,101,0,0,625,641,5,115,0,0,626,627,5,104,0,0,627,628,5, - 111,0,0,628,629,5,117,0,0,629,630,5,114,0,0,630,641,5,115,0,0,631,632,5, - 100,0,0,632,633,5,97,0,0,633,634,5,121,0,0,634,641,5,115,0,0,635,636,5, - 119,0,0,636,637,5,101,0,0,637,638,5,101,0,0,638,639,5,107,0,0,639,641,5, - 115,0,0,640,583,1,0,0,0,640,591,1,0,0,0,640,595,1,0,0,0,640,601,1,0,0,0, - 640,605,1,0,0,0,640,612,1,0,0,0,640,619,1,0,0,0,640,626,1,0,0,0,640,631, - 1,0,0,0,640,635,1,0,0,0,641,134,1,0,0,0,642,644,5,45,0,0,643,642,1,0,0, - 0,643,644,1,0,0,0,644,645,1,0,0,0,645,647,3,137,68,0,646,648,3,139,69,0, - 647,646,1,0,0,0,647,648,1,0,0,0,648,136,1,0,0,0,649,651,7,0,0,0,650,649, - 1,0,0,0,651,652,1,0,0,0,652,650,1,0,0,0,652,653,1,0,0,0,653,662,1,0,0,0, - 654,656,5,95,0,0,655,657,7,0,0,0,656,655,1,0,0,0,657,658,1,0,0,0,658,656, - 1,0,0,0,658,659,1,0,0,0,659,661,1,0,0,0,660,654,1,0,0,0,661,664,1,0,0,0, - 662,660,1,0,0,0,662,663,1,0,0,0,663,138,1,0,0,0,664,662,1,0,0,0,665,666, - 7,1,0,0,666,667,3,137,68,0,667,140,1,0,0,0,668,669,5,105,0,0,669,670,5, - 110,0,0,670,698,5,116,0,0,671,672,5,98,0,0,672,673,5,111,0,0,673,674,5, - 111,0,0,674,698,5,108,0,0,675,676,5,115,0,0,676,677,5,116,0,0,677,678,5, - 114,0,0,678,679,5,105,0,0,679,680,5,110,0,0,680,698,5,103,0,0,681,682,5, - 112,0,0,682,683,5,117,0,0,683,684,5,98,0,0,684,685,5,107,0,0,685,686,5, - 101,0,0,686,698,5,121,0,0,687,688,5,115,0,0,688,689,5,105,0,0,689,698,5, - 103,0,0,690,691,5,100,0,0,691,692,5,97,0,0,692,693,5,116,0,0,693,694,5, - 97,0,0,694,695,5,115,0,0,695,696,5,105,0,0,696,698,5,103,0,0,697,668,1, - 0,0,0,697,671,1,0,0,0,697,675,1,0,0,0,697,681,1,0,0,0,697,687,1,0,0,0,697, - 690,1,0,0,0,698,142,1,0,0,0,699,700,5,98,0,0,700,701,5,121,0,0,701,702, - 5,116,0,0,702,703,5,101,0,0,703,704,5,115,0,0,704,144,1,0,0,0,705,706,5, - 98,0,0,706,707,5,121,0,0,707,708,5,116,0,0,708,709,5,101,0,0,709,710,5, - 115,0,0,710,711,1,0,0,0,711,717,3,147,73,0,712,713,5,98,0,0,713,714,5,121, - 0,0,714,715,5,116,0,0,715,717,5,101,0,0,716,705,1,0,0,0,716,712,1,0,0,0, - 717,146,1,0,0,0,718,722,7,2,0,0,719,721,7,0,0,0,720,719,1,0,0,0,721,724, - 1,0,0,0,722,720,1,0,0,0,722,723,1,0,0,0,723,148,1,0,0,0,724,722,1,0,0,0, - 725,731,5,34,0,0,726,727,5,92,0,0,727,730,5,34,0,0,728,730,8,3,0,0,729, - 726,1,0,0,0,729,728,1,0,0,0,730,733,1,0,0,0,731,732,1,0,0,0,731,729,1,0, - 0,0,732,734,1,0,0,0,733,731,1,0,0,0,734,746,5,34,0,0,735,741,5,39,0,0,736, - 737,5,92,0,0,737,740,5,39,0,0,738,740,8,4,0,0,739,736,1,0,0,0,739,738,1, - 0,0,0,740,743,1,0,0,0,741,742,1,0,0,0,741,739,1,0,0,0,742,744,1,0,0,0,743, - 741,1,0,0,0,744,746,5,39,0,0,745,725,1,0,0,0,745,735,1,0,0,0,746,150,1, - 0,0,0,747,748,5,100,0,0,748,749,5,97,0,0,749,750,5,116,0,0,750,751,5,101, - 0,0,751,752,5,40,0,0,752,753,1,0,0,0,753,754,3,149,74,0,754,755,5,41,0, - 0,755,152,1,0,0,0,756,757,5,48,0,0,757,761,7,5,0,0,758,760,7,6,0,0,759, - 758,1,0,0,0,760,763,1,0,0,0,761,759,1,0,0,0,761,762,1,0,0,0,762,154,1,0, - 0,0,763,761,1,0,0,0,764,765,5,116,0,0,765,766,5,104,0,0,766,767,5,105,0, - 0,767,768,5,115,0,0,768,769,5,46,0,0,769,770,5,97,0,0,770,771,5,103,0,0, - 771,780,5,101,0,0,772,773,5,116,0,0,773,774,5,120,0,0,774,775,5,46,0,0, - 775,776,5,116,0,0,776,777,5,105,0,0,777,778,5,109,0,0,778,780,5,101,0,0, - 779,764,1,0,0,0,779,772,1,0,0,0,780,156,1,0,0,0,781,782,5,117,0,0,782,783, - 5,110,0,0,783,784,5,115,0,0,784,785,5,97,0,0,785,786,5,102,0,0,786,787, - 5,101,0,0,787,788,5,95,0,0,788,789,5,105,0,0,789,790,5,110,0,0,790,830, - 5,116,0,0,791,792,5,117,0,0,792,793,5,110,0,0,793,794,5,115,0,0,794,795, - 5,97,0,0,795,796,5,102,0,0,796,797,5,101,0,0,797,798,5,95,0,0,798,799,5, - 98,0,0,799,800,5,111,0,0,800,801,5,111,0,0,801,830,5,108,0,0,802,803,5, - 117,0,0,803,804,5,110,0,0,804,805,5,115,0,0,805,806,5,97,0,0,806,807,5, - 102,0,0,807,808,5,101,0,0,808,809,5,95,0,0,809,810,5,98,0,0,810,811,5,121, - 0,0,811,812,5,116,0,0,812,813,5,101,0,0,813,814,5,115,0,0,814,816,1,0,0, - 0,815,817,3,147,73,0,816,815,1,0,0,0,816,817,1,0,0,0,817,830,1,0,0,0,818, - 819,5,117,0,0,819,820,5,110,0,0,820,821,5,115,0,0,821,822,5,97,0,0,822, - 823,5,102,0,0,823,824,5,101,0,0,824,825,5,95,0,0,825,826,5,98,0,0,826,827, - 5,121,0,0,827,828,5,116,0,0,828,830,5,101,0,0,829,781,1,0,0,0,829,791,1, - 0,0,0,829,802,1,0,0,0,829,818,1,0,0,0,830,158,1,0,0,0,831,832,5,116,0,0, - 832,833,5,104,0,0,833,834,5,105,0,0,834,835,5,115,0,0,835,836,5,46,0,0, - 836,837,5,97,0,0,837,838,5,99,0,0,838,839,5,116,0,0,839,840,5,105,0,0,840, - 841,5,118,0,0,841,842,5,101,0,0,842,843,5,73,0,0,843,844,5,110,0,0,844, - 845,5,112,0,0,845,846,5,117,0,0,846,847,5,116,0,0,847,848,5,73,0,0,848, - 849,5,110,0,0,849,850,5,100,0,0,850,851,5,101,0,0,851,926,5,120,0,0,852, - 853,5,116,0,0,853,854,5,104,0,0,854,855,5,105,0,0,855,856,5,115,0,0,856, - 857,5,46,0,0,857,858,5,97,0,0,858,859,5,99,0,0,859,860,5,116,0,0,860,861, - 5,105,0,0,861,862,5,118,0,0,862,863,5,101,0,0,863,864,5,66,0,0,864,865, - 5,121,0,0,865,866,5,116,0,0,866,867,5,101,0,0,867,868,5,99,0,0,868,869, - 5,111,0,0,869,870,5,100,0,0,870,926,5,101,0,0,871,872,5,116,0,0,872,873, - 5,120,0,0,873,874,5,46,0,0,874,875,5,105,0,0,875,876,5,110,0,0,876,877, - 5,112,0,0,877,878,5,117,0,0,878,879,5,116,0,0,879,880,5,115,0,0,880,881, - 5,46,0,0,881,882,5,108,0,0,882,883,5,101,0,0,883,884,5,110,0,0,884,885, - 5,103,0,0,885,886,5,116,0,0,886,926,5,104,0,0,887,888,5,116,0,0,888,889, - 5,120,0,0,889,890,5,46,0,0,890,891,5,111,0,0,891,892,5,117,0,0,892,893, - 5,116,0,0,893,894,5,112,0,0,894,895,5,117,0,0,895,896,5,116,0,0,896,897, - 5,115,0,0,897,898,5,46,0,0,898,899,5,108,0,0,899,900,5,101,0,0,900,901, - 5,110,0,0,901,902,5,103,0,0,902,903,5,116,0,0,903,926,5,104,0,0,904,905, - 5,116,0,0,905,906,5,120,0,0,906,907,5,46,0,0,907,908,5,118,0,0,908,909, - 5,101,0,0,909,910,5,114,0,0,910,911,5,115,0,0,911,912,5,105,0,0,912,913, - 5,111,0,0,913,926,5,110,0,0,914,915,5,116,0,0,915,916,5,120,0,0,916,917, - 5,46,0,0,917,918,5,108,0,0,918,919,5,111,0,0,919,920,5,99,0,0,920,921,5, - 107,0,0,921,922,5,116,0,0,922,923,5,105,0,0,923,924,5,109,0,0,924,926,5, - 101,0,0,925,831,1,0,0,0,925,852,1,0,0,0,925,871,1,0,0,0,925,887,1,0,0,0, - 925,904,1,0,0,0,925,914,1,0,0,0,926,160,1,0,0,0,927,931,7,7,0,0,928,930, - 7,8,0,0,929,928,1,0,0,0,930,933,1,0,0,0,931,929,1,0,0,0,931,932,1,0,0,0, - 932,162,1,0,0,0,933,931,1,0,0,0,934,936,7,9,0,0,935,934,1,0,0,0,936,937, - 1,0,0,0,937,935,1,0,0,0,937,938,1,0,0,0,938,939,1,0,0,0,939,940,6,81,0, - 0,940,164,1,0,0,0,941,942,5,47,0,0,942,943,5,42,0,0,943,947,1,0,0,0,944, - 946,9,0,0,0,945,944,1,0,0,0,946,949,1,0,0,0,947,948,1,0,0,0,947,945,1,0, - 0,0,948,950,1,0,0,0,949,947,1,0,0,0,950,951,5,42,0,0,951,952,5,47,0,0,952, - 953,1,0,0,0,953,954,6,82,1,0,954,166,1,0,0,0,955,956,5,47,0,0,956,957,5, - 47,0,0,957,961,1,0,0,0,958,960,8,10,0,0,959,958,1,0,0,0,960,963,1,0,0,0, - 961,959,1,0,0,0,961,962,1,0,0,0,962,964,1,0,0,0,963,961,1,0,0,0,964,965, - 6,83,1,0,965,168,1,0,0,0,28,0,558,564,570,581,640,643,647,652,658,662,697, - 716,722,729,731,739,741,745,761,779,816,829,925,931,937,947,961,2,6,0,0, - 0,1,0]; + 3,79,826,8,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,1,79,3, + 79,839,8,79,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80, + 1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1, + 80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80, + 1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1, + 80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80, + 1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1, + 80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,1,80,3,80,935,8,80,1,81,1,81, + 5,81,939,8,81,10,81,12,81,942,9,81,1,82,4,82,945,8,82,11,82,12,82,946,1, + 82,1,82,1,83,1,83,1,83,1,83,5,83,955,8,83,10,83,12,83,958,9,83,1,83,1,83, + 1,83,1,83,1,83,1,84,1,84,1,84,1,84,5,84,969,8,84,10,84,12,84,972,9,84,1, + 84,1,84,3,740,750,956,0,85,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10, + 21,11,23,12,25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22, + 45,23,47,24,49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34, + 69,35,71,36,73,37,75,38,77,39,79,40,81,41,83,42,85,43,87,44,89,45,91,46, + 93,47,95,48,97,49,99,50,101,51,103,52,105,53,107,54,109,55,111,56,113,57, + 115,58,117,59,119,60,121,61,123,62,125,63,127,64,129,65,131,66,133,67,135, + 68,137,69,139,70,141,71,143,72,145,73,147,74,149,75,151,76,153,77,155,78, + 157,79,159,80,161,81,163,82,165,83,167,84,169,85,1,0,11,1,0,48,57,2,0,69, + 69,101,101,1,0,49,57,3,0,10,10,13,13,34,34,3,0,10,10,13,13,39,39,2,0,88, + 88,120,120,3,0,48,57,65,70,97,102,2,0,65,90,97,122,4,0,48,57,65,90,95,95, + 97,122,3,0,9,10,12,13,32,32,2,0,10,10,13,13,1019,0,1,1,0,0,0,0,3,1,0,0, + 0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,0,13,1,0,0,0,0,15,1, + 0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,1,0,0,0,0,25,1,0,0,0, + 0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,0,0,0,35,1,0,0,0,0,37,1, + 0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,0,45,1,0,0,0,0,47,1,0,0,0, + 0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,1,0,0,0,0,57,1,0,0,0,0,59,1, + 0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,0,0,0,67,1,0,0,0,0,69,1,0,0,0, + 0,71,1,0,0,0,0,73,1,0,0,0,0,75,1,0,0,0,0,77,1,0,0,0,0,79,1,0,0,0,0,81,1, + 0,0,0,0,83,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,0,89,1,0,0,0,0,91,1,0,0,0, + 0,93,1,0,0,0,0,95,1,0,0,0,0,97,1,0,0,0,0,99,1,0,0,0,0,101,1,0,0,0,0,103, + 1,0,0,0,0,105,1,0,0,0,0,107,1,0,0,0,0,109,1,0,0,0,0,111,1,0,0,0,0,113,1, + 0,0,0,0,115,1,0,0,0,0,117,1,0,0,0,0,119,1,0,0,0,0,121,1,0,0,0,0,123,1,0, + 0,0,0,125,1,0,0,0,0,127,1,0,0,0,0,129,1,0,0,0,0,131,1,0,0,0,0,133,1,0,0, + 0,0,135,1,0,0,0,0,137,1,0,0,0,0,139,1,0,0,0,0,141,1,0,0,0,0,143,1,0,0,0, + 0,145,1,0,0,0,0,147,1,0,0,0,0,149,1,0,0,0,0,151,1,0,0,0,0,153,1,0,0,0,0, + 155,1,0,0,0,0,157,1,0,0,0,0,159,1,0,0,0,0,161,1,0,0,0,0,163,1,0,0,0,0,165, + 1,0,0,0,0,167,1,0,0,0,0,169,1,0,0,0,1,171,1,0,0,0,3,178,1,0,0,0,5,180,1, + 0,0,0,7,191,1,0,0,0,9,193,1,0,0,0,11,195,1,0,0,0,13,198,1,0,0,0,15,200, + 1,0,0,0,17,202,1,0,0,0,19,205,1,0,0,0,21,207,1,0,0,0,23,214,1,0,0,0,25, + 223,1,0,0,0,27,232,1,0,0,0,29,240,1,0,0,0,31,242,1,0,0,0,33,244,1,0,0,0, + 35,246,1,0,0,0,37,255,1,0,0,0,39,257,1,0,0,0,41,259,1,0,0,0,43,266,1,0, + 0,0,45,269,1,0,0,0,47,272,1,0,0,0,49,275,1,0,0,0,51,278,1,0,0,0,53,286, + 1,0,0,0,55,298,1,0,0,0,57,301,1,0,0,0,59,306,1,0,0,0,61,309,1,0,0,0,63, + 315,1,0,0,0,65,319,1,0,0,0,67,323,1,0,0,0,69,325,1,0,0,0,71,327,1,0,0,0, + 73,338,1,0,0,0,75,345,1,0,0,0,77,362,1,0,0,0,79,377,1,0,0,0,81,392,1,0, + 0,0,83,405,1,0,0,0,85,415,1,0,0,0,87,440,1,0,0,0,89,455,1,0,0,0,91,474, + 1,0,0,0,93,490,1,0,0,0,95,501,1,0,0,0,97,509,1,0,0,0,99,516,1,0,0,0,101, + 523,1,0,0,0,103,525,1,0,0,0,105,527,1,0,0,0,107,529,1,0,0,0,109,531,1,0, + 0,0,111,533,1,0,0,0,113,535,1,0,0,0,115,538,1,0,0,0,117,541,1,0,0,0,119, + 544,1,0,0,0,121,547,1,0,0,0,123,549,1,0,0,0,125,551,1,0,0,0,127,554,1,0, + 0,0,129,557,1,0,0,0,131,565,1,0,0,0,133,590,1,0,0,0,135,649,1,0,0,0,137, + 652,1,0,0,0,139,659,1,0,0,0,141,674,1,0,0,0,143,706,1,0,0,0,145,708,1,0, + 0,0,147,725,1,0,0,0,149,727,1,0,0,0,151,754,1,0,0,0,153,756,1,0,0,0,155, + 765,1,0,0,0,157,788,1,0,0,0,159,838,1,0,0,0,161,934,1,0,0,0,163,936,1,0, + 0,0,165,944,1,0,0,0,167,950,1,0,0,0,169,964,1,0,0,0,171,172,5,112,0,0,172, + 173,5,114,0,0,173,174,5,97,0,0,174,175,5,103,0,0,175,176,5,109,0,0,176, + 177,5,97,0,0,177,2,1,0,0,0,178,179,5,59,0,0,179,4,1,0,0,0,180,181,5,99, + 0,0,181,182,5,97,0,0,182,183,5,115,0,0,183,184,5,104,0,0,184,185,5,115, + 0,0,185,186,5,99,0,0,186,187,5,114,0,0,187,188,5,105,0,0,188,189,5,112, + 0,0,189,190,5,116,0,0,190,6,1,0,0,0,191,192,5,94,0,0,192,8,1,0,0,0,193, + 194,5,126,0,0,194,10,1,0,0,0,195,196,5,62,0,0,196,197,5,61,0,0,197,12,1, + 0,0,0,198,199,5,62,0,0,199,14,1,0,0,0,200,201,5,60,0,0,201,16,1,0,0,0,202, + 203,5,60,0,0,203,204,5,61,0,0,204,18,1,0,0,0,205,206,5,61,0,0,206,20,1, + 0,0,0,207,208,5,105,0,0,208,209,5,109,0,0,209,210,5,112,0,0,210,211,5,111, + 0,0,211,212,5,114,0,0,212,213,5,116,0,0,213,22,1,0,0,0,214,215,5,99,0,0, + 215,216,5,111,0,0,216,217,5,110,0,0,217,218,5,115,0,0,218,219,5,116,0,0, + 219,220,5,97,0,0,220,221,5,110,0,0,221,222,5,116,0,0,222,24,1,0,0,0,223, + 224,5,102,0,0,224,225,5,117,0,0,225,226,5,110,0,0,226,227,5,99,0,0,227, + 228,5,116,0,0,228,229,5,105,0,0,229,230,5,111,0,0,230,231,5,110,0,0,231, + 26,1,0,0,0,232,233,5,114,0,0,233,234,5,101,0,0,234,235,5,116,0,0,235,236, + 5,117,0,0,236,237,5,114,0,0,237,238,5,110,0,0,238,239,5,115,0,0,239,28, + 1,0,0,0,240,241,5,40,0,0,241,30,1,0,0,0,242,243,5,44,0,0,243,32,1,0,0,0, + 244,245,5,41,0,0,245,34,1,0,0,0,246,247,5,99,0,0,247,248,5,111,0,0,248, + 249,5,110,0,0,249,250,5,116,0,0,250,251,5,114,0,0,251,252,5,97,0,0,252, + 253,5,99,0,0,253,254,5,116,0,0,254,36,1,0,0,0,255,256,5,123,0,0,256,38, + 1,0,0,0,257,258,5,125,0,0,258,40,1,0,0,0,259,260,5,114,0,0,260,261,5,101, + 0,0,261,262,5,116,0,0,262,263,5,117,0,0,263,264,5,114,0,0,264,265,5,110, + 0,0,265,42,1,0,0,0,266,267,5,43,0,0,267,268,5,61,0,0,268,44,1,0,0,0,269, + 270,5,45,0,0,270,271,5,61,0,0,271,46,1,0,0,0,272,273,5,43,0,0,273,274,5, + 43,0,0,274,48,1,0,0,0,275,276,5,45,0,0,276,277,5,45,0,0,277,50,1,0,0,0, + 278,279,5,114,0,0,279,280,5,101,0,0,280,281,5,113,0,0,281,282,5,117,0,0, + 282,283,5,105,0,0,283,284,5,114,0,0,284,285,5,101,0,0,285,52,1,0,0,0,286, + 287,5,99,0,0,287,288,5,111,0,0,288,289,5,110,0,0,289,290,5,115,0,0,290, + 291,5,111,0,0,291,292,5,108,0,0,292,293,5,101,0,0,293,294,5,46,0,0,294, + 295,5,108,0,0,295,296,5,111,0,0,296,297,5,103,0,0,297,54,1,0,0,0,298,299, + 5,105,0,0,299,300,5,102,0,0,300,56,1,0,0,0,301,302,5,101,0,0,302,303,5, + 108,0,0,303,304,5,115,0,0,304,305,5,101,0,0,305,58,1,0,0,0,306,307,5,100, + 0,0,307,308,5,111,0,0,308,60,1,0,0,0,309,310,5,119,0,0,310,311,5,104,0, + 0,311,312,5,105,0,0,312,313,5,108,0,0,313,314,5,101,0,0,314,62,1,0,0,0, + 315,316,5,102,0,0,316,317,5,111,0,0,317,318,5,114,0,0,318,64,1,0,0,0,319, + 320,5,110,0,0,320,321,5,101,0,0,321,322,5,119,0,0,322,66,1,0,0,0,323,324, + 5,91,0,0,324,68,1,0,0,0,325,326,5,93,0,0,326,70,1,0,0,0,327,328,5,116,0, + 0,328,329,5,120,0,0,329,330,5,46,0,0,330,331,5,111,0,0,331,332,5,117,0, + 0,332,333,5,116,0,0,333,334,5,112,0,0,334,335,5,117,0,0,335,336,5,116,0, + 0,336,337,5,115,0,0,337,72,1,0,0,0,338,339,5,46,0,0,339,340,5,118,0,0,340, + 341,5,97,0,0,341,342,5,108,0,0,342,343,5,117,0,0,343,344,5,101,0,0,344, + 74,1,0,0,0,345,346,5,46,0,0,346,347,5,108,0,0,347,348,5,111,0,0,348,349, + 5,99,0,0,349,350,5,107,0,0,350,351,5,105,0,0,351,352,5,110,0,0,352,353, + 5,103,0,0,353,354,5,66,0,0,354,355,5,121,0,0,355,356,5,116,0,0,356,357, + 5,101,0,0,357,358,5,99,0,0,358,359,5,111,0,0,359,360,5,100,0,0,360,361, + 5,101,0,0,361,76,1,0,0,0,362,363,5,46,0,0,363,364,5,116,0,0,364,365,5,111, + 0,0,365,366,5,107,0,0,366,367,5,101,0,0,367,368,5,110,0,0,368,369,5,67, + 0,0,369,370,5,97,0,0,370,371,5,116,0,0,371,372,5,101,0,0,372,373,5,103, + 0,0,373,374,5,111,0,0,374,375,5,114,0,0,375,376,5,121,0,0,376,78,1,0,0, + 0,377,378,5,46,0,0,378,379,5,110,0,0,379,380,5,102,0,0,380,381,5,116,0, + 0,381,382,5,67,0,0,382,383,5,111,0,0,383,384,5,109,0,0,384,385,5,109,0, + 0,385,386,5,105,0,0,386,387,5,116,0,0,387,388,5,109,0,0,388,389,5,101,0, + 0,389,390,5,110,0,0,390,391,5,116,0,0,391,80,1,0,0,0,392,393,5,46,0,0,393, + 394,5,116,0,0,394,395,5,111,0,0,395,396,5,107,0,0,396,397,5,101,0,0,397, + 398,5,110,0,0,398,399,5,65,0,0,399,400,5,109,0,0,400,401,5,111,0,0,401, + 402,5,117,0,0,402,403,5,110,0,0,403,404,5,116,0,0,404,82,1,0,0,0,405,406, + 5,116,0,0,406,407,5,120,0,0,407,408,5,46,0,0,408,409,5,105,0,0,409,410, + 5,110,0,0,410,411,5,112,0,0,411,412,5,117,0,0,412,413,5,116,0,0,413,414, + 5,115,0,0,414,84,1,0,0,0,415,416,5,46,0,0,416,417,5,111,0,0,417,418,5,117, + 0,0,418,419,5,116,0,0,419,420,5,112,0,0,420,421,5,111,0,0,421,422,5,105, + 0,0,422,423,5,110,0,0,423,424,5,116,0,0,424,425,5,84,0,0,425,426,5,114, + 0,0,426,427,5,97,0,0,427,428,5,110,0,0,428,429,5,115,0,0,429,430,5,97,0, + 0,430,431,5,99,0,0,431,432,5,116,0,0,432,433,5,105,0,0,433,434,5,111,0, + 0,434,435,5,110,0,0,435,436,5,72,0,0,436,437,5,97,0,0,437,438,5,115,0,0, + 438,439,5,104,0,0,439,86,1,0,0,0,440,441,5,46,0,0,441,442,5,111,0,0,442, + 443,5,117,0,0,443,444,5,116,0,0,444,445,5,112,0,0,445,446,5,111,0,0,446, + 447,5,105,0,0,447,448,5,110,0,0,448,449,5,116,0,0,449,450,5,73,0,0,450, + 451,5,110,0,0,451,452,5,100,0,0,452,453,5,101,0,0,453,454,5,120,0,0,454, + 88,1,0,0,0,455,456,5,46,0,0,456,457,5,117,0,0,457,458,5,110,0,0,458,459, + 5,108,0,0,459,460,5,111,0,0,460,461,5,99,0,0,461,462,5,107,0,0,462,463, + 5,105,0,0,463,464,5,110,0,0,464,465,5,103,0,0,465,466,5,66,0,0,466,467, + 5,121,0,0,467,468,5,116,0,0,468,469,5,101,0,0,469,470,5,99,0,0,470,471, + 5,111,0,0,471,472,5,100,0,0,472,473,5,101,0,0,473,90,1,0,0,0,474,475,5, + 46,0,0,475,476,5,115,0,0,476,477,5,101,0,0,477,478,5,113,0,0,478,479,5, + 117,0,0,479,480,5,101,0,0,480,481,5,110,0,0,481,482,5,99,0,0,482,483,5, + 101,0,0,483,484,5,78,0,0,484,485,5,117,0,0,485,486,5,109,0,0,486,487,5, + 98,0,0,487,488,5,101,0,0,488,489,5,114,0,0,489,92,1,0,0,0,490,491,5,46, + 0,0,491,492,5,114,0,0,492,493,5,101,0,0,493,494,5,118,0,0,494,495,5,101, + 0,0,495,496,5,114,0,0,496,497,5,115,0,0,497,498,5,101,0,0,498,499,5,40, + 0,0,499,500,5,41,0,0,500,94,1,0,0,0,501,502,5,46,0,0,502,503,5,108,0,0, + 503,504,5,101,0,0,504,505,5,110,0,0,505,506,5,103,0,0,506,507,5,116,0,0, + 507,508,5,104,0,0,508,96,1,0,0,0,509,510,5,46,0,0,510,511,5,115,0,0,511, + 512,5,112,0,0,512,513,5,108,0,0,513,514,5,105,0,0,514,515,5,116,0,0,515, + 98,1,0,0,0,516,517,5,46,0,0,517,518,5,115,0,0,518,519,5,108,0,0,519,520, + 5,105,0,0,520,521,5,99,0,0,521,522,5,101,0,0,522,100,1,0,0,0,523,524,5, + 33,0,0,524,102,1,0,0,0,525,526,5,45,0,0,526,104,1,0,0,0,527,528,5,42,0, + 0,528,106,1,0,0,0,529,530,5,47,0,0,530,108,1,0,0,0,531,532,5,37,0,0,532, + 110,1,0,0,0,533,534,5,43,0,0,534,112,1,0,0,0,535,536,5,62,0,0,536,537,5, + 62,0,0,537,114,1,0,0,0,538,539,5,60,0,0,539,540,5,60,0,0,540,116,1,0,0, + 0,541,542,5,61,0,0,542,543,5,61,0,0,543,118,1,0,0,0,544,545,5,33,0,0,545, + 546,5,61,0,0,546,120,1,0,0,0,547,548,5,38,0,0,548,122,1,0,0,0,549,550,5, + 124,0,0,550,124,1,0,0,0,551,552,5,38,0,0,552,553,5,38,0,0,553,126,1,0,0, + 0,554,555,5,124,0,0,555,556,5,124,0,0,556,128,1,0,0,0,557,558,5,117,0,0, + 558,559,5,110,0,0,559,560,5,117,0,0,560,561,5,115,0,0,561,562,5,101,0,0, + 562,563,5,100,0,0,563,130,1,0,0,0,564,566,7,0,0,0,565,564,1,0,0,0,566,567, + 1,0,0,0,567,565,1,0,0,0,567,568,1,0,0,0,568,569,1,0,0,0,569,571,5,46,0, + 0,570,572,7,0,0,0,571,570,1,0,0,0,572,573,1,0,0,0,573,571,1,0,0,0,573,574, + 1,0,0,0,574,575,1,0,0,0,575,577,5,46,0,0,576,578,7,0,0,0,577,576,1,0,0, + 0,578,579,1,0,0,0,579,577,1,0,0,0,579,580,1,0,0,0,580,132,1,0,0,0,581,582, + 5,116,0,0,582,583,5,114,0,0,583,584,5,117,0,0,584,591,5,101,0,0,585,586, + 5,102,0,0,586,587,5,97,0,0,587,588,5,108,0,0,588,589,5,115,0,0,589,591, + 5,101,0,0,590,581,1,0,0,0,590,585,1,0,0,0,591,134,1,0,0,0,592,593,5,115, + 0,0,593,594,5,97,0,0,594,595,5,116,0,0,595,596,5,111,0,0,596,597,5,115, + 0,0,597,598,5,104,0,0,598,599,5,105,0,0,599,650,5,115,0,0,600,601,5,115, + 0,0,601,602,5,97,0,0,602,603,5,116,0,0,603,650,5,115,0,0,604,605,5,102, + 0,0,605,606,5,105,0,0,606,607,5,110,0,0,607,608,5,110,0,0,608,609,5,101, + 0,0,609,650,5,121,0,0,610,611,5,98,0,0,611,612,5,105,0,0,612,613,5,116, + 0,0,613,650,5,115,0,0,614,615,5,98,0,0,615,616,5,105,0,0,616,617,5,116, + 0,0,617,618,5,99,0,0,618,619,5,111,0,0,619,620,5,105,0,0,620,650,5,110, + 0,0,621,622,5,115,0,0,622,623,5,101,0,0,623,624,5,99,0,0,624,625,5,111, + 0,0,625,626,5,110,0,0,626,627,5,100,0,0,627,650,5,115,0,0,628,629,5,109, + 0,0,629,630,5,105,0,0,630,631,5,110,0,0,631,632,5,117,0,0,632,633,5,116, + 0,0,633,634,5,101,0,0,634,650,5,115,0,0,635,636,5,104,0,0,636,637,5,111, + 0,0,637,638,5,117,0,0,638,639,5,114,0,0,639,650,5,115,0,0,640,641,5,100, + 0,0,641,642,5,97,0,0,642,643,5,121,0,0,643,650,5,115,0,0,644,645,5,119, + 0,0,645,646,5,101,0,0,646,647,5,101,0,0,647,648,5,107,0,0,648,650,5,115, + 0,0,649,592,1,0,0,0,649,600,1,0,0,0,649,604,1,0,0,0,649,610,1,0,0,0,649, + 614,1,0,0,0,649,621,1,0,0,0,649,628,1,0,0,0,649,635,1,0,0,0,649,640,1,0, + 0,0,649,644,1,0,0,0,650,136,1,0,0,0,651,653,5,45,0,0,652,651,1,0,0,0,652, + 653,1,0,0,0,653,654,1,0,0,0,654,656,3,139,69,0,655,657,3,141,70,0,656,655, + 1,0,0,0,656,657,1,0,0,0,657,138,1,0,0,0,658,660,7,0,0,0,659,658,1,0,0,0, + 660,661,1,0,0,0,661,659,1,0,0,0,661,662,1,0,0,0,662,671,1,0,0,0,663,665, + 5,95,0,0,664,666,7,0,0,0,665,664,1,0,0,0,666,667,1,0,0,0,667,665,1,0,0, + 0,667,668,1,0,0,0,668,670,1,0,0,0,669,663,1,0,0,0,670,673,1,0,0,0,671,669, + 1,0,0,0,671,672,1,0,0,0,672,140,1,0,0,0,673,671,1,0,0,0,674,675,7,1,0,0, + 675,676,3,139,69,0,676,142,1,0,0,0,677,678,5,105,0,0,678,679,5,110,0,0, + 679,707,5,116,0,0,680,681,5,98,0,0,681,682,5,111,0,0,682,683,5,111,0,0, + 683,707,5,108,0,0,684,685,5,115,0,0,685,686,5,116,0,0,686,687,5,114,0,0, + 687,688,5,105,0,0,688,689,5,110,0,0,689,707,5,103,0,0,690,691,5,112,0,0, + 691,692,5,117,0,0,692,693,5,98,0,0,693,694,5,107,0,0,694,695,5,101,0,0, + 695,707,5,121,0,0,696,697,5,115,0,0,697,698,5,105,0,0,698,707,5,103,0,0, + 699,700,5,100,0,0,700,701,5,97,0,0,701,702,5,116,0,0,702,703,5,97,0,0,703, + 704,5,115,0,0,704,705,5,105,0,0,705,707,5,103,0,0,706,677,1,0,0,0,706,680, + 1,0,0,0,706,684,1,0,0,0,706,690,1,0,0,0,706,696,1,0,0,0,706,699,1,0,0,0, + 707,144,1,0,0,0,708,709,5,98,0,0,709,710,5,121,0,0,710,711,5,116,0,0,711, + 712,5,101,0,0,712,713,5,115,0,0,713,146,1,0,0,0,714,715,5,98,0,0,715,716, + 5,121,0,0,716,717,5,116,0,0,717,718,5,101,0,0,718,719,5,115,0,0,719,720, + 1,0,0,0,720,726,3,149,74,0,721,722,5,98,0,0,722,723,5,121,0,0,723,724,5, + 116,0,0,724,726,5,101,0,0,725,714,1,0,0,0,725,721,1,0,0,0,726,148,1,0,0, + 0,727,731,7,2,0,0,728,730,7,0,0,0,729,728,1,0,0,0,730,733,1,0,0,0,731,729, + 1,0,0,0,731,732,1,0,0,0,732,150,1,0,0,0,733,731,1,0,0,0,734,740,5,34,0, + 0,735,736,5,92,0,0,736,739,5,34,0,0,737,739,8,3,0,0,738,735,1,0,0,0,738, + 737,1,0,0,0,739,742,1,0,0,0,740,741,1,0,0,0,740,738,1,0,0,0,741,743,1,0, + 0,0,742,740,1,0,0,0,743,755,5,34,0,0,744,750,5,39,0,0,745,746,5,92,0,0, + 746,749,5,39,0,0,747,749,8,4,0,0,748,745,1,0,0,0,748,747,1,0,0,0,749,752, + 1,0,0,0,750,751,1,0,0,0,750,748,1,0,0,0,751,753,1,0,0,0,752,750,1,0,0,0, + 753,755,5,39,0,0,754,734,1,0,0,0,754,744,1,0,0,0,755,152,1,0,0,0,756,757, + 5,100,0,0,757,758,5,97,0,0,758,759,5,116,0,0,759,760,5,101,0,0,760,761, + 5,40,0,0,761,762,1,0,0,0,762,763,3,151,75,0,763,764,5,41,0,0,764,154,1, + 0,0,0,765,766,5,48,0,0,766,770,7,5,0,0,767,769,7,6,0,0,768,767,1,0,0,0, + 769,772,1,0,0,0,770,768,1,0,0,0,770,771,1,0,0,0,771,156,1,0,0,0,772,770, + 1,0,0,0,773,774,5,116,0,0,774,775,5,104,0,0,775,776,5,105,0,0,776,777,5, + 115,0,0,777,778,5,46,0,0,778,779,5,97,0,0,779,780,5,103,0,0,780,789,5,101, + 0,0,781,782,5,116,0,0,782,783,5,120,0,0,783,784,5,46,0,0,784,785,5,116, + 0,0,785,786,5,105,0,0,786,787,5,109,0,0,787,789,5,101,0,0,788,773,1,0,0, + 0,788,781,1,0,0,0,789,158,1,0,0,0,790,791,5,117,0,0,791,792,5,110,0,0,792, + 793,5,115,0,0,793,794,5,97,0,0,794,795,5,102,0,0,795,796,5,101,0,0,796, + 797,5,95,0,0,797,798,5,105,0,0,798,799,5,110,0,0,799,839,5,116,0,0,800, + 801,5,117,0,0,801,802,5,110,0,0,802,803,5,115,0,0,803,804,5,97,0,0,804, + 805,5,102,0,0,805,806,5,101,0,0,806,807,5,95,0,0,807,808,5,98,0,0,808,809, + 5,111,0,0,809,810,5,111,0,0,810,839,5,108,0,0,811,812,5,117,0,0,812,813, + 5,110,0,0,813,814,5,115,0,0,814,815,5,97,0,0,815,816,5,102,0,0,816,817, + 5,101,0,0,817,818,5,95,0,0,818,819,5,98,0,0,819,820,5,121,0,0,820,821,5, + 116,0,0,821,822,5,101,0,0,822,823,5,115,0,0,823,825,1,0,0,0,824,826,3,149, + 74,0,825,824,1,0,0,0,825,826,1,0,0,0,826,839,1,0,0,0,827,828,5,117,0,0, + 828,829,5,110,0,0,829,830,5,115,0,0,830,831,5,97,0,0,831,832,5,102,0,0, + 832,833,5,101,0,0,833,834,5,95,0,0,834,835,5,98,0,0,835,836,5,121,0,0,836, + 837,5,116,0,0,837,839,5,101,0,0,838,790,1,0,0,0,838,800,1,0,0,0,838,811, + 1,0,0,0,838,827,1,0,0,0,839,160,1,0,0,0,840,841,5,116,0,0,841,842,5,104, + 0,0,842,843,5,105,0,0,843,844,5,115,0,0,844,845,5,46,0,0,845,846,5,97,0, + 0,846,847,5,99,0,0,847,848,5,116,0,0,848,849,5,105,0,0,849,850,5,118,0, + 0,850,851,5,101,0,0,851,852,5,73,0,0,852,853,5,110,0,0,853,854,5,112,0, + 0,854,855,5,117,0,0,855,856,5,116,0,0,856,857,5,73,0,0,857,858,5,110,0, + 0,858,859,5,100,0,0,859,860,5,101,0,0,860,935,5,120,0,0,861,862,5,116,0, + 0,862,863,5,104,0,0,863,864,5,105,0,0,864,865,5,115,0,0,865,866,5,46,0, + 0,866,867,5,97,0,0,867,868,5,99,0,0,868,869,5,116,0,0,869,870,5,105,0,0, + 870,871,5,118,0,0,871,872,5,101,0,0,872,873,5,66,0,0,873,874,5,121,0,0, + 874,875,5,116,0,0,875,876,5,101,0,0,876,877,5,99,0,0,877,878,5,111,0,0, + 878,879,5,100,0,0,879,935,5,101,0,0,880,881,5,116,0,0,881,882,5,120,0,0, + 882,883,5,46,0,0,883,884,5,105,0,0,884,885,5,110,0,0,885,886,5,112,0,0, + 886,887,5,117,0,0,887,888,5,116,0,0,888,889,5,115,0,0,889,890,5,46,0,0, + 890,891,5,108,0,0,891,892,5,101,0,0,892,893,5,110,0,0,893,894,5,103,0,0, + 894,895,5,116,0,0,895,935,5,104,0,0,896,897,5,116,0,0,897,898,5,120,0,0, + 898,899,5,46,0,0,899,900,5,111,0,0,900,901,5,117,0,0,901,902,5,116,0,0, + 902,903,5,112,0,0,903,904,5,117,0,0,904,905,5,116,0,0,905,906,5,115,0,0, + 906,907,5,46,0,0,907,908,5,108,0,0,908,909,5,101,0,0,909,910,5,110,0,0, + 910,911,5,103,0,0,911,912,5,116,0,0,912,935,5,104,0,0,913,914,5,116,0,0, + 914,915,5,120,0,0,915,916,5,46,0,0,916,917,5,118,0,0,917,918,5,101,0,0, + 918,919,5,114,0,0,919,920,5,115,0,0,920,921,5,105,0,0,921,922,5,111,0,0, + 922,935,5,110,0,0,923,924,5,116,0,0,924,925,5,120,0,0,925,926,5,46,0,0, + 926,927,5,108,0,0,927,928,5,111,0,0,928,929,5,99,0,0,929,930,5,107,0,0, + 930,931,5,116,0,0,931,932,5,105,0,0,932,933,5,109,0,0,933,935,5,101,0,0, + 934,840,1,0,0,0,934,861,1,0,0,0,934,880,1,0,0,0,934,896,1,0,0,0,934,913, + 1,0,0,0,934,923,1,0,0,0,935,162,1,0,0,0,936,940,7,7,0,0,937,939,7,8,0,0, + 938,937,1,0,0,0,939,942,1,0,0,0,940,938,1,0,0,0,940,941,1,0,0,0,941,164, + 1,0,0,0,942,940,1,0,0,0,943,945,7,9,0,0,944,943,1,0,0,0,945,946,1,0,0,0, + 946,944,1,0,0,0,946,947,1,0,0,0,947,948,1,0,0,0,948,949,6,82,0,0,949,166, + 1,0,0,0,950,951,5,47,0,0,951,952,5,42,0,0,952,956,1,0,0,0,953,955,9,0,0, + 0,954,953,1,0,0,0,955,958,1,0,0,0,956,957,1,0,0,0,956,954,1,0,0,0,957,959, + 1,0,0,0,958,956,1,0,0,0,959,960,5,42,0,0,960,961,5,47,0,0,961,962,1,0,0, + 0,962,963,6,83,1,0,963,168,1,0,0,0,964,965,5,47,0,0,965,966,5,47,0,0,966, + 970,1,0,0,0,967,969,8,10,0,0,968,967,1,0,0,0,969,972,1,0,0,0,970,968,1, + 0,0,0,970,971,1,0,0,0,971,973,1,0,0,0,972,970,1,0,0,0,973,974,6,84,1,0, + 974,170,1,0,0,0,28,0,567,573,579,590,649,652,656,661,667,671,706,725,731, + 738,740,748,750,754,770,788,825,838,934,940,946,956,970,2,6,0,0,0,1,0]; private static __ATN: ATN; public static get _ATN(): ATN { diff --git a/packages/cashc/src/grammar/CashScriptParser.ts b/packages/cashc/src/grammar/CashScriptParser.ts index 0833d80e..83ce3075 100644 --- a/packages/cashc/src/grammar/CashScriptParser.ts +++ b/packages/cashc/src/grammar/CashScriptParser.ts @@ -1,4 +1,4 @@ -// Generated from src/grammar/CashScript.g4 by ANTLR 4.13.1 +// Generated from CashScript.g4 by ANTLR 4.13.2 // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { @@ -82,27 +82,28 @@ export default class CashScriptParser extends Parser { public static readonly T__61 = 62; public static readonly T__62 = 63; public static readonly T__63 = 64; - public static readonly VersionLiteral = 65; - public static readonly BooleanLiteral = 66; - public static readonly NumberUnit = 67; - public static readonly NumberLiteral = 68; - public static readonly NumberPart = 69; - public static readonly ExponentPart = 70; - public static readonly PrimitiveType = 71; - public static readonly UnboundedBytes = 72; - public static readonly BoundedBytes = 73; - public static readonly Bound = 74; - public static readonly StringLiteral = 75; - public static readonly DateLiteral = 76; - public static readonly HexLiteral = 77; - public static readonly TxVar = 78; - public static readonly UnsafeCast = 79; - public static readonly NullaryOp = 80; - public static readonly Identifier = 81; - public static readonly WHITESPACE = 82; - public static readonly COMMENT = 83; - public static readonly LINE_COMMENT = 84; - public static readonly EOF = Token.EOF; + public static readonly T__64 = 65; + public static readonly VersionLiteral = 66; + public static readonly BooleanLiteral = 67; + public static readonly NumberUnit = 68; + public static readonly NumberLiteral = 69; + public static readonly NumberPart = 70; + public static readonly ExponentPart = 71; + public static readonly PrimitiveType = 72; + public static readonly UnboundedBytes = 73; + public static readonly BoundedBytes = 74; + public static readonly Bound = 75; + public static readonly StringLiteral = 76; + public static readonly DateLiteral = 77; + public static readonly HexLiteral = 78; + public static readonly TxVar = 79; + public static readonly UnsafeCast = 80; + public static readonly NullaryOp = 81; + public static readonly Identifier = 82; + public static readonly WHITESPACE = 83; + public static readonly COMMENT = 84; + public static readonly LINE_COMMENT = 85; + public static override readonly EOF = Token.EOF; public static readonly RULE_sourceFile = 0; public static readonly RULE_pragmaDirective = 1; public static readonly RULE_pragmaName = 2; @@ -111,53 +112,56 @@ export default class CashScriptParser extends Parser { public static readonly RULE_versionOperator = 5; public static readonly RULE_importDirective = 6; public static readonly RULE_topLevelDefinition = 7; - public static readonly RULE_globalFunctionDefinition = 8; - public static readonly RULE_contractDefinition = 9; - public static readonly RULE_contractFunctionDefinition = 10; - public static readonly RULE_functionBody = 11; - public static readonly RULE_parameterList = 12; - public static readonly RULE_parameter = 13; - public static readonly RULE_block = 14; - public static readonly RULE_statement = 15; - public static readonly RULE_nonControlStatement = 16; - public static readonly RULE_functionCallStatement = 17; - public static readonly RULE_returnStatement = 18; - public static readonly RULE_controlStatement = 19; - public static readonly RULE_variableDefinition = 20; - public static readonly RULE_tupleAssignment = 21; - public static readonly RULE_assignStatement = 22; - public static readonly RULE_timeOpStatement = 23; - public static readonly RULE_requireStatement = 24; - public static readonly RULE_consoleStatement = 25; - public static readonly RULE_ifStatement = 26; - public static readonly RULE_loopStatement = 27; - public static readonly RULE_doWhileStatement = 28; - public static readonly RULE_whileStatement = 29; - public static readonly RULE_forStatement = 30; - public static readonly RULE_forInit = 31; - public static readonly RULE_requireMessage = 32; - public static readonly RULE_consoleParameter = 33; - public static readonly RULE_consoleParameterList = 34; - public static readonly RULE_functionCall = 35; - public static readonly RULE_expressionList = 36; - public static readonly RULE_expression = 37; - public static readonly RULE_modifier = 38; - public static readonly RULE_literal = 39; - public static readonly RULE_numberLiteral = 40; - public static readonly RULE_typeName = 41; - public static readonly RULE_typeCast = 42; + public static readonly RULE_constantDefinition = 8; + public static readonly RULE_globalFunctionDefinition = 9; + public static readonly RULE_contractDefinition = 10; + public static readonly RULE_contractFunctionDefinition = 11; + public static readonly RULE_functionBody = 12; + public static readonly RULE_parameterList = 13; + public static readonly RULE_parameter = 14; + public static readonly RULE_block = 15; + public static readonly RULE_statement = 16; + public static readonly RULE_nonControlStatement = 17; + public static readonly RULE_functionCallStatement = 18; + public static readonly RULE_returnStatement = 19; + public static readonly RULE_controlStatement = 20; + public static readonly RULE_variableDefinition = 21; + public static readonly RULE_tupleAssignment = 22; + public static readonly RULE_tupleTarget = 23; + public static readonly RULE_assignStatement = 24; + public static readonly RULE_timeOpStatement = 25; + public static readonly RULE_requireStatement = 26; + public static readonly RULE_consoleStatement = 27; + public static readonly RULE_ifStatement = 28; + public static readonly RULE_loopStatement = 29; + public static readonly RULE_doWhileStatement = 30; + public static readonly RULE_whileStatement = 31; + public static readonly RULE_forStatement = 32; + public static readonly RULE_forInit = 33; + public static readonly RULE_requireMessage = 34; + public static readonly RULE_consoleParameter = 35; + public static readonly RULE_consoleParameterList = 36; + public static readonly RULE_functionCall = 37; + public static readonly RULE_expressionList = 38; + public static readonly RULE_expression = 39; + public static readonly RULE_modifier = 40; + public static readonly RULE_literal = 41; + public static readonly RULE_numberLiteral = 42; + public static readonly RULE_typeName = 43; + public static readonly RULE_typeCast = 44; public static readonly literalNames: (string | null)[] = [ null, "'pragma'", "';'", "'cashscript'", "'^'", "'~'", "'>='", "'>'", "'<'", "'<='", "'='", "'import'", + "'constant'", "'function'", "'returns'", - "'('", "')'", - "'contract'", + "'('", "','", + "')'", "'contract'", "'{'", "'}'", - "','", "'return'", + "'return'", "'+='", "'-='", "'++'", "'--'", "'require'", @@ -188,7 +192,7 @@ export default class CashScriptParser extends Parser { "'=='", "'!='", "'&'", "'|'", "'&&'", "'||'", - "'constant'", + "'unused'", null, null, null, null, null, null, @@ -225,7 +229,8 @@ export default class CashScriptParser extends Parser { null, null, null, null, null, null, - null, "VersionLiteral", + null, null, + "VersionLiteral", "BooleanLiteral", "NumberUnit", "NumberLiteral", @@ -246,15 +251,15 @@ export default class CashScriptParser extends Parser { // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ "sourceFile", "pragmaDirective", "pragmaName", "pragmaValue", "versionConstraint", - "versionOperator", "importDirective", "topLevelDefinition", "globalFunctionDefinition", - "contractDefinition", "contractFunctionDefinition", "functionBody", "parameterList", - "parameter", "block", "statement", "nonControlStatement", "functionCallStatement", - "returnStatement", "controlStatement", "variableDefinition", "tupleAssignment", - "assignStatement", "timeOpStatement", "requireStatement", "consoleStatement", - "ifStatement", "loopStatement", "doWhileStatement", "whileStatement", - "forStatement", "forInit", "requireMessage", "consoleParameter", "consoleParameterList", - "functionCall", "expressionList", "expression", "modifier", "literal", - "numberLiteral", "typeName", "typeCast", + "versionOperator", "importDirective", "topLevelDefinition", "constantDefinition", + "globalFunctionDefinition", "contractDefinition", "contractFunctionDefinition", + "functionBody", "parameterList", "parameter", "block", "statement", "nonControlStatement", + "functionCallStatement", "returnStatement", "controlStatement", "variableDefinition", + "tupleAssignment", "tupleTarget", "assignStatement", "timeOpStatement", + "requireStatement", "consoleStatement", "ifStatement", "loopStatement", + "doWhileStatement", "whileStatement", "forStatement", "forInit", "requireMessage", + "consoleParameter", "consoleParameterList", "functionCall", "expressionList", + "expression", "modifier", "literal", "numberLiteral", "typeName", "typeCast", ]; public get grammarFileName(): string { return "CashScript.g4"; } public get literalNames(): (string | null)[] { return CashScriptParser.literalNames; } @@ -278,49 +283,49 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 89; + this.state = 93; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===1) { { { - this.state = 86; + this.state = 90; this.pragmaDirective(); } } - this.state = 91; + this.state = 95; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 95; + this.state = 99; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===11) { { { - this.state = 92; + this.state = 96; this.importDirective(); } } - this.state = 97; + this.state = 101; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 101; + this.state = 105; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===12 || _la===16) { + while (_la===13 || _la===18 || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 7) !== 0)) { { { - this.state = 98; + this.state = 102; this.topLevelDefinition(); } } - this.state = 103; + this.state = 107; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 104; + this.state = 108; this.match(CashScriptParser.EOF); } } @@ -345,13 +350,13 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 106; + this.state = 110; this.match(CashScriptParser.T__0); - this.state = 107; + this.state = 111; this.pragmaName(); - this.state = 108; + this.state = 112; this.pragmaValue(); - this.state = 109; + this.state = 113; this.match(CashScriptParser.T__1); } } @@ -376,7 +381,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 111; + this.state = 115; this.match(CashScriptParser.T__2); } } @@ -402,14 +407,14 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 113; + this.state = 117; this.versionConstraint(); - this.state = 115; + this.state = 119; this._errHandler.sync(this); _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0) || _la===65) { + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0) || _la===66) { { - this.state = 114; + this.state = 118; this.versionConstraint(); } } @@ -438,17 +443,17 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 118; + this.state = 122; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0)) { { - this.state = 117; + this.state = 121; this.versionOperator(); } } - this.state = 120; + this.state = 124; this.match(CashScriptParser.VersionLiteral); } } @@ -474,7 +479,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 122; + this.state = 126; _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0))) { this._errHandler.recoverInline(this); @@ -506,11 +511,11 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 124; + this.state = 128; this.match(CashScriptParser.T__10); - this.state = 125; + this.state = 129; this.match(CashScriptParser.StringLiteral); - this.state = 126; + this.state = 130; this.match(CashScriptParser.T__1); } } @@ -533,20 +538,29 @@ export default class CashScriptParser extends Parser { let localctx: TopLevelDefinitionContext = new TopLevelDefinitionContext(this, this._ctx, this.state); this.enterRule(localctx, 14, CashScriptParser.RULE_topLevelDefinition); try { - this.state = 130; + this.state = 135; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 12: + case 13: this.enterOuterAlt(localctx, 1); { - this.state = 128; + this.state = 132; this.globalFunctionDefinition(); } break; - case 16: + case 72: + case 73: + case 74: this.enterOuterAlt(localctx, 2); { - this.state = 129; + this.state = 133; + this.constantDefinition(); + } + break; + case 18: + this.enterOuterAlt(localctx, 3); + { + this.state = 134; this.contractDefinition(); } break; @@ -569,36 +583,87 @@ export default class CashScriptParser extends Parser { return localctx; } // @RuleVersion(0) + public constantDefinition(): ConstantDefinitionContext { + let localctx: ConstantDefinitionContext = new ConstantDefinitionContext(this, this._ctx, this.state); + this.enterRule(localctx, 16, CashScriptParser.RULE_constantDefinition); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 137; + this.typeName(); + this.state = 138; + this.match(CashScriptParser.T__11); + this.state = 139; + this.match(CashScriptParser.Identifier); + this.state = 140; + this.match(CashScriptParser.T__9); + this.state = 141; + this.expression(0); + this.state = 142; + this.match(CashScriptParser.T__1); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) public globalFunctionDefinition(): GlobalFunctionDefinitionContext { let localctx: GlobalFunctionDefinitionContext = new GlobalFunctionDefinitionContext(this, this._ctx, this.state); - this.enterRule(localctx, 16, CashScriptParser.RULE_globalFunctionDefinition); + this.enterRule(localctx, 18, CashScriptParser.RULE_globalFunctionDefinition); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 132; - this.match(CashScriptParser.T__11); - this.state = 133; + this.state = 144; + this.match(CashScriptParser.T__12); + this.state = 145; this.match(CashScriptParser.Identifier); - this.state = 134; + this.state = 146; this.parameterList(); - this.state = 140; + this.state = 159; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===13) { + if (_la===14) { { - this.state = 135; - this.match(CashScriptParser.T__12); - this.state = 136; + this.state = 147; this.match(CashScriptParser.T__13); - this.state = 137; - this.typeName(); - this.state = 138; + this.state = 148; this.match(CashScriptParser.T__14); + this.state = 149; + this.typeName(); + this.state = 154; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===16) { + { + { + this.state = 150; + this.match(CashScriptParser.T__15); + this.state = 151; + this.typeName(); + } + } + this.state = 156; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 157; + this.match(CashScriptParser.T__16); } } - this.state = 142; + this.state = 161; this.functionBody(); } } @@ -619,35 +684,35 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public contractDefinition(): ContractDefinitionContext { let localctx: ContractDefinitionContext = new ContractDefinitionContext(this, this._ctx, this.state); - this.enterRule(localctx, 18, CashScriptParser.RULE_contractDefinition); + this.enterRule(localctx, 20, CashScriptParser.RULE_contractDefinition); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 144; - this.match(CashScriptParser.T__15); - this.state = 145; + this.state = 163; + this.match(CashScriptParser.T__17); + this.state = 164; this.match(CashScriptParser.Identifier); - this.state = 146; + this.state = 165; this.parameterList(); - this.state = 147; - this.match(CashScriptParser.T__16); - this.state = 151; + this.state = 166; + this.match(CashScriptParser.T__18); + this.state = 170; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===12) { + while (_la===13) { { { - this.state = 148; + this.state = 167; this.contractFunctionDefinition(); } } - this.state = 153; + this.state = 172; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 154; - this.match(CashScriptParser.T__17); + this.state = 173; + this.match(CashScriptParser.T__19); } } catch (re) { @@ -667,17 +732,17 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public contractFunctionDefinition(): ContractFunctionDefinitionContext { let localctx: ContractFunctionDefinitionContext = new ContractFunctionDefinitionContext(this, this._ctx, this.state); - this.enterRule(localctx, 20, CashScriptParser.RULE_contractFunctionDefinition); + this.enterRule(localctx, 22, CashScriptParser.RULE_contractFunctionDefinition); try { this.enterOuterAlt(localctx, 1); { - this.state = 156; - this.match(CashScriptParser.T__11); - this.state = 157; + this.state = 175; + this.match(CashScriptParser.T__12); + this.state = 176; this.match(CashScriptParser.Identifier); - this.state = 158; + this.state = 177; this.parameterList(); - this.state = 159; + this.state = 178; this.functionBody(); } } @@ -698,29 +763,29 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public functionBody(): FunctionBodyContext { let localctx: FunctionBodyContext = new FunctionBodyContext(this, this._ctx, this.state); - this.enterRule(localctx, 22, CashScriptParser.RULE_functionBody); + this.enterRule(localctx, 24, CashScriptParser.RULE_functionBody); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 161; - this.match(CashScriptParser.T__16); - this.state = 165; + this.state = 180; + this.match(CashScriptParser.T__18); + this.state = 184; this._errHandler.sync(this); _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 3994025984) !== 0) || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 1031) !== 0)) { + while (((((_la - 15)) & ~0x1F) === 0 && ((1 << (_la - 15)) & 243777) !== 0) || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 1031) !== 0)) { { { - this.state = 162; + this.state = 181; this.statement(); } } - this.state = 167; + this.state = 186; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 168; - this.match(CashScriptParser.T__17); + this.state = 187; + this.match(CashScriptParser.T__19); } } catch (re) { @@ -740,54 +805,54 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public parameterList(): ParameterListContext { let localctx: ParameterListContext = new ParameterListContext(this, this._ctx, this.state); - this.enterRule(localctx, 24, CashScriptParser.RULE_parameterList); + this.enterRule(localctx, 26, CashScriptParser.RULE_parameterList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 170; - this.match(CashScriptParser.T__13); - this.state = 182; + this.state = 189; + this.match(CashScriptParser.T__14); + this.state = 201; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0)) { + if (((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 7) !== 0)) { { - this.state = 171; + this.state = 190; this.parameter(); - this.state = 176; + this.state = 195; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 9, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 10, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 172; - this.match(CashScriptParser.T__18); - this.state = 173; + this.state = 191; + this.match(CashScriptParser.T__15); + this.state = 192; this.parameter(); } } } - this.state = 178; + this.state = 197; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 9, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 10, this._ctx); } - this.state = 180; + this.state = 199; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===16) { { - this.state = 179; - this.match(CashScriptParser.T__18); + this.state = 198; + this.match(CashScriptParser.T__15); } } } } - this.state = 184; - this.match(CashScriptParser.T__14); + this.state = 203; + this.match(CashScriptParser.T__16); } } catch (re) { @@ -807,13 +872,28 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public parameter(): ParameterContext { let localctx: ParameterContext = new ParameterContext(this, this._ctx, this.state); - this.enterRule(localctx, 26, CashScriptParser.RULE_parameter); + this.enterRule(localctx, 28, CashScriptParser.RULE_parameter); + let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 186; + this.state = 205; this.typeName(); - this.state = 187; + this.state = 209; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===12 || _la===65) { + { + { + this.state = 206; + this.modifier(); + } + } + this.state = 211; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 212; this.match(CashScriptParser.Identifier); } } @@ -834,49 +914,50 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public block(): BlockContext { let localctx: BlockContext = new BlockContext(this, this._ctx, this.state); - this.enterRule(localctx, 28, CashScriptParser.RULE_block); + this.enterRule(localctx, 30, CashScriptParser.RULE_block); let _la: number; try { - this.state = 198; + this.state = 223; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 17: + case 19: this.enterOuterAlt(localctx, 1); { - this.state = 189; - this.match(CashScriptParser.T__16); - this.state = 193; + this.state = 214; + this.match(CashScriptParser.T__18); + this.state = 218; this._errHandler.sync(this); _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 3994025984) !== 0) || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 1031) !== 0)) { + while (((((_la - 15)) & ~0x1F) === 0 && ((1 << (_la - 15)) & 243777) !== 0) || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 1031) !== 0)) { { { - this.state = 190; + this.state = 215; this.statement(); } } - this.state = 195; + this.state = 220; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 196; - this.match(CashScriptParser.T__17); + this.state = 221; + this.match(CashScriptParser.T__19); } break; - case 20: - case 25: + case 15: + case 21: case 26: case 27: - case 29: + case 28: case 30: case 31: - case 71: + case 32: case 72: case 73: - case 81: + case 74: + case 82: this.enterOuterAlt(localctx, 2); { - this.state = 197; + this.state = 222; this.statement(); } break; @@ -901,33 +982,34 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public statement(): StatementContext { let localctx: StatementContext = new StatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 30, CashScriptParser.RULE_statement); + this.enterRule(localctx, 32, CashScriptParser.RULE_statement); try { - this.state = 204; + this.state = 229; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 27: - case 29: + case 28: case 30: case 31: + case 32: this.enterOuterAlt(localctx, 1); { - this.state = 200; + this.state = 225; this.controlStatement(); } break; - case 20: - case 25: + case 15: + case 21: case 26: - case 71: + case 27: case 72: case 73: - case 81: + case 74: + case 82: this.enterOuterAlt(localctx, 2); { - this.state = 201; + this.state = 226; this.nonControlStatement(); - this.state = 202; + this.state = 227; this.match(CashScriptParser.T__1); } break; @@ -952,64 +1034,64 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public nonControlStatement(): NonControlStatementContext { let localctx: NonControlStatementContext = new NonControlStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 32, CashScriptParser.RULE_nonControlStatement); + this.enterRule(localctx, 34, CashScriptParser.RULE_nonControlStatement); try { - this.state = 214; + this.state = 239; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 15, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 17, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 206; + this.state = 231; this.variableDefinition(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 207; + this.state = 232; this.tupleAssignment(); } break; case 3: this.enterOuterAlt(localctx, 3); { - this.state = 208; + this.state = 233; this.assignStatement(); } break; case 4: this.enterOuterAlt(localctx, 4); { - this.state = 209; + this.state = 234; this.timeOpStatement(); } break; case 5: this.enterOuterAlt(localctx, 5); { - this.state = 210; + this.state = 235; this.requireStatement(); } break; case 6: this.enterOuterAlt(localctx, 6); { - this.state = 211; + this.state = 236; this.functionCallStatement(); } break; case 7: this.enterOuterAlt(localctx, 7); { - this.state = 212; + this.state = 237; this.consoleStatement(); } break; case 8: this.enterOuterAlt(localctx, 8); { - this.state = 213; + this.state = 238; this.returnStatement(); } break; @@ -1032,11 +1114,11 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public functionCallStatement(): FunctionCallStatementContext { let localctx: FunctionCallStatementContext = new FunctionCallStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 34, CashScriptParser.RULE_functionCallStatement); + this.enterRule(localctx, 36, CashScriptParser.RULE_functionCallStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 216; + this.state = 241; this.functionCall(); } } @@ -1057,14 +1139,31 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public returnStatement(): ReturnStatementContext { let localctx: ReturnStatementContext = new ReturnStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 36, CashScriptParser.RULE_returnStatement); + this.enterRule(localctx, 38, CashScriptParser.RULE_returnStatement); + let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 218; - this.match(CashScriptParser.T__19); - this.state = 219; + this.state = 243; + this.match(CashScriptParser.T__20); + this.state = 244; this.expression(0); + this.state = 249; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===16) { + { + { + this.state = 245; + this.match(CashScriptParser.T__15); + this.state = 246; + this.expression(0); + } + } + this.state = 251; + this._errHandler.sync(this); + _la = this._input.LA(1); + } } } catch (re) { @@ -1084,24 +1183,24 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public controlStatement(): ControlStatementContext { let localctx: ControlStatementContext = new ControlStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 38, CashScriptParser.RULE_controlStatement); + this.enterRule(localctx, 40, CashScriptParser.RULE_controlStatement); try { - this.state = 223; + this.state = 254; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 27: + case 28: this.enterOuterAlt(localctx, 1); { - this.state = 221; + this.state = 252; this.ifStatement(); } break; - case 29: case 30: case 31: + case 32: this.enterOuterAlt(localctx, 2); { - this.state = 222; + this.state = 253; this.loopStatement(); } break; @@ -1126,32 +1225,32 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public variableDefinition(): VariableDefinitionContext { let localctx: VariableDefinitionContext = new VariableDefinitionContext(this, this._ctx, this.state); - this.enterRule(localctx, 40, CashScriptParser.RULE_variableDefinition); + this.enterRule(localctx, 42, CashScriptParser.RULE_variableDefinition); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 225; + this.state = 256; this.typeName(); - this.state = 229; + this.state = 260; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===64) { + while (_la===12 || _la===65) { { { - this.state = 226; + this.state = 257; this.modifier(); } } - this.state = 231; + this.state = 262; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 232; + this.state = 263; this.match(CashScriptParser.Identifier); - this.state = 233; + this.state = 264; this.match(CashScriptParser.T__9); - this.state = 234; + this.state = 265; this.expression(0); } } @@ -1172,24 +1271,119 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public tupleAssignment(): TupleAssignmentContext { let localctx: TupleAssignmentContext = new TupleAssignmentContext(this, this._ctx, this.state); - this.enterRule(localctx, 42, CashScriptParser.RULE_tupleAssignment); + this.enterRule(localctx, 44, CashScriptParser.RULE_tupleAssignment); + let _la: number; try { - this.enterOuterAlt(localctx, 1); - { - this.state = 236; - this.typeName(); - this.state = 237; - this.match(CashScriptParser.Identifier); - this.state = 238; - this.match(CashScriptParser.T__18); - this.state = 239; - this.typeName(); - this.state = 240; - this.match(CashScriptParser.Identifier); - this.state = 241; - this.match(CashScriptParser.T__9); - this.state = 242; - this.expression(0); + this.state = 289; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 72: + case 73: + case 74: + case 82: + this.enterOuterAlt(localctx, 1); + { + this.state = 267; + this.tupleTarget(); + this.state = 270; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 268; + this.match(CashScriptParser.T__15); + this.state = 269; + this.tupleTarget(); + } + } + this.state = 272; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la===16); + this.state = 274; + this.match(CashScriptParser.T__9); + this.state = 275; + this.expression(0); + } + break; + case 15: + this.enterOuterAlt(localctx, 2); + { + this.state = 277; + this.match(CashScriptParser.T__14); + this.state = 278; + this.tupleTarget(); + this.state = 281; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 279; + this.match(CashScriptParser.T__15); + this.state = 280; + this.tupleTarget(); + } + } + this.state = 283; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la===16); + this.state = 285; + this.match(CashScriptParser.T__16); + this.state = 286; + this.match(CashScriptParser.T__9); + this.state = 287; + this.expression(0); + } + break; + default: + throw new NoViableAltException(this); + } + } + catch (re) { + if (re instanceof RecognitionException) { + localctx.exception = re; + this._errHandler.reportError(this, re); + this._errHandler.recover(this, re); + } else { + throw re; + } + } + finally { + this.exitRule(); + } + return localctx; + } + // @RuleVersion(0) + public tupleTarget(): TupleTargetContext { + let localctx: TupleTargetContext = new TupleTargetContext(this, this._ctx, this.state); + this.enterRule(localctx, 46, CashScriptParser.RULE_tupleTarget); + try { + this.state = 295; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 72: + case 73: + case 74: + this.enterOuterAlt(localctx, 1); + { + this.state = 291; + this.typeName(); + this.state = 292; + this.match(CashScriptParser.Identifier); + } + break; + case 82: + this.enterOuterAlt(localctx, 2); + { + this.state = 294; + this.match(CashScriptParser.Identifier); + } + break; + default: + throw new NoViableAltException(this); } } catch (re) { @@ -1209,40 +1403,40 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public assignStatement(): AssignStatementContext { let localctx: AssignStatementContext = new AssignStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 44, CashScriptParser.RULE_assignStatement); + this.enterRule(localctx, 48, CashScriptParser.RULE_assignStatement); let _la: number; try { - this.state = 249; + this.state = 302; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 18, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 25, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 244; + this.state = 297; this.match(CashScriptParser.Identifier); - this.state = 245; + this.state = 298; localctx._op = this._input.LT(1); _la = this._input.LA(1); - if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 6292480) !== 0))) { + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 12583936) !== 0))) { localctx._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 246; + this.state = 299; this.expression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 247; + this.state = 300; this.match(CashScriptParser.Identifier); - this.state = 248; + this.state = 301; localctx._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===23 || _la===24)) { + if(!(_la===24 || _la===25)) { localctx._op = this._errHandler.recoverInline(this); } else { @@ -1270,35 +1464,35 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public timeOpStatement(): TimeOpStatementContext { let localctx: TimeOpStatementContext = new TimeOpStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 46, CashScriptParser.RULE_timeOpStatement); + this.enterRule(localctx, 50, CashScriptParser.RULE_timeOpStatement); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 251; - this.match(CashScriptParser.T__24); - this.state = 252; - this.match(CashScriptParser.T__13); - this.state = 253; + this.state = 304; + this.match(CashScriptParser.T__25); + this.state = 305; + this.match(CashScriptParser.T__14); + this.state = 306; this.match(CashScriptParser.TxVar); - this.state = 254; + this.state = 307; this.match(CashScriptParser.T__5); - this.state = 255; + this.state = 308; this.expression(0); - this.state = 258; + this.state = 311; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===16) { { - this.state = 256; - this.match(CashScriptParser.T__18); - this.state = 257; + this.state = 309; + this.match(CashScriptParser.T__15); + this.state = 310; this.requireMessage(); } } - this.state = 260; - this.match(CashScriptParser.T__14); + this.state = 313; + this.match(CashScriptParser.T__16); } } catch (re) { @@ -1318,31 +1512,31 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public requireStatement(): RequireStatementContext { let localctx: RequireStatementContext = new RequireStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 48, CashScriptParser.RULE_requireStatement); + this.enterRule(localctx, 52, CashScriptParser.RULE_requireStatement); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 262; - this.match(CashScriptParser.T__24); - this.state = 263; - this.match(CashScriptParser.T__13); - this.state = 264; + this.state = 315; + this.match(CashScriptParser.T__25); + this.state = 316; + this.match(CashScriptParser.T__14); + this.state = 317; this.expression(0); - this.state = 267; + this.state = 320; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===16) { { - this.state = 265; - this.match(CashScriptParser.T__18); - this.state = 266; + this.state = 318; + this.match(CashScriptParser.T__15); + this.state = 319; this.requireMessage(); } } - this.state = 269; - this.match(CashScriptParser.T__14); + this.state = 322; + this.match(CashScriptParser.T__16); } } catch (re) { @@ -1362,13 +1556,13 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public consoleStatement(): ConsoleStatementContext { let localctx: ConsoleStatementContext = new ConsoleStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 50, CashScriptParser.RULE_consoleStatement); + this.enterRule(localctx, 54, CashScriptParser.RULE_consoleStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 271; - this.match(CashScriptParser.T__25); - this.state = 272; + this.state = 324; + this.match(CashScriptParser.T__26); + this.state = 325; this.consoleParameterList(); } } @@ -1389,28 +1583,28 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public ifStatement(): IfStatementContext { let localctx: IfStatementContext = new IfStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 52, CashScriptParser.RULE_ifStatement); + this.enterRule(localctx, 56, CashScriptParser.RULE_ifStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 274; - this.match(CashScriptParser.T__26); - this.state = 275; - this.match(CashScriptParser.T__13); - this.state = 276; - this.expression(0); - this.state = 277; + this.state = 327; + this.match(CashScriptParser.T__27); + this.state = 328; this.match(CashScriptParser.T__14); - this.state = 278; + this.state = 329; + this.expression(0); + this.state = 330; + this.match(CashScriptParser.T__16); + this.state = 331; localctx._ifBlock = this.block(); - this.state = 281; + this.state = 334; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 21, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 28, this._ctx) ) { case 1: { - this.state = 279; - this.match(CashScriptParser.T__27); - this.state = 280; + this.state = 332; + this.match(CashScriptParser.T__28); + this.state = 333; localctx._elseBlock = this.block(); } break; @@ -1434,29 +1628,29 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public loopStatement(): LoopStatementContext { let localctx: LoopStatementContext = new LoopStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 54, CashScriptParser.RULE_loopStatement); + this.enterRule(localctx, 58, CashScriptParser.RULE_loopStatement); try { - this.state = 286; + this.state = 339; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 29: + case 30: this.enterOuterAlt(localctx, 1); { - this.state = 283; + this.state = 336; this.doWhileStatement(); } break; - case 30: + case 31: this.enterOuterAlt(localctx, 2); { - this.state = 284; + this.state = 337; this.whileStatement(); } break; - case 31: + case 32: this.enterOuterAlt(localctx, 3); { - this.state = 285; + this.state = 338; this.forStatement(); } break; @@ -1481,23 +1675,23 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public doWhileStatement(): DoWhileStatementContext { let localctx: DoWhileStatementContext = new DoWhileStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 56, CashScriptParser.RULE_doWhileStatement); + this.enterRule(localctx, 60, CashScriptParser.RULE_doWhileStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 288; - this.match(CashScriptParser.T__28); - this.state = 289; - this.block(); - this.state = 290; + this.state = 341; this.match(CashScriptParser.T__29); - this.state = 291; - this.match(CashScriptParser.T__13); - this.state = 292; - this.expression(0); - this.state = 293; + this.state = 342; + this.block(); + this.state = 343; + this.match(CashScriptParser.T__30); + this.state = 344; this.match(CashScriptParser.T__14); - this.state = 294; + this.state = 345; + this.expression(0); + this.state = 346; + this.match(CashScriptParser.T__16); + this.state = 347; this.match(CashScriptParser.T__1); } } @@ -1518,19 +1712,19 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public whileStatement(): WhileStatementContext { let localctx: WhileStatementContext = new WhileStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 58, CashScriptParser.RULE_whileStatement); + this.enterRule(localctx, 62, CashScriptParser.RULE_whileStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 296; - this.match(CashScriptParser.T__29); - this.state = 297; - this.match(CashScriptParser.T__13); - this.state = 298; - this.expression(0); - this.state = 299; + this.state = 349; + this.match(CashScriptParser.T__30); + this.state = 350; this.match(CashScriptParser.T__14); - this.state = 300; + this.state = 351; + this.expression(0); + this.state = 352; + this.match(CashScriptParser.T__16); + this.state = 353; this.block(); } } @@ -1551,27 +1745,27 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public forStatement(): ForStatementContext { let localctx: ForStatementContext = new ForStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 60, CashScriptParser.RULE_forStatement); + this.enterRule(localctx, 64, CashScriptParser.RULE_forStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 302; - this.match(CashScriptParser.T__30); - this.state = 303; - this.match(CashScriptParser.T__13); - this.state = 304; + this.state = 355; + this.match(CashScriptParser.T__31); + this.state = 356; + this.match(CashScriptParser.T__14); + this.state = 357; this.forInit(); - this.state = 305; + this.state = 358; this.match(CashScriptParser.T__1); - this.state = 306; + this.state = 359; this.expression(0); - this.state = 307; + this.state = 360; this.match(CashScriptParser.T__1); - this.state = 308; + this.state = 361; this.assignStatement(); - this.state = 309; - this.match(CashScriptParser.T__14); - this.state = 310; + this.state = 362; + this.match(CashScriptParser.T__16); + this.state = 363; this.block(); } } @@ -1592,24 +1786,24 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public forInit(): ForInitContext { let localctx: ForInitContext = new ForInitContext(this, this._ctx, this.state); - this.enterRule(localctx, 62, CashScriptParser.RULE_forInit); + this.enterRule(localctx, 66, CashScriptParser.RULE_forInit); try { - this.state = 314; + this.state = 367; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 71: case 72: case 73: + case 74: this.enterOuterAlt(localctx, 1); { - this.state = 312; + this.state = 365; this.variableDefinition(); } break; - case 81: + case 82: this.enterOuterAlt(localctx, 2); { - this.state = 313; + this.state = 366; this.assignStatement(); } break; @@ -1634,11 +1828,11 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public requireMessage(): RequireMessageContext { let localctx: RequireMessageContext = new RequireMessageContext(this, this._ctx, this.state); - this.enterRule(localctx, 64, CashScriptParser.RULE_requireMessage); + this.enterRule(localctx, 68, CashScriptParser.RULE_requireMessage); try { this.enterOuterAlt(localctx, 1); { - this.state = 316; + this.state = 369; this.match(CashScriptParser.StringLiteral); } } @@ -1659,26 +1853,26 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public consoleParameter(): ConsoleParameterContext { let localctx: ConsoleParameterContext = new ConsoleParameterContext(this, this._ctx, this.state); - this.enterRule(localctx, 66, CashScriptParser.RULE_consoleParameter); + this.enterRule(localctx, 70, CashScriptParser.RULE_consoleParameter); try { - this.state = 320; + this.state = 373; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 81: + case 82: this.enterOuterAlt(localctx, 1); { - this.state = 318; + this.state = 371; this.match(CashScriptParser.Identifier); } break; - case 66: - case 68: - case 75: + case 67: + case 69: case 76: case 77: + case 78: this.enterOuterAlt(localctx, 2); { - this.state = 319; + this.state = 372; this.literal(); } break; @@ -1703,54 +1897,54 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public consoleParameterList(): ConsoleParameterListContext { let localctx: ConsoleParameterListContext = new ConsoleParameterListContext(this, this._ctx, this.state); - this.enterRule(localctx, 68, CashScriptParser.RULE_consoleParameterList); + this.enterRule(localctx, 72, CashScriptParser.RULE_consoleParameterList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 322; - this.match(CashScriptParser.T__13); - this.state = 334; + this.state = 375; + this.match(CashScriptParser.T__14); + this.state = 387; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 36357) !== 0)) { + if (((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 36357) !== 0)) { { - this.state = 323; + this.state = 376; this.consoleParameter(); - this.state = 328; + this.state = 381; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 324; - this.match(CashScriptParser.T__18); - this.state = 325; + this.state = 377; + this.match(CashScriptParser.T__15); + this.state = 378; this.consoleParameter(); } } } - this.state = 330; + this.state = 383; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); } - this.state = 332; + this.state = 385; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===16) { { - this.state = 331; - this.match(CashScriptParser.T__18); + this.state = 384; + this.match(CashScriptParser.T__15); } } } } - this.state = 336; - this.match(CashScriptParser.T__14); + this.state = 389; + this.match(CashScriptParser.T__16); } } catch (re) { @@ -1770,13 +1964,13 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public functionCall(): FunctionCallContext { let localctx: FunctionCallContext = new FunctionCallContext(this, this._ctx, this.state); - this.enterRule(localctx, 70, CashScriptParser.RULE_functionCall); + this.enterRule(localctx, 74, CashScriptParser.RULE_functionCall); try { this.enterOuterAlt(localctx, 1); { - this.state = 338; + this.state = 391; this.match(CashScriptParser.Identifier); - this.state = 339; + this.state = 392; this.expressionList(); } } @@ -1797,54 +1991,54 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public expressionList(): ExpressionListContext { let localctx: ExpressionListContext = new ExpressionListContext(this, this._ctx, this.state); - this.enterRule(localctx, 72, CashScriptParser.RULE_expressionList); + this.enterRule(localctx, 76, CashScriptParser.RULE_expressionList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 341; - this.match(CashScriptParser.T__13); - this.state = 353; + this.state = 394; + this.match(CashScriptParser.T__14); + this.state = 406; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===5 || _la===14 || ((((_la - 32)) & ~0x1F) === 0 && ((1 << (_la - 32)) & 786955) !== 0) || ((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 61029) !== 0)) { + if (_la===5 || _la===15 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 61029) !== 0)) { { - this.state = 342; + this.state = 395; this.expression(0); - this.state = 347; + this.state = 400; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 343; - this.match(CashScriptParser.T__18); - this.state = 344; + this.state = 396; + this.match(CashScriptParser.T__15); + this.state = 397; this.expression(0); } } } - this.state = 349; + this.state = 402; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); } - this.state = 351; + this.state = 404; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===16) { { - this.state = 350; - this.match(CashScriptParser.T__18); + this.state = 403; + this.match(CashScriptParser.T__15); } } } } - this.state = 355; - this.match(CashScriptParser.T__14); + this.state = 408; + this.match(CashScriptParser.T__16); } } catch (re) { @@ -1874,28 +2068,28 @@ export default class CashScriptParser extends Parser { let _parentState: number = this.state; let localctx: ExpressionContext = new ExpressionContext(this, this._ctx, _parentState); let _prevctx: ExpressionContext = localctx; - let _startState: number = 74; - this.enterRecursionRule(localctx, 74, CashScriptParser.RULE_expression, _p); + let _startState: number = 78; + this.enterRecursionRule(localctx, 78, CashScriptParser.RULE_expression, _p); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 406; + this.state = 459; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 35, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 42, this._ctx) ) { case 1: { localctx = new ParenthesisedContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 358; - this.match(CashScriptParser.T__13); - this.state = 359; - this.expression(0); - this.state = 360; + this.state = 411; this.match(CashScriptParser.T__14); + this.state = 412; + this.expression(0); + this.state = 413; + this.match(CashScriptParser.T__16); } break; case 2: @@ -1903,24 +2097,24 @@ export default class CashScriptParser extends Parser { localctx = new CastContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 362; + this.state = 415; this.typeCast(); - this.state = 363; - this.match(CashScriptParser.T__13); - this.state = 364; + this.state = 416; + this.match(CashScriptParser.T__14); + this.state = 417; (localctx as CastContext)._castable = this.expression(0); - this.state = 366; + this.state = 419; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===16) { { - this.state = 365; - this.match(CashScriptParser.T__18); + this.state = 418; + this.match(CashScriptParser.T__15); } } - this.state = 368; - this.match(CashScriptParser.T__14); + this.state = 421; + this.match(CashScriptParser.T__16); } break; case 3: @@ -1928,7 +2122,7 @@ export default class CashScriptParser extends Parser { localctx = new FunctionCallExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 370; + this.state = 423; this.functionCall(); } break; @@ -1937,11 +2131,11 @@ export default class CashScriptParser extends Parser { localctx = new InstantiationContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 371; - this.match(CashScriptParser.T__31); - this.state = 372; + this.state = 424; + this.match(CashScriptParser.T__32); + this.state = 425; this.match(CashScriptParser.Identifier); - this.state = 373; + this.state = 426; this.expressionList(); } break; @@ -1950,18 +2144,18 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 374; - (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__34); - this.state = 375; - this.match(CashScriptParser.T__32); - this.state = 376; - this.expression(0); - this.state = 377; + this.state = 427; + (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__35); + this.state = 428; this.match(CashScriptParser.T__33); - this.state = 378; + this.state = 429; + this.expression(0); + this.state = 430; + this.match(CashScriptParser.T__34); + this.state = 431; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(((((_la - 36)) & ~0x1F) === 0 && ((1 << (_la - 36)) & 31) !== 0))) { + if(!(((((_la - 37)) & ~0x1F) === 0 && ((1 << (_la - 37)) & 31) !== 0))) { (localctx as UnaryIntrospectionOpContext)._op = this._errHandler.recoverInline(this); } else { @@ -1975,18 +2169,18 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 380; - (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__40); - this.state = 381; - this.match(CashScriptParser.T__32); - this.state = 382; - this.expression(0); - this.state = 383; + this.state = 433; + (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__41); + this.state = 434; this.match(CashScriptParser.T__33); - this.state = 384; + this.state = 435; + this.expression(0); + this.state = 436; + this.match(CashScriptParser.T__34); + this.state = 437; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(((((_la - 36)) & ~0x1F) === 0 && ((1 << (_la - 36)) & 991) !== 0))) { + if(!(((((_la - 37)) & ~0x1F) === 0 && ((1 << (_la - 37)) & 991) !== 0))) { (localctx as UnaryIntrospectionOpContext)._op = this._errHandler.recoverInline(this); } else { @@ -2000,17 +2194,17 @@ export default class CashScriptParser extends Parser { localctx = new UnaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 386; + this.state = 439; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===5 || _la===50 || _la===51)) { + if(!(_la===5 || _la===51 || _la===52)) { (localctx as UnaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 387; + this.state = 440; this.expression(15); } break; @@ -2019,48 +2213,48 @@ export default class CashScriptParser extends Parser { localctx = new ArrayContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 388; - this.match(CashScriptParser.T__32); - this.state = 400; + this.state = 441; + this.match(CashScriptParser.T__33); + this.state = 453; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===5 || _la===14 || ((((_la - 32)) & ~0x1F) === 0 && ((1 << (_la - 32)) & 786955) !== 0) || ((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 61029) !== 0)) { + if (_la===5 || _la===15 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 61029) !== 0)) { { - this.state = 389; + this.state = 442; this.expression(0); - this.state = 394; + this.state = 447; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 390; - this.match(CashScriptParser.T__18); - this.state = 391; + this.state = 443; + this.match(CashScriptParser.T__15); + this.state = 444; this.expression(0); } } } - this.state = 396; + this.state = 449; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); } - this.state = 398; + this.state = 451; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===16) { { - this.state = 397; - this.match(CashScriptParser.T__18); + this.state = 450; + this.match(CashScriptParser.T__15); } } } } - this.state = 402; - this.match(CashScriptParser.T__33); + this.state = 455; + this.match(CashScriptParser.T__34); } break; case 9: @@ -2068,7 +2262,7 @@ export default class CashScriptParser extends Parser { localctx = new NullaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 403; + this.state = 456; this.match(CashScriptParser.NullaryOp); } break; @@ -2077,7 +2271,7 @@ export default class CashScriptParser extends Parser { localctx = new IdentifierContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 404; + this.state = 457; this.match(CashScriptParser.Identifier); } break; @@ -2086,15 +2280,15 @@ export default class CashScriptParser extends Parser { localctx = new LiteralExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 405; + this.state = 458; this.literal(); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 460; + this.state = 513; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 37, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -2102,29 +2296,29 @@ export default class CashScriptParser extends Parser { } _prevctx = localctx; { - this.state = 458; + this.state = 511; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 36, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 43, this._ctx) ) { case 1: { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 408; + this.state = 461; if (!(this.precpred(this._ctx, 14))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 14)"); } - this.state = 409; + this.state = 462; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(((((_la - 52)) & ~0x1F) === 0 && ((1 << (_la - 52)) & 7) !== 0))) { + if(!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & 7) !== 0))) { (localctx as BinaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 410; + this.state = 463; (localctx as BinaryOpContext)._right = this.expression(15); } break; @@ -2133,21 +2327,21 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 411; + this.state = 464; if (!(this.precpred(this._ctx, 13))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 13)"); } - this.state = 412; + this.state = 465; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===51 || _la===55)) { + if(!(_la===52 || _la===56)) { (localctx as BinaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 413; + this.state = 466; (localctx as BinaryOpContext)._right = this.expression(14); } break; @@ -2156,21 +2350,21 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 414; + this.state = 467; if (!(this.precpred(this._ctx, 12))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 12)"); } - this.state = 415; + this.state = 468; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===56 || _la===57)) { + if(!(_la===57 || _la===58)) { (localctx as BinaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 416; + this.state = 469; (localctx as BinaryOpContext)._right = this.expression(13); } break; @@ -2179,11 +2373,11 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 417; + this.state = 470; if (!(this.precpred(this._ctx, 11))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 11)"); } - this.state = 418; + this.state = 471; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 960) !== 0))) { @@ -2193,7 +2387,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 419; + this.state = 472; (localctx as BinaryOpContext)._right = this.expression(12); } break; @@ -2202,21 +2396,21 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 420; + this.state = 473; if (!(this.precpred(this._ctx, 10))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 10)"); } - this.state = 421; + this.state = 474; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===58 || _la===59)) { + if(!(_la===59 || _la===60)) { (localctx as BinaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 422; + this.state = 475; (localctx as BinaryOpContext)._right = this.expression(11); } break; @@ -2225,13 +2419,13 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 423; + this.state = 476; if (!(this.precpred(this._ctx, 9))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 9)"); } - this.state = 424; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__59); - this.state = 425; + this.state = 477; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); + this.state = 478; (localctx as BinaryOpContext)._right = this.expression(10); } break; @@ -2240,13 +2434,13 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 426; + this.state = 479; if (!(this.precpred(this._ctx, 8))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 8)"); } - this.state = 427; + this.state = 480; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__3); - this.state = 428; + this.state = 481; (localctx as BinaryOpContext)._right = this.expression(9); } break; @@ -2255,13 +2449,13 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 429; + this.state = 482; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 430; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); - this.state = 431; + this.state = 483; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); + this.state = 484; (localctx as BinaryOpContext)._right = this.expression(8); } break; @@ -2270,13 +2464,13 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 432; + this.state = 485; if (!(this.precpred(this._ctx, 6))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 6)"); } - this.state = 433; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); - this.state = 434; + this.state = 486; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); + this.state = 487; (localctx as BinaryOpContext)._right = this.expression(7); } break; @@ -2285,13 +2479,13 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 435; + this.state = 488; if (!(this.precpred(this._ctx, 5))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 5)"); } - this.state = 436; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); - this.state = 437; + this.state = 489; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__63); + this.state = 490; (localctx as BinaryOpContext)._right = this.expression(6); } break; @@ -2299,30 +2493,30 @@ export default class CashScriptParser extends Parser { { localctx = new TupleIndexOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 438; + this.state = 491; if (!(this.precpred(this._ctx, 21))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 21)"); } - this.state = 439; - this.match(CashScriptParser.T__32); - this.state = 440; - (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); - this.state = 441; + this.state = 492; this.match(CashScriptParser.T__33); + this.state = 493; + (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); + this.state = 494; + this.match(CashScriptParser.T__34); } break; case 12: { localctx = new UnaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 442; + this.state = 495; if (!(this.precpred(this._ctx, 18))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 18)"); } - this.state = 443; + this.state = 496; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===46 || _la===47)) { + if(!(_la===47 || _la===48)) { (localctx as UnaryOpContext)._op = this._errHandler.recoverInline(this); } else { @@ -2336,18 +2530,18 @@ export default class CashScriptParser extends Parser { localctx = new BinaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as BinaryOpContext)._left = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 444; + this.state = 497; if (!(this.precpred(this._ctx, 17))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 17)"); } - this.state = 445; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__47); - this.state = 446; - this.match(CashScriptParser.T__13); - this.state = 447; - (localctx as BinaryOpContext)._right = this.expression(0); - this.state = 448; + this.state = 498; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__48); + this.state = 499; this.match(CashScriptParser.T__14); + this.state = 500; + (localctx as BinaryOpContext)._right = this.expression(0); + this.state = 501; + this.match(CashScriptParser.T__16); } break; case 14: @@ -2355,30 +2549,30 @@ export default class CashScriptParser extends Parser { localctx = new SliceContext(this, new ExpressionContext(this, _parentctx, _parentState)); (localctx as SliceContext)._element = _prevctx; this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 450; + this.state = 503; if (!(this.precpred(this._ctx, 16))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 16)"); } - this.state = 451; - this.match(CashScriptParser.T__48); - this.state = 452; - this.match(CashScriptParser.T__13); - this.state = 453; + this.state = 504; + this.match(CashScriptParser.T__49); + this.state = 505; + this.match(CashScriptParser.T__14); + this.state = 506; (localctx as SliceContext)._start = this.expression(0); - this.state = 454; - this.match(CashScriptParser.T__18); - this.state = 455; + this.state = 507; + this.match(CashScriptParser.T__15); + this.state = 508; (localctx as SliceContext)._end = this.expression(0); - this.state = 456; - this.match(CashScriptParser.T__14); + this.state = 509; + this.match(CashScriptParser.T__16); } break; } } } - this.state = 462; + this.state = 515; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 37, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); } } } @@ -2399,12 +2593,20 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public modifier(): ModifierContext { let localctx: ModifierContext = new ModifierContext(this, this._ctx, this.state); - this.enterRule(localctx, 76, CashScriptParser.RULE_modifier); + this.enterRule(localctx, 80, CashScriptParser.RULE_modifier); + let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 463; - this.match(CashScriptParser.T__63); + this.state = 516; + _la = this._input.LA(1); + if(!(_la===12 || _la===65)) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -2424,43 +2626,43 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public literal(): LiteralContext { let localctx: LiteralContext = new LiteralContext(this, this._ctx, this.state); - this.enterRule(localctx, 78, CashScriptParser.RULE_literal); + this.enterRule(localctx, 82, CashScriptParser.RULE_literal); try { - this.state = 470; + this.state = 523; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 66: + case 67: this.enterOuterAlt(localctx, 1); { - this.state = 465; + this.state = 518; this.match(CashScriptParser.BooleanLiteral); } break; - case 68: + case 69: this.enterOuterAlt(localctx, 2); { - this.state = 466; + this.state = 519; this.numberLiteral(); } break; - case 75: + case 76: this.enterOuterAlt(localctx, 3); { - this.state = 467; + this.state = 520; this.match(CashScriptParser.StringLiteral); } break; - case 76: + case 77: this.enterOuterAlt(localctx, 4); { - this.state = 468; + this.state = 521; this.match(CashScriptParser.DateLiteral); } break; - case 77: + case 78: this.enterOuterAlt(localctx, 5); { - this.state = 469; + this.state = 522; this.match(CashScriptParser.HexLiteral); } break; @@ -2485,18 +2687,18 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public numberLiteral(): NumberLiteralContext { let localctx: NumberLiteralContext = new NumberLiteralContext(this, this._ctx, this.state); - this.enterRule(localctx, 80, CashScriptParser.RULE_numberLiteral); + this.enterRule(localctx, 84, CashScriptParser.RULE_numberLiteral); try { this.enterOuterAlt(localctx, 1); { - this.state = 472; + this.state = 525; this.match(CashScriptParser.NumberLiteral); - this.state = 474; + this.state = 527; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 39, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 46, this._ctx) ) { case 1: { - this.state = 473; + this.state = 526; this.match(CashScriptParser.NumberUnit); } break; @@ -2520,14 +2722,14 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public typeName(): TypeNameContext { let localctx: TypeNameContext = new TypeNameContext(this, this._ctx, this.state); - this.enterRule(localctx, 82, CashScriptParser.RULE_typeName); + this.enterRule(localctx, 86, CashScriptParser.RULE_typeName); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 476; + this.state = 529; _la = this._input.LA(1); - if(!(((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0))) { + if(!(((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 7) !== 0))) { this._errHandler.recoverInline(this); } else { @@ -2553,14 +2755,14 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public typeCast(): TypeCastContext { let localctx: TypeCastContext = new TypeCastContext(this, this._ctx, this.state); - this.enterRule(localctx, 84, CashScriptParser.RULE_typeCast); + this.enterRule(localctx, 88, CashScriptParser.RULE_typeCast); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 478; + this.state = 531; _la = this._input.LA(1); - if(!(((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 259) !== 0))) { + if(!(((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 259) !== 0))) { this._errHandler.recoverInline(this); } else { @@ -2586,7 +2788,7 @@ export default class CashScriptParser extends Parser { public sempred(localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 37: + case 39: return this.expression_sempred(localctx as ExpressionContext, predIndex); } return true; @@ -2625,165 +2827,183 @@ export default class CashScriptParser extends Parser { return true; } - public static readonly _serializedATN: number[] = [4,1,84,481,2,0,7,0,2, + public static readonly _serializedATN: number[] = [4,1,85,534,2,0,7,0,2, 1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,6,2,7,7,7,2,8,7,8,2,9,7,9,2, 10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,7,14,2,15,7,15,2,16,7,16,2,17, 7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,7,21,2,22,7,22,2,23,7,23,2,24,7, 24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,7,28,2,29,7,29,2,30,7,30,2,31,7,31, 2,32,7,32,2,33,7,33,2,34,7,34,2,35,7,35,2,36,7,36,2,37,7,37,2,38,7,38,2, - 39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,1,0,5,0,88,8,0,10,0,12,0,91,9,0,1, - 0,5,0,94,8,0,10,0,12,0,97,9,0,1,0,5,0,100,8,0,10,0,12,0,103,9,0,1,0,1,0, - 1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,3,1,3,3,3,116,8,3,1,4,3,4,119,8,4,1,4,1,4, - 1,5,1,5,1,6,1,6,1,6,1,6,1,7,1,7,3,7,131,8,7,1,8,1,8,1,8,1,8,1,8,1,8,1,8, - 1,8,3,8,141,8,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,5,9,150,8,9,10,9,12,9,153,9, - 9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,1,11,1,11,5,11,164,8,11,10,11,12,11, - 167,9,11,1,11,1,11,1,12,1,12,1,12,1,12,5,12,175,8,12,10,12,12,12,178,9, - 12,1,12,3,12,181,8,12,3,12,183,8,12,1,12,1,12,1,13,1,13,1,13,1,14,1,14, - 5,14,192,8,14,10,14,12,14,195,9,14,1,14,1,14,3,14,199,8,14,1,15,1,15,1, - 15,1,15,3,15,205,8,15,1,16,1,16,1,16,1,16,1,16,1,16,1,16,1,16,3,16,215, - 8,16,1,17,1,17,1,18,1,18,1,18,1,19,1,19,3,19,224,8,19,1,20,1,20,5,20,228, - 8,20,10,20,12,20,231,9,20,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1,21,1,21, - 1,21,1,21,1,21,1,22,1,22,1,22,1,22,1,22,3,22,250,8,22,1,23,1,23,1,23,1, - 23,1,23,1,23,1,23,3,23,259,8,23,1,23,1,23,1,24,1,24,1,24,1,24,1,24,3,24, - 268,8,24,1,24,1,24,1,25,1,25,1,25,1,26,1,26,1,26,1,26,1,26,1,26,1,26,3, - 26,282,8,26,1,27,1,27,1,27,3,27,287,8,27,1,28,1,28,1,28,1,28,1,28,1,28, - 1,28,1,28,1,29,1,29,1,29,1,29,1,29,1,29,1,30,1,30,1,30,1,30,1,30,1,30,1, - 30,1,30,1,30,1,30,1,31,1,31,3,31,315,8,31,1,32,1,32,1,33,1,33,3,33,321, - 8,33,1,34,1,34,1,34,1,34,5,34,327,8,34,10,34,12,34,330,9,34,1,34,3,34,333, - 8,34,3,34,335,8,34,1,34,1,34,1,35,1,35,1,35,1,36,1,36,1,36,1,36,5,36,346, - 8,36,10,36,12,36,349,9,36,1,36,3,36,352,8,36,3,36,354,8,36,1,36,1,36,1, - 37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,3,37,367,8,37,1,37,1,37,1,37, - 1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1, - 37,1,37,1,37,1,37,1,37,1,37,1,37,5,37,393,8,37,10,37,12,37,396,9,37,1,37, - 3,37,399,8,37,3,37,401,8,37,1,37,1,37,1,37,1,37,3,37,407,8,37,1,37,1,37, - 1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1, - 37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37, - 1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1,37,1, - 37,1,37,1,37,1,37,1,37,5,37,459,8,37,10,37,12,37,462,9,37,1,38,1,38,1,39, - 1,39,1,39,1,39,1,39,3,39,471,8,39,1,40,1,40,3,40,475,8,40,1,41,1,41,1,42, - 1,42,1,42,0,1,74,43,0,2,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36, - 38,40,42,44,46,48,50,52,54,56,58,60,62,64,66,68,70,72,74,76,78,80,82,84, - 0,14,1,0,4,10,2,0,10,10,21,22,1,0,23,24,1,0,36,40,2,0,36,40,42,45,2,0,5, - 5,50,51,1,0,52,54,2,0,51,51,55,55,1,0,56,57,1,0,6,9,1,0,58,59,1,0,46,47, - 1,0,71,73,2,0,71,72,79,79,508,0,89,1,0,0,0,2,106,1,0,0,0,4,111,1,0,0,0, - 6,113,1,0,0,0,8,118,1,0,0,0,10,122,1,0,0,0,12,124,1,0,0,0,14,130,1,0,0, - 0,16,132,1,0,0,0,18,144,1,0,0,0,20,156,1,0,0,0,22,161,1,0,0,0,24,170,1, - 0,0,0,26,186,1,0,0,0,28,198,1,0,0,0,30,204,1,0,0,0,32,214,1,0,0,0,34,216, - 1,0,0,0,36,218,1,0,0,0,38,223,1,0,0,0,40,225,1,0,0,0,42,236,1,0,0,0,44, - 249,1,0,0,0,46,251,1,0,0,0,48,262,1,0,0,0,50,271,1,0,0,0,52,274,1,0,0,0, - 54,286,1,0,0,0,56,288,1,0,0,0,58,296,1,0,0,0,60,302,1,0,0,0,62,314,1,0, - 0,0,64,316,1,0,0,0,66,320,1,0,0,0,68,322,1,0,0,0,70,338,1,0,0,0,72,341, - 1,0,0,0,74,406,1,0,0,0,76,463,1,0,0,0,78,470,1,0,0,0,80,472,1,0,0,0,82, - 476,1,0,0,0,84,478,1,0,0,0,86,88,3,2,1,0,87,86,1,0,0,0,88,91,1,0,0,0,89, - 87,1,0,0,0,89,90,1,0,0,0,90,95,1,0,0,0,91,89,1,0,0,0,92,94,3,12,6,0,93, - 92,1,0,0,0,94,97,1,0,0,0,95,93,1,0,0,0,95,96,1,0,0,0,96,101,1,0,0,0,97, - 95,1,0,0,0,98,100,3,14,7,0,99,98,1,0,0,0,100,103,1,0,0,0,101,99,1,0,0,0, - 101,102,1,0,0,0,102,104,1,0,0,0,103,101,1,0,0,0,104,105,5,0,0,1,105,1,1, - 0,0,0,106,107,5,1,0,0,107,108,3,4,2,0,108,109,3,6,3,0,109,110,5,2,0,0,110, - 3,1,0,0,0,111,112,5,3,0,0,112,5,1,0,0,0,113,115,3,8,4,0,114,116,3,8,4,0, - 115,114,1,0,0,0,115,116,1,0,0,0,116,7,1,0,0,0,117,119,3,10,5,0,118,117, - 1,0,0,0,118,119,1,0,0,0,119,120,1,0,0,0,120,121,5,65,0,0,121,9,1,0,0,0, - 122,123,7,0,0,0,123,11,1,0,0,0,124,125,5,11,0,0,125,126,5,75,0,0,126,127, - 5,2,0,0,127,13,1,0,0,0,128,131,3,16,8,0,129,131,3,18,9,0,130,128,1,0,0, - 0,130,129,1,0,0,0,131,15,1,0,0,0,132,133,5,12,0,0,133,134,5,81,0,0,134, - 140,3,24,12,0,135,136,5,13,0,0,136,137,5,14,0,0,137,138,3,82,41,0,138,139, - 5,15,0,0,139,141,1,0,0,0,140,135,1,0,0,0,140,141,1,0,0,0,141,142,1,0,0, - 0,142,143,3,22,11,0,143,17,1,0,0,0,144,145,5,16,0,0,145,146,5,81,0,0,146, - 147,3,24,12,0,147,151,5,17,0,0,148,150,3,20,10,0,149,148,1,0,0,0,150,153, - 1,0,0,0,151,149,1,0,0,0,151,152,1,0,0,0,152,154,1,0,0,0,153,151,1,0,0,0, - 154,155,5,18,0,0,155,19,1,0,0,0,156,157,5,12,0,0,157,158,5,81,0,0,158,159, - 3,24,12,0,159,160,3,22,11,0,160,21,1,0,0,0,161,165,5,17,0,0,162,164,3,30, - 15,0,163,162,1,0,0,0,164,167,1,0,0,0,165,163,1,0,0,0,165,166,1,0,0,0,166, - 168,1,0,0,0,167,165,1,0,0,0,168,169,5,18,0,0,169,23,1,0,0,0,170,182,5,14, - 0,0,171,176,3,26,13,0,172,173,5,19,0,0,173,175,3,26,13,0,174,172,1,0,0, - 0,175,178,1,0,0,0,176,174,1,0,0,0,176,177,1,0,0,0,177,180,1,0,0,0,178,176, - 1,0,0,0,179,181,5,19,0,0,180,179,1,0,0,0,180,181,1,0,0,0,181,183,1,0,0, - 0,182,171,1,0,0,0,182,183,1,0,0,0,183,184,1,0,0,0,184,185,5,15,0,0,185, - 25,1,0,0,0,186,187,3,82,41,0,187,188,5,81,0,0,188,27,1,0,0,0,189,193,5, - 17,0,0,190,192,3,30,15,0,191,190,1,0,0,0,192,195,1,0,0,0,193,191,1,0,0, - 0,193,194,1,0,0,0,194,196,1,0,0,0,195,193,1,0,0,0,196,199,5,18,0,0,197, - 199,3,30,15,0,198,189,1,0,0,0,198,197,1,0,0,0,199,29,1,0,0,0,200,205,3, - 38,19,0,201,202,3,32,16,0,202,203,5,2,0,0,203,205,1,0,0,0,204,200,1,0,0, - 0,204,201,1,0,0,0,205,31,1,0,0,0,206,215,3,40,20,0,207,215,3,42,21,0,208, - 215,3,44,22,0,209,215,3,46,23,0,210,215,3,48,24,0,211,215,3,34,17,0,212, - 215,3,50,25,0,213,215,3,36,18,0,214,206,1,0,0,0,214,207,1,0,0,0,214,208, - 1,0,0,0,214,209,1,0,0,0,214,210,1,0,0,0,214,211,1,0,0,0,214,212,1,0,0,0, - 214,213,1,0,0,0,215,33,1,0,0,0,216,217,3,70,35,0,217,35,1,0,0,0,218,219, - 5,20,0,0,219,220,3,74,37,0,220,37,1,0,0,0,221,224,3,52,26,0,222,224,3,54, - 27,0,223,221,1,0,0,0,223,222,1,0,0,0,224,39,1,0,0,0,225,229,3,82,41,0,226, - 228,3,76,38,0,227,226,1,0,0,0,228,231,1,0,0,0,229,227,1,0,0,0,229,230,1, - 0,0,0,230,232,1,0,0,0,231,229,1,0,0,0,232,233,5,81,0,0,233,234,5,10,0,0, - 234,235,3,74,37,0,235,41,1,0,0,0,236,237,3,82,41,0,237,238,5,81,0,0,238, - 239,5,19,0,0,239,240,3,82,41,0,240,241,5,81,0,0,241,242,5,10,0,0,242,243, - 3,74,37,0,243,43,1,0,0,0,244,245,5,81,0,0,245,246,7,1,0,0,246,250,3,74, - 37,0,247,248,5,81,0,0,248,250,7,2,0,0,249,244,1,0,0,0,249,247,1,0,0,0,250, - 45,1,0,0,0,251,252,5,25,0,0,252,253,5,14,0,0,253,254,5,78,0,0,254,255,5, - 6,0,0,255,258,3,74,37,0,256,257,5,19,0,0,257,259,3,64,32,0,258,256,1,0, - 0,0,258,259,1,0,0,0,259,260,1,0,0,0,260,261,5,15,0,0,261,47,1,0,0,0,262, - 263,5,25,0,0,263,264,5,14,0,0,264,267,3,74,37,0,265,266,5,19,0,0,266,268, - 3,64,32,0,267,265,1,0,0,0,267,268,1,0,0,0,268,269,1,0,0,0,269,270,5,15, - 0,0,270,49,1,0,0,0,271,272,5,26,0,0,272,273,3,68,34,0,273,51,1,0,0,0,274, - 275,5,27,0,0,275,276,5,14,0,0,276,277,3,74,37,0,277,278,5,15,0,0,278,281, - 3,28,14,0,279,280,5,28,0,0,280,282,3,28,14,0,281,279,1,0,0,0,281,282,1, - 0,0,0,282,53,1,0,0,0,283,287,3,56,28,0,284,287,3,58,29,0,285,287,3,60,30, - 0,286,283,1,0,0,0,286,284,1,0,0,0,286,285,1,0,0,0,287,55,1,0,0,0,288,289, - 5,29,0,0,289,290,3,28,14,0,290,291,5,30,0,0,291,292,5,14,0,0,292,293,3, - 74,37,0,293,294,5,15,0,0,294,295,5,2,0,0,295,57,1,0,0,0,296,297,5,30,0, - 0,297,298,5,14,0,0,298,299,3,74,37,0,299,300,5,15,0,0,300,301,3,28,14,0, - 301,59,1,0,0,0,302,303,5,31,0,0,303,304,5,14,0,0,304,305,3,62,31,0,305, - 306,5,2,0,0,306,307,3,74,37,0,307,308,5,2,0,0,308,309,3,44,22,0,309,310, - 5,15,0,0,310,311,3,28,14,0,311,61,1,0,0,0,312,315,3,40,20,0,313,315,3,44, - 22,0,314,312,1,0,0,0,314,313,1,0,0,0,315,63,1,0,0,0,316,317,5,75,0,0,317, - 65,1,0,0,0,318,321,5,81,0,0,319,321,3,78,39,0,320,318,1,0,0,0,320,319,1, - 0,0,0,321,67,1,0,0,0,322,334,5,14,0,0,323,328,3,66,33,0,324,325,5,19,0, - 0,325,327,3,66,33,0,326,324,1,0,0,0,327,330,1,0,0,0,328,326,1,0,0,0,328, - 329,1,0,0,0,329,332,1,0,0,0,330,328,1,0,0,0,331,333,5,19,0,0,332,331,1, - 0,0,0,332,333,1,0,0,0,333,335,1,0,0,0,334,323,1,0,0,0,334,335,1,0,0,0,335, - 336,1,0,0,0,336,337,5,15,0,0,337,69,1,0,0,0,338,339,5,81,0,0,339,340,3, - 72,36,0,340,71,1,0,0,0,341,353,5,14,0,0,342,347,3,74,37,0,343,344,5,19, - 0,0,344,346,3,74,37,0,345,343,1,0,0,0,346,349,1,0,0,0,347,345,1,0,0,0,347, - 348,1,0,0,0,348,351,1,0,0,0,349,347,1,0,0,0,350,352,5,19,0,0,351,350,1, - 0,0,0,351,352,1,0,0,0,352,354,1,0,0,0,353,342,1,0,0,0,353,354,1,0,0,0,354, - 355,1,0,0,0,355,356,5,15,0,0,356,73,1,0,0,0,357,358,6,37,-1,0,358,359,5, - 14,0,0,359,360,3,74,37,0,360,361,5,15,0,0,361,407,1,0,0,0,362,363,3,84, - 42,0,363,364,5,14,0,0,364,366,3,74,37,0,365,367,5,19,0,0,366,365,1,0,0, - 0,366,367,1,0,0,0,367,368,1,0,0,0,368,369,5,15,0,0,369,407,1,0,0,0,370, - 407,3,70,35,0,371,372,5,32,0,0,372,373,5,81,0,0,373,407,3,72,36,0,374,375, - 5,35,0,0,375,376,5,33,0,0,376,377,3,74,37,0,377,378,5,34,0,0,378,379,7, - 3,0,0,379,407,1,0,0,0,380,381,5,41,0,0,381,382,5,33,0,0,382,383,3,74,37, - 0,383,384,5,34,0,0,384,385,7,4,0,0,385,407,1,0,0,0,386,387,7,5,0,0,387, - 407,3,74,37,15,388,400,5,33,0,0,389,394,3,74,37,0,390,391,5,19,0,0,391, - 393,3,74,37,0,392,390,1,0,0,0,393,396,1,0,0,0,394,392,1,0,0,0,394,395,1, - 0,0,0,395,398,1,0,0,0,396,394,1,0,0,0,397,399,5,19,0,0,398,397,1,0,0,0, - 398,399,1,0,0,0,399,401,1,0,0,0,400,389,1,0,0,0,400,401,1,0,0,0,401,402, - 1,0,0,0,402,407,5,34,0,0,403,407,5,80,0,0,404,407,5,81,0,0,405,407,3,78, - 39,0,406,357,1,0,0,0,406,362,1,0,0,0,406,370,1,0,0,0,406,371,1,0,0,0,406, - 374,1,0,0,0,406,380,1,0,0,0,406,386,1,0,0,0,406,388,1,0,0,0,406,403,1,0, - 0,0,406,404,1,0,0,0,406,405,1,0,0,0,407,460,1,0,0,0,408,409,10,14,0,0,409, - 410,7,6,0,0,410,459,3,74,37,15,411,412,10,13,0,0,412,413,7,7,0,0,413,459, - 3,74,37,14,414,415,10,12,0,0,415,416,7,8,0,0,416,459,3,74,37,13,417,418, - 10,11,0,0,418,419,7,9,0,0,419,459,3,74,37,12,420,421,10,10,0,0,421,422, - 7,10,0,0,422,459,3,74,37,11,423,424,10,9,0,0,424,425,5,60,0,0,425,459,3, - 74,37,10,426,427,10,8,0,0,427,428,5,4,0,0,428,459,3,74,37,9,429,430,10, - 7,0,0,430,431,5,61,0,0,431,459,3,74,37,8,432,433,10,6,0,0,433,434,5,62, - 0,0,434,459,3,74,37,7,435,436,10,5,0,0,436,437,5,63,0,0,437,459,3,74,37, - 6,438,439,10,21,0,0,439,440,5,33,0,0,440,441,5,68,0,0,441,459,5,34,0,0, - 442,443,10,18,0,0,443,459,7,11,0,0,444,445,10,17,0,0,445,446,5,48,0,0,446, - 447,5,14,0,0,447,448,3,74,37,0,448,449,5,15,0,0,449,459,1,0,0,0,450,451, - 10,16,0,0,451,452,5,49,0,0,452,453,5,14,0,0,453,454,3,74,37,0,454,455,5, - 19,0,0,455,456,3,74,37,0,456,457,5,15,0,0,457,459,1,0,0,0,458,408,1,0,0, - 0,458,411,1,0,0,0,458,414,1,0,0,0,458,417,1,0,0,0,458,420,1,0,0,0,458,423, - 1,0,0,0,458,426,1,0,0,0,458,429,1,0,0,0,458,432,1,0,0,0,458,435,1,0,0,0, - 458,438,1,0,0,0,458,442,1,0,0,0,458,444,1,0,0,0,458,450,1,0,0,0,459,462, - 1,0,0,0,460,458,1,0,0,0,460,461,1,0,0,0,461,75,1,0,0,0,462,460,1,0,0,0, - 463,464,5,64,0,0,464,77,1,0,0,0,465,471,5,66,0,0,466,471,3,80,40,0,467, - 471,5,75,0,0,468,471,5,76,0,0,469,471,5,77,0,0,470,465,1,0,0,0,470,466, - 1,0,0,0,470,467,1,0,0,0,470,468,1,0,0,0,470,469,1,0,0,0,471,79,1,0,0,0, - 472,474,5,68,0,0,473,475,5,67,0,0,474,473,1,0,0,0,474,475,1,0,0,0,475,81, - 1,0,0,0,476,477,7,12,0,0,477,83,1,0,0,0,478,479,7,13,0,0,479,85,1,0,0,0, - 40,89,95,101,115,118,130,140,151,165,176,180,182,193,198,204,214,223,229, - 249,258,267,281,286,314,320,328,332,334,347,351,353,366,394,398,400,406, - 458,460,470,474]; + 39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,2,44,7,44,1,0,5,0,92,8, + 0,10,0,12,0,95,9,0,1,0,5,0,98,8,0,10,0,12,0,101,9,0,1,0,5,0,104,8,0,10, + 0,12,0,107,9,0,1,0,1,0,1,1,1,1,1,1,1,1,1,1,1,2,1,2,1,3,1,3,3,3,120,8,3, + 1,4,3,4,123,8,4,1,4,1,4,1,5,1,5,1,6,1,6,1,6,1,6,1,7,1,7,1,7,3,7,136,8,7, + 1,8,1,8,1,8,1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,9,5,9,153,8,9, + 10,9,12,9,156,9,9,1,9,1,9,3,9,160,8,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10, + 5,10,169,8,10,10,10,12,10,172,9,10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1, + 12,1,12,5,12,183,8,12,10,12,12,12,186,9,12,1,12,1,12,1,13,1,13,1,13,1,13, + 5,13,194,8,13,10,13,12,13,197,9,13,1,13,3,13,200,8,13,3,13,202,8,13,1,13, + 1,13,1,14,1,14,5,14,208,8,14,10,14,12,14,211,9,14,1,14,1,14,1,15,1,15,5, + 15,217,8,15,10,15,12,15,220,9,15,1,15,1,15,3,15,224,8,15,1,16,1,16,1,16, + 1,16,3,16,230,8,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,3,17,240,8,17, + 1,18,1,18,1,19,1,19,1,19,1,19,5,19,248,8,19,10,19,12,19,251,9,19,1,20,1, + 20,3,20,255,8,20,1,21,1,21,5,21,259,8,21,10,21,12,21,262,9,21,1,21,1,21, + 1,21,1,21,1,22,1,22,1,22,4,22,271,8,22,11,22,12,22,272,1,22,1,22,1,22,1, + 22,1,22,1,22,1,22,4,22,282,8,22,11,22,12,22,283,1,22,1,22,1,22,1,22,3,22, + 290,8,22,1,23,1,23,1,23,1,23,3,23,296,8,23,1,24,1,24,1,24,1,24,1,24,3,24, + 303,8,24,1,25,1,25,1,25,1,25,1,25,1,25,1,25,3,25,312,8,25,1,25,1,25,1,26, + 1,26,1,26,1,26,1,26,3,26,321,8,26,1,26,1,26,1,27,1,27,1,27,1,28,1,28,1, + 28,1,28,1,28,1,28,1,28,3,28,335,8,28,1,29,1,29,1,29,3,29,340,8,29,1,30, + 1,30,1,30,1,30,1,30,1,30,1,30,1,30,1,31,1,31,1,31,1,31,1,31,1,31,1,32,1, + 32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,33,1,33,3,33,368,8,33,1,34, + 1,34,1,35,1,35,3,35,374,8,35,1,36,1,36,1,36,1,36,5,36,380,8,36,10,36,12, + 36,383,9,36,1,36,3,36,386,8,36,3,36,388,8,36,1,36,1,36,1,37,1,37,1,37,1, + 38,1,38,1,38,1,38,5,38,399,8,38,10,38,12,38,402,9,38,1,38,3,38,405,8,38, + 3,38,407,8,38,1,38,1,38,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,3, + 39,420,8,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39, + 1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,5,39,446,8, + 39,10,39,12,39,449,9,39,1,39,3,39,452,8,39,3,39,454,8,39,1,39,1,39,1,39, + 1,39,3,39,460,8,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1, + 39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39, + 1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1, + 39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,5,39,512,8,39,10,39, + 12,39,515,9,39,1,40,1,40,1,41,1,41,1,41,1,41,1,41,3,41,524,8,41,1,42,1, + 42,3,42,528,8,42,1,43,1,43,1,44,1,44,1,44,0,1,78,45,0,2,4,6,8,10,12,14, + 16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,58,60,62, + 64,66,68,70,72,74,76,78,80,82,84,86,88,0,15,1,0,4,10,2,0,10,10,22,23,1, + 0,24,25,1,0,37,41,2,0,37,41,43,46,2,0,5,5,51,52,1,0,53,55,2,0,52,52,56, + 56,1,0,57,58,1,0,6,9,1,0,59,60,1,0,47,48,2,0,12,12,65,65,1,0,72,74,2,0, + 72,73,80,80,567,0,93,1,0,0,0,2,110,1,0,0,0,4,115,1,0,0,0,6,117,1,0,0,0, + 8,122,1,0,0,0,10,126,1,0,0,0,12,128,1,0,0,0,14,135,1,0,0,0,16,137,1,0,0, + 0,18,144,1,0,0,0,20,163,1,0,0,0,22,175,1,0,0,0,24,180,1,0,0,0,26,189,1, + 0,0,0,28,205,1,0,0,0,30,223,1,0,0,0,32,229,1,0,0,0,34,239,1,0,0,0,36,241, + 1,0,0,0,38,243,1,0,0,0,40,254,1,0,0,0,42,256,1,0,0,0,44,289,1,0,0,0,46, + 295,1,0,0,0,48,302,1,0,0,0,50,304,1,0,0,0,52,315,1,0,0,0,54,324,1,0,0,0, + 56,327,1,0,0,0,58,339,1,0,0,0,60,341,1,0,0,0,62,349,1,0,0,0,64,355,1,0, + 0,0,66,367,1,0,0,0,68,369,1,0,0,0,70,373,1,0,0,0,72,375,1,0,0,0,74,391, + 1,0,0,0,76,394,1,0,0,0,78,459,1,0,0,0,80,516,1,0,0,0,82,523,1,0,0,0,84, + 525,1,0,0,0,86,529,1,0,0,0,88,531,1,0,0,0,90,92,3,2,1,0,91,90,1,0,0,0,92, + 95,1,0,0,0,93,91,1,0,0,0,93,94,1,0,0,0,94,99,1,0,0,0,95,93,1,0,0,0,96,98, + 3,12,6,0,97,96,1,0,0,0,98,101,1,0,0,0,99,97,1,0,0,0,99,100,1,0,0,0,100, + 105,1,0,0,0,101,99,1,0,0,0,102,104,3,14,7,0,103,102,1,0,0,0,104,107,1,0, + 0,0,105,103,1,0,0,0,105,106,1,0,0,0,106,108,1,0,0,0,107,105,1,0,0,0,108, + 109,5,0,0,1,109,1,1,0,0,0,110,111,5,1,0,0,111,112,3,4,2,0,112,113,3,6,3, + 0,113,114,5,2,0,0,114,3,1,0,0,0,115,116,5,3,0,0,116,5,1,0,0,0,117,119,3, + 8,4,0,118,120,3,8,4,0,119,118,1,0,0,0,119,120,1,0,0,0,120,7,1,0,0,0,121, + 123,3,10,5,0,122,121,1,0,0,0,122,123,1,0,0,0,123,124,1,0,0,0,124,125,5, + 66,0,0,125,9,1,0,0,0,126,127,7,0,0,0,127,11,1,0,0,0,128,129,5,11,0,0,129, + 130,5,76,0,0,130,131,5,2,0,0,131,13,1,0,0,0,132,136,3,18,9,0,133,136,3, + 16,8,0,134,136,3,20,10,0,135,132,1,0,0,0,135,133,1,0,0,0,135,134,1,0,0, + 0,136,15,1,0,0,0,137,138,3,86,43,0,138,139,5,12,0,0,139,140,5,82,0,0,140, + 141,5,10,0,0,141,142,3,78,39,0,142,143,5,2,0,0,143,17,1,0,0,0,144,145,5, + 13,0,0,145,146,5,82,0,0,146,159,3,26,13,0,147,148,5,14,0,0,148,149,5,15, + 0,0,149,154,3,86,43,0,150,151,5,16,0,0,151,153,3,86,43,0,152,150,1,0,0, + 0,153,156,1,0,0,0,154,152,1,0,0,0,154,155,1,0,0,0,155,157,1,0,0,0,156,154, + 1,0,0,0,157,158,5,17,0,0,158,160,1,0,0,0,159,147,1,0,0,0,159,160,1,0,0, + 0,160,161,1,0,0,0,161,162,3,24,12,0,162,19,1,0,0,0,163,164,5,18,0,0,164, + 165,5,82,0,0,165,166,3,26,13,0,166,170,5,19,0,0,167,169,3,22,11,0,168,167, + 1,0,0,0,169,172,1,0,0,0,170,168,1,0,0,0,170,171,1,0,0,0,171,173,1,0,0,0, + 172,170,1,0,0,0,173,174,5,20,0,0,174,21,1,0,0,0,175,176,5,13,0,0,176,177, + 5,82,0,0,177,178,3,26,13,0,178,179,3,24,12,0,179,23,1,0,0,0,180,184,5,19, + 0,0,181,183,3,32,16,0,182,181,1,0,0,0,183,186,1,0,0,0,184,182,1,0,0,0,184, + 185,1,0,0,0,185,187,1,0,0,0,186,184,1,0,0,0,187,188,5,20,0,0,188,25,1,0, + 0,0,189,201,5,15,0,0,190,195,3,28,14,0,191,192,5,16,0,0,192,194,3,28,14, + 0,193,191,1,0,0,0,194,197,1,0,0,0,195,193,1,0,0,0,195,196,1,0,0,0,196,199, + 1,0,0,0,197,195,1,0,0,0,198,200,5,16,0,0,199,198,1,0,0,0,199,200,1,0,0, + 0,200,202,1,0,0,0,201,190,1,0,0,0,201,202,1,0,0,0,202,203,1,0,0,0,203,204, + 5,17,0,0,204,27,1,0,0,0,205,209,3,86,43,0,206,208,3,80,40,0,207,206,1,0, + 0,0,208,211,1,0,0,0,209,207,1,0,0,0,209,210,1,0,0,0,210,212,1,0,0,0,211, + 209,1,0,0,0,212,213,5,82,0,0,213,29,1,0,0,0,214,218,5,19,0,0,215,217,3, + 32,16,0,216,215,1,0,0,0,217,220,1,0,0,0,218,216,1,0,0,0,218,219,1,0,0,0, + 219,221,1,0,0,0,220,218,1,0,0,0,221,224,5,20,0,0,222,224,3,32,16,0,223, + 214,1,0,0,0,223,222,1,0,0,0,224,31,1,0,0,0,225,230,3,40,20,0,226,227,3, + 34,17,0,227,228,5,2,0,0,228,230,1,0,0,0,229,225,1,0,0,0,229,226,1,0,0,0, + 230,33,1,0,0,0,231,240,3,42,21,0,232,240,3,44,22,0,233,240,3,48,24,0,234, + 240,3,50,25,0,235,240,3,52,26,0,236,240,3,36,18,0,237,240,3,54,27,0,238, + 240,3,38,19,0,239,231,1,0,0,0,239,232,1,0,0,0,239,233,1,0,0,0,239,234,1, + 0,0,0,239,235,1,0,0,0,239,236,1,0,0,0,239,237,1,0,0,0,239,238,1,0,0,0,240, + 35,1,0,0,0,241,242,3,74,37,0,242,37,1,0,0,0,243,244,5,21,0,0,244,249,3, + 78,39,0,245,246,5,16,0,0,246,248,3,78,39,0,247,245,1,0,0,0,248,251,1,0, + 0,0,249,247,1,0,0,0,249,250,1,0,0,0,250,39,1,0,0,0,251,249,1,0,0,0,252, + 255,3,56,28,0,253,255,3,58,29,0,254,252,1,0,0,0,254,253,1,0,0,0,255,41, + 1,0,0,0,256,260,3,86,43,0,257,259,3,80,40,0,258,257,1,0,0,0,259,262,1,0, + 0,0,260,258,1,0,0,0,260,261,1,0,0,0,261,263,1,0,0,0,262,260,1,0,0,0,263, + 264,5,82,0,0,264,265,5,10,0,0,265,266,3,78,39,0,266,43,1,0,0,0,267,270, + 3,46,23,0,268,269,5,16,0,0,269,271,3,46,23,0,270,268,1,0,0,0,271,272,1, + 0,0,0,272,270,1,0,0,0,272,273,1,0,0,0,273,274,1,0,0,0,274,275,5,10,0,0, + 275,276,3,78,39,0,276,290,1,0,0,0,277,278,5,15,0,0,278,281,3,46,23,0,279, + 280,5,16,0,0,280,282,3,46,23,0,281,279,1,0,0,0,282,283,1,0,0,0,283,281, + 1,0,0,0,283,284,1,0,0,0,284,285,1,0,0,0,285,286,5,17,0,0,286,287,5,10,0, + 0,287,288,3,78,39,0,288,290,1,0,0,0,289,267,1,0,0,0,289,277,1,0,0,0,290, + 45,1,0,0,0,291,292,3,86,43,0,292,293,5,82,0,0,293,296,1,0,0,0,294,296,5, + 82,0,0,295,291,1,0,0,0,295,294,1,0,0,0,296,47,1,0,0,0,297,298,5,82,0,0, + 298,299,7,1,0,0,299,303,3,78,39,0,300,301,5,82,0,0,301,303,7,2,0,0,302, + 297,1,0,0,0,302,300,1,0,0,0,303,49,1,0,0,0,304,305,5,26,0,0,305,306,5,15, + 0,0,306,307,5,79,0,0,307,308,5,6,0,0,308,311,3,78,39,0,309,310,5,16,0,0, + 310,312,3,68,34,0,311,309,1,0,0,0,311,312,1,0,0,0,312,313,1,0,0,0,313,314, + 5,17,0,0,314,51,1,0,0,0,315,316,5,26,0,0,316,317,5,15,0,0,317,320,3,78, + 39,0,318,319,5,16,0,0,319,321,3,68,34,0,320,318,1,0,0,0,320,321,1,0,0,0, + 321,322,1,0,0,0,322,323,5,17,0,0,323,53,1,0,0,0,324,325,5,27,0,0,325,326, + 3,72,36,0,326,55,1,0,0,0,327,328,5,28,0,0,328,329,5,15,0,0,329,330,3,78, + 39,0,330,331,5,17,0,0,331,334,3,30,15,0,332,333,5,29,0,0,333,335,3,30,15, + 0,334,332,1,0,0,0,334,335,1,0,0,0,335,57,1,0,0,0,336,340,3,60,30,0,337, + 340,3,62,31,0,338,340,3,64,32,0,339,336,1,0,0,0,339,337,1,0,0,0,339,338, + 1,0,0,0,340,59,1,0,0,0,341,342,5,30,0,0,342,343,3,30,15,0,343,344,5,31, + 0,0,344,345,5,15,0,0,345,346,3,78,39,0,346,347,5,17,0,0,347,348,5,2,0,0, + 348,61,1,0,0,0,349,350,5,31,0,0,350,351,5,15,0,0,351,352,3,78,39,0,352, + 353,5,17,0,0,353,354,3,30,15,0,354,63,1,0,0,0,355,356,5,32,0,0,356,357, + 5,15,0,0,357,358,3,66,33,0,358,359,5,2,0,0,359,360,3,78,39,0,360,361,5, + 2,0,0,361,362,3,48,24,0,362,363,5,17,0,0,363,364,3,30,15,0,364,65,1,0,0, + 0,365,368,3,42,21,0,366,368,3,48,24,0,367,365,1,0,0,0,367,366,1,0,0,0,368, + 67,1,0,0,0,369,370,5,76,0,0,370,69,1,0,0,0,371,374,5,82,0,0,372,374,3,82, + 41,0,373,371,1,0,0,0,373,372,1,0,0,0,374,71,1,0,0,0,375,387,5,15,0,0,376, + 381,3,70,35,0,377,378,5,16,0,0,378,380,3,70,35,0,379,377,1,0,0,0,380,383, + 1,0,0,0,381,379,1,0,0,0,381,382,1,0,0,0,382,385,1,0,0,0,383,381,1,0,0,0, + 384,386,5,16,0,0,385,384,1,0,0,0,385,386,1,0,0,0,386,388,1,0,0,0,387,376, + 1,0,0,0,387,388,1,0,0,0,388,389,1,0,0,0,389,390,5,17,0,0,390,73,1,0,0,0, + 391,392,5,82,0,0,392,393,3,76,38,0,393,75,1,0,0,0,394,406,5,15,0,0,395, + 400,3,78,39,0,396,397,5,16,0,0,397,399,3,78,39,0,398,396,1,0,0,0,399,402, + 1,0,0,0,400,398,1,0,0,0,400,401,1,0,0,0,401,404,1,0,0,0,402,400,1,0,0,0, + 403,405,5,16,0,0,404,403,1,0,0,0,404,405,1,0,0,0,405,407,1,0,0,0,406,395, + 1,0,0,0,406,407,1,0,0,0,407,408,1,0,0,0,408,409,5,17,0,0,409,77,1,0,0,0, + 410,411,6,39,-1,0,411,412,5,15,0,0,412,413,3,78,39,0,413,414,5,17,0,0,414, + 460,1,0,0,0,415,416,3,88,44,0,416,417,5,15,0,0,417,419,3,78,39,0,418,420, + 5,16,0,0,419,418,1,0,0,0,419,420,1,0,0,0,420,421,1,0,0,0,421,422,5,17,0, + 0,422,460,1,0,0,0,423,460,3,74,37,0,424,425,5,33,0,0,425,426,5,82,0,0,426, + 460,3,76,38,0,427,428,5,36,0,0,428,429,5,34,0,0,429,430,3,78,39,0,430,431, + 5,35,0,0,431,432,7,3,0,0,432,460,1,0,0,0,433,434,5,42,0,0,434,435,5,34, + 0,0,435,436,3,78,39,0,436,437,5,35,0,0,437,438,7,4,0,0,438,460,1,0,0,0, + 439,440,7,5,0,0,440,460,3,78,39,15,441,453,5,34,0,0,442,447,3,78,39,0,443, + 444,5,16,0,0,444,446,3,78,39,0,445,443,1,0,0,0,446,449,1,0,0,0,447,445, + 1,0,0,0,447,448,1,0,0,0,448,451,1,0,0,0,449,447,1,0,0,0,450,452,5,16,0, + 0,451,450,1,0,0,0,451,452,1,0,0,0,452,454,1,0,0,0,453,442,1,0,0,0,453,454, + 1,0,0,0,454,455,1,0,0,0,455,460,5,35,0,0,456,460,5,81,0,0,457,460,5,82, + 0,0,458,460,3,82,41,0,459,410,1,0,0,0,459,415,1,0,0,0,459,423,1,0,0,0,459, + 424,1,0,0,0,459,427,1,0,0,0,459,433,1,0,0,0,459,439,1,0,0,0,459,441,1,0, + 0,0,459,456,1,0,0,0,459,457,1,0,0,0,459,458,1,0,0,0,460,513,1,0,0,0,461, + 462,10,14,0,0,462,463,7,6,0,0,463,512,3,78,39,15,464,465,10,13,0,0,465, + 466,7,7,0,0,466,512,3,78,39,14,467,468,10,12,0,0,468,469,7,8,0,0,469,512, + 3,78,39,13,470,471,10,11,0,0,471,472,7,9,0,0,472,512,3,78,39,12,473,474, + 10,10,0,0,474,475,7,10,0,0,475,512,3,78,39,11,476,477,10,9,0,0,477,478, + 5,61,0,0,478,512,3,78,39,10,479,480,10,8,0,0,480,481,5,4,0,0,481,512,3, + 78,39,9,482,483,10,7,0,0,483,484,5,62,0,0,484,512,3,78,39,8,485,486,10, + 6,0,0,486,487,5,63,0,0,487,512,3,78,39,7,488,489,10,5,0,0,489,490,5,64, + 0,0,490,512,3,78,39,6,491,492,10,21,0,0,492,493,5,34,0,0,493,494,5,69,0, + 0,494,512,5,35,0,0,495,496,10,18,0,0,496,512,7,11,0,0,497,498,10,17,0,0, + 498,499,5,49,0,0,499,500,5,15,0,0,500,501,3,78,39,0,501,502,5,17,0,0,502, + 512,1,0,0,0,503,504,10,16,0,0,504,505,5,50,0,0,505,506,5,15,0,0,506,507, + 3,78,39,0,507,508,5,16,0,0,508,509,3,78,39,0,509,510,5,17,0,0,510,512,1, + 0,0,0,511,461,1,0,0,0,511,464,1,0,0,0,511,467,1,0,0,0,511,470,1,0,0,0,511, + 473,1,0,0,0,511,476,1,0,0,0,511,479,1,0,0,0,511,482,1,0,0,0,511,485,1,0, + 0,0,511,488,1,0,0,0,511,491,1,0,0,0,511,495,1,0,0,0,511,497,1,0,0,0,511, + 503,1,0,0,0,512,515,1,0,0,0,513,511,1,0,0,0,513,514,1,0,0,0,514,79,1,0, + 0,0,515,513,1,0,0,0,516,517,7,12,0,0,517,81,1,0,0,0,518,524,5,67,0,0,519, + 524,3,84,42,0,520,524,5,76,0,0,521,524,5,77,0,0,522,524,5,78,0,0,523,518, + 1,0,0,0,523,519,1,0,0,0,523,520,1,0,0,0,523,521,1,0,0,0,523,522,1,0,0,0, + 524,83,1,0,0,0,525,527,5,69,0,0,526,528,5,68,0,0,527,526,1,0,0,0,527,528, + 1,0,0,0,528,85,1,0,0,0,529,530,7,13,0,0,530,87,1,0,0,0,531,532,7,14,0,0, + 532,89,1,0,0,0,47,93,99,105,119,122,135,154,159,170,184,195,199,201,209, + 218,223,229,239,249,254,260,272,283,289,295,302,311,320,334,339,367,373, + 381,385,387,400,404,406,419,447,451,453,459,511,513,523,527]; private static __ATN: ATN; public static get _ATN(): ATN { @@ -2982,6 +3202,9 @@ export class TopLevelDefinitionContext extends ParserRuleContext { public globalFunctionDefinition(): GlobalFunctionDefinitionContext { return this.getTypedRuleContext(GlobalFunctionDefinitionContext, 0) as GlobalFunctionDefinitionContext; } + public constantDefinition(): ConstantDefinitionContext { + return this.getTypedRuleContext(ConstantDefinitionContext, 0) as ConstantDefinitionContext; + } public contractDefinition(): ContractDefinitionContext { return this.getTypedRuleContext(ContractDefinitionContext, 0) as ContractDefinitionContext; } @@ -2999,6 +3222,34 @@ export class TopLevelDefinitionContext extends ParserRuleContext { } +export class ConstantDefinitionContext extends ParserRuleContext { + constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public typeName(): TypeNameContext { + return this.getTypedRuleContext(TypeNameContext, 0) as TypeNameContext; + } + public Identifier(): TerminalNode { + return this.getToken(CashScriptParser.Identifier, 0); + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return CashScriptParser.RULE_constantDefinition; + } + // @Override + public accept(visitor: CashScriptVisitor): Result { + if (visitor.visitConstantDefinition) { + return visitor.visitConstantDefinition(this); + } else { + return visitor.visitChildren(this); + } + } +} + + export class GlobalFunctionDefinitionContext extends ParserRuleContext { constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { super(parent, invokingState); @@ -3013,8 +3264,11 @@ export class GlobalFunctionDefinitionContext extends ParserRuleContext { public functionBody(): FunctionBodyContext { return this.getTypedRuleContext(FunctionBodyContext, 0) as FunctionBodyContext; } - public typeName(): TypeNameContext { - return this.getTypedRuleContext(TypeNameContext, 0) as TypeNameContext; + public typeName_list(): TypeNameContext[] { + return this.getTypedRuleContexts(TypeNameContext) as TypeNameContext[]; + } + public typeName(i: number): TypeNameContext { + return this.getTypedRuleContext(TypeNameContext, i) as TypeNameContext; } public get ruleIndex(): number { return CashScriptParser.RULE_globalFunctionDefinition; @@ -3150,6 +3404,12 @@ export class ParameterContext extends ParserRuleContext { public Identifier(): TerminalNode { return this.getToken(CashScriptParser.Identifier, 0); } + public modifier_list(): ModifierContext[] { + return this.getTypedRuleContexts(ModifierContext) as ModifierContext[]; + } + public modifier(i: number): ModifierContext { + return this.getTypedRuleContext(ModifierContext, i) as ModifierContext; + } public get ruleIndex(): number { return CashScriptParser.RULE_parameter; } @@ -3284,8 +3544,11 @@ export class ReturnStatementContext extends ParserRuleContext { super(parent, invokingState); this.parser = parser; } - public expression(): ExpressionContext { - return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + public expression_list(): ExpressionContext[] { + return this.getTypedRuleContexts(ExpressionContext) as ExpressionContext[]; + } + public expression(i: number): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, i) as ExpressionContext; } public get ruleIndex(): number { return CashScriptParser.RULE_returnStatement; @@ -3365,17 +3628,11 @@ export class TupleAssignmentContext extends ParserRuleContext { super(parent, invokingState); this.parser = parser; } - public typeName_list(): TypeNameContext[] { - return this.getTypedRuleContexts(TypeNameContext) as TypeNameContext[]; - } - public typeName(i: number): TypeNameContext { - return this.getTypedRuleContext(TypeNameContext, i) as TypeNameContext; - } - public Identifier_list(): TerminalNode[] { - return this.getTokens(CashScriptParser.Identifier); + public tupleTarget_list(): TupleTargetContext[] { + return this.getTypedRuleContexts(TupleTargetContext) as TupleTargetContext[]; } - public Identifier(i: number): TerminalNode { - return this.getToken(CashScriptParser.Identifier, i); + public tupleTarget(i: number): TupleTargetContext { + return this.getTypedRuleContext(TupleTargetContext, i) as TupleTargetContext; } public expression(): ExpressionContext { return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; @@ -3394,6 +3651,31 @@ export class TupleAssignmentContext extends ParserRuleContext { } +export class TupleTargetContext extends ParserRuleContext { + constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public typeName(): TypeNameContext { + return this.getTypedRuleContext(TypeNameContext, 0) as TypeNameContext; + } + public Identifier(): TerminalNode { + return this.getToken(CashScriptParser.Identifier, 0); + } + public get ruleIndex(): number { + return CashScriptParser.RULE_tupleTarget; + } + // @Override + public accept(visitor: CashScriptVisitor): Result { + if (visitor.visitTupleTarget) { + return visitor.visitTupleTarget(this); + } else { + return visitor.visitChildren(this); + } + } +} + + export class AssignStatementContext extends ParserRuleContext { public _op!: Token; constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { @@ -3789,7 +4071,7 @@ export class ExpressionContext extends ParserRuleContext { public get ruleIndex(): number { return CashScriptParser.RULE_expression; } - public copyFrom(ctx: ExpressionContext): void { + public override copyFrom(ctx: ExpressionContext): void { super.copyFrom(ctx); } } diff --git a/packages/cashc/src/grammar/CashScriptVisitor.ts b/packages/cashc/src/grammar/CashScriptVisitor.ts index 6b47aa00..7715c3fe 100644 --- a/packages/cashc/src/grammar/CashScriptVisitor.ts +++ b/packages/cashc/src/grammar/CashScriptVisitor.ts @@ -1,4 +1,4 @@ -// Generated from src/grammar/CashScript.g4 by ANTLR 4.13.1 +// Generated from CashScript.g4 by ANTLR 4.13.2 import {ParseTreeVisitor} from 'antlr4'; @@ -11,6 +11,7 @@ import { VersionConstraintContext } from "./CashScriptParser.js"; import { VersionOperatorContext } from "./CashScriptParser.js"; import { ImportDirectiveContext } from "./CashScriptParser.js"; import { TopLevelDefinitionContext } from "./CashScriptParser.js"; +import { ConstantDefinitionContext } from "./CashScriptParser.js"; import { GlobalFunctionDefinitionContext } from "./CashScriptParser.js"; import { ContractDefinitionContext } from "./CashScriptParser.js"; import { ContractFunctionDefinitionContext } from "./CashScriptParser.js"; @@ -25,6 +26,7 @@ import { ReturnStatementContext } from "./CashScriptParser.js"; import { ControlStatementContext } from "./CashScriptParser.js"; import { VariableDefinitionContext } from "./CashScriptParser.js"; import { TupleAssignmentContext } from "./CashScriptParser.js"; +import { TupleTargetContext } from "./CashScriptParser.js"; import { AssignStatementContext } from "./CashScriptParser.js"; import { TimeOpStatementContext } from "./CashScriptParser.js"; import { RequireStatementContext } from "./CashScriptParser.js"; @@ -116,6 +118,12 @@ export default class CashScriptVisitor extends ParseTreeVisitor * @return the visitor result */ visitTopLevelDefinition?: (ctx: TopLevelDefinitionContext) => Result; + /** + * Visit a parse tree produced by `CashScriptParser.constantDefinition`. + * @param ctx the parse tree + * @return the visitor result + */ + visitConstantDefinition?: (ctx: ConstantDefinitionContext) => Result; /** * Visit a parse tree produced by `CashScriptParser.globalFunctionDefinition`. * @param ctx the parse tree @@ -200,6 +208,12 @@ export default class CashScriptVisitor extends ParseTreeVisitor * @return the visitor result */ visitTupleAssignment?: (ctx: TupleAssignmentContext) => Result; + /** + * Visit a parse tree produced by `CashScriptParser.tupleTarget`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTupleTarget?: (ctx: TupleTargetContext) => Result; /** * Visit a parse tree produced by `CashScriptParser.assignStatement`. * @param ctx the parse tree diff --git a/packages/cashc/src/print/OutputSourceCodeTraversal.ts b/packages/cashc/src/print/OutputSourceCodeTraversal.ts index 7f703f8a..62ba3c79 100644 --- a/packages/cashc/src/print/OutputSourceCodeTraversal.ts +++ b/packages/cashc/src/print/OutputSourceCodeTraversal.ts @@ -36,6 +36,7 @@ import { WhileNode, ForNode, NonControlStatementNode, + ExpressionNode, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; @@ -96,7 +97,7 @@ export default class OutputSourceCodeTraversal extends AstTraversal { this.addOutput(`function ${node.name}(`, true); node.parameters = this.visitCommaList(node.parameters) as ParameterNode[]; this.addOutput(')'); - if (node.returnType) this.addOutput(` returns (${node.returnType})`); + if (node.returnTypes) this.addOutput(` returns (${node.returnTypes.join(', ')})`); this.outputSymbolTable(node.symbolTable); this.addOutput(' '); @@ -129,7 +130,11 @@ export default class OutputSourceCodeTraversal extends AstTraversal { } visitTupleAssignment(node: TupleAssignmentNode): Node { - this.addOutput(`${node.left.type} ${node.left.name}, ${node.right.type} ${node.right.name} = `, true); + // A reassignment target (no declared type) prints as a bare identifier; a declaration as `type name`. + const targets = node.targets + .map((target) => (target.isReassignment ? target.name : `${target.type} ${target.name}`)) + .join(', '); + this.addOutput(`${targets} = `, true); this.visit(node.tuple); return node; @@ -166,7 +171,7 @@ export default class OutputSourceCodeTraversal extends AstTraversal { visitReturn(node: ReturnNode): Node { this.addOutput('return ', true); - node.expression = this.visit(node.expression); + node.expressions = this.visitCommaList(node.expressions) as ExpressionNode[]; return node; } diff --git a/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts b/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts index e5d9115f..50ef9dcf 100644 --- a/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts +++ b/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts @@ -46,7 +46,7 @@ export default class EnsureFinalRequireTraversal extends AstTraversal { if (node.kind === FunctionKind.CONTRACT) { ensureFinalStatementIsRequire(node.body); - } else if (node.returnType !== undefined) { + } else if (node.returnTypes !== undefined) { ensureSingleTailReturn(node.body); } diff --git a/packages/cashc/src/semantic/SymbolTableTraversal.ts b/packages/cashc/src/semantic/SymbolTableTraversal.ts index 41b49cd4..14fa4cb9 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -27,6 +27,9 @@ import { UnusedVariableError, InvalidSymbolTypeError, ConstantModificationError, + InvalidModifierError, + DuplicateTupleTargetError, + TupleTargetOrderError, } from '../Errors.js'; export default class SymbolTableTraversal extends AstTraversal { @@ -78,7 +81,13 @@ export default class SymbolTableTraversal extends AstTraversal { throw new VariableRedefinitionError(node); } - this.symbolTables[0].set(Symbol.variable(node)); + // `constant` is meaningless on a parameter (parameters are never reassigned), so only `unused` + // is accepted; any other or duplicate modifier is rejected. + validateModifiers(node, node.modifiers, [Modifier.UNUSED]); + + const symbol = Symbol.variable(node); + symbol.ignoreUnused = node.modifiers.includes(Modifier.UNUSED); + this.symbolTables[0].set(symbol); return node; } @@ -145,9 +154,13 @@ export default class SymbolTableTraversal extends AstTraversal { throw new VariableRedefinitionError(node); } + validateModifiers(node, node.modifier, [Modifier.CONSTANT, Modifier.UNUSED]); + node.expression = this.visit(node.expression); - this.symbolTables[0].set(Symbol.variable(node)); + const symbol = Symbol.variable(node); + symbol.ignoreUnused = node.modifier.includes(Modifier.UNUSED); + this.symbolTables[0].set(symbol); return node; } @@ -166,7 +179,43 @@ export default class SymbolTableTraversal extends AstTraversal { } visitTupleAssignment(node: TupleAssignmentNode): Node { - [node.left, node.right].forEach((variable) => { + // Declarations must form a contiguous block before all reassignment targets — the one layout + // scoped codegen can fold in place (see GenerateTargetTraversal.visitTupleAssignment). Enforced + // uniformly so a statement's legality does not depend on whether it sits inside a loop/branch. + const firstReassignment = node.targets.findIndex((target) => target.isReassignment); + if (firstReassignment !== -1 && node.targets.slice(firstReassignment).some((target) => !target.isReassignment)) { + throw new TupleTargetOrderError(node); + } + + const seenTargetNames = new Set(); + node.targets.forEach((variable) => { + if (seenTargetNames.has(variable.name)) { + throw new DuplicateTupleTargetError(node, variable.name); + } + seenTargetNames.add(variable.name); + + if (variable.isReassignment) { + // Reassignment of an existing variable (`x`, no type): adopt its type for the type-check and + // register a reference (so it isn't flagged unused). Do NOT create a new symbol. + const reference = new IdentifierNode(variable.name); + reference.location = node.location; + const existing = this.symbolTables[0].get(variable.name); + if (!existing) { + throw new UndefinedReferenceError(reference); + } + // only variables can be reassigned (not functions or classes) + if (existing.symbolType !== SymbolType.VARIABLE) { + throw new InvalidSymbolTypeError(reference, SymbolType.VARIABLE); + } + const definition = existing.definition as VariableDefinitionNode | undefined; + if (definition?.modifier?.includes(Modifier.CONSTANT)) { + throw new ConstantModificationError(definition); + } + variable.type = existing.type; + existing.references.push(reference); + return; + } + const definition = createTupleVariableDefinition(node, variable); const { name } = variable; @@ -229,11 +278,34 @@ export default class SymbolTableTraversal extends AstTraversal { } } +// Rejects duplicate modifiers and any modifier outside the set allowed in the given declaration +// context (parameters allow only `unused`; variable definitions allow `constant` / `unused`). +function validateModifiers( + node: ParameterNode | VariableDefinitionNode, + modifiers: string[], + allowed: Modifier[], +): void { + const seen = new Set(); + modifiers.forEach((modifier) => { + if (seen.has(modifier)) { + throw new InvalidModifierError(node, `Duplicate modifier '${modifier}'`); + } + seen.add(modifier); + + if (!allowed.includes(modifier as Modifier)) { + const target = node instanceof ParameterNode ? 'parameters' : 'variables'; + throw new InvalidModifierError(node, `Modifier '${modifier}' is not allowed on ${target}`); + } + }); +} + function createTupleVariableDefinition( node: TupleAssignmentNode, - variable: TupleAssignmentNode['left'], + variable: TupleAssignmentNode['targets'][number], ): VariableDefinitionNode { - const definition = new VariableDefinitionNode(variable.type, [], variable.name, node.tuple); + // Only declaration targets reach here (reassignment targets are handled before this is called), + // so `type` is always defined. + const definition = new VariableDefinitionNode(variable.type!, [], variable.name, node.tuple); definition.location = node.location; return definition; } diff --git a/packages/cashc/src/semantic/TypeCheckTraversal.ts b/packages/cashc/src/semantic/TypeCheckTraversal.ts index 4c5d120c..f4f8f6f3 100644 --- a/packages/cashc/src/semantic/TypeCheckTraversal.ts +++ b/packages/cashc/src/semantic/TypeCheckTraversal.ts @@ -53,6 +53,9 @@ import { BitshiftBitcountNegativeError, UnusedFunctionReturnError, ReturnTypeError, + ReturnCountError, + TupleArityError, + MultiReturnDestructureError, } from '../Errors.js'; import { BinaryOperator, NullaryOperator, UnaryOperator } from '../ast/Operator.js'; import { GlobalFunction } from '../ast/Globals.js'; @@ -60,7 +63,12 @@ import { Symbol } from '../ast/SymbolTable.js'; import { resultingTypeForBinaryOp } from '../utils.js'; export default class TypeCheckTraversal extends AstTraversal { - private currentFunctionReturnType: Type = PrimitiveType.VOID; + // Declared return types of the function currently being checked (empty for a void function). + private currentFunctionReturnTypes: Type[] = []; + // The one expression allowed to be a multi-return call: the RHS of the tuple destructuring being + // visited. Matched by NODE IDENTITY in visitFunctionCall, so a call merely nested inside the RHS + // tree (e.g. `pair().split(1)`) is still rejected — it would silently discard return values. + private tupleAssignmentRhs: Node | null = null; visitVariableDefinition(node: VariableDefinitionNode): Node { node.expression = this.visit(node.expression); @@ -69,19 +77,41 @@ export default class TypeCheckTraversal extends AstTraversal { } visitTupleAssignment(node: TupleAssignmentNode): Node { + this.tupleAssignmentRhs = node.tuple; node.tuple = this.visit(node.tuple); + this.tupleAssignmentRhs = null; + + // A multi-return function call is the only N-ary tuple source: its return types must match the + // destructuring targets one-to-one (count and types). + const callReturnTypes = functionCallReturnTypes(node.tuple); + if (callReturnTypes !== undefined) { + this.checkTupleTargets(node, callReturnTypes); + return node; + } + + // Otherwise the tuple must come from `.split`, which always produces exactly two values. if (!(node.tuple instanceof BinaryOpNode) || node.tuple.operator !== BinaryOperator.SPLIT) { throw new TupleAssignmentError(node.tuple); } + this.checkTupleTargets(node, [(node.tuple.type as TupleType).leftType, (node.tuple.type as TupleType).rightType]); + return node; + } - const assignmentType = new TupleType(node.left.type, node.right.type); - - if (!implicitlyCastable(node.tuple.type, assignmentType)) { - const syntheticAssignment = new VariableDefinitionNode(assignmentType, [], node.left.name, node.tuple); - syntheticAssignment.location = node.location; - throw new AssignTypeError(syntheticAssignment); + private checkTupleTargets(node: TupleAssignmentNode, sourceTypes: Type[]): void { + if (node.targets.length !== sourceTypes.length) { + throw new TupleArityError(node, node.targets.length, sourceTypes.length); } - return node; + + node.targets.forEach((target, i) => { + // target.type is resolved for every target by SymbolTableTraversal before this pass (declared + // targets carry their declared type; reassignment targets adopt the existing variable's type). + const targetType = target.type!; + if (!implicitlyCastable(sourceTypes[i], targetType)) { + const syntheticAssignment = new VariableDefinitionNode(targetType, [], target.name, node.tuple); + syntheticAssignment.location = node.location; + throw new AssignTypeError(syntheticAssignment); + } + }); } visitAssign(node: AssignNode): Node { @@ -195,27 +225,45 @@ export default class TypeCheckTraversal extends AstTraversal { } visitFunctionDefinition(node: FunctionDefinitionNode): Node { - this.currentFunctionReturnType = node.returnType ?? PrimitiveType.VOID; + this.currentFunctionReturnTypes = node.returnTypes ?? []; node.parameters = this.visitList(node.parameters) as ParameterNode[]; node.body = this.visit(node.body) as BlockNode; return node; } visitReturn(node: ReturnNode): Node { - node.expression = this.visit(node.expression); - if (!implicitlyCastable(node.expression.type, this.currentFunctionReturnType)) { - throw new ReturnTypeError(node.expression, node.expression.type, this.currentFunctionReturnType); + node.expressions = this.visitList(node.expressions); + + const expectedTypes = this.currentFunctionReturnTypes; + if (node.expressions.length !== expectedTypes.length) { + throw new ReturnCountError(node, node.expressions.length, expectedTypes.length); } + + node.expressions.forEach((expression, i) => { + if (!implicitlyCastable(expression.type, expectedTypes[i])) { + throw new ReturnTypeError(expression, expression.type, expectedTypes[i]); + } + }); + return node; } visitFunctionCall(node: FunctionCallNode): Node { + // Only the destructuring RHS itself qualifies (identity check) — never a nested call. + const isTupleAssignmentRhs = this.tupleAssignmentRhs === node; + node.identifier = this.visit(node.identifier) as IdentifierNode; node.parameters = this.visitList(node.parameters); const { symbol, type } = node.identifier; if (!symbol || !symbol.parameters) return node; // already checked in symbol table + // A multi-return function produces no single value, so it is only valid as a tuple-destructuring + // RHS (validated in visitTupleAssignment). Anywhere a single value is expected is an error. + if (symbol.returnTypes.length > 1 && !isTupleAssignmentRhs) { + throw new MultiReturnDestructureError(node, symbol.returnTypes.length); + } + const parameterTypes = node.parameters.map((p) => p.type!); expectParameters(node, parameterTypes, symbol.parameters); @@ -655,3 +703,10 @@ function matchSizeLiteral(expr: BinaryOpNode): { sizeNode: UnaryOpNode, literalN const isSizeOp = (node: ExpressionNode): node is UnaryOpNode => ( node instanceof UnaryOpNode && node.operator === UnaryOperator.SIZE ); + +// If the expression is a function call, returns that function's ordered return types (undefined +// otherwise). A user-defined function is the only source of an N-ary (N >= 2) tuple to destructure. +function functionCallReturnTypes(node: ExpressionNode): Type[] | undefined { + if (!(node instanceof FunctionCallNode)) return undefined; + return node.identifier.symbol?.returnTypes; +} diff --git a/packages/cashc/test/ast/fixtures.ts b/packages/cashc/test/ast/fixtures.ts index 55f856a5..da3e9d90 100644 --- a/packages/cashc/test/ast/fixtures.ts +++ b/packages/cashc/test/ast/fixtures.ts @@ -366,8 +366,10 @@ export const fixtures: Fixture[] = [ ], new BlockNode([ new TupleAssignmentNode( - { name: 'blockHeightBin', type: new BytesType(4) }, - { name: 'priceBin', type: new BytesType(4) }, + [ + { name: 'blockHeightBin', type: new BytesType(4) }, + { name: 'priceBin', type: new BytesType(4) }, + ], new BinaryOpNode( new IdentifierNode('oracleMessage'), BinaryOperator.SPLIT, diff --git a/packages/cashc/test/compiler/ConstantDefinitionError/runtime_value.cash b/packages/cashc/test/compiler/ConstantDefinitionError/runtime_value.cash new file mode 100644 index 00000000..5605631c --- /dev/null +++ b/packages/cashc/test/compiler/ConstantDefinitionError/runtime_value.cash @@ -0,0 +1,7 @@ +int constant LOCKTIME = tx.locktime; + +contract Test() { + function spend() { + require(LOCKTIME > 0); + } +} diff --git a/packages/cashc/test/compiler/ConstantDefinitionError/type_mismatch.cash b/packages/cashc/test/compiler/ConstantDefinitionError/type_mismatch.cash new file mode 100644 index 00000000..7c2c284a --- /dev/null +++ b/packages/cashc/test/compiler/ConstantDefinitionError/type_mismatch.cash @@ -0,0 +1,7 @@ +bytes32 constant HASH = 0xbeef; + +contract Test() { + function spend(bytes32 h) { + require(h == HASH); + } +} diff --git a/packages/cashc/test/compiler/ConstantDefinitionError/unknown_reference.cash b/packages/cashc/test/compiler/ConstantDefinitionError/unknown_reference.cash new file mode 100644 index 00000000..35de3a90 --- /dev/null +++ b/packages/cashc/test/compiler/ConstantDefinitionError/unknown_reference.cash @@ -0,0 +1,8 @@ +int constant DERIVED = BASE + 1; +int constant BASE = 10; + +contract Test() { + function spend() { + require(DERIVED > 0); + } +} diff --git a/packages/cashc/test/compiler/ConstantModificationError/tuple_reassign_constant.cash b/packages/cashc/test/compiler/ConstantModificationError/tuple_reassign_constant.cash new file mode 100644 index 00000000..f439d564 --- /dev/null +++ b/packages/cashc/test/compiler/ConstantModificationError/tuple_reassign_constant.cash @@ -0,0 +1,11 @@ +function pair(int n) returns (int, int) { + return n + 1, n + 2; +} + +contract Test() { + function spend(int n) { + int constant f = 5; + int q, f = pair(n); + require(q > f); + } +} diff --git a/packages/cashc/test/compiler/ConstantNameCollisionError/assign_to_constant.cash b/packages/cashc/test/compiler/ConstantNameCollisionError/assign_to_constant.cash new file mode 100644 index 00000000..c3e1fa59 --- /dev/null +++ b/packages/cashc/test/compiler/ConstantNameCollisionError/assign_to_constant.cash @@ -0,0 +1,8 @@ +int constant FEE = 1000; + +contract Test() { + function spend(int x) { + FEE = x; + require(FEE > 0); + } +} diff --git a/packages/cashc/test/compiler/ConstantNameCollisionError/function_shadows_constant.cash b/packages/cashc/test/compiler/ConstantNameCollisionError/function_shadows_constant.cash new file mode 100644 index 00000000..ae645f76 --- /dev/null +++ b/packages/cashc/test/compiler/ConstantNameCollisionError/function_shadows_constant.cash @@ -0,0 +1,11 @@ +int constant FEE = 1000; + +function FEE(int x) returns (int) { + return x; +} + +contract Test() { + function spend(int x) { + require(FEE(x) > 0); + } +} diff --git a/packages/cashc/test/compiler/ConstantNameCollisionError/local_shadows_constant.cash b/packages/cashc/test/compiler/ConstantNameCollisionError/local_shadows_constant.cash new file mode 100644 index 00000000..9cafa354 --- /dev/null +++ b/packages/cashc/test/compiler/ConstantNameCollisionError/local_shadows_constant.cash @@ -0,0 +1,8 @@ +int constant FEE = 1000; + +contract Test() { + function spend() { + int FEE = 5; + require(FEE > 0); + } +} diff --git a/packages/cashc/test/compiler/ConstantNameCollisionError/param_shadows_constant.cash b/packages/cashc/test/compiler/ConstantNameCollisionError/param_shadows_constant.cash new file mode 100644 index 00000000..0e02302e --- /dev/null +++ b/packages/cashc/test/compiler/ConstantNameCollisionError/param_shadows_constant.cash @@ -0,0 +1,7 @@ +int constant FEE = 1000; + +contract Test() { + function spend(int FEE) { + require(FEE > 0); + } +} diff --git a/packages/cashc/test/compiler/ConstantRedefinitionError/duplicate_constant.cash b/packages/cashc/test/compiler/ConstantRedefinitionError/duplicate_constant.cash new file mode 100644 index 00000000..66ef1c53 --- /dev/null +++ b/packages/cashc/test/compiler/ConstantRedefinitionError/duplicate_constant.cash @@ -0,0 +1,8 @@ +int constant FEE = 1000; +int constant FEE = 2000; + +contract Test() { + function spend() { + require(FEE > 0); + } +} diff --git a/packages/cashc/test/compiler/DuplicateTupleTargetError/declaration_then_reassignment.cash b/packages/cashc/test/compiler/DuplicateTupleTargetError/declaration_then_reassignment.cash new file mode 100644 index 00000000..b1785eb5 --- /dev/null +++ b/packages/cashc/test/compiler/DuplicateTupleTargetError/declaration_then_reassignment.cash @@ -0,0 +1,10 @@ +function pair(int n) returns (int, int) { + return n + 1, n + 2; +} + +contract Test() { + function spend(int n) { + int a, a = pair(n); + require(a > 0); + } +} diff --git a/packages/cashc/test/compiler/DuplicateTupleTargetError/duplicate_reassignment_targets.cash b/packages/cashc/test/compiler/DuplicateTupleTargetError/duplicate_reassignment_targets.cash new file mode 100644 index 00000000..d4a72125 --- /dev/null +++ b/packages/cashc/test/compiler/DuplicateTupleTargetError/duplicate_reassignment_targets.cash @@ -0,0 +1,11 @@ +function pair(int n) returns (int, int) { + return n + 1, n + 2; +} + +contract Test() { + function spend(int n) { + int a = n; + (a, a) = pair(n); + require(a > 0); + } +} diff --git a/packages/cashc/test/compiler/InvalidModifierError/constant_on_contract_parameter.cash b/packages/cashc/test/compiler/InvalidModifierError/constant_on_contract_parameter.cash new file mode 100644 index 00000000..0ad5a077 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/constant_on_contract_parameter.cash @@ -0,0 +1,6 @@ +contract Test(int constant a) { + function hello(sig s, pubkey pk) { + require(checkSig(s, pk)); + require(a > 0); + } +} diff --git a/packages/cashc/test/compiler/InvalidModifierError/constant_on_function_parameter.cash b/packages/cashc/test/compiler/InvalidModifierError/constant_on_function_parameter.cash new file mode 100644 index 00000000..6c93ddbf --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/constant_on_function_parameter.cash @@ -0,0 +1,5 @@ +contract Test() { + function hello(int constant a) { + require(a > 0); + } +} diff --git a/packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier.cash b/packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier.cash new file mode 100644 index 00000000..5c8d3e57 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier.cash @@ -0,0 +1,5 @@ +contract Test() { + function hello(int a, bytes unused unused zeroPadding) { + require(a > 0); + } +} diff --git a/packages/cashc/test/compiler/InvalidSymbolTypeError/tuple_reassign_function_name.cash b/packages/cashc/test/compiler/InvalidSymbolTypeError/tuple_reassign_function_name.cash new file mode 100644 index 00000000..572e098e --- /dev/null +++ b/packages/cashc/test/compiler/InvalidSymbolTypeError/tuple_reassign_function_name.cash @@ -0,0 +1,10 @@ +function pair(int n) returns (int, int) { + return n + 1, n + 2; +} + +contract Test() { + function spend(int n) { + int q, pair = pair(n); + require(q > 0); + } +} diff --git a/packages/cashc/test/compiler/MultiReturnDestructureError/multi_return_nested_in_split_rhs.cash b/packages/cashc/test/compiler/MultiReturnDestructureError/multi_return_nested_in_split_rhs.cash new file mode 100644 index 00000000..dd4d4610 --- /dev/null +++ b/packages/cashc/test/compiler/MultiReturnDestructureError/multi_return_nested_in_split_rhs.cash @@ -0,0 +1,12 @@ +function pair() returns (bytes, bytes) { + return 0x0102, 0x030405; +} + +contract Test() { + function spend() { + // pair() is nested inside the RHS, not the RHS itself: its first return value + // would be silently discarded + bytes a, bytes b = pair().split(1); + require(a != b); + } +} diff --git a/packages/cashc/test/compiler/MultiReturnDestructureError/used_as_single_value.cash b/packages/cashc/test/compiler/MultiReturnDestructureError/used_as_single_value.cash new file mode 100644 index 00000000..27e7c92e --- /dev/null +++ b/packages/cashc/test/compiler/MultiReturnDestructureError/used_as_single_value.cash @@ -0,0 +1,9 @@ +function pair(int a) returns (int, int) { + return a, a + 1; +} + +contract Test() { + function spend(int x) { + require(pair(x) == 3); + } +} diff --git a/packages/cashc/test/compiler/ParseError/single_type_destructuring.cash b/packages/cashc/test/compiler/ParseError/single_type_destructuring.cash deleted file mode 100644 index 89afb1bf..00000000 --- a/packages/cashc/test/compiler/ParseError/single_type_destructuring.cash +++ /dev/null @@ -1,5 +0,0 @@ -contract Test() { - function test1(string s) { - string x, y = s.split(5); - } -} diff --git a/packages/cashc/test/compiler/ReturnTypeError/return_in_contract_function.cash b/packages/cashc/test/compiler/ReturnCountError/return_in_contract_function.cash similarity index 100% rename from packages/cashc/test/compiler/ReturnTypeError/return_in_contract_function.cash rename to packages/cashc/test/compiler/ReturnCountError/return_in_contract_function.cash diff --git a/packages/cashc/test/compiler/ReturnCountError/too_many_return_values.cash b/packages/cashc/test/compiler/ReturnCountError/too_many_return_values.cash new file mode 100644 index 00000000..d4df23cf --- /dev/null +++ b/packages/cashc/test/compiler/ReturnCountError/too_many_return_values.cash @@ -0,0 +1,10 @@ +function bad(int a) returns (int, int) { + return a; +} + +contract Test() { + function spend(int x) { + int p, int q = bad(x); + require(p == q); + } +} diff --git a/packages/cashc/test/compiler/TupleArityError/destructure_count_mismatch.cash b/packages/cashc/test/compiler/TupleArityError/destructure_count_mismatch.cash new file mode 100644 index 00000000..6f56ddb3 --- /dev/null +++ b/packages/cashc/test/compiler/TupleArityError/destructure_count_mismatch.cash @@ -0,0 +1,11 @@ +function pair(int a) returns (int, int) { + return a, a + 1; +} + +contract Test() { + function spend(int x) { + int p, int q, int r = pair(x); + require(p == q); + require(q == r); + } +} diff --git a/packages/cashc/test/compiler/TupleTargetOrderError/reassignment_before_declaration.cash b/packages/cashc/test/compiler/TupleTargetOrderError/reassignment_before_declaration.cash new file mode 100644 index 00000000..72ae284f --- /dev/null +++ b/packages/cashc/test/compiler/TupleTargetOrderError/reassignment_before_declaration.cash @@ -0,0 +1,11 @@ +function pair(int n) returns (int, int) { + return n + 1, n + 2; +} + +contract Test() { + function spend(int n) { + int a = n; + a, int b = pair(n); + require(a > b); + } +} diff --git a/packages/cashc/test/compiler/UndefinedReferenceError/tuple_reassign_undefined.cash b/packages/cashc/test/compiler/UndefinedReferenceError/tuple_reassign_undefined.cash new file mode 100644 index 00000000..396dcf8a --- /dev/null +++ b/packages/cashc/test/compiler/UndefinedReferenceError/tuple_reassign_undefined.cash @@ -0,0 +1,12 @@ +function swap(int x, int y) returns (int, int) { + return y, x; +} + +contract Test() { + function spend(int seed) { + int a = seed; + // `b` is never declared, so reassigning it must fail + (a, b) = swap(a, seed); + require(a + b >= 0); + } +} diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash b/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash index a37120dd..f4966201 100644 --- a/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash +++ b/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash @@ -1,5 +1,5 @@ function withUnusedLocal(int a) returns (int) { - int unused = a + 1; + int scratch = a + 1; return a; } diff --git a/packages/cashc/test/compiler/compiler.test.ts b/packages/cashc/test/compiler/compiler.test.ts index f121476c..d62c7ff1 100644 --- a/packages/cashc/test/compiler/compiler.test.ts +++ b/packages/cashc/test/compiler/compiler.test.ts @@ -86,6 +86,7 @@ describe('Compiler', () => { expect(artifact.compiler.options).toEqual({ enforceFunctionParameterTypes: true, enforceLocktimeGuard: false, + optimizeFor: 'opcost', }); }); }); diff --git a/packages/cashc/test/constant-folding.test.ts b/packages/cashc/test/constant-folding.test.ts new file mode 100644 index 00000000..678c8941 --- /dev/null +++ b/packages/cashc/test/constant-folding.test.ts @@ -0,0 +1,49 @@ +import { compileString } from '../src/index.js'; + +describe('Top-level constants', () => { + it('inlines a constant as a literal push at each use site', () => { + const code = ` + int constant FEE = 1000; + contract C() { function spend(int x) { require(x - FEE >= FEE); } }`; + const { bytecode } = compileString(code); + // 1000 = 0xe803 as a minimally-encoded script number, pushed at both use sites + expect([...bytecode.matchAll(/e803/g)]).toHaveLength(2); + }); + + it('folds constant arithmetic and references to earlier constants', () => { + const withConstants = ` + int constant BASE = 40; + int constant DERIVED = BASE + 2; + contract C() { function spend(int x) { require(x == DERIVED); } }`; + const literal = ` + contract C() { function spend(int x) { require(x == 42); } }`; + expect(compileString(withConstants).bytecode).toEqual(compileString(literal).bytecode); + }); + + it('substitutes constants inside global function bodies', () => { + const code = ` + int constant PRIME = 7919; + function modP(int x) returns (int) { return x % PRIME; } + contract C() { function spend(int n) { require(modP(n) >= 0); } }`; + const { bytecode } = compileString(code); + // 7919 = 0xef1e as a minimally-encoded script number + expect(bytecode).toContain('ef1e'); + }); + + it('compiles bytes and bool constants with matching declared types', () => { + const code = ` + bytes2 constant TAG = 0xbeef; + bool constant ENABLED = true; + contract C() { function spend(bytes2 tag) { require(ENABLED); require(tag == TAG); } }`; + expect(() => compileString(code)).not.toThrow(); + }); + + it('allows a constant that is never used', () => { + const code = ` + int constant UNUSED = 123456789; + contract C() { function spend() { require(true); } }`; + const { bytecode } = compileString(code); + // The folded literal never reaches the bytecode + expect(bytecode).not.toContain('15cd5b07'); + }); +}); diff --git a/packages/cashc/test/constant-hoisting.test.ts b/packages/cashc/test/constant-hoisting.test.ts new file mode 100644 index 00000000..2d5000a8 --- /dev/null +++ b/packages/cashc/test/constant-hoisting.test.ts @@ -0,0 +1,96 @@ +import { compileString } from '../src/index.js'; + +const P = '21888242871839275222246405745257275088696311157297823662689037894645226208583'; + +const asm = (code: string, hoist: boolean): string => ( + compileString(code, { optimizeFor: hoist ? 'size' : 'opcost' }).bytecode +); +const count = (haystack: string, needle: string): number => haystack.split(needle).length - 1; + +// The prime's minimal VM-number encoding as it appears in ASM (64 hex chars), derived +// from a single-use compile so the tests don't hardcode the encoding. +const PRIME_ASM = asm(`contract C() { function spend(int x) { require(x == ${P}); } }`, false) + .match(/[0-9a-f]{64}/)![0]; + +describe("Repeated-constant hoisting (optimizeFor: 'size')", () => { + const doubleUse = ` + contract C() { + function spend(int x, int y) { + require((x - y + ${P}) % ${P} == 1); + } + }`; + + it('is off by default: the duplicate literal is pushed twice', () => { + expect(count(asm(doubleUse, false), PRIME_ASM)).toBe(2); + }); + + it("defaults to the 'opcost' objective when the option is unset", () => { + expect(compileString(doubleUse).bytecode).toBe(asm(doubleUse, false)); + }); + + it('binds a duplicated big literal to a local under the flag', () => { + expect(count(asm(doubleUse, true), PRIME_ASM)).toBe(1); + }); + + it('shrinks the bytecode under the flag', () => { + expect(asm(doubleUse, true).length).toBeLessThan(asm(doubleUse, false).length); + }); + + it('hoists inside global function bodies too', () => { + const code = ` + function subFp(int x, int y) returns (int) { return (x - y + ${P}) % ${P}; } + contract C() { + function spend(int x, int y) { require(subFp(x, y) == 1); } + }`; + expect(count(asm(code, false), PRIME_ASM)).toBe(2); + expect(count(asm(code, true), PRIME_ASM)).toBe(1); + }); + + it('hoists a duplicated big hex literal', () => { + const blob = 'aa'.repeat(32); + const code = ` + contract C() { + function spend(bytes b) { + require(b.split(32)[0] == 0x${blob} || b.split(32)[1] == 0x${blob}); + } + }`; + expect(count(asm(code, false), blob)).toBe(2); + expect(count(asm(code, true), blob)).toBe(1); + }); + + it('leaves small repeated literals alone (hoisting would cost bytes)', () => { + const code = ` + contract C() { + function spend(int x) { require((x + 3) % 3 == 1); } + }`; + expect(asm(code, true)).toBe(asm(code, false)); + }); + + it('avoids colliding with existing names', () => { + const code = ` + contract C() { + function spend(int hc0, int y) { + require((hc0 - y + ${P}) % ${P} == 1); + } + }`; + expect(count(asm(code, true), PRIME_ASM)).toBe(1); // compiles (no shadowing), still hoisted + }); + + it('composes with folded top-level constants', () => { + const code = ` + int constant PRIME = ${P}; + contract C() { + function spend(int x, int y) { + require((x - y + PRIME) % PRIME == 1); + } + }`; + expect(count(asm(code, false), PRIME_ASM)).toBe(2); + expect(count(asm(code, true), PRIME_ASM)).toBe(1); + }); + + it('produces the same ABI either way', () => { + const a = compileString(doubleUse, { optimizeFor: 'size' }); + const b = compileString(doubleUse, { optimizeFor: 'opcost' }); + expect(a.abi).toEqual(b.abi); + }); +}); diff --git a/packages/cashc/test/dead-code-elimination.test.ts b/packages/cashc/test/dead-code-elimination.test.ts index 1665bdc0..a06c36d2 100644 --- a/packages/cashc/test/dead-code-elimination.test.ts +++ b/packages/cashc/test/dead-code-elimination.test.ts @@ -6,7 +6,7 @@ describe('Dead-code elimination', () => { it('does not define a global function that is never invoked', () => { const code = ` function used(int a) returns (int) { return a + 1; } - function unused(int a) returns (int) { return a * 2; } + function notInvoked(int a) returns (int) { return a * 2; } contract Test() { function spend(int x) { @@ -14,7 +14,8 @@ describe('Dead-code elimination', () => { } }`; - const artifact = compileString(code); + // Disable inlining so OP_DEFINE count reflects dead-code elimination alone. + const artifact = compileString(code, { disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(1); expect(artifact.bytecode).toContain('OP_INVOKE'); }); @@ -32,7 +33,8 @@ describe('Dead-code elimination', () => { }`; // Only `used` is reachable; both `deadCaller` and the function it calls (`deadLeaf`) are dropped. - const artifact = compileString(code); + // Disable inlining so OP_DEFINE count reflects dead-code elimination alone. + const artifact = compileString(code, { disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(1); }); @@ -48,7 +50,8 @@ describe('Dead-code elimination', () => { }`; // `outer` is called directly and `inner` only through `outer` — both must be defined. - const artifact = compileString(code); + // Disable inlining so OP_DEFINE count reflects dead-code elimination alone. + const artifact = compileString(code, { disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(2); }); @@ -62,7 +65,8 @@ describe('Dead-code elimination', () => { } }`; - const artifact = compileString(code); + // Disable inlining so OP_DEFINE count reflects dead-code elimination alone. + const artifact = compileString(code, { disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(1); }); @@ -77,7 +81,8 @@ describe('Dead-code elimination', () => { } }`; - const artifact = compileString(code); + // Disable inlining so OP_DEFINE count reflects dead-code elimination alone. + const artifact = compileString(code, { disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(2); }); @@ -94,7 +99,8 @@ describe('Dead-code elimination', () => { }`; // deadA <-> deadB form a cycle but neither is reachable, so both are dropped. - const artifact = compileString(code); + // Disable inlining so OP_DEFINE count reflects dead-code elimination alone. + const artifact = compileString(code, { disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(1); }); @@ -106,7 +112,7 @@ describe('Dead-code elimination', () => { function double(int a) returns (int) { return a * 2; } `; - const artifact = compileString(code, { files: { './math.cash': mathSource } }); + const artifact = compileString(code, { files: { './math.cash': mathSource }, disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(1); }); }); diff --git a/packages/cashc/test/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts index a22d7743..b435034d 100644 --- a/packages/cashc/test/generation/fixtures.ts +++ b/packages/cashc/test/generation/fixtures.ts @@ -37,6 +37,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -83,6 +84,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -135,6 +137,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -181,6 +184,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -259,6 +263,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -287,6 +292,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -322,6 +328,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -355,6 +362,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -420,6 +428,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -457,6 +466,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -488,6 +498,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -526,6 +537,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -621,6 +633,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -704,6 +717,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -759,6 +773,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -787,6 +802,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -815,6 +831,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -846,6 +863,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -874,6 +892,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -904,6 +923,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -949,6 +969,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -980,6 +1001,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1012,6 +1034,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1044,6 +1067,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1073,6 +1097,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1102,6 +1127,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1133,6 +1159,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1175,6 +1202,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1206,6 +1234,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1238,6 +1267,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1268,6 +1298,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1297,6 +1328,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1350,6 +1382,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1402,6 +1435,7 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: false, enforceLocktimeGuard: true, + optimizeFor: 'opcost', }, }, updatedAt: '', @@ -1411,6 +1445,8 @@ export const fixtures: Fixture[] = [ { // A single global function — the basic OP_DEFINE / OP_INVOKE calling convention. fn: 'global_function_simple.cash', + // Disable inlining so this fixture locks in the OP_DEFINE/OP_INVOKE codegen path. + compilerOptions: { disableInlining: true }, artifact: { contractName: 'GlobalFunctionSimple', constructorInputs: [], @@ -1446,6 +1482,8 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', + disableInlining: true, }, }, updatedAt: '', @@ -1456,29 +1494,30 @@ export const fixtures: Fixture[] = [ // A multi-parameter global function — locks in the parameter stack-seeding and argument order // (the contract OP_SWAPs x and y into place; the body computes a - b directly). fn: 'global_function_multi_param.cash', + compilerOptions: { disableInlining: true }, artifact: { contractName: 'GlobalFunctionMultiParam', constructorInputs: [], abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }] }], bytecode: - // OP_DEFINE sub (id 0): return a - b - '94 OP_0 OP_DEFINE ' - // require(sub(x, y) == 7) - + 'OP_SWAP OP_0 OP_INVOKE OP_7 OP_NUMEQUAL', + // OP_DEFINE sub (id 0): return a - b (entry layout is first-param-on-top, hence the swap) + '7c94 OP_0 OP_DEFINE ' + // require(sub(x, y) == 7) — declaration-order args need no staging at the call site + + 'OP_0 OP_INVOKE OP_7 OP_NUMEQUAL', debug: { - bytecode: '019400897c008a579c', + bytecode: '027c940089008a579c', logs: [], requires: [ - { ip: 8, line: 7 }, + { ip: 7, line: 7 }, ], - sourceMap: '1::3:1;;::::1;7:23:7:24:0;:16::25:1;;:29::30:0;:8::32:1', + sourceMap: '1::3:1;;::::1;7:16:7:25;;:29::30:0;:8::32:1', functions: [ { id: 0, name: 'sub', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }], - bytecode: '94', - sourceMap: '2:11:2:16:1', + bytecode: '7c94', + sourceMap: '2:15:2:16;:11:::1', logs: [], requires: [], }, @@ -1491,15 +1530,18 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', + disableInlining: true, }, }, updatedAt: '', - fingerprint: '8fc72a3f89ee3238266d6dd9ad3919f7238c8d6a31296cc8925968a31c78c7dc', + fingerprint: 'ef6dd7819e66a430286fe16f3d6dad7e026cf1970eda6bc620be7e7a3bdd2a4d', }, }, { // A void global function called as a statement — no return value, and the void stack-cleanup path. fn: 'global_function_void.cash', + compilerOptions: { disableInlining: true }, artifact: { contractName: 'GlobalFunctionVoid', constructorInputs: [], @@ -1535,6 +1577,8 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', + disableInlining: true, }, }, updatedAt: '', @@ -1545,6 +1589,7 @@ export const fixtures: Fixture[] = [ // Imports resolved across a diamond (mid1 and mid2 both import leaf): leaf is defined once, and // m1/m2 invoke it transitively. fn: '../import-fixtures/diamond.cash', + compilerOptions: { disableInlining: true }, artifact: { contractName: 'Diamond', constructorInputs: [], @@ -1609,6 +1654,8 @@ export const fixtures: Fixture[] = [ options: { enforceFunctionParameterTypes: true, enforceLocktimeGuard: true, + optimizeFor: 'opcost', + disableInlining: true, }, }, updatedAt: '', diff --git a/packages/cashc/test/import-fixtures/constants_lib.cash b/packages/cashc/test/import-fixtures/constants_lib.cash new file mode 100644 index 00000000..e8681a80 --- /dev/null +++ b/packages/cashc/test/import-fixtures/constants_lib.cash @@ -0,0 +1,7 @@ +pragma cashscript ^0.14.0; + +int constant PRIME = 7919; + +function modP(int x) returns (int) { + return x % PRIME; +} diff --git a/packages/cashc/test/import-fixtures/constants_main.cash b/packages/cashc/test/import-fixtures/constants_main.cash new file mode 100644 index 00000000..ae476e38 --- /dev/null +++ b/packages/cashc/test/import-fixtures/constants_main.cash @@ -0,0 +1,9 @@ +pragma cashscript ^0.14.0; + +import "./constants_lib.cash"; + +contract ConstantsMain() { + function spend(int n) { + require(modP(n) < PRIME); + } +} diff --git a/packages/cashc/test/import-fixtures/multi_return_lib.cash b/packages/cashc/test/import-fixtures/multi_return_lib.cash new file mode 100644 index 00000000..f243ae4b --- /dev/null +++ b/packages/cashc/test/import-fixtures/multi_return_lib.cash @@ -0,0 +1,3 @@ +function divmod(int a, int b) returns (int, int) { + return a / b, a % b; +} diff --git a/packages/cashc/test/import-fixtures/multi_return_main.cash b/packages/cashc/test/import-fixtures/multi_return_main.cash new file mode 100644 index 00000000..2298ab64 --- /dev/null +++ b/packages/cashc/test/import-fixtures/multi_return_main.cash @@ -0,0 +1,9 @@ +import "./multi_return_lib.cash"; + +contract MultiReturnMain() { + function spend(int x) { + int q, int r = divmod(x, 3); + require(q == 4); + require(r == 1); + } +} diff --git a/packages/cashc/test/imports.test.ts b/packages/cashc/test/imports.test.ts index f797016e..27de3198 100644 --- a/packages/cashc/test/imports.test.ts +++ b/packages/cashc/test/imports.test.ts @@ -11,7 +11,8 @@ const countOpDefines = (bytecode: string): number => [...bytecode.matchAll(/OP_D describe('Imports from the filesystem (compileFile)', () => { it('merges global functions from an imported file', () => { - const artifact = compileFile(fixture('main.cash')); + // Disable inlining so the merged functions are observable as OP_DEFINE/OP_INVOKE. + const artifact = compileFile(fixture('main.cash'), { disableInlining: true }); expect(artifact.contractName).toEqual('Main'); expect(artifact.bytecode).toContain('OP_INVOKE'); // both imported functions are defined (one OP_DEFINE each) @@ -21,11 +22,28 @@ describe('Imports from the filesystem (compileFile)', () => { it('de-duplicates a diamond import so a shared leaf is defined once', () => { // Diamond imports mid1 and mid2, which both import leaf. The leaf function must be merged once // (otherwise it would be a redefinition): leaf, m1, m2 = 3 OP_DEFINEs. - const artifact = compileFile(fixture('diamond.cash')); + const artifact = compileFile(fixture('diamond.cash'), { disableInlining: true }); expect(artifact.contractName).toEqual('Diamond'); expect(countOpDefines(artifact.bytecode)).toEqual(3); }); + it('destructures a multi-return function imported from another file', () => { + // The multi-return function is defined in an imported file and destructured in the contract, + // proving multi-return composes with the import/module system. + const artifact = compileFile(fixture('multi_return_main.cash'), { disableInlining: true }); + expect(artifact.contractName).toEqual('MultiReturnMain'); + expect(artifact.bytecode).toContain('OP_INVOKE'); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('merges top-level constants from an imported file', () => { + // The imported constant is usable both inside the imported function body and in the contract. + const artifact = compileFile(fixture('constants_main.cash')); + expect(artifact.contractName).toEqual('ConstantsMain'); + // 7919 = 0xef1e as a minimally-encoded script number, pushed at both use sites + expect([...artifact.bytecode.matchAll(/ef1e/g)]).toHaveLength(2); + }); + it('throws when an imported file cannot be found', () => { expect(() => compileFile(fixture('missing_import_main.cash'))).toThrow(ImportResolutionError); }); @@ -38,13 +56,14 @@ describe('Imports from the filesystem (compileFile)', () => { it('resolves a cyclic import without infinite looping', () => { // cycle_a imports cycle_b which imports cycle_a back; de-duplication by canonical path breaks the // cycle, and both functions (a and b) end up defined exactly once. - const artifact = compileFile(fixture('cycle_main.cash')); + const artifact = compileFile(fixture('cycle_main.cash'), { disableInlining: true }); expect(artifact.contractName).toEqual('Cycle'); expect(countOpDefines(artifact.bytecode)).toEqual(2); }); it('records provenance as the path relative to the main file', () => { - const artifact = compileFile(fixture('nested_main.cash')); + // Disable inlining so the imported function keeps its OP_DEFINE and debug frame. + const artifact = compileFile(fixture('nested_main.cash'), { disableInlining: true }); expect(artifact.debug?.functions?.map((func) => func.sourceFile)).toEqual(['nested/helper.cash']); }); @@ -63,14 +82,15 @@ describe('Imports from in-memory files (compileString)', () => { const mainCode = 'import "./math.cash";\ncontract Main() { function spend(int x) { require(double(addOne(x)) == 8); } }'; it('merges global functions from a provided file', () => { - const artifact = compileString(mainCode, { files: { './math.cash': mathSource } }); + // Disable inlining so the merged functions are observable as OP_DEFINE/OP_INVOKE. + const artifact = compileString(mainCode, { files: { './math.cash': mathSource }, disableInlining: true }); expect(artifact.contractName).toEqual('Main'); expect(artifact.bytecode).toContain('OP_INVOKE'); expect(countOpDefines(artifact.bytecode)).toEqual(2); }); it('normalises file keys so they match regardless of a leading ./', () => { - const artifact = compileString(mainCode, { files: { 'math.cash': mathSource } }); + const artifact = compileString(mainCode, { files: { 'math.cash': mathSource }, disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(2); }); @@ -82,7 +102,7 @@ describe('Imports from in-memory files (compileString)', () => { 'lib/b.cash': 'function b(int n) returns (int) { return n * 3; }', }; - const artifact = compileString(code, { files }); + const artifact = compileString(code, { files, disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(2); expect(artifact.debug?.functions?.map((func) => func.sourceFile).sort()).toEqual(['lib/a.cash', 'lib/b.cash']); }); @@ -95,7 +115,7 @@ describe('Imports from in-memory files (compileString)', () => { 'b/helper.cash': 'function helperB(int n) returns (int) { return n * 2; }', }; - const artifact = compileString(code, { files }); + const artifact = compileString(code, { files, disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(2); }); @@ -108,7 +128,7 @@ describe('Imports from in-memory files (compileString)', () => { 'leaf.cash': 'function leaf(int a) returns (int) { return a + 1; }', }; - const artifact = compileString(code, { files }); + const artifact = compileString(code, { files, disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(3); }); @@ -116,7 +136,7 @@ describe('Imports from in-memory files (compileString)', () => { const code = 'import "../shared.cash";\ncontract C() { function spend(int x) { require(shared(x) == 4); } }'; const files = { '../shared.cash': 'function shared(int n) returns (int) { return n + 1; }' }; - const artifact = compileString(code, { files }); + const artifact = compileString(code, { files, disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(1); }); @@ -130,7 +150,7 @@ describe('Imports from in-memory files (compileString)', () => { it('compiles when the pragmas of all imported files are satisfied', () => { const files = { './math.cash': `pragma cashscript >=0.14.0;\n${mathSource}` }; - const artifact = compileString(mainCode, { files }); + const artifact = compileString(mainCode, { files, disableInlining: true }); expect(countOpDefines(artifact.bytecode)).toEqual(2); }); @@ -160,7 +180,8 @@ describe('compileFile / compileString equivalence', () => { // and a parent-directory import reached through two different routes (main imports // '../shared.cash' and lib/a.cash imports '../../shared.cash' — both must de-duplicate to the // same file). - const fromDisk = compileFile(fixture('complex/main.cash')); + // Disable inlining so the OP_DEFINE count below observes all four imported functions. + const fromDisk = compileFile(fixture('complex/main.cash'), { disableInlining: true }); const files = { 'lib/a.cash': readFixture('complex/lib/a.cash'), @@ -168,7 +189,7 @@ describe('compileFile / compileString equivalence', () => { 'lib/util/leaf.cash': readFixture('complex/lib/util/leaf.cash'), '../shared.cash': readFixture('shared.cash'), }; - const fromString = compileString(readFixture('complex/main.cash'), { files }); + const fromString = compileString(readFixture('complex/main.cash'), { files, disableInlining: true }); // sanity-check the fixture actually pulls in all four imported functions expect(countOpDefines(fromDisk.bytecode)).toEqual(4); diff --git a/packages/cashc/test/inlining.test.ts b/packages/cashc/test/inlining.test.ts new file mode 100644 index 00000000..06fd7d0c --- /dev/null +++ b/packages/cashc/test/inlining.test.ts @@ -0,0 +1,119 @@ +import { compileString } from '../src/index.js'; + +const hasDefine = (bytecode: string): boolean => /OP_DEFINE/.test(bytecode); +const hasInvoke = (bytecode: string): boolean => /OP_INVOKE/.test(bytecode); + +describe('Function inlining', () => { + it('inlines a single-use function (OP_DEFINE/OP_INVOKE would be pure overhead)', () => { + const code = ` + function triple(int x) returns (int) { return x * 3; } + contract C() { function spend(int n) { require(triple(n) == 12); } }`; + const { bytecode } = compileString(code); + expect(hasDefine(bytecode)).toBe(false); + expect(hasInvoke(bytecode)).toBe(false); + }); + + it('inlines a small multi-use function', () => { + const code = ` + function inc(int x) returns (int) { return x + 1; } + contract C() { function spend(int n) { require(inc(n) + inc(n) == 12); } }`; + expect(hasDefine(compileString(code).bytecode)).toBe(false); + }); + + it('shares a large multi-use function via OP_DEFINE/OP_INVOKE', () => { + const code = ` + function big(int x) returns (int) { return (x * 7 + 3) * (x + 11) - 5; } + contract C() { function spend(int n) { require(big(n) + big(n + 1) > 0); } }`; + const { bytecode } = compileString(code); + expect(hasDefine(bytecode)).toBe(true); + expect(hasInvoke(bytecode)).toBe(true); + }); + + it("inlines a small multi-use body under 'opcost' (default) even when OP_DEFINE would be smaller", () => { + // 5-byte body used 4x: byte-exact accounting prefers OP_DEFINE (16 vs 20 bytes), but every + // invocation costs ~2 executed instructions that splicing avoids — the 'opcost' objective + // (the default) takes the ops, the 'size' objective takes the bytes. + const code = ` + function addF(int x, int y) returns (int) { return (x + y) % 7919; } + contract C() { + function spend(int a, int b) { + int t1 = addF(a, b); + int t2 = addF(t1, a); + int t3 = addF(t2, b); + require(addF(t3, t1) >= 0); + } + }`; + expect(hasDefine(compileString(code).bytecode)).toBe(false); + expect(hasDefine(compileString(code, { optimizeFor: 'opcost' }).bytecode)).toBe(false); + expect(hasDefine(compileString(code, { optimizeFor: 'size' }).bytecode)).toBe(true); + }); + + it('never inlines a recursive function (would splice a call to an undefined body)', () => { + const code = ` + function loop(int x) returns (int) { return loop(x) + 1; } + contract C() { function spend(int n) { require(loop(n) == 1); } }`; + const { bytecode } = compileString(code); + expect(hasDefine(bytecode)).toBe(true); + expect(hasInvoke(bytecode)).toBe(true); + }); + + it('keeps a function called inside a loop shared via OP_DEFINE (skipped-branch stepping cost)', () => { + const code = ` + function big(int x) returns (int) { return (x * 7 + 3) * (x + 11) - 5; } + contract C() { + function spend(int n) { + int acc = 0; + for (int i = 0; i < 10; i = i + 1) { + if (n > i) { acc = big(acc + i); } + } + require(acc > 0); + } + }`; + const { bytecode } = compileString(code); + expect(hasDefine(bytecode)).toBe(true); + expect(hasInvoke(bytecode)).toBe(true); + }); + + it('keeps the callees of a loop-called function shared too (they would be stepped per iteration)', () => { + const code = ` + function inner(int x) returns (int) { return (x * 7 + 3) * (x + 11) - 5; } + function outer(int x) returns (int) { if (x > 5) { x = inner(x); } return x; } + contract C() { + function spend(int n) { + int acc = 0; + for (int i = 0; i < 10; i = i + 1) { acc = outer(acc + n); } + require(acc > 0); + } + }`; + const { bytecode } = compileString(code); + // both outer and inner stay defined -> two OP_DEFINEs + expect((bytecode.match(/OP_DEFINE/g) ?? []).length).toBe(2); + expect(hasInvoke(bytecode)).toBe(true); + }); + + it('still inlines a tiny body inside a loop (steps no more than the invoke site would)', () => { + const code = ` + function inc(int x) returns (int) { return x + 1; } + contract C() { + function spend(int n) { + int acc = 0; + for (int i = 0; i < 10; i = i + 1) { + if (n > i) { acc = inc(acc); } + } + require(acc > 0); + } + }`; + const { bytecode } = compileString(code); + expect(hasDefine(bytecode)).toBe(false); + expect(hasInvoke(bytecode)).toBe(false); + }); + + it('disableInlining keeps a single-use function shared via OP_DEFINE', () => { + const code = ` + function triple(int x) returns (int) { return x * 3; } + contract C() { function spend(int n) { require(triple(n) == 12); } }`; + const { bytecode } = compileString(code, { disableInlining: true }); + expect(hasDefine(bytecode)).toBe(true); + expect(hasInvoke(bytecode)).toBe(true); + }); +}); diff --git a/packages/cashc/test/tuple-destructuring.test.ts b/packages/cashc/test/tuple-destructuring.test.ts new file mode 100644 index 00000000..67366821 --- /dev/null +++ b/packages/cashc/test/tuple-destructuring.test.ts @@ -0,0 +1,101 @@ +import { + createTestAuthenticationProgramBch, + createVirtualMachineBch2026, +} from '@bitauth/libauth'; +import { asmToBytecode, encodeInt, scriptToBytecode } from '@cashscript/utils'; +import { compileString } from '../src/index.js'; + +const vm = createVirtualMachineBch2026(false); + +// evaluate a compiled contract (no constructor args) directly against pushed spend args +function evaluate(bytecodeAsm: string, args: bigint[]): boolean { + // spend args are pushed in reverse declaration order (first parameter on top) + const unlocking = scriptToBytecode([...args].reverse().map((arg) => encodeInt(arg))); + const state = vm.evaluate(createTestAuthenticationProgramBch({ + lockingBytecode: asmToBytecode(bytecodeAsm), + unlockingBytecode: unlocking, + valueSatoshis: 1000n, + })); + const top = state.stack[state.stack.length - 1]; + return state.error === undefined && state.stack.length === 1 && top !== undefined && top.length === 1 && top[0] === 1; +} + +// Execution coverage for the SCOPED destructuring fold (GenerateTargetTraversal +// visitTupleAssignment): inside a loop/branch the stack layout must be preserved, so +// reassignments are folded into the existing slots via emitReplace instead of the +// depth-0 pure-rename strategy. +describe('tuple destructuring into existing variables (scoped fold)', () => { + it.each([[true], [false]] as const)( + 'folds pure reassignment in a loop (disableInlining: %s)', + (disableInlining) => { + const code = ` + function swap(int x, int y) returns (int, int) { + return y, x; + } + contract LoopSwap() { + function spend(int a, int b) { + // odd iteration count: the net effect is one swap + for (int i = 0; i < 3; i = i + 1) { + (a, b) = swap(a, b); + } + require(a > b); + } + }`; + const artifact = compileString(code, { disableInlining }); + + // after the net swap, a holds the original b + expect(evaluate(artifact.bytecode, [2n, 5n])).toBe(true); + expect(evaluate(artifact.bytecode, [5n, 2n])).toBe(false); + }, + ); + + it('folds mixed declaration + reassignment inside a branch', () => { + const code = ` + function pair(int n) returns (int, int) { + return n * 2, n + 1; + } + contract BranchFold() { + function spend(int a) { + int total = 0; + if (a > 10) { + int d, total = pair(a); + require(d == a * 2); + } + require(total > 0); + } + }`; + const artifact = compileString(code); + + // branch taken: total is reassigned to a + 1 > 0 + expect(evaluate(artifact.bytecode, [11n])).toBe(true); + // branch not taken: total stays 0 and the final require fails + expect(evaluate(artifact.bytecode, [5n])).toBe(false); + }); + + it('folds mixed declaration + reassignment of loop-carried state', () => { + const code = ` + function step(int x, int y) returns (int, int, int) { + return x + y, x + y, y; + } + contract Fib() { + // pad buys op-cost budget for the loop (the budget scales with unlocking bytes) + function spend(int expected, int unused pad) { + int a = 0; + int b = 1; + int last = 0; + for (int i = 0; i < 5; i = i + 1) { + // fresh declaration first, then the two updated accumulators + (int next, b, a) = step(a, b); + last = next; + } + require(last == expected); + } + }`; + const artifact = compileString(code); + const pad = 1n << 4000n; // ~500-byte push + + // fib recurrence (a, b = b, a + b): iterations produce 1, 2, 3, 5, 8 + expect(evaluate(artifact.bytecode, [8n, pad])).toBe(true); + expect(evaluate(artifact.bytecode, [5n, pad])).toBe(false); + }); +}); diff --git a/packages/cashc/test/valid-contract-files/global_constants.cash b/packages/cashc/test/valid-contract-files/global_constants.cash new file mode 100644 index 00000000..83c791e9 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_constants.cash @@ -0,0 +1,20 @@ +pragma cashscript ^0.14.0; + +int constant PRIME = 21888242871839275222246405745257275088696311157297823662689037894645226208583; +int constant PRIME_MINUS_2 = PRIME - 2; +int constant DOUBLED = 2 * 21; +bool constant ENABLED = true && !false; +bytes2 constant TAG = 0xbeef; + +function modP(int x) returns (int) { + return x % PRIME; +} + +contract GlobalConstants() { + function spend(int n, bytes2 tag) { + require(ENABLED); + require(tag == TAG); + require(PRIME_MINUS_2 < PRIME); + require(modP(n) + DOUBLED >= 0); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_function_multi_return.cash b/packages/cashc/test/valid-contract-files/global_function_multi_return.cash new file mode 100644 index 00000000..384ab960 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_multi_return.cash @@ -0,0 +1,11 @@ +function divmod(int a, int b) returns (int, int) { + return a / b, a % b; +} + +contract GlobalFunctionMultiReturn() { + function spend(int x) { + int q, int r = divmod(x, 3); + require(q == 4); + require(r == 1); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_function_multi_return_three.cash b/packages/cashc/test/valid-contract-files/global_function_multi_return_three.cash new file mode 100644 index 00000000..15e1ffcf --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_multi_return_three.cash @@ -0,0 +1,12 @@ +function spread(int a) returns (int, int, int) { + return a, a + 1, a + 2; +} + +contract GlobalFunctionMultiReturnThree() { + function spend(int x) { + int p, int q, int r = spread(x); + require(p == 5); + require(q == 6); + require(r == 7); + } +} diff --git a/packages/cashc/test/valid-contract-files/tuple_reassignment.cash b/packages/cashc/test/valid-contract-files/tuple_reassignment.cash new file mode 100644 index 00000000..f0aa91ec --- /dev/null +++ b/packages/cashc/test/valid-contract-files/tuple_reassignment.cash @@ -0,0 +1,40 @@ +// Destructuring into existing variables: a target without a type reassigns an already-declared +// variable instead of declaring a fresh one. Covers straight-line reassignment, mixed +// declaration+reassignment, and in-loop reassignment of loop-carried state (the case that previously +// needed a fresh-temp + per-element rebind workaround). + +function swap(int x, int y) returns (int, int) { + return y, x; +} + +// returns a fresh scalar followed by the two updated accumulators +function step(int x, int y) returns (int, int, int) { + return x * x + 1, y, x; +} + +contract TupleReassignment() { + function spend(int seed) { + int a = seed; + int b = seed + 1; + + // straight-line reassignment of both existing variables + (a, b) = swap(a, b); + + // mixed: declare c fresh, reassign a (allowed at the top level) + (int c, a) = swap(a, b); + + // loop-carried state reassigned in place each iteration + for (int i = 0; i < 4; i = i + 1) { + (a, b) = swap(a, b); + } + + // mixed declaration + reassignment IN A LOOP: declarations form a contiguous block at the + // front, the loop-carried reassignments trail at the end. + for (int j = 0; j < 4; j = j + 1) { + (int lo, a, b) = step(a, b); + require(lo >= 0); + } + + require(a + b + c >= 0); + } +} diff --git a/packages/cashc/test/valid-contract-files/unused_modifier.cash b/packages/cashc/test/valid-contract-files/unused_modifier.cash new file mode 100644 index 00000000..3e973704 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/unused_modifier.cash @@ -0,0 +1,7 @@ +contract UnusedModifier(int unused salt) { + function spend(int a, int b, bytes unused zeroPadding) { + int unused scratch = a + b; + int constant unused magic = 42; + require(a + b == 5); + } +} diff --git a/packages/cashscript/test/debugging.test.ts b/packages/cashscript/test/debugging.test.ts index 40810929..e3e99abd 100644 --- a/packages/cashscript/test/debugging.test.ts +++ b/packages/cashscript/test/debugging.test.ts @@ -15,8 +15,12 @@ import { artifactTestRequireInsideLoop, artifactTestLogInsideLoop, artifactTestFunctionDebugging, + artifactTestFunctionDebuggingDefined, artifactTestFunctionIntermediateResults, artifactTestImportedFunctionDebugging, + artifactTestImportedFunctionDebuggingDefined, + artifactTestMultiReturnDebugging, + artifactTestMultiReturnDebuggingDefined, } from './fixture/debugging/debugging_contracts.js'; import { sha256 } from '@cashscript/utils'; @@ -821,12 +825,21 @@ describe('VM Resources', () => { describe('Debugging tests - user-defined function frames', () => { const provider = new MockNetworkProvider(); + // Default compilation: the single-use functions in these fixtures are inlined, so their debug + // info is spliced into the caller instead of living in a frame. const contract = new Contract(artifactTestFunctionDebugging, [], { provider }); const contractUtxo = provider.addUtxo(contract.address, randomUtxo()); const importedContract = new Contract(artifactTestImportedFunctionDebugging, [], { provider }); const importedUtxo = provider.addUtxo(importedContract.address, randomUtxo()); + // Compiled with disableInlining: the same functions stay OP_DEFINE'd and get a debug frame. + const definedContract = new Contract(artifactTestFunctionDebuggingDefined, [], { provider }); + const definedUtxo = provider.addUtxo(definedContract.address, randomUtxo()); + + const importedDefinedContract = new Contract(artifactTestImportedFunctionDebuggingDefined, [], { provider }); + const importedDefinedUtxo = provider.addUtxo(importedDefinedContract.address, randomUtxo()); + it('attributes a console.log inside a function to the function source line', () => { const transaction = new TransactionBuilder({ provider }) .addInput(contractUtxo, contract.unlock.spend(5n)) @@ -853,11 +866,39 @@ describe('Debugging tests - user-defined function frames', () => { expect(transaction).toFailRequireWith('Failing statement: require(x < 100, "x must be small")'); }); - it('attributes a require failing inside an imported function to the imported file', () => { + it('attributes a require failing inside an inlined imported function to the call site', () => { const transaction = new TransactionBuilder({ provider }) .addInput(importedUtxo, importedContract.unlock.spend(0n)) .addOutput({ to: importedContract.address, amount: 10000n }); + // The imported function is inlined, and a source map cannot reference another file, so the + // failure is attributed to the call site — with the require message kept intact. + expect(transaction).toFailRequireWith('Test.cash:5 Require statement failed at input 0 in contract Test.cash at line 5 with the following message: value must be positive.'); + expect(transaction).toFailRequireWith('Failing statement: assertPositive(x)'); + }); + + it('attributes a require failing inside a function frame to the function source line', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(definedUtxo, definedContract.unlock.spend(0n)) + .addOutput({ to: definedContract.address, amount: 10000n }); + + expect(transaction).toFailRequireWith('Test.cash:4 Require statement failed at input 0 in contract Test.cash at line 4 with the following message: value must be positive.'); + expect(transaction).toFailRequireWith('Failing statement: require(value > 0, "value must be positive")'); + }); + + it('attributes a console.log inside a function frame to the function source line', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(definedUtxo, definedContract.unlock.spend(5n)) + .addOutput({ to: definedContract.address, amount: 10000n }); + + expect(transaction).toLog(new RegExp('^\\[Input #0] Test.cash:3 checking 5$')); + }); + + it('attributes a require failing inside an imported function to the imported file', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(importedDefinedUtxo, importedDefinedContract.unlock.spend(0n)) + .addOutput({ to: importedDefinedContract.address, amount: 10000n }); + expect(transaction).toFailRequireWith('function_helpers.cash:2 Require statement failed at input 0 in contract Test, function assertPositive (function_helpers.cash, line 2) with the following message: value must be positive.'); expect(transaction).toFailRequireWith('Failing statement: require(value > 0, "value must be positive")'); }); @@ -876,11 +917,11 @@ describe('Debugging tests - user-defined function frames', () => { it('renders source-mapped function definitions in the BitAuth IDE template', () => { const transaction = new TransactionBuilder({ provider }) - .addInput(contractUtxo, contract.unlock.spend(5n)) - .addOutput({ to: contract.address, amount: 10000n }); + .addInput(definedUtxo, definedContract.unlock.spend(5n)) + .addOutput({ to: definedContract.address, amount: 10000n }); const template = transaction.getLibauthTemplate(); - const lockScript = template.scripts[getLockScriptName(contract)].script; + const lockScript = template.scripts[getLockScriptName(definedContract)].script; // The function body is rendered as a `<...>` push group annotated with its own source lines expect(lockScript).toContain('/* function checkValue(int value) {'); @@ -890,14 +931,78 @@ describe('Debugging tests - user-defined function frames', () => { it('renders imported function definitions with their import provenance in the BitAuth IDE template', () => { const transaction = new TransactionBuilder({ provider }) - .addInput(importedUtxo, importedContract.unlock.spend(5n)) - .addOutput({ to: importedContract.address, amount: 10000n }); + .addInput(importedDefinedUtxo, importedDefinedContract.unlock.spend(5n)) + .addOutput({ to: importedDefinedContract.address, amount: 10000n }); const template = transaction.getLibauthTemplate(); - const lockScript = template.scripts[getLockScriptName(importedContract)].script; + const lockScript = template.scripts[getLockScriptName(importedDefinedContract)].script; expect(lockScript).toContain('>>> function assertPositive (imported from function_helpers.cash)'); expect(lockScript).toContain('/* function assertPositive(int value) {'); expect(lockScript).toContain('> OP_0 OP_DEFINE'); }); + + describe('multi-return functions', () => { + const multiReturnContract = new Contract(artifactTestMultiReturnDebugging, [], { provider }); + const multiReturnUtxo = provider.addUtxo(multiReturnContract.address, randomUtxo()); + + const multiReturnDefinedContract = new Contract(artifactTestMultiReturnDebuggingDefined, [], { provider }); + const multiReturnDefinedUtxo = provider.addUtxo(multiReturnDefinedContract.address, randomUtxo()); + + it('attributes a console.log inside an inlined multi-return function to the function source line', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(multiReturnUtxo, multiReturnContract.unlock.spend(5n)) + .addOutput({ to: multiReturnContract.address, amount: 10000n }); + + expect(transaction).toLog(new RegExp('^\\[Input #0] Test.cash:3 dividing 5$')); + }); + + it('attributes a require failing inside an inlined multi-return function to the function source line', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(multiReturnUtxo, multiReturnContract.unlock.spend(1n)) + .addOutput({ to: multiReturnContract.address, amount: 10000n }); + + expect(transaction).toFailRequireWith('Test.cash:4 Require statement failed at input 0 in contract Test.cash at line 4 with the following message: divisor must be positive.'); + expect(transaction).toFailRequireWith('Failing statement: require(b > 0, "divisor must be positive")'); + }); + + it('attributes a contract-level require after a multi-return call to the contract source line', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(multiReturnUtxo, multiReturnContract.unlock.spend(2n)) + .addOutput({ to: multiReturnContract.address, amount: 10000n }); + + expect(transaction).toFailRequireWith('Test.cash:11 Require statement failed at input 0 in contract Test.cash at line 11 with the following message: quotient must be 1.'); + expect(transaction).toFailRequireWith('Failing statement: require(q == 1, "quotient must be 1")'); + }); + + it('attributes debug info inside a defined multi-return function frame to the function source lines', () => { + const logTransaction = new TransactionBuilder({ provider }) + .addInput(multiReturnDefinedUtxo, multiReturnDefinedContract.unlock.spend(5n)) + .addOutput({ to: multiReturnDefinedContract.address, amount: 10000n }); + + expect(logTransaction).toLog(new RegExp('^\\[Input #0] Test.cash:3 dividing 5$')); + + const failTransaction = new TransactionBuilder({ provider }) + .addInput(multiReturnDefinedUtxo, multiReturnDefinedContract.unlock.spend(1n)) + .addOutput({ to: multiReturnDefinedContract.address, amount: 10000n }); + + expect(failTransaction).toFailRequireWith('Test.cash:4 Require statement failed at input 0 in contract Test.cash at line 4 with the following message: divisor must be positive.'); + expect(failTransaction).toFailRequireWith('Failing statement: require(b > 0, "divisor must be positive")'); + }); + }); + + it('renders an inlined function body at its call site in the BitAuth IDE template', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(contractUtxo, contract.unlock.spend(5n)) + .addOutput({ to: contract.address, amount: 10000n }); + + const template = transaction.getLibauthTemplate(); + const lockScript = template.scripts[getLockScriptName(contract)].script; + + // The single-use function is inlined: no definition/invocation remains, and the spliced body + // is annotated with the function's own source lines (same-file, so they stay expressible). + expect(lockScript).not.toContain('OP_DEFINE'); + expect(lockScript).not.toContain('OP_INVOKE'); + expect(lockScript).toContain('require(value > 0, "value must be positive")'); + }); }); diff --git a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts index a54f7604..c720fc0b 100644 --- a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts +++ b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts @@ -14,6 +14,22 @@ contract Test() { } `; +const CONTRACT_TEST_MULTI_RETURN_DEBUGGING = ` +function divmod(int a, int b) returns (int, int) { + console.log("dividing", a); + require(b > 0, "divisor must be positive"); + return a / b, a % b; +} + +contract Test() { + function spend(int x) { + int q, int r = divmod(x, x - 1); + require(q == 1, "quotient must be 1"); + require(r >= 0, "remainder must be non-negative"); + } +} +`; + const CONTRACT_TEST_FUNCTION_INTERMEDIATE_RESULTS = ` function hashTwice(pubkey pk) returns (bytes32) { bytes32 singleHash = sha256(pk); @@ -471,3 +487,20 @@ export const artifactTestFunctionIntermediateResults = compileString(CONTRACT_TE // Compiled from a file so the imported function (function_helpers.cash) keeps its own source provenance. export const artifactTestImportedFunctionDebugging = compileFile(new URL('./function_importer.cash', import.meta.url)); + +// Variants with inlining disabled, so single-use functions stay OP_DEFINE'd and get a debug frame +// (the default artifacts above inline them, splicing their debug info into the caller instead). +export const artifactTestFunctionDebuggingDefined = compileString( + CONTRACT_TEST_FUNCTION_DEBUGGING, + { disableInlining: true }, +); +export const artifactTestImportedFunctionDebuggingDefined = compileFile( + new URL('./function_importer.cash', import.meta.url), + { disableInlining: true }, +); + +export const artifactTestMultiReturnDebugging = compileString(CONTRACT_TEST_MULTI_RETURN_DEBUGGING); +export const artifactTestMultiReturnDebuggingDefined = compileString( + CONTRACT_TEST_MULTI_RETURN_DEBUGGING, + { disableInlining: true }, +); diff --git a/packages/utils/src/artifact.ts b/packages/utils/src/artifact.ts index 040c3b47..8bd5f34c 100644 --- a/packages/utils/src/artifact.ts +++ b/packages/utils/src/artifact.ts @@ -1,8 +1,24 @@ export interface CompilerOptions { enforceFunctionParameterTypes?: boolean; enforceLocktimeGuard?: boolean; + // Disable inlining of global functions at their call sites (they are always shared via + // OP_DEFINE/OP_INVOKE instead). Inlining is on by default. + disableInlining?: boolean; + // Skip the backwards-compat cross-check that re-optimises the bytecode with the legacy + // ASM-regex optimiser and compares the results. The check is also skipped automatically + // for large scripts, where the legacy optimiser's quadratic cost would dominate compile time. + disableOptimisationCrossCheck?: boolean; + // The optimisation objective for decisions that trade bytecode size against op-cost. + // 'size' minimises bytecode bytes (e.g. binds a literal repeated within one function body to a + // local, so later uses are ~2-byte stack picks instead of repeated pushes: ~-30 bytes per + // duplicate of a 32-byte constant, ~+2 ops per execution of the binding). 'opcost' (the + // default) minimises executed op-cost instead — right for op-bound contracts, whose unlocking + // scripts are zero-padded to buy op budget, making byte savings free and extra ops pure cost. + optimizeFor?: OptimizationTarget; } +export type OptimizationTarget = 'size' | 'opcost'; + export interface AbiInput { name: string; type: string; diff --git a/packages/utils/src/script.ts b/packages/utils/src/script.ts index c5892e5c..a3d859e4 100644 --- a/packages/utils/src/script.ts +++ b/packages/utils/src/script.ts @@ -154,7 +154,7 @@ export function generateContractBytecodeScript(baseScript: Script, encodedConstr return [...encodedConstructorArgs.slice().reverse(), ...baseScript]; } -interface OptimiseBytecodeResult { +export interface OptimiseBytecodeResult { script: Script; locationData: FullLocationData; logs: LogEntry[]; @@ -162,6 +162,72 @@ interface OptimiseBytecodeResult { sourceTags: SourceTagEntry[]; } +// Pre-parse the ASM-string optimisation patterns into opcode-number sequences once, so the +// optimiser can match directly against the Script array instead of stringifying it to ASM and +// regex-scanning a growing string on every match. The old approach recovered each match's script +// index with [...processedAsm.matchAll(/\s+/g)].length over the growing prefix, making replaceOps +// O(asm-length) per match — quadratic in script size and pathological for large, constant-heavy +// contracts (e.g. the BN254 pairing chunks that bake dozens of 32-40 byte field constants). +interface ParsedOptimisation { + pattern: Op[]; + replacement: Op[]; + // The original pattern split into tokens, kept only for the console.log transformation bookkeeping. + patternTokens: string[]; +} + +function parseOpcodeTokens(asm: string): Op[] { + const trimmed = asm.trim(); + if (trimmed === '') return []; + return trimmed.split(/\s+/).map((token) => Op[token as keyof typeof Op] as Op); +} + +const parsedOptimisations: ParsedOptimisation[] = optimisationReplacements.map(([pattern, replacement]) => ({ + pattern: parseOpcodeTokens(pattern), + replacement: parseOpcodeTokens(replacement), + patternTokens: pattern.trim() === '' ? [] : pattern.trim().split(/\s+/), +})); + +// Structural equality on Script arrays: opcodes by value, data pushes by byte content. Replaces the +// previous fixed-point check that compared scriptToAsm(old) === scriptToAsm(new) (a full stringify +// of both scripts every pass). +function scriptsEqual(a: Script, b: Script): boolean { + if (a.length !== b.length) return false; + for (let i = 0; i < a.length; i += 1) { + const x = a[i]; + const y = b[i]; + if (typeof x === 'number' || typeof y === 'number') { + if (x !== y) return false; + } else { + if (x.length !== y.length) return false; + for (let k = 0; k < x.length; k += 1) { + if (x[k] !== y[k]) return false; + } + } + } + return true; +} + +// The opcode a script element represents for matching purposes. Opcodes are stored as numbers, but +// small integer pushes are stored as data (encodeInt(0n) -> empty, 1n -> [1], -1n -> [0x81]); under +// minimal-push encoding these disassemble to OP_0 / OP_1..OP_16 / OP_1NEGATE, which the optimisation +// patterns reference. We derive that opcode exactly as scriptToBytecode/disassembly would: a data +// element whose minimal push is a single byte IS that opcode. Anything else (a genuine multi-byte +// data push) returns -1, which never equals a real opcode. +function elementOpcode(element: OpOrData): number { + if (typeof element === 'number') return element; + if (element.length >= 2) return -1; + const push = encodeDataPush(element); + return push.length === 1 ? push[0] : -1; +} + +// Does the optimisation pattern (a pure opcode sequence) match the script starting at `index`? +function patternMatchesAt(script: Script, index: number, pattern: Op[]): boolean { + for (let j = 0; j < pattern.length; j += 1) { + if (elementOpcode(script[index + j]) !== pattern[j]) return false; + } + return true; +} + export function optimiseBytecode( script: Script, locationData: FullLocationData, @@ -179,10 +245,10 @@ export function optimiseBytecode( logs: newLogs, requires: newRequires, sourceTags: newSourceTags, - } = replaceOps(script, locationData, logs, requires, sourceTags, constructorParamLength, optimisationReplacements); + } = replaceOps(script, locationData, logs, requires, sourceTags, constructorParamLength, parsedOptimisations); // Break on fixed point - if (scriptToAsm(oldScript) === scriptToAsm(newScript)) break; + if (scriptsEqual(oldScript, newScript)) break; script = newScript; locationData = newLocationData; @@ -280,32 +346,32 @@ function replaceOps( requires: RequireStatement[], sourceTags: SourceTagEntry[], constructorParamLength: number, - optimisations: string[][], + optimisations: ParsedOptimisation[], ): ReplaceOpsResult { - let asm = scriptToAsm(script); + const newScript: Script = [...script]; let newLocationData = [...locationData]; let newLogs = [...logs]; let newRequires = [...requires]; let newSourceTags = [...sourceTags]; - optimisations.forEach(([pattern, replacement]) => { - let processedAsm = ''; - let asmToSearch = asm; - - // We add a space or end of string to the end of the pattern to ensure that we match the whole pattern - // (no partial matches) - const regex = new RegExp(`${pattern}(\\s|$)`, 'g'); - - let matchIndex = asmToSearch.search(regex); - while (matchIndex !== -1) { - // We add the part before the match to the processed asm - processedAsm = mergeAsm(processedAsm, asmToSearch.slice(0, matchIndex)); + optimisations.forEach(({ pattern, replacement, patternTokens }) => { + const patternLength = pattern.length; + if (patternLength === 0) return; + const replacementLength = replacement.length; + const lengthDiff = patternLength - replacementLength; + + // Scan the script array left-to-right. On a match we splice in the replacement and continue + // AFTER it (the replacement is not re-examined within this pass), matching the previous + // string-based behaviour exactly while avoiding any ASM stringification. + let scriptIndex = 0; + while (scriptIndex <= newScript.length - patternLength) { + if (!patternMatchesAt(newScript, scriptIndex, pattern)) { + scriptIndex += 1; + continue; + } - // We count the number of spaces in the processed asm + 1, which is equal to the script index - // We do the same thing to calculate the number of opcodes in the pattern and replacement - const scriptIndex = processedAsm === '' ? 0 : [...processedAsm.matchAll(/\s+/g)].length + 1; - const patternLength = [...pattern.matchAll(/\s+/g)].length + 1; - const replacementLength = replacement === '' ? 0 : [...replacement.matchAll(/\s+/g)].length + 1; + // Splice the matched pattern out of the script array, inserting the replacement opcodes. + newScript.splice(scriptIndex, patternLength, ...replacement); // We get the locationData entries for every opcode in the pattern const patternLocations = newLocationData.slice(scriptIndex, scriptIndex + patternLength); @@ -336,8 +402,6 @@ function replaceOps( const replacementLocations = new Array(replacementLength).fill(mergedLocation); newLocationData.splice(scriptIndex, patternLength, ...replacementLocations); - const lengthDiff = patternLength - replacementLength; // 2 or 1 - // The IP of an opcode in the script is its index within the script + the constructor parameters, because // the constructor parameters still have to get added to the front of the script when a new Contract is created. const scriptIp = scriptIndex + constructorParamLength; @@ -375,7 +439,7 @@ function replaceOps( } const addedTransformationsCount = data.ip - scriptIp; - const addedTransformations = [...pattern.split(/\s+/g)].slice(0, addedTransformationsCount).join(' '); + const addedTransformations = patternTokens.slice(0, addedTransformationsCount).join(' '); const newTransformations = data.transformations ? `${addedTransformations} ${data.transformations}` : addedTransformations; return { @@ -387,34 +451,22 @@ function replaceOps( }; }); - // Source tags use raw script indices (no constructor offset), so we adjust using scriptIndex directly + // Source tags use raw script indices (no constructor offset), so we adjust using the script index directly + // (snapshotted to a const since scriptIndex advances as the scan continues) + const tagIndex = scriptIndex; newSourceTags = newSourceTags.map((tag) => ({ ...tag, - startIndex: tag.startIndex >= scriptIndex ? Math.max(scriptIndex, tag.startIndex - lengthDiff) : tag.startIndex, - endIndex: tag.endIndex >= scriptIndex ? Math.max(scriptIndex, tag.endIndex - lengthDiff) : tag.endIndex, + startIndex: tag.startIndex >= tagIndex ? Math.max(tagIndex, tag.startIndex - lengthDiff) : tag.startIndex, + endIndex: tag.endIndex >= tagIndex ? Math.max(tagIndex, tag.endIndex - lengthDiff) : tag.endIndex, })); - // We add the replacement to the processed asm - processedAsm = mergeAsm(processedAsm, replacement); - - // We do not add the matched pattern anywhere since it gets replaced - - // We set the asmToSearch to the part after the match - asmToSearch = asmToSearch.slice(matchIndex + pattern.length).trim(); - - // Find the next match - matchIndex = asmToSearch.search(regex); + // Continue scanning after the inserted replacement (it is not re-examined within this pass). + scriptIndex += replacementLength; } - - // We add the remaining asm to the processed asm - processedAsm = mergeAsm(processedAsm, asmToSearch); - - // We replace the original asm with the processed asm so that the next optimisation can use the updated asm - asm = processedAsm; }); return { - script: asmToScript(asm), + script: newScript, locationData: newLocationData, logs: newLogs, requires: newRequires, @@ -454,8 +506,3 @@ const getLowestStartLocation = (locations: SingleLocationData[]): SingleLocation }, locations[0]); }; -const mergeAsm = (asm1: string, asm2: string): string => { - // We merge two ASM strings by adding a space between them, and removing any duplicate spaces - // or trailing/leading spaces, which might have been introduced due to regex matching / replacements / empty asm strings - return `${asm1} ${asm2}`.replace(/\s+/g, ' ').trim(); -}; diff --git a/packages/utils/test/bitauth-script.test.ts b/packages/utils/test/bitauth-script.test.ts index 06e1a782..d956e31a 100644 --- a/packages/utils/test/bitauth-script.test.ts +++ b/packages/utils/test/bitauth-script.test.ts @@ -53,9 +53,11 @@ describe('Libauth Script formatting', () => { }); describe('User-defined function formatting', () => { + // These fixtures pin the OP_DEFINE/OP_INVOKE rendering of function frames, so inlining is + // disabled (inlined functions have no frame; their body is spliced into the caller). const compileFixture = (fixture: FunctionFixture): Artifact => (fixture.file - ? compileFile(new URL(`./fixtures/${fixture.file}`, import.meta.url)) - : compileString(fixture.sourceCode!)); + ? compileFile(new URL(`./fixtures/${fixture.file}`, import.meta.url), { disableInlining: true }) + : compileString(fixture.sourceCode!, { disableInlining: true })); functionFixtures.forEach((fixture) => { describe(fixture.name, () => { diff --git a/packages/utils/test/fixtures/bitauth-script.fixture.ts b/packages/utils/test/fixtures/bitauth-script.fixture.ts index 97bbb9b9..083419cc 100644 --- a/packages/utils/test/fixtures/bitauth-script.fixture.ts +++ b/packages/utils/test/fixtures/bitauth-script.fixture.ts @@ -478,7 +478,7 @@ OP_7 OP_1 OP_INVOKE OP_13 OP_NUMEQUAL /* */ /* >>> function addChecked (imported from helpers.cash) */ < /* function addChecked(int a, int b) returns (int) { */ - OP_OVER OP_ADD /* int sum = a + b; */ + OP_DUP OP_ROT OP_ADD /* int sum = a + b; */ OP_DUP OP_ROT OP_GREATERTHANOREQUAL OP_VERIFY /* require(sum >= a, "overflow"); */ /* return sum; */ > OP_1 OP_DEFINE /* } */ @@ -488,7 +488,7 @@ OP_7 OP_1 OP_INVOKE OP_13 OP_NUMEQUAL /* contract ImportedFunctions() { */ /* function spend(int x) { */ OP_DUP OP_0 OP_INVOKE /* int doubled = double(x); */ -OP_SWAP OP_1 OP_INVOKE OP_15 OP_NUMEQUAL /* require(addChecked(doubled, x) == 15, "sum mismatch"); */ +OP_1 OP_INVOKE OP_15 OP_NUMEQUAL /* require(addChecked(doubled, x) == 15, "sum mismatch"); */ /* } */ /* } */ /* */