From 009e11c5fbd36f2063bb90edc48f0bbbfb21399f Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Fri, 26 Jun 2026 16:08:19 +0200 Subject: [PATCH 01/37] Add minimal user-defined functions implementation (#413) Co-authored-by: lightswarm124 Co-authored-by: Mathieu Geukens --- .cspell.json | 1 + packages/cashc/src/Errors.ts | 66 +- packages/cashc/src/artifact/Artifact.ts | 1 + packages/cashc/src/ast/AST.ts | 52 +- packages/cashc/src/ast/AstBuilder.ts | 74 +- packages/cashc/src/ast/AstTraversal.ts | 20 +- packages/cashc/src/ast/AstVisitor.ts | 6 + packages/cashc/src/ast/Globals.ts | 99 +- packages/cashc/src/ast/SymbolTable.ts | 27 +- packages/cashc/src/compiler.ts | 59 +- packages/cashc/src/dependency-resolution.ts | 55 + .../src/generation/GenerateTargetTraversal.ts | 74 +- packages/cashc/src/generation/utils.ts | 22 +- packages/cashc/src/grammar/CashScript.g4 | 31 +- packages/cashc/src/grammar/CashScript.interp | 21 +- packages/cashc/src/grammar/CashScript.tokens | 150 +- .../cashc/src/grammar/CashScriptLexer.interp | 17 +- .../cashc/src/grammar/CashScriptLexer.tokens | 150 +- packages/cashc/src/grammar/CashScriptLexer.ts | 678 +++---- .../cashc/src/grammar/CashScriptParser.ts | 1737 ++++++++++------- .../cashc/src/grammar/CashScriptVisitor.ts | 41 +- packages/cashc/src/parser.ts | 30 + .../src/print/OutputSourceCodeTraversal.ts | 29 + .../semantic/DeadCodeEliminationTraversal.ts | 40 + .../semantic/EnsureFinalRequireTraversal.ts | 59 +- .../semantic/EnsureFunctionsSafeTraversal.ts | 46 + .../semantic/InjectLocktimeGuardTraversal.ts | 86 +- .../src/semantic/SymbolTableTraversal.ts | 45 +- .../cashc/src/semantic/TypeCheckTraversal.ts | 53 +- packages/cashc/test/ast/AST.test.ts | 2 +- packages/cashc/test/ast/Location.test.ts | 7 +- packages/cashc/test/ast/fixtures.ts | 15 + .../void_function_as_value.cash | 10 + .../conditional_return.cash | 12 + .../global_function_missing_return.cash | 10 + .../ParseError/import_after_contract.cash | 7 + .../ParseError/import_after_function.cash | 11 + .../duplicate_global_function.cash | 13 + .../return_in_contract_function.cash | 5 + .../ReturnTypeError/wrong_return_type.cash | 9 + .../active_bytecode_in_function.cash | 9 + .../checkmultisig_in_function.cash | 9 + .../checksig_in_function.cash | 9 + .../nonvoid_function_call.cash | 0 .../unused_global_function_local.cash | 10 + .../unused_global_function_parameter.cash | 9 + .../cashc/test/dead-code-elimination.test.ts | 162 ++ packages/cashc/test/generation/fixtures.ts | 139 ++ .../cashc/test/import-fixtures/cycle_a.cash | 5 + .../cashc/test/import-fixtures/cycle_b.cash | 5 + .../test/import-fixtures/cycle_main.cash | 7 + .../cashc/test/import-fixtures/diamond.cash | 8 + .../duplicate_import_helper.cash | 3 + .../duplicate_import_main.cash | 11 + packages/cashc/test/import-fixtures/leaf.cash | 3 + packages/cashc/test/import-fixtures/main.cash | 7 + packages/cashc/test/import-fixtures/math.cash | 7 + packages/cashc/test/import-fixtures/mid1.cash | 4 + packages/cashc/test/import-fixtures/mid2.cash | 4 + packages/cashc/test/imports.test.ts | 46 + .../InjectLocktimeGuardTraversal.test.ts | 99 + .../checkdatasig_in_function.cash | 9 + .../global_function_in_control_flow.cash | 17 + .../global_function_multi_param.cash | 9 + .../global_function_nested.cash | 13 + .../global_function_simple.cash | 9 + .../global_function_void.cash | 10 + packages/utils/src/types.ts | 8 + website/docs/compiler/compiler.md | 8 + website/docs/compiler/grammar.md | 31 +- website/docs/language/contracts.md | 79 +- website/docs/releases/release-notes.md | 8 + 72 files changed, 3290 insertions(+), 1337 deletions(-) create mode 100644 packages/cashc/src/dependency-resolution.ts create mode 100644 packages/cashc/src/parser.ts create mode 100644 packages/cashc/src/semantic/DeadCodeEliminationTraversal.ts create mode 100644 packages/cashc/src/semantic/EnsureFunctionsSafeTraversal.ts create mode 100644 packages/cashc/test/compiler/AssignTypeError/void_function_as_value.cash create mode 100644 packages/cashc/test/compiler/MisplacedReturnError/conditional_return.cash create mode 100644 packages/cashc/test/compiler/MissingReturnError/global_function_missing_return.cash create mode 100644 packages/cashc/test/compiler/ParseError/import_after_contract.cash create mode 100644 packages/cashc/test/compiler/ParseError/import_after_function.cash create mode 100644 packages/cashc/test/compiler/RedefinitionError/duplicate_global_function.cash create mode 100644 packages/cashc/test/compiler/ReturnTypeError/return_in_contract_function.cash create mode 100644 packages/cashc/test/compiler/ReturnTypeError/wrong_return_type.cash create mode 100644 packages/cashc/test/compiler/UnsafeFunctionOperationError/active_bytecode_in_function.cash create mode 100644 packages/cashc/test/compiler/UnsafeFunctionOperationError/checkmultisig_in_function.cash create mode 100644 packages/cashc/test/compiler/UnsafeFunctionOperationError/checksig_in_function.cash rename packages/cashc/test/compiler/{ParseError => UnusedFunctionReturnError}/nonvoid_function_call.cash (100%) create mode 100644 packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash create mode 100644 packages/cashc/test/compiler/UnusedVariableError/unused_global_function_parameter.cash create mode 100644 packages/cashc/test/dead-code-elimination.test.ts create mode 100644 packages/cashc/test/import-fixtures/cycle_a.cash create mode 100644 packages/cashc/test/import-fixtures/cycle_b.cash create mode 100644 packages/cashc/test/import-fixtures/cycle_main.cash create mode 100644 packages/cashc/test/import-fixtures/diamond.cash create mode 100644 packages/cashc/test/import-fixtures/duplicate_import_helper.cash create mode 100644 packages/cashc/test/import-fixtures/duplicate_import_main.cash create mode 100644 packages/cashc/test/import-fixtures/leaf.cash create mode 100644 packages/cashc/test/import-fixtures/main.cash create mode 100644 packages/cashc/test/import-fixtures/math.cash create mode 100644 packages/cashc/test/import-fixtures/mid1.cash create mode 100644 packages/cashc/test/import-fixtures/mid2.cash create mode 100644 packages/cashc/test/imports.test.ts create mode 100644 packages/cashc/test/valid-contract-files/checkdatasig_in_function.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_in_control_flow.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_multi_param.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_nested.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_simple.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_void.cash diff --git a/.cspell.json b/.cspell.json index 948da88f2..56f78ca2b 100644 --- a/.cspell.json +++ b/.cspell.json @@ -108,6 +108,7 @@ "lshift", "LSHIFTNUM", "LSHIFTBIN", + "math", "mecenas", "meep", "minimaldata", diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index 511d75214..7ff6b4096 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -1,6 +1,7 @@ import { Type, PrimitiveType } from '@cashscript/utils'; import { IdentifierNode, + ImportNode, FunctionDefinitionNode, VariableDefinitionNode, ParameterNode, @@ -69,7 +70,7 @@ export class InvalidSymbolTypeError extends CashScriptError { public node: IdentifierNode, public expected: SymbolType, ) { - super(node, `Found symbol ${node.name} with type ${node.definition?.symbolType} where type ${expected} was expected`); + super(node, `Found symbol ${node.name} with type ${node.symbol?.symbolType} where type ${expected} was expected`); } } @@ -83,6 +84,22 @@ export class FunctionRedefinitionError extends RedefinitionError { } } +export class MissingContractError extends Error { + constructor() { + super('Source file does not contain a contract definition'); + this.name = this.constructor.name; + } +} + +export class ImportResolutionError extends CashScriptError { + constructor( + public node: ImportNode, + message: string, + ) { + super(node, message); + } +} + export class VariableRedefinitionError extends RedefinitionError { constructor( public node: VariableDefinitionNode | ParameterNode, @@ -123,6 +140,43 @@ export class FinalRequireStatementError extends CashScriptError { } } +export class UnusedFunctionReturnError extends CashScriptError { + constructor( + public node: FunctionCallNode, + ) { + super(node, `Return value of ${node.identifier.name} must be used; only void functions may be called as a statement`); + } +} + +export class MissingReturnError extends CashScriptError { + constructor( + public node: Node, + ) { + super(node, 'A value-returning function must end with a return statement'); + } +} + +export class MisplacedReturnError extends CashScriptError { + constructor( + public node: StatementNode, + ) { + super(node, 'A return statement is only allowed as the final statement of a function body'); + } +} + +export class UnsafeFunctionOperationError extends CashScriptError { + constructor( + node: Node, + operation: string, + ) { + super( + node, + `'${operation}' cannot be used inside a user-defined function. Use it directly in a ` + + 'contract function instead, or pass the resulting value into the function as a parameter', + ); + } +} + export class TypeError extends CashScriptError { constructor( node: Node, @@ -134,6 +188,16 @@ export class TypeError extends CashScriptError { } } +export class ReturnTypeError extends TypeError { + constructor( + node: Node, + actual?: Type, + expected?: Type, + ) { + super(node, actual, expected, `Cannot return type '${actual}' from a function with return type '${expected}'`); + } +} + export class InvalidParameterTypeError extends TypeError { constructor( node: FunctionCallNode | RequireNode | InstantiationNode, diff --git a/packages/cashc/src/artifact/Artifact.ts b/packages/cashc/src/artifact/Artifact.ts index ff09b9f32..159aa0ef3 100644 --- a/packages/cashc/src/artifact/Artifact.ts +++ b/packages/cashc/src/artifact/Artifact.ts @@ -13,6 +13,7 @@ export function generateArtifact( fingerprint: string, ): Artifact { const { contract } = ast; + if (!contract) throw new Error('Internal error: cannot generate an artifact for a source file with no contract'); const constructorInputs = contract.parameters .map((parameter) => ({ name: parameter.name, type: parameter.type.toString() })); diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index 3b4a869a0..8d0970232 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -21,9 +21,19 @@ export interface Typed { type: Type; } +export enum FunctionKind { + CONTRACT = 'contract', + GLOBAL = 'global', +} + export class SourceFileNode extends Node { + // The source file's scope: the table of global functions (each symbol carries its VM function-table id). + symbolTable?: SymbolTable; + constructor( - public contract: ContractNode, + public contract?: ContractNode, + public functions: FunctionDefinitionNode[] = [], + public imports: ImportNode[] = [], ) { super(); } @@ -33,6 +43,18 @@ export class SourceFileNode extends Node { } } +export class ImportNode extends Node { + constructor( + public path: string, + ) { + super(); + } + + accept(visitor: AstVisitor): T { + return visitor.visitImport(this); + } +} + export class ContractNode extends Node implements Named { symbolTable?: SymbolTable; @@ -54,9 +76,11 @@ export class FunctionDefinitionNode extends Node implements Named { opRolls: Map = new Map(); constructor( + public kind: FunctionKind, public name: string, public parameters: ParameterNode[], public body: BlockNode, + public returnType?: Type, ) { super(); } @@ -168,6 +192,30 @@ export class ConsoleStatementNode extends NonControlStatementNode { } } +export class FunctionCallStatementNode extends NonControlStatementNode { + constructor( + public functionCall: FunctionCallNode, + ) { + super(); + } + + accept(visitor: AstVisitor): T { + return visitor.visitFunctionCallStatement(this); + } +} + +export class ReturnNode extends NonControlStatementNode { + constructor( + public expression: ExpressionNode, + ) { + super(); + } + + accept(visitor: AstVisitor): T { + return visitor.visitReturn(this); + } +} + export class BranchNode extends ControlStatementNode { constructor( public condition: ExpressionNode, @@ -362,7 +410,7 @@ export class ArrayNode extends ExpressionNode { } export class IdentifierNode extends ExpressionNode implements Named { - definition?: Symbol; + symbol?: Symbol; constructor( public name: string, diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index fc671b030..c2bdd0e37 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -1,14 +1,16 @@ import { ParseTree, ParseTreeVisitor } from 'antlr4'; import { hexToBin } from '@bitauth/libauth'; -import { parseType } from '@cashscript/utils'; +import { parseType, Type } from '@cashscript/utils'; import semver from 'semver'; import { Node, SourceFileNode, + ImportNode, ContractNode, ParameterNode, VariableDefinitionNode, FunctionDefinitionNode, + FunctionKind, AssignNode, IdentifierNode, BranchNode, @@ -28,11 +30,13 @@ import { ArrayNode, TupleIndexOpNode, RequireNode, + ReturnNode, InstantiationNode, TupleAssignmentNode, NullaryOpNode, ConsoleStatementNode, ConsoleParameterNode, + FunctionCallStatementNode, SliceNode, DoWhileNode, WhileNode, @@ -40,8 +44,12 @@ import { } from './AST.js'; import { UnaryOperator, BinaryOperator, NullaryOperator } from './Operator.js'; import type { + ImportDirectiveContext, ContractDefinitionContext, - FunctionDefinitionContext, + ContractFunctionDefinitionContext, + GlobalFunctionDefinitionContext, + ReturnStatementContext, + FunctionCallStatementContext, VariableDefinitionContext, TupleAssignmentContext, ParameterContext, @@ -110,12 +118,34 @@ export default class AstBuilder this.processPragma(pragma); }); - const contract = this.visit(ctx.contractDefinition()) as ContractNode; - const sourceFileNode = new SourceFileNode(contract); + const imports = ctx.importDirective_list().map((directive) => this.visit(directive) as ImportNode); + + const functions: FunctionDefinitionNode[] = []; + let contract: ContractNode | undefined; + + ctx.topLevelDefinition_list().forEach((def) => { + if (def.globalFunctionDefinition()) { + functions.push(this.visit(def.globalFunctionDefinition()) as FunctionDefinitionNode); + } else if (def.contractDefinition()) { + if (contract) { + throw new ParseError('A source file may define at most one contract', Location.fromCtx(def.contractDefinition())); + } + contract = this.visit(def.contractDefinition()) as ContractNode; + } + }); + + const sourceFileNode = new SourceFileNode(contract, functions, imports); sourceFileNode.location = Location.fromCtx(ctx); return sourceFileNode; } + visitImportDirective(ctx: ImportDirectiveContext): ImportNode { + const raw = ctx.StringLiteral().getText(); + const importNode = new ImportNode(raw.substring(1, raw.length - 1)); + importNode.location = Location.fromCtx(ctx); + return importNode; + } + processPragma(ctx: PragmaDirectiveContext): void { const pragmaName = getPragmaName(ctx.pragmaName().getText()); if (pragmaName !== PragmaName.CASHSCRIPT) throw new Error(); // Shouldn't happen @@ -135,17 +165,31 @@ export default class AstBuilder visitContractDefinition(ctx: ContractDefinitionContext): ContractNode { const name = ctx.Identifier().getText(); const parameters = ctx.parameterList().parameter_list().map((p) => this.visit(p) as ParameterNode); - const functions = ctx.functionDefinition_list().map((f) => this.visit(f) as FunctionDefinitionNode); + const functions = ctx.contractFunctionDefinition_list() + .map((f) => this.visit(f) as FunctionDefinitionNode); const contract = new ContractNode(name, parameters, functions); contract.location = Location.fromCtx(ctx); return contract; } - visitFunctionDefinition(ctx: FunctionDefinitionContext): FunctionDefinitionNode { + visitContractFunctionDefinition(ctx: ContractFunctionDefinitionContext): FunctionDefinitionNode { + return this.buildFunctionDefinition(ctx, FunctionKind.CONTRACT); + } + + visitGlobalFunctionDefinition(ctx: GlobalFunctionDefinitionContext): FunctionDefinitionNode { + const returnType = ctx.typeName() ? parseType(ctx.typeName().getText()) : undefined; + return this.buildFunctionDefinition(ctx, FunctionKind.GLOBAL, returnType); + } + + private buildFunctionDefinition( + ctx: ContractFunctionDefinitionContext | GlobalFunctionDefinitionContext, + kind: FunctionKind, + returnType?: 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()); - const functionDefinition = new FunctionDefinitionNode(name, parameters, body); + const body = this.visit(ctx.functionBody()) as BlockNode; + const functionDefinition = new FunctionDefinitionNode(kind, name, parameters, body, returnType); functionDefinition.location = Location.fromCtx(ctx); return functionDefinition; } @@ -260,6 +304,20 @@ export default class AstBuilder return require; } + visitReturnStatement(ctx: ReturnStatementContext): ReturnNode { + const expression = this.visit(ctx.expression()); + const returnNode = new ReturnNode(expression); + returnNode.location = Location.fromCtx(ctx); + return returnNode; + } + + visitFunctionCallStatement(ctx: FunctionCallStatementContext): FunctionCallStatementNode { + const functionCall = this.visit(ctx.functionCall()) as FunctionCallNode; + const node = new FunctionCallStatementNode(functionCall); + node.location = Location.fromCtx(ctx); + return node; + } + visitIfStatement(ctx: IfStatementContext): BranchNode { const condition = this.visit(ctx.expression()); const ifBlock = this.visit(ctx._ifBlock) as StatementNode; diff --git a/packages/cashc/src/ast/AstTraversal.ts b/packages/cashc/src/ast/AstTraversal.ts index ba73d204a..bd428132c 100644 --- a/packages/cashc/src/ast/AstTraversal.ts +++ b/packages/cashc/src/ast/AstTraversal.ts @@ -1,6 +1,7 @@ import { Node, SourceFileNode, + ImportNode, ContractNode, ParameterNode, VariableDefinitionNode, @@ -22,11 +23,13 @@ import { ArrayNode, TupleIndexOpNode, RequireNode, + ReturnNode, InstantiationNode, TupleAssignmentNode, NullaryOpNode, ConsoleStatementNode, ConsoleParameterNode, + FunctionCallStatementNode, SliceNode, DoWhileNode, WhileNode, @@ -36,7 +39,12 @@ import AstVisitor from './AstVisitor.js'; export default class AstTraversal extends AstVisitor { visitSourceFile(node: SourceFileNode): Node { - node.contract = this.visit(node.contract) as ContractNode; + node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; + node.contract = this.visitOptional(node.contract) as ContractNode | undefined; + return node; + } + + visitImport(node: ImportNode): Node { return node; } @@ -82,11 +90,21 @@ export default class AstTraversal extends AstVisitor { return node; } + visitReturn(node: ReturnNode): Node { + node.expression = this.visit(node.expression); + return node; + } + visitConsoleStatement(node: ConsoleStatementNode): Node { node.parameters = this.visitList(node.parameters) as ConsoleParameterNode[]; return node; } + visitFunctionCallStatement(node: FunctionCallStatementNode): Node { + node.functionCall = this.visit(node.functionCall) as FunctionCallNode; + return node; + } + visitBranch(node: BranchNode): Node { node.condition = this.visit(node.condition); node.ifBlock = this.visit(node.ifBlock) as StatementNode; diff --git a/packages/cashc/src/ast/AstVisitor.ts b/packages/cashc/src/ast/AstVisitor.ts index 1c131bf35..3b72d57f4 100644 --- a/packages/cashc/src/ast/AstVisitor.ts +++ b/packages/cashc/src/ast/AstVisitor.ts @@ -1,6 +1,7 @@ import { Node, SourceFileNode, + ImportNode, ContractNode, ParameterNode, VariableDefinitionNode, @@ -21,10 +22,12 @@ import { ArrayNode, TupleIndexOpNode, RequireNode, + ReturnNode, InstantiationNode, TupleAssignmentNode, NullaryOpNode, ConsoleStatementNode, + FunctionCallStatementNode, SliceNode, DoWhileNode, WhileNode, @@ -33,6 +36,7 @@ import { export default abstract class AstVisitor { abstract visitSourceFile(node: SourceFileNode): T; + abstract visitImport(node: ImportNode): T; abstract visitContract(node: ContractNode): T; abstract visitFunctionDefinition(node: FunctionDefinitionNode): T; abstract visitParameter(node: ParameterNode): T; @@ -41,7 +45,9 @@ export default abstract class AstVisitor { abstract visitAssign(node: AssignNode): T; abstract visitTimeOp(node: TimeOpNode): T; abstract visitRequire(node: RequireNode): T; + abstract visitReturn(node: ReturnNode): T; abstract visitConsoleStatement(node: ConsoleStatementNode): T; + abstract visitFunctionCallStatement(node: FunctionCallStatementNode): T; abstract visitBranch(node: BranchNode): T; abstract visitDoWhile(node: DoWhileNode): T; abstract visitWhile(node: WhileNode): T; diff --git a/packages/cashc/src/ast/Globals.ts b/packages/cashc/src/ast/Globals.ts index cc1273d77..878475c69 100644 --- a/packages/cashc/src/ast/Globals.ts +++ b/packages/cashc/src/ast/Globals.ts @@ -1,4 +1,4 @@ -import { PrimitiveType, ArrayType, BytesType } from '@cashscript/utils'; +import { PrimitiveType, ArrayType, BytesType, Op } from '@cashscript/utils'; import { SymbolTable, Symbol } from './SymbolTable.js'; export const NumberUnit: { [index: string]: number } = { @@ -63,47 +63,88 @@ GLOBAL_SYMBOL_TABLE.set( ); // Global functions + +// abs(int) -> int +GLOBAL_SYMBOL_TABLE.set( + Symbol.builtinFunction(GlobalFunction.ABS, PrimitiveType.INT, [PrimitiveType.INT], [Op.OP_ABS]), +); + +// min(int, int) -> int GLOBAL_SYMBOL_TABLE.set( - Symbol.function(GlobalFunction.ABS, PrimitiveType.INT, [PrimitiveType.INT]), + Symbol.builtinFunction(GlobalFunction.MIN, PrimitiveType.INT, [PrimitiveType.INT, PrimitiveType.INT], [Op.OP_MIN]), ); + +// max(int, int) -> int GLOBAL_SYMBOL_TABLE.set( - Symbol.function(GlobalFunction.MIN, PrimitiveType.INT, [PrimitiveType.INT, PrimitiveType.INT]), + Symbol.builtinFunction(GlobalFunction.MAX, PrimitiveType.INT, [PrimitiveType.INT, PrimitiveType.INT], [Op.OP_MAX]), ); + +// within(int, int, int) -> bool GLOBAL_SYMBOL_TABLE.set( - Symbol.function(GlobalFunction.MAX, PrimitiveType.INT, [PrimitiveType.INT, PrimitiveType.INT]), + Symbol.builtinFunction( + GlobalFunction.WITHIN, PrimitiveType.BOOL, + [PrimitiveType.INT, PrimitiveType.INT, PrimitiveType.INT], + [Op.OP_WITHIN], + ), ); -GLOBAL_SYMBOL_TABLE.set(Symbol.function( - GlobalFunction.WITHIN, PrimitiveType.BOOL, - [PrimitiveType.INT, PrimitiveType.INT, PrimitiveType.INT], -)); + +// ripemd160(any) -> bytes20 GLOBAL_SYMBOL_TABLE.set( - Symbol.function(GlobalFunction.RIPEMD160, new BytesType(20), [PrimitiveType.ANY]), + Symbol.builtinFunction(GlobalFunction.RIPEMD160, new BytesType(20), [PrimitiveType.ANY], [Op.OP_RIPEMD160]), ); + +// sha1(any) -> bytes20 GLOBAL_SYMBOL_TABLE.set( - Symbol.function(GlobalFunction.SHA1, new BytesType(20), [PrimitiveType.ANY]), + Symbol.builtinFunction(GlobalFunction.SHA1, new BytesType(20), [PrimitiveType.ANY], [Op.OP_SHA1]), ); + +// sha256(any) -> bytes32 GLOBAL_SYMBOL_TABLE.set( - Symbol.function(GlobalFunction.SHA256, new BytesType(32), [PrimitiveType.ANY]), + Symbol.builtinFunction(GlobalFunction.SHA256, new BytesType(32), [PrimitiveType.ANY], [Op.OP_SHA256]), ); + +// hash160(any) -> bytes20 GLOBAL_SYMBOL_TABLE.set( - Symbol.function(GlobalFunction.HASH160, new BytesType(20), [PrimitiveType.ANY]), + Symbol.builtinFunction(GlobalFunction.HASH160, new BytesType(20), [PrimitiveType.ANY], [Op.OP_HASH160]), ); + +// hash256(any) -> bytes32 +GLOBAL_SYMBOL_TABLE.set( + Symbol.builtinFunction(GlobalFunction.HASH256, new BytesType(32), [PrimitiveType.ANY], [Op.OP_HASH256]), +); + +// checkSig(sig, pubkey) -> bool +GLOBAL_SYMBOL_TABLE.set( + Symbol.builtinFunction( + GlobalFunction.CHECKSIG, PrimitiveType.BOOL, + [PrimitiveType.SIG, PrimitiveType.PUBKEY], + [Op.OP_CHECKSIG], + ), +); + +// checkMultiSig(sig[], pubkey[]) -> bool +GLOBAL_SYMBOL_TABLE.set( + Symbol.builtinFunction( + GlobalFunction.CHECKMULTISIG, PrimitiveType.BOOL, + [new ArrayType(PrimitiveType.SIG), new ArrayType(PrimitiveType.PUBKEY)], + [Op.OP_CHECKMULTISIG], + ), +); + +// checkDataSig(datasig, bytes, pubkey) -> bool +GLOBAL_SYMBOL_TABLE.set( + Symbol.builtinFunction( + GlobalFunction.CHECKDATASIG, PrimitiveType.BOOL, + [PrimitiveType.DATASIG, new BytesType(), PrimitiveType.PUBKEY], + [Op.OP_CHECKDATASIG], + ), +); + +// toPaddedBytes(int, int) -> bytes GLOBAL_SYMBOL_TABLE.set( - Symbol.function(GlobalFunction.HASH256, new BytesType(32), [PrimitiveType.ANY]), + Symbol.builtinFunction( + GlobalFunction.TO_PADDED_BYTES, new BytesType(), + [PrimitiveType.INT, PrimitiveType.INT], + [Op.OP_NUM2BIN], + ), ); -GLOBAL_SYMBOL_TABLE.set(Symbol.function( - GlobalFunction.CHECKSIG, PrimitiveType.BOOL, - [PrimitiveType.SIG, PrimitiveType.PUBKEY], -)); -GLOBAL_SYMBOL_TABLE.set(Symbol.function( - GlobalFunction.CHECKMULTISIG, PrimitiveType.BOOL, - [new ArrayType(PrimitiveType.SIG), new ArrayType(PrimitiveType.PUBKEY)], -)); -GLOBAL_SYMBOL_TABLE.set(Symbol.function( - GlobalFunction.CHECKDATASIG, PrimitiveType.BOOL, - [PrimitiveType.DATASIG, new BytesType(), PrimitiveType.PUBKEY], -)); -GLOBAL_SYMBOL_TABLE.set(Symbol.function( - GlobalFunction.TO_PADDED_BYTES, new BytesType(), - [PrimitiveType.INT, PrimitiveType.INT], -)); diff --git a/packages/cashc/src/ast/SymbolTable.ts b/packages/cashc/src/ast/SymbolTable.ts index fcfada947..36a25525b 100644 --- a/packages/cashc/src/ast/SymbolTable.ts +++ b/packages/cashc/src/ast/SymbolTable.ts @@ -1,20 +1,24 @@ -import { Type } from '@cashscript/utils'; +import { Type, PrimitiveType, Script, Op, encodeInt } from '@cashscript/utils'; import { VariableDefinitionNode, ParameterNode, + FunctionDefinitionNode, IdentifierNode, Node, } from './AST.js'; export class Symbol { references: IdentifierNode[] = []; + private constructor( public name: string, public type: Type, public symbolType: SymbolType, public definition?: Node, public parameters?: Type[], - ) {} + public bytecode?: Script, + public functionId?: number, + ) { } static variable(node: VariableDefinitionNode | ParameterNode): Symbol { return new Symbol(node.name, node.type, SymbolType.VARIABLE, node); @@ -24,8 +28,21 @@ export class Symbol { return new Symbol(name, type, SymbolType.VARIABLE); } - static function(name: string, type: Type, parameters: Type[]): Symbol { - return new Symbol(name, type, SymbolType.FUNCTION, undefined, parameters); + static builtinFunction(name: string, returnType: Type, parameters: Type[], bytecode: Script): Symbol { + return new Symbol(name, returnType, SymbolType.FUNCTION, undefined, parameters, bytecode); + } + + 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); + symbol.setFunctionId(functionId); + return symbol; + } + + setFunctionId(functionId: number): void { + this.functionId = functionId; + this.bytecode = [encodeInt(BigInt(functionId)), Op.OP_INVOKE]; } static class(name: string, type: Type, parameters: Type[]): Symbol { @@ -52,7 +69,7 @@ export class SymbolTable { constructor( public parent?: SymbolTable, - ) {} + ) { } set(symbol: Symbol): void { this.symbols.set(symbol.name, symbol); diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index 46c24927a..efdb98591 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -1,4 +1,3 @@ -import { CharStream, CommonTokenStream } from 'antlr4'; import { binToHex } from '@bitauth/libauth'; import { Artifact, @@ -13,17 +12,21 @@ import { sourceMapToLocationData, } from '@cashscript/utils'; import fs, { PathLike } from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; import { generateArtifact } from './artifact/Artifact.js'; import { Ast } from './ast/AST.js'; -import AstBuilder from './ast/AstBuilder.js'; -import { ThrowingErrorListener, CashScriptErrorListener, ForwardingErrorListener } from './ast/error-listeners.js'; +import { CashScriptErrorListener } from './ast/error-listeners.js'; +import { MissingContractError } from './Errors.js'; +import { parseCode } from './parser.js'; +import { resolveDependencies } from './dependency-resolution.js'; import GenerateTargetTraversal from './generation/GenerateTargetTraversal.js'; -import CashScriptLexer from './grammar/CashScriptLexer.js'; -import CashScriptParser from './grammar/CashScriptParser.js'; import SymbolTableTraversal from './semantic/SymbolTableTraversal.js'; import TypeCheckTraversal from './semantic/TypeCheckTraversal.js'; import EnsureFinalRequireTraversal from './semantic/EnsureFinalRequireTraversal.js'; +import EnsureFunctionsSafeTraversal from './semantic/EnsureFunctionsSafeTraversal.js'; import InjectLocktimeGuardTraversal from './semantic/InjectLocktimeGuardTraversal.js'; +import DeadCodeEliminationTraversal from './semantic/DeadCodeEliminationTraversal.js'; export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = { enforceFunctionParameterTypes: true, @@ -32,6 +35,7 @@ export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = { export interface CompileOptions extends CompilerOptions { errorListener?: CashScriptErrorListener; + basePath?: string; } /** @@ -43,26 +47,33 @@ export interface CompileOptions extends CompilerOptions { * @throws If the source code contains a syntax, semantic, or type error. */ export function compileString(code: string, compilerOptions: CompileOptions = {}): Artifact { - const { errorListener, ...artifactCompilerOptions } = compilerOptions; + const { errorListener, basePath, ...artifactCompilerOptions } = compilerOptions; const mergedCompilerOptions = { ...DEFAULT_COMPILER_OPTIONS, ...artifactCompilerOptions }; // Lexing + parsing let ast = parseCode(code, errorListener); + ast = resolveDependencies(ast, { basePath, errorListener }) as Ast; + if (!ast.contract) throw new MissingContractError(); + + const constructorParamLength = ast.contract.parameters.length; + // Semantic analysis ast = ast.accept(new SymbolTableTraversal()) as Ast; ast = ast.accept(new TypeCheckTraversal()) as Ast; + ast = ast.accept(new EnsureFunctionsSafeTraversal()) as Ast; ast = ast.accept(new EnsureFinalRequireTraversal()) as Ast; if (mergedCompilerOptions.enforceLocktimeGuard) { ast = ast.accept(new InjectLocktimeGuardTraversal()) as Ast; } + // Dead-code elimination: drop global functions that are never invoked before code generation + ast = ast.accept(new DeadCodeEliminationTraversal()) as Ast; + // Code generation const traversal = new GenerateTargetTraversal(mergedCompilerOptions); ast = ast.accept(traversal) as Ast; - const constructorParamLength = ast.contract.parameters.length; - // Bytecode optimisation const optimisedBytecodeOld = optimiseBytecodeOld(traversal.output); const optimisationResult = optimiseBytecode( @@ -104,32 +115,8 @@ export function compileString(code: string, compilerOptions: CompileOptions = {} * @throws If the file cannot be read, or if the source contains a compilation error. */ export function compileFile(codeFile: PathLike, compilerOptions: CompileOptions = {}): Artifact { - const code = fs.readFileSync(codeFile, { encoding: 'utf-8' }); - return compileString(code, compilerOptions); -} - -export function parseCode( - code: string, - errorListener: CashScriptErrorListener = ThrowingErrorListener.INSTANCE, -): Ast { - const syntaxErrorListener = new ForwardingErrorListener(errorListener); - - // Lexing (throwing on errors) - const inputStream = new CharStream(code); - const lexer = new CashScriptLexer(inputStream); - lexer.removeErrorListeners(); - lexer.addErrorListener(syntaxErrorListener); - const tokenStream = new CommonTokenStream(lexer); - - // Parsing (throwing on errors) - const parser = new CashScriptParser(tokenStream); - parser.removeErrorListeners(); - parser.addErrorListener(syntaxErrorListener); - const parseTree = parser.sourceFile(); - syntaxErrorListener.throwFirstError(); - - // AST building - const ast = new AstBuilder(parseTree).build() as Ast; - - return ast; + const filePath = codeFile instanceof URL ? fileURLToPath(codeFile) : codeFile.toString(); + const code = fs.readFileSync(filePath, { encoding: 'utf-8' }); + const basePath = compilerOptions.basePath ?? path.dirname(filePath); + return compileString(code, { ...compilerOptions, basePath }); } diff --git a/packages/cashc/src/dependency-resolution.ts b/packages/cashc/src/dependency-resolution.ts new file mode 100644 index 000000000..c182d5095 --- /dev/null +++ b/packages/cashc/src/dependency-resolution.ts @@ -0,0 +1,55 @@ +import fs from 'fs'; +import path from 'path'; +import { SourceFileNode, FunctionDefinitionNode, ImportNode } from './ast/AST.js'; +import type { CompileOptions } from './compiler.js'; +import { ImportResolutionError } from './Errors.js'; +import { parseCode } from './parser.js'; + +export function resolveDependencies(ast: SourceFileNode, options: CompileOptions): SourceFileNode { + if (ast.imports.length === 0) return ast; + + const importedFunctions = collectImports(ast.imports, options.basePath, options); + ast.functions = [...importedFunctions, ...ast.functions]; + 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 absolute 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[], + fileDir: string | undefined, + options: CompileOptions, +): FunctionDefinitionNode[] { + const visitedPaths = new Set(); + + const collect = (currentImports: ImportNode[], currentDir: string | undefined): FunctionDefinitionNode[] => + currentImports.flatMap((importNode) => { + if (currentDir === undefined) { + throw new ImportResolutionError(importNode, 'Cannot resolve imports without a base path (compile from a file)'); + } + + const absolutePath = path.resolve(currentDir, importNode.path); + if (visitedPaths.has(absolutePath)) return []; + visitedPaths.add(absolutePath); + + const importedAst = parseCode(readImportedFile(importNode, absolutePath), options.errorListener); + return [...collect(importedAst.imports, path.dirname(absolutePath)), ...importedAst.functions]; + }); + + return collect(imports, fileDir); +} + +function readImportedFile(importNode: ImportNode, absolutePath: string): string { + try { + return fs.readFileSync(absolutePath, { encoding: 'utf-8' }); + } catch { + throw new ImportResolutionError( + importNode, + `Could not read imported file '${importNode.path}' (resolved to ${absolutePath})`, + ); + } +} diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index ef0a0096b..73e7e5e2c 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -9,6 +9,8 @@ import { PrimitiveType, Script, scriptToAsm, + scriptToBytecode, + optimiseBytecode, generateSourceMap, FullLocationData, LogEntry, @@ -26,6 +28,7 @@ import { ParameterNode, VariableDefinitionNode, FunctionDefinitionNode, + FunctionKind, AssignNode, IdentifierNode, BranchNode, @@ -60,14 +63,13 @@ import { BinaryOperator } from '../ast/Operator.js'; import { compileBinaryOp, compileCast, - compileGlobalFunction, compileNullaryOp, compileTimeOp, compileUnaryOp, } from './utils.js'; import { isNumericType } from '../utils.js'; -export default class GenerateTargetTraversalWithLocation extends AstTraversal { +export default class GenerateTargetTraversal extends AstTraversal { private locationData: FullLocationData = []; // detailed location data needed for sourcemap creation sourceMap: string; output: Script = []; @@ -133,7 +135,10 @@ export default class GenerateTargetTraversalWithLocation extends AstTraversal { } visitSourceFile(node: SourceFileNode): Node { - node.contract = this.visit(node.contract) as ContractNode; + this.defineGlobalFunctions(node); + + // The contract is guaranteed to exist here (compileString throws MissingContractError otherwise). + node.contract = this.visit(node.contract!) as ContractNode; // Minimally encode output by going Script -> ASM -> Script this.output = asmToScript(scriptToAsm(this.output)); @@ -143,6 +148,52 @@ export default class GenerateTargetTraversalWithLocation extends AstTraversal { return node; } + private defineGlobalFunctions(node: SourceFileNode): void { + node.functions.forEach((func) => { + const { functionId } = node.symbolTable!.getFromThis(func.name)!; + const bodyBytecode = this.compileGlobalFunctionBody(func); + + const locationData = { location: func.location, positionHint: PositionHint.START }; + this.emit(bodyBytecode, locationData); // + this.emit(encodeInt(BigInt(functionId!)), locationData); // + this.emit(Op.OP_DEFINE, { ...locationData, positionHint: PositionHint.END }); + }); + } + + private compileGlobalFunctionBody(node: FunctionDefinitionNode): Uint8Array { + const bodyTraversal = new GenerateTargetTraversal(this.compilerOptions); + bodyTraversal.currentFunction = node; + bodyTraversal.constructorParameterCount = 0; + + // 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]); + } + + bodyTraversal.visit(node.body); + bodyTraversal.cleanGlobalFunctionStack(node); + + const optimised = optimiseBytecode( + bodyTraversal.output, + bodyTraversal.locationData, + bodyTraversal.consoleLogs, + bodyTraversal.requires, + bodyTraversal.sourceTags, + 0, + ); + + return scriptToBytecode(optimised.script); + } + + cleanGlobalFunctionStack(node: FunctionDefinitionNode): void { + if (node.returnType === undefined) { + 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 + } + } + visitContract(node: ContractNode): Node { node.parameters = this.visitList(node.parameters) as ParameterNode[]; @@ -196,6 +247,10 @@ export default class GenerateTargetTraversalWithLocation extends AstTraversal { } visitFunctionDefinition(node: FunctionDefinitionNode): Node { + if (node.kind !== FunctionKind.CONTRACT) { + throw new Error('Internal error: global functions are compiled via defineGlobalFunctions'); + } + this.currentFunction = node; node.parameters = this.visitList(node.parameters) as ParameterNode[]; @@ -402,7 +457,7 @@ export default class GenerateTargetTraversalWithLocation extends AstTraversal { const data = node.parameters.map((parameter: ConsoleParameterNode) => { if (parameter instanceof IdentifierNode) { - const symbol = parameter.definition!; + const symbol = parameter.symbol!; // If the variable is not on the stack, then we add the final stack usage to the console log const stackIndex = this.getStackIndex(parameter.name, true); @@ -587,14 +642,11 @@ export default class GenerateTargetTraversalWithLocation extends AstTraversal { return this.visitMultiSig(node); } + const symbol = node.identifier.symbol!; node.parameters = this.visitList(node.parameters); - - this.emit( - compileGlobalFunction(node.identifier.name as GlobalFunction), - { location: node.location, positionHint: PositionHint.END }, - ); + this.emit(symbol.bytecode!, { location: node.location, positionHint: PositionHint.END }); this.popFromStack(node.parameters.length); - this.pushToStack('(value)'); + if (symbol.type !== PrimitiveType.VOID) this.pushToStack('(value)'); return node; } @@ -774,7 +826,7 @@ export default class GenerateTargetTraversalWithLocation extends AstTraversal { // If the final use is inside an if-statement, we still OP_PICK it // We do this so that there's no difference in stack depths between execution paths if (this.isOpRoll(node)) { - const symbol = node.definition!; + const symbol = node.symbol!; this.finalStackUsage[node.name] = { type: symbol.type.toString(), stackIndex, diff --git a/packages/cashc/src/generation/utils.ts b/packages/cashc/src/generation/utils.ts index fa017aac5..b6bac2195 100644 --- a/packages/cashc/src/generation/utils.ts +++ b/packages/cashc/src/generation/utils.ts @@ -7,7 +7,7 @@ import { Type, } from '@cashscript/utils'; import { UnaryOperator, BinaryOperator, NullaryOperator } from '../ast/Operator.js'; -import { GlobalFunction, TimeOp } from '../ast/Globals.js'; +import { TimeOp } from '../ast/Globals.js'; export function compileTimeOp(op: TimeOp): Script { const mapping = { @@ -36,26 +36,6 @@ export function compileCast(from: Type, to: Type, isUnsafe: boolean): Script { return []; } -export function compileGlobalFunction(fn: GlobalFunction): Script { - const mapping = { - [GlobalFunction.ABS]: [Op.OP_ABS], - [GlobalFunction.CHECKDATASIG]: [Op.OP_CHECKDATASIG], - [GlobalFunction.CHECKMULTISIG]: [Op.OP_CHECKMULTISIG], - [GlobalFunction.CHECKSIG]: [Op.OP_CHECKSIG], - [GlobalFunction.MAX]: [Op.OP_MAX], - [GlobalFunction.MIN]: [Op.OP_MIN], - [GlobalFunction.RIPEMD160]: [Op.OP_RIPEMD160], - [GlobalFunction.SHA1]: [Op.OP_SHA1], - [GlobalFunction.SHA256]: [Op.OP_SHA256], - [GlobalFunction.HASH160]: [Op.OP_HASH160], - [GlobalFunction.HASH256]: [Op.OP_HASH256], - [GlobalFunction.WITHIN]: [Op.OP_WITHIN], - [GlobalFunction.TO_PADDED_BYTES]: [Op.OP_NUM2BIN], - }; - - return mapping[fn]; -} - export function compileBinaryOp(op: BinaryOperator, numeric: boolean = false): Script { const mapping: { [key in BinaryOperator]: Script } = { [BinaryOperator.MUL]: [Op.OP_MUL], diff --git a/packages/cashc/src/grammar/CashScript.g4 b/packages/cashc/src/grammar/CashScript.g4 index e4ad1d4bf..c221b077a 100644 --- a/packages/cashc/src/grammar/CashScript.g4 +++ b/packages/cashc/src/grammar/CashScript.g4 @@ -1,7 +1,7 @@ grammar CashScript; sourceFile - : pragmaDirective* contractDefinition EOF + : pragmaDirective* importDirective* topLevelDefinition* EOF ; pragmaDirective @@ -24,11 +24,24 @@ versionOperator : '^' | '~' | '>=' | '>' | '<' | '<=' | '=' ; +importDirective + : 'import' StringLiteral ';' + ; + +topLevelDefinition + : globalFunctionDefinition + | contractDefinition + ; + +globalFunctionDefinition + : 'function' Identifier parameterList ('returns' '(' typeName ')')? functionBody + ; + contractDefinition - : 'contract' Identifier parameterList '{' functionDefinition* '}' + : 'contract' Identifier parameterList '{' contractFunctionDefinition* '}' ; -functionDefinition +contractFunctionDefinition : 'function' Identifier parameterList functionBody ; @@ -60,7 +73,17 @@ nonControlStatement | assignStatement | timeOpStatement | requireStatement + | functionCallStatement | consoleStatement + | returnStatement + ; + +functionCallStatement + : functionCall + ; + +returnStatement + : 'return' expression ; controlStatement @@ -134,7 +157,7 @@ consoleParameterList ; functionCall - : Identifier expressionList // Only built-in functions are accepted + : Identifier expressionList // Built-in global functions and user-defined global functions ; expressionList diff --git a/packages/cashc/src/grammar/CashScript.interp b/packages/cashc/src/grammar/CashScript.interp index 7368b9dd3..30fbbbcdf 100644 --- a/packages/cashc/src/grammar/CashScript.interp +++ b/packages/cashc/src/grammar/CashScript.interp @@ -10,13 +10,16 @@ null '<' '<=' '=' +'import' +'function' +'returns' +'(' +')' 'contract' '{' '}' -'function' -'(' ',' -')' +'return' '+=' '-=' '++' @@ -145,6 +148,9 @@ null null null null +null +null +null VersionLiteral BooleanLiteral NumberUnit @@ -173,14 +179,19 @@ pragmaName pragmaValue versionConstraint versionOperator +importDirective +topLevelDefinition +globalFunctionDefinition contractDefinition -functionDefinition +contractFunctionDefinition functionBody parameterList parameter block statement nonControlStatement +functionCallStatement +returnStatement controlStatement variableDefinition tupleAssignment @@ -208,4 +219,4 @@ typeCast atn: -[4, 1, 81, 433, 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, 1, 0, 5, 0, 78, 8, 0, 10, 0, 12, 0, 81, 9, 0, 1, 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, 95, 8, 3, 1, 4, 3, 4, 98, 8, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 6, 1, 6, 5, 6, 109, 8, 6, 10, 6, 12, 6, 112, 9, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 5, 8, 123, 8, 8, 10, 8, 12, 8, 126, 9, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 5, 9, 134, 8, 9, 10, 9, 12, 9, 137, 9, 9, 1, 9, 3, 9, 140, 8, 9, 3, 9, 142, 8, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 5, 11, 151, 8, 11, 10, 11, 12, 11, 154, 9, 11, 1, 11, 1, 11, 3, 11, 158, 8, 11, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 164, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 3, 13, 172, 8, 13, 1, 14, 1, 14, 3, 14, 176, 8, 14, 1, 15, 1, 15, 5, 15, 180, 8, 15, 10, 15, 12, 15, 183, 9, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 202, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 1, 18, 3, 18, 211, 8, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 19, 3, 19, 220, 8, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 234, 8, 21, 1, 22, 1, 22, 1, 22, 3, 22, 239, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 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, 26, 1, 26, 3, 26, 267, 8, 26, 1, 27, 1, 27, 1, 28, 1, 28, 3, 28, 273, 8, 28, 1, 29, 1, 29, 1, 29, 1, 29, 5, 29, 279, 8, 29, 10, 29, 12, 29, 282, 9, 29, 1, 29, 3, 29, 285, 8, 29, 3, 29, 287, 8, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 5, 31, 298, 8, 31, 10, 31, 12, 31, 301, 9, 31, 1, 31, 3, 31, 304, 8, 31, 3, 31, 306, 8, 31, 1, 31, 1, 31, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 319, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 345, 8, 32, 10, 32, 12, 32, 348, 9, 32, 1, 32, 3, 32, 351, 8, 32, 3, 32, 353, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 3, 32, 359, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 5, 32, 411, 8, 32, 10, 32, 12, 32, 414, 9, 32, 1, 33, 1, 33, 1, 34, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 423, 8, 34, 1, 35, 1, 35, 3, 35, 427, 8, 35, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 0, 1, 64, 38, 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, 0, 14, 1, 0, 4, 10, 2, 0, 10, 10, 18, 19, 1, 0, 20, 21, 1, 0, 33, 37, 2, 0, 33, 37, 39, 42, 2, 0, 5, 5, 47, 48, 1, 0, 49, 51, 2, 0, 48, 48, 52, 52, 1, 0, 53, 54, 1, 0, 6, 9, 1, 0, 55, 56, 1, 0, 43, 44, 1, 0, 68, 70, 2, 0, 68, 69, 76, 76, 459, 0, 79, 1, 0, 0, 0, 2, 85, 1, 0, 0, 0, 4, 90, 1, 0, 0, 0, 6, 92, 1, 0, 0, 0, 8, 97, 1, 0, 0, 0, 10, 101, 1, 0, 0, 0, 12, 103, 1, 0, 0, 0, 14, 115, 1, 0, 0, 0, 16, 120, 1, 0, 0, 0, 18, 129, 1, 0, 0, 0, 20, 145, 1, 0, 0, 0, 22, 157, 1, 0, 0, 0, 24, 163, 1, 0, 0, 0, 26, 171, 1, 0, 0, 0, 28, 175, 1, 0, 0, 0, 30, 177, 1, 0, 0, 0, 32, 188, 1, 0, 0, 0, 34, 201, 1, 0, 0, 0, 36, 203, 1, 0, 0, 0, 38, 214, 1, 0, 0, 0, 40, 223, 1, 0, 0, 0, 42, 226, 1, 0, 0, 0, 44, 238, 1, 0, 0, 0, 46, 240, 1, 0, 0, 0, 48, 248, 1, 0, 0, 0, 50, 254, 1, 0, 0, 0, 52, 266, 1, 0, 0, 0, 54, 268, 1, 0, 0, 0, 56, 272, 1, 0, 0, 0, 58, 274, 1, 0, 0, 0, 60, 290, 1, 0, 0, 0, 62, 293, 1, 0, 0, 0, 64, 358, 1, 0, 0, 0, 66, 415, 1, 0, 0, 0, 68, 422, 1, 0, 0, 0, 70, 424, 1, 0, 0, 0, 72, 428, 1, 0, 0, 0, 74, 430, 1, 0, 0, 0, 76, 78, 3, 2, 1, 0, 77, 76, 1, 0, 0, 0, 78, 81, 1, 0, 0, 0, 79, 77, 1, 0, 0, 0, 79, 80, 1, 0, 0, 0, 80, 82, 1, 0, 0, 0, 81, 79, 1, 0, 0, 0, 82, 83, 3, 12, 6, 0, 83, 84, 5, 0, 0, 1, 84, 1, 1, 0, 0, 0, 85, 86, 5, 1, 0, 0, 86, 87, 3, 4, 2, 0, 87, 88, 3, 6, 3, 0, 88, 89, 5, 2, 0, 0, 89, 3, 1, 0, 0, 0, 90, 91, 5, 3, 0, 0, 91, 5, 1, 0, 0, 0, 92, 94, 3, 8, 4, 0, 93, 95, 3, 8, 4, 0, 94, 93, 1, 0, 0, 0, 94, 95, 1, 0, 0, 0, 95, 7, 1, 0, 0, 0, 96, 98, 3, 10, 5, 0, 97, 96, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 99, 1, 0, 0, 0, 99, 100, 5, 62, 0, 0, 100, 9, 1, 0, 0, 0, 101, 102, 7, 0, 0, 0, 102, 11, 1, 0, 0, 0, 103, 104, 5, 11, 0, 0, 104, 105, 5, 78, 0, 0, 105, 106, 3, 18, 9, 0, 106, 110, 5, 12, 0, 0, 107, 109, 3, 14, 7, 0, 108, 107, 1, 0, 0, 0, 109, 112, 1, 0, 0, 0, 110, 108, 1, 0, 0, 0, 110, 111, 1, 0, 0, 0, 111, 113, 1, 0, 0, 0, 112, 110, 1, 0, 0, 0, 113, 114, 5, 13, 0, 0, 114, 13, 1, 0, 0, 0, 115, 116, 5, 14, 0, 0, 116, 117, 5, 78, 0, 0, 117, 118, 3, 18, 9, 0, 118, 119, 3, 16, 8, 0, 119, 15, 1, 0, 0, 0, 120, 124, 5, 12, 0, 0, 121, 123, 3, 24, 12, 0, 122, 121, 1, 0, 0, 0, 123, 126, 1, 0, 0, 0, 124, 122, 1, 0, 0, 0, 124, 125, 1, 0, 0, 0, 125, 127, 1, 0, 0, 0, 126, 124, 1, 0, 0, 0, 127, 128, 5, 13, 0, 0, 128, 17, 1, 0, 0, 0, 129, 141, 5, 15, 0, 0, 130, 135, 3, 20, 10, 0, 131, 132, 5, 16, 0, 0, 132, 134, 3, 20, 10, 0, 133, 131, 1, 0, 0, 0, 134, 137, 1, 0, 0, 0, 135, 133, 1, 0, 0, 0, 135, 136, 1, 0, 0, 0, 136, 139, 1, 0, 0, 0, 137, 135, 1, 0, 0, 0, 138, 140, 5, 16, 0, 0, 139, 138, 1, 0, 0, 0, 139, 140, 1, 0, 0, 0, 140, 142, 1, 0, 0, 0, 141, 130, 1, 0, 0, 0, 141, 142, 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 144, 5, 17, 0, 0, 144, 19, 1, 0, 0, 0, 145, 146, 3, 72, 36, 0, 146, 147, 5, 78, 0, 0, 147, 21, 1, 0, 0, 0, 148, 152, 5, 12, 0, 0, 149, 151, 3, 24, 12, 0, 150, 149, 1, 0, 0, 0, 151, 154, 1, 0, 0, 0, 152, 150, 1, 0, 0, 0, 152, 153, 1, 0, 0, 0, 153, 155, 1, 0, 0, 0, 154, 152, 1, 0, 0, 0, 155, 158, 5, 13, 0, 0, 156, 158, 3, 24, 12, 0, 157, 148, 1, 0, 0, 0, 157, 156, 1, 0, 0, 0, 158, 23, 1, 0, 0, 0, 159, 164, 3, 28, 14, 0, 160, 161, 3, 26, 13, 0, 161, 162, 5, 2, 0, 0, 162, 164, 1, 0, 0, 0, 163, 159, 1, 0, 0, 0, 163, 160, 1, 0, 0, 0, 164, 25, 1, 0, 0, 0, 165, 172, 3, 30, 15, 0, 166, 172, 3, 32, 16, 0, 167, 172, 3, 34, 17, 0, 168, 172, 3, 36, 18, 0, 169, 172, 3, 38, 19, 0, 170, 172, 3, 40, 20, 0, 171, 165, 1, 0, 0, 0, 171, 166, 1, 0, 0, 0, 171, 167, 1, 0, 0, 0, 171, 168, 1, 0, 0, 0, 171, 169, 1, 0, 0, 0, 171, 170, 1, 0, 0, 0, 172, 27, 1, 0, 0, 0, 173, 176, 3, 42, 21, 0, 174, 176, 3, 44, 22, 0, 175, 173, 1, 0, 0, 0, 175, 174, 1, 0, 0, 0, 176, 29, 1, 0, 0, 0, 177, 181, 3, 72, 36, 0, 178, 180, 3, 66, 33, 0, 179, 178, 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 184, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 185, 5, 78, 0, 0, 185, 186, 5, 10, 0, 0, 186, 187, 3, 64, 32, 0, 187, 31, 1, 0, 0, 0, 188, 189, 3, 72, 36, 0, 189, 190, 5, 78, 0, 0, 190, 191, 5, 16, 0, 0, 191, 192, 3, 72, 36, 0, 192, 193, 5, 78, 0, 0, 193, 194, 5, 10, 0, 0, 194, 195, 3, 64, 32, 0, 195, 33, 1, 0, 0, 0, 196, 197, 5, 78, 0, 0, 197, 198, 7, 1, 0, 0, 198, 202, 3, 64, 32, 0, 199, 200, 5, 78, 0, 0, 200, 202, 7, 2, 0, 0, 201, 196, 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 202, 35, 1, 0, 0, 0, 203, 204, 5, 22, 0, 0, 204, 205, 5, 15, 0, 0, 205, 206, 5, 75, 0, 0, 206, 207, 5, 6, 0, 0, 207, 210, 3, 64, 32, 0, 208, 209, 5, 16, 0, 0, 209, 211, 3, 54, 27, 0, 210, 208, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 212, 1, 0, 0, 0, 212, 213, 5, 17, 0, 0, 213, 37, 1, 0, 0, 0, 214, 215, 5, 22, 0, 0, 215, 216, 5, 15, 0, 0, 216, 219, 3, 64, 32, 0, 217, 218, 5, 16, 0, 0, 218, 220, 3, 54, 27, 0, 219, 217, 1, 0, 0, 0, 219, 220, 1, 0, 0, 0, 220, 221, 1, 0, 0, 0, 221, 222, 5, 17, 0, 0, 222, 39, 1, 0, 0, 0, 223, 224, 5, 23, 0, 0, 224, 225, 3, 58, 29, 0, 225, 41, 1, 0, 0, 0, 226, 227, 5, 24, 0, 0, 227, 228, 5, 15, 0, 0, 228, 229, 3, 64, 32, 0, 229, 230, 5, 17, 0, 0, 230, 233, 3, 22, 11, 0, 231, 232, 5, 25, 0, 0, 232, 234, 3, 22, 11, 0, 233, 231, 1, 0, 0, 0, 233, 234, 1, 0, 0, 0, 234, 43, 1, 0, 0, 0, 235, 239, 3, 46, 23, 0, 236, 239, 3, 48, 24, 0, 237, 239, 3, 50, 25, 0, 238, 235, 1, 0, 0, 0, 238, 236, 1, 0, 0, 0, 238, 237, 1, 0, 0, 0, 239, 45, 1, 0, 0, 0, 240, 241, 5, 26, 0, 0, 241, 242, 3, 22, 11, 0, 242, 243, 5, 27, 0, 0, 243, 244, 5, 15, 0, 0, 244, 245, 3, 64, 32, 0, 245, 246, 5, 17, 0, 0, 246, 247, 5, 2, 0, 0, 247, 47, 1, 0, 0, 0, 248, 249, 5, 27, 0, 0, 249, 250, 5, 15, 0, 0, 250, 251, 3, 64, 32, 0, 251, 252, 5, 17, 0, 0, 252, 253, 3, 22, 11, 0, 253, 49, 1, 0, 0, 0, 254, 255, 5, 28, 0, 0, 255, 256, 5, 15, 0, 0, 256, 257, 3, 52, 26, 0, 257, 258, 5, 2, 0, 0, 258, 259, 3, 64, 32, 0, 259, 260, 5, 2, 0, 0, 260, 261, 3, 34, 17, 0, 261, 262, 5, 17, 0, 0, 262, 263, 3, 22, 11, 0, 263, 51, 1, 0, 0, 0, 264, 267, 3, 30, 15, 0, 265, 267, 3, 34, 17, 0, 266, 264, 1, 0, 0, 0, 266, 265, 1, 0, 0, 0, 267, 53, 1, 0, 0, 0, 268, 269, 5, 72, 0, 0, 269, 55, 1, 0, 0, 0, 270, 273, 5, 78, 0, 0, 271, 273, 3, 68, 34, 0, 272, 270, 1, 0, 0, 0, 272, 271, 1, 0, 0, 0, 273, 57, 1, 0, 0, 0, 274, 286, 5, 15, 0, 0, 275, 280, 3, 56, 28, 0, 276, 277, 5, 16, 0, 0, 277, 279, 3, 56, 28, 0, 278, 276, 1, 0, 0, 0, 279, 282, 1, 0, 0, 0, 280, 278, 1, 0, 0, 0, 280, 281, 1, 0, 0, 0, 281, 284, 1, 0, 0, 0, 282, 280, 1, 0, 0, 0, 283, 285, 5, 16, 0, 0, 284, 283, 1, 0, 0, 0, 284, 285, 1, 0, 0, 0, 285, 287, 1, 0, 0, 0, 286, 275, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 289, 5, 17, 0, 0, 289, 59, 1, 0, 0, 0, 290, 291, 5, 78, 0, 0, 291, 292, 3, 62, 31, 0, 292, 61, 1, 0, 0, 0, 293, 305, 5, 15, 0, 0, 294, 299, 3, 64, 32, 0, 295, 296, 5, 16, 0, 0, 296, 298, 3, 64, 32, 0, 297, 295, 1, 0, 0, 0, 298, 301, 1, 0, 0, 0, 299, 297, 1, 0, 0, 0, 299, 300, 1, 0, 0, 0, 300, 303, 1, 0, 0, 0, 301, 299, 1, 0, 0, 0, 302, 304, 5, 16, 0, 0, 303, 302, 1, 0, 0, 0, 303, 304, 1, 0, 0, 0, 304, 306, 1, 0, 0, 0, 305, 294, 1, 0, 0, 0, 305, 306, 1, 0, 0, 0, 306, 307, 1, 0, 0, 0, 307, 308, 5, 17, 0, 0, 308, 63, 1, 0, 0, 0, 309, 310, 6, 32, -1, 0, 310, 311, 5, 15, 0, 0, 311, 312, 3, 64, 32, 0, 312, 313, 5, 17, 0, 0, 313, 359, 1, 0, 0, 0, 314, 315, 3, 74, 37, 0, 315, 316, 5, 15, 0, 0, 316, 318, 3, 64, 32, 0, 317, 319, 5, 16, 0, 0, 318, 317, 1, 0, 0, 0, 318, 319, 1, 0, 0, 0, 319, 320, 1, 0, 0, 0, 320, 321, 5, 17, 0, 0, 321, 359, 1, 0, 0, 0, 322, 359, 3, 60, 30, 0, 323, 324, 5, 29, 0, 0, 324, 325, 5, 78, 0, 0, 325, 359, 3, 62, 31, 0, 326, 327, 5, 32, 0, 0, 327, 328, 5, 30, 0, 0, 328, 329, 3, 64, 32, 0, 329, 330, 5, 31, 0, 0, 330, 331, 7, 3, 0, 0, 331, 359, 1, 0, 0, 0, 332, 333, 5, 38, 0, 0, 333, 334, 5, 30, 0, 0, 334, 335, 3, 64, 32, 0, 335, 336, 5, 31, 0, 0, 336, 337, 7, 4, 0, 0, 337, 359, 1, 0, 0, 0, 338, 339, 7, 5, 0, 0, 339, 359, 3, 64, 32, 15, 340, 352, 5, 30, 0, 0, 341, 346, 3, 64, 32, 0, 342, 343, 5, 16, 0, 0, 343, 345, 3, 64, 32, 0, 344, 342, 1, 0, 0, 0, 345, 348, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 347, 350, 1, 0, 0, 0, 348, 346, 1, 0, 0, 0, 349, 351, 5, 16, 0, 0, 350, 349, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 351, 353, 1, 0, 0, 0, 352, 341, 1, 0, 0, 0, 352, 353, 1, 0, 0, 0, 353, 354, 1, 0, 0, 0, 354, 359, 5, 31, 0, 0, 355, 359, 5, 77, 0, 0, 356, 359, 5, 78, 0, 0, 357, 359, 3, 68, 34, 0, 358, 309, 1, 0, 0, 0, 358, 314, 1, 0, 0, 0, 358, 322, 1, 0, 0, 0, 358, 323, 1, 0, 0, 0, 358, 326, 1, 0, 0, 0, 358, 332, 1, 0, 0, 0, 358, 338, 1, 0, 0, 0, 358, 340, 1, 0, 0, 0, 358, 355, 1, 0, 0, 0, 358, 356, 1, 0, 0, 0, 358, 357, 1, 0, 0, 0, 359, 412, 1, 0, 0, 0, 360, 361, 10, 14, 0, 0, 361, 362, 7, 6, 0, 0, 362, 411, 3, 64, 32, 15, 363, 364, 10, 13, 0, 0, 364, 365, 7, 7, 0, 0, 365, 411, 3, 64, 32, 14, 366, 367, 10, 12, 0, 0, 367, 368, 7, 8, 0, 0, 368, 411, 3, 64, 32, 13, 369, 370, 10, 11, 0, 0, 370, 371, 7, 9, 0, 0, 371, 411, 3, 64, 32, 12, 372, 373, 10, 10, 0, 0, 373, 374, 7, 10, 0, 0, 374, 411, 3, 64, 32, 11, 375, 376, 10, 9, 0, 0, 376, 377, 5, 57, 0, 0, 377, 411, 3, 64, 32, 10, 378, 379, 10, 8, 0, 0, 379, 380, 5, 4, 0, 0, 380, 411, 3, 64, 32, 9, 381, 382, 10, 7, 0, 0, 382, 383, 5, 58, 0, 0, 383, 411, 3, 64, 32, 8, 384, 385, 10, 6, 0, 0, 385, 386, 5, 59, 0, 0, 386, 411, 3, 64, 32, 7, 387, 388, 10, 5, 0, 0, 388, 389, 5, 60, 0, 0, 389, 411, 3, 64, 32, 6, 390, 391, 10, 21, 0, 0, 391, 392, 5, 30, 0, 0, 392, 393, 5, 65, 0, 0, 393, 411, 5, 31, 0, 0, 394, 395, 10, 18, 0, 0, 395, 411, 7, 11, 0, 0, 396, 397, 10, 17, 0, 0, 397, 398, 5, 45, 0, 0, 398, 399, 5, 15, 0, 0, 399, 400, 3, 64, 32, 0, 400, 401, 5, 17, 0, 0, 401, 411, 1, 0, 0, 0, 402, 403, 10, 16, 0, 0, 403, 404, 5, 46, 0, 0, 404, 405, 5, 15, 0, 0, 405, 406, 3, 64, 32, 0, 406, 407, 5, 16, 0, 0, 407, 408, 3, 64, 32, 0, 408, 409, 5, 17, 0, 0, 409, 411, 1, 0, 0, 0, 410, 360, 1, 0, 0, 0, 410, 363, 1, 0, 0, 0, 410, 366, 1, 0, 0, 0, 410, 369, 1, 0, 0, 0, 410, 372, 1, 0, 0, 0, 410, 375, 1, 0, 0, 0, 410, 378, 1, 0, 0, 0, 410, 381, 1, 0, 0, 0, 410, 384, 1, 0, 0, 0, 410, 387, 1, 0, 0, 0, 410, 390, 1, 0, 0, 0, 410, 394, 1, 0, 0, 0, 410, 396, 1, 0, 0, 0, 410, 402, 1, 0, 0, 0, 411, 414, 1, 0, 0, 0, 412, 410, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 65, 1, 0, 0, 0, 414, 412, 1, 0, 0, 0, 415, 416, 5, 61, 0, 0, 416, 67, 1, 0, 0, 0, 417, 423, 5, 63, 0, 0, 418, 423, 3, 70, 35, 0, 419, 423, 5, 72, 0, 0, 420, 423, 5, 73, 0, 0, 421, 423, 5, 74, 0, 0, 422, 417, 1, 0, 0, 0, 422, 418, 1, 0, 0, 0, 422, 419, 1, 0, 0, 0, 422, 420, 1, 0, 0, 0, 422, 421, 1, 0, 0, 0, 423, 69, 1, 0, 0, 0, 424, 426, 5, 65, 0, 0, 425, 427, 5, 64, 0, 0, 426, 425, 1, 0, 0, 0, 426, 427, 1, 0, 0, 0, 427, 71, 1, 0, 0, 0, 428, 429, 7, 12, 0, 0, 429, 73, 1, 0, 0, 0, 430, 431, 7, 13, 0, 0, 431, 75, 1, 0, 0, 0, 36, 79, 94, 97, 110, 124, 135, 139, 141, 152, 157, 163, 171, 175, 181, 201, 210, 219, 233, 238, 266, 272, 280, 284, 286, 299, 303, 305, 318, 346, 350, 352, 358, 410, 412, 422, 426] \ No newline at end of file +[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 diff --git a/packages/cashc/src/grammar/CashScript.tokens b/packages/cashc/src/grammar/CashScript.tokens index b9cfb61bd..16dc361de 100644 --- a/packages/cashc/src/grammar/CashScript.tokens +++ b/packages/cashc/src/grammar/CashScript.tokens @@ -59,26 +59,29 @@ T__57=58 T__58=59 T__59=60 T__60=61 -VersionLiteral=62 -BooleanLiteral=63 -NumberUnit=64 -NumberLiteral=65 -NumberPart=66 -ExponentPart=67 -PrimitiveType=68 -UnboundedBytes=69 -BoundedBytes=70 -Bound=71 -StringLiteral=72 -DateLiteral=73 -HexLiteral=74 -TxVar=75 -UnsafeCast=76 -NullaryOp=77 -Identifier=78 -WHITESPACE=79 -COMMENT=80 -LINE_COMMENT=81 +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 'pragma'=1 ';'=2 'cashscript'=3 @@ -89,55 +92,58 @@ LINE_COMMENT=81 '<'=8 '<='=9 '='=10 -'contract'=11 -'{'=12 -'}'=13 -'function'=14 -'('=15 -','=16 -')'=17 -'+='=18 -'-='=19 -'++'=20 -'--'=21 -'require'=22 -'console.log'=23 -'if'=24 -'else'=25 -'do'=26 -'while'=27 -'for'=28 -'new'=29 -'['=30 -']'=31 -'tx.outputs'=32 -'.value'=33 -'.lockingBytecode'=34 -'.tokenCategory'=35 -'.nftCommitment'=36 -'.tokenAmount'=37 -'tx.inputs'=38 -'.outpointTransactionHash'=39 -'.outpointIndex'=40 -'.unlockingBytecode'=41 -'.sequenceNumber'=42 -'.reverse()'=43 -'.length'=44 -'.split'=45 -'.slice'=46 -'!'=47 -'-'=48 -'*'=49 -'/'=50 -'%'=51 -'+'=52 -'>>'=53 -'<<'=54 -'=='=55 -'!='=56 -'&'=57 -'|'=58 -'&&'=59 -'||'=60 -'constant'=61 -'bytes'=69 +'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 diff --git a/packages/cashc/src/grammar/CashScriptLexer.interp b/packages/cashc/src/grammar/CashScriptLexer.interp index e2bb72fc8..d394bd0e5 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.interp +++ b/packages/cashc/src/grammar/CashScriptLexer.interp @@ -10,13 +10,16 @@ null '<' '<=' '=' +'import' +'function' +'returns' +'(' +')' 'contract' '{' '}' -'function' -'(' ',' -')' +'return' '+=' '-=' '++' @@ -145,6 +148,9 @@ null null null null +null +null +null VersionLiteral BooleanLiteral NumberUnit @@ -228,6 +234,9 @@ T__57 T__58 T__59 T__60 +T__61 +T__62 +T__63 VersionLiteral BooleanLiteral NumberUnit @@ -257,4 +266,4 @@ mode names: DEFAULT_MODE atn: -[4, 0, 81, 938, 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, 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, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 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, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 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, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 29, 1, 29, 1, 30, 1, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 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, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 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, 34, 1, 34, 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, 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, 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, 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, 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, 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, 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, 46, 1, 46, 1, 47, 1, 47, 1, 48, 1, 48, 1, 49, 1, 49, 1, 50, 1, 50, 1, 51, 1, 51, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 4, 61, 529, 8, 61, 11, 61, 12, 61, 530, 1, 61, 1, 61, 4, 61, 535, 8, 61, 11, 61, 12, 61, 536, 1, 61, 1, 61, 4, 61, 541, 8, 61, 11, 61, 12, 61, 542, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 1, 62, 3, 62, 554, 8, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 1, 63, 3, 63, 613, 8, 63, 1, 64, 3, 64, 616, 8, 64, 1, 64, 1, 64, 3, 64, 620, 8, 64, 1, 65, 4, 65, 623, 8, 65, 11, 65, 12, 65, 624, 1, 65, 1, 65, 4, 65, 629, 8, 65, 11, 65, 12, 65, 630, 5, 65, 633, 8, 65, 10, 65, 12, 65, 636, 9, 65, 1, 66, 1, 66, 1, 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, 3, 67, 670, 8, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 1, 69, 3, 69, 689, 8, 69, 1, 70, 1, 70, 5, 70, 693, 8, 70, 10, 70, 12, 70, 696, 9, 70, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 702, 8, 71, 10, 71, 12, 71, 705, 9, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 5, 71, 712, 8, 71, 10, 71, 12, 71, 715, 9, 71, 1, 71, 3, 71, 718, 8, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 5, 73, 732, 8, 73, 10, 73, 12, 73, 735, 9, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 1, 74, 3, 74, 752, 8, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 3, 75, 789, 8, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75, 3, 75, 802, 8, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 1, 76, 3, 76, 898, 8, 76, 1, 77, 1, 77, 5, 77, 902, 8, 77, 10, 77, 12, 77, 905, 9, 77, 1, 78, 4, 78, 908, 8, 78, 11, 78, 12, 78, 909, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 5, 79, 918, 8, 79, 10, 79, 12, 79, 921, 9, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 5, 80, 932, 8, 80, 10, 80, 12, 80, 935, 9, 80, 1, 80, 1, 80, 3, 703, 713, 919, 0, 81, 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, 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, 982, 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, 1, 163, 1, 0, 0, 0, 3, 170, 1, 0, 0, 0, 5, 172, 1, 0, 0, 0, 7, 183, 1, 0, 0, 0, 9, 185, 1, 0, 0, 0, 11, 187, 1, 0, 0, 0, 13, 190, 1, 0, 0, 0, 15, 192, 1, 0, 0, 0, 17, 194, 1, 0, 0, 0, 19, 197, 1, 0, 0, 0, 21, 199, 1, 0, 0, 0, 23, 208, 1, 0, 0, 0, 25, 210, 1, 0, 0, 0, 27, 212, 1, 0, 0, 0, 29, 221, 1, 0, 0, 0, 31, 223, 1, 0, 0, 0, 33, 225, 1, 0, 0, 0, 35, 227, 1, 0, 0, 0, 37, 230, 1, 0, 0, 0, 39, 233, 1, 0, 0, 0, 41, 236, 1, 0, 0, 0, 43, 239, 1, 0, 0, 0, 45, 247, 1, 0, 0, 0, 47, 259, 1, 0, 0, 0, 49, 262, 1, 0, 0, 0, 51, 267, 1, 0, 0, 0, 53, 270, 1, 0, 0, 0, 55, 276, 1, 0, 0, 0, 57, 280, 1, 0, 0, 0, 59, 284, 1, 0, 0, 0, 61, 286, 1, 0, 0, 0, 63, 288, 1, 0, 0, 0, 65, 299, 1, 0, 0, 0, 67, 306, 1, 0, 0, 0, 69, 323, 1, 0, 0, 0, 71, 338, 1, 0, 0, 0, 73, 353, 1, 0, 0, 0, 75, 366, 1, 0, 0, 0, 77, 376, 1, 0, 0, 0, 79, 401, 1, 0, 0, 0, 81, 416, 1, 0, 0, 0, 83, 435, 1, 0, 0, 0, 85, 451, 1, 0, 0, 0, 87, 462, 1, 0, 0, 0, 89, 470, 1, 0, 0, 0, 91, 477, 1, 0, 0, 0, 93, 484, 1, 0, 0, 0, 95, 486, 1, 0, 0, 0, 97, 488, 1, 0, 0, 0, 99, 490, 1, 0, 0, 0, 101, 492, 1, 0, 0, 0, 103, 494, 1, 0, 0, 0, 105, 496, 1, 0, 0, 0, 107, 499, 1, 0, 0, 0, 109, 502, 1, 0, 0, 0, 111, 505, 1, 0, 0, 0, 113, 508, 1, 0, 0, 0, 115, 510, 1, 0, 0, 0, 117, 512, 1, 0, 0, 0, 119, 515, 1, 0, 0, 0, 121, 518, 1, 0, 0, 0, 123, 528, 1, 0, 0, 0, 125, 553, 1, 0, 0, 0, 127, 612, 1, 0, 0, 0, 129, 615, 1, 0, 0, 0, 131, 622, 1, 0, 0, 0, 133, 637, 1, 0, 0, 0, 135, 669, 1, 0, 0, 0, 137, 671, 1, 0, 0, 0, 139, 688, 1, 0, 0, 0, 141, 690, 1, 0, 0, 0, 143, 717, 1, 0, 0, 0, 145, 719, 1, 0, 0, 0, 147, 728, 1, 0, 0, 0, 149, 751, 1, 0, 0, 0, 151, 801, 1, 0, 0, 0, 153, 897, 1, 0, 0, 0, 155, 899, 1, 0, 0, 0, 157, 907, 1, 0, 0, 0, 159, 913, 1, 0, 0, 0, 161, 927, 1, 0, 0, 0, 163, 164, 5, 112, 0, 0, 164, 165, 5, 114, 0, 0, 165, 166, 5, 97, 0, 0, 166, 167, 5, 103, 0, 0, 167, 168, 5, 109, 0, 0, 168, 169, 5, 97, 0, 0, 169, 2, 1, 0, 0, 0, 170, 171, 5, 59, 0, 0, 171, 4, 1, 0, 0, 0, 172, 173, 5, 99, 0, 0, 173, 174, 5, 97, 0, 0, 174, 175, 5, 115, 0, 0, 175, 176, 5, 104, 0, 0, 176, 177, 5, 115, 0, 0, 177, 178, 5, 99, 0, 0, 178, 179, 5, 114, 0, 0, 179, 180, 5, 105, 0, 0, 180, 181, 5, 112, 0, 0, 181, 182, 5, 116, 0, 0, 182, 6, 1, 0, 0, 0, 183, 184, 5, 94, 0, 0, 184, 8, 1, 0, 0, 0, 185, 186, 5, 126, 0, 0, 186, 10, 1, 0, 0, 0, 187, 188, 5, 62, 0, 0, 188, 189, 5, 61, 0, 0, 189, 12, 1, 0, 0, 0, 190, 191, 5, 62, 0, 0, 191, 14, 1, 0, 0, 0, 192, 193, 5, 60, 0, 0, 193, 16, 1, 0, 0, 0, 194, 195, 5, 60, 0, 0, 195, 196, 5, 61, 0, 0, 196, 18, 1, 0, 0, 0, 197, 198, 5, 61, 0, 0, 198, 20, 1, 0, 0, 0, 199, 200, 5, 99, 0, 0, 200, 201, 5, 111, 0, 0, 201, 202, 5, 110, 0, 0, 202, 203, 5, 116, 0, 0, 203, 204, 5, 114, 0, 0, 204, 205, 5, 97, 0, 0, 205, 206, 5, 99, 0, 0, 206, 207, 5, 116, 0, 0, 207, 22, 1, 0, 0, 0, 208, 209, 5, 123, 0, 0, 209, 24, 1, 0, 0, 0, 210, 211, 5, 125, 0, 0, 211, 26, 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, 28, 1, 0, 0, 0, 221, 222, 5, 40, 0, 0, 222, 30, 1, 0, 0, 0, 223, 224, 5, 44, 0, 0, 224, 32, 1, 0, 0, 0, 225, 226, 5, 41, 0, 0, 226, 34, 1, 0, 0, 0, 227, 228, 5, 43, 0, 0, 228, 229, 5, 61, 0, 0, 229, 36, 1, 0, 0, 0, 230, 231, 5, 45, 0, 0, 231, 232, 5, 61, 0, 0, 232, 38, 1, 0, 0, 0, 233, 234, 5, 43, 0, 0, 234, 235, 5, 43, 0, 0, 235, 40, 1, 0, 0, 0, 236, 237, 5, 45, 0, 0, 237, 238, 5, 45, 0, 0, 238, 42, 1, 0, 0, 0, 239, 240, 5, 114, 0, 0, 240, 241, 5, 101, 0, 0, 241, 242, 5, 113, 0, 0, 242, 243, 5, 117, 0, 0, 243, 244, 5, 105, 0, 0, 244, 245, 5, 114, 0, 0, 245, 246, 5, 101, 0, 0, 246, 44, 1, 0, 0, 0, 247, 248, 5, 99, 0, 0, 248, 249, 5, 111, 0, 0, 249, 250, 5, 110, 0, 0, 250, 251, 5, 115, 0, 0, 251, 252, 5, 111, 0, 0, 252, 253, 5, 108, 0, 0, 253, 254, 5, 101, 0, 0, 254, 255, 5, 46, 0, 0, 255, 256, 5, 108, 0, 0, 256, 257, 5, 111, 0, 0, 257, 258, 5, 103, 0, 0, 258, 46, 1, 0, 0, 0, 259, 260, 5, 105, 0, 0, 260, 261, 5, 102, 0, 0, 261, 48, 1, 0, 0, 0, 262, 263, 5, 101, 0, 0, 263, 264, 5, 108, 0, 0, 264, 265, 5, 115, 0, 0, 265, 266, 5, 101, 0, 0, 266, 50, 1, 0, 0, 0, 267, 268, 5, 100, 0, 0, 268, 269, 5, 111, 0, 0, 269, 52, 1, 0, 0, 0, 270, 271, 5, 119, 0, 0, 271, 272, 5, 104, 0, 0, 272, 273, 5, 105, 0, 0, 273, 274, 5, 108, 0, 0, 274, 275, 5, 101, 0, 0, 275, 54, 1, 0, 0, 0, 276, 277, 5, 102, 0, 0, 277, 278, 5, 111, 0, 0, 278, 279, 5, 114, 0, 0, 279, 56, 1, 0, 0, 0, 280, 281, 5, 110, 0, 0, 281, 282, 5, 101, 0, 0, 282, 283, 5, 119, 0, 0, 283, 58, 1, 0, 0, 0, 284, 285, 5, 91, 0, 0, 285, 60, 1, 0, 0, 0, 286, 287, 5, 93, 0, 0, 287, 62, 1, 0, 0, 0, 288, 289, 5, 116, 0, 0, 289, 290, 5, 120, 0, 0, 290, 291, 5, 46, 0, 0, 291, 292, 5, 111, 0, 0, 292, 293, 5, 117, 0, 0, 293, 294, 5, 116, 0, 0, 294, 295, 5, 112, 0, 0, 295, 296, 5, 117, 0, 0, 296, 297, 5, 116, 0, 0, 297, 298, 5, 115, 0, 0, 298, 64, 1, 0, 0, 0, 299, 300, 5, 46, 0, 0, 300, 301, 5, 118, 0, 0, 301, 302, 5, 97, 0, 0, 302, 303, 5, 108, 0, 0, 303, 304, 5, 117, 0, 0, 304, 305, 5, 101, 0, 0, 305, 66, 1, 0, 0, 0, 306, 307, 5, 46, 0, 0, 307, 308, 5, 108, 0, 0, 308, 309, 5, 111, 0, 0, 309, 310, 5, 99, 0, 0, 310, 311, 5, 107, 0, 0, 311, 312, 5, 105, 0, 0, 312, 313, 5, 110, 0, 0, 313, 314, 5, 103, 0, 0, 314, 315, 5, 66, 0, 0, 315, 316, 5, 121, 0, 0, 316, 317, 5, 116, 0, 0, 317, 318, 5, 101, 0, 0, 318, 319, 5, 99, 0, 0, 319, 320, 5, 111, 0, 0, 320, 321, 5, 100, 0, 0, 321, 322, 5, 101, 0, 0, 322, 68, 1, 0, 0, 0, 323, 324, 5, 46, 0, 0, 324, 325, 5, 116, 0, 0, 325, 326, 5, 111, 0, 0, 326, 327, 5, 107, 0, 0, 327, 328, 5, 101, 0, 0, 328, 329, 5, 110, 0, 0, 329, 330, 5, 67, 0, 0, 330, 331, 5, 97, 0, 0, 331, 332, 5, 116, 0, 0, 332, 333, 5, 101, 0, 0, 333, 334, 5, 103, 0, 0, 334, 335, 5, 111, 0, 0, 335, 336, 5, 114, 0, 0, 336, 337, 5, 121, 0, 0, 337, 70, 1, 0, 0, 0, 338, 339, 5, 46, 0, 0, 339, 340, 5, 110, 0, 0, 340, 341, 5, 102, 0, 0, 341, 342, 5, 116, 0, 0, 342, 343, 5, 67, 0, 0, 343, 344, 5, 111, 0, 0, 344, 345, 5, 109, 0, 0, 345, 346, 5, 109, 0, 0, 346, 347, 5, 105, 0, 0, 347, 348, 5, 116, 0, 0, 348, 349, 5, 109, 0, 0, 349, 350, 5, 101, 0, 0, 350, 351, 5, 110, 0, 0, 351, 352, 5, 116, 0, 0, 352, 72, 1, 0, 0, 0, 353, 354, 5, 46, 0, 0, 354, 355, 5, 116, 0, 0, 355, 356, 5, 111, 0, 0, 356, 357, 5, 107, 0, 0, 357, 358, 5, 101, 0, 0, 358, 359, 5, 110, 0, 0, 359, 360, 5, 65, 0, 0, 360, 361, 5, 109, 0, 0, 361, 362, 5, 111, 0, 0, 362, 363, 5, 117, 0, 0, 363, 364, 5, 110, 0, 0, 364, 365, 5, 116, 0, 0, 365, 74, 1, 0, 0, 0, 366, 367, 5, 116, 0, 0, 367, 368, 5, 120, 0, 0, 368, 369, 5, 46, 0, 0, 369, 370, 5, 105, 0, 0, 370, 371, 5, 110, 0, 0, 371, 372, 5, 112, 0, 0, 372, 373, 5, 117, 0, 0, 373, 374, 5, 116, 0, 0, 374, 375, 5, 115, 0, 0, 375, 76, 1, 0, 0, 0, 376, 377, 5, 46, 0, 0, 377, 378, 5, 111, 0, 0, 378, 379, 5, 117, 0, 0, 379, 380, 5, 116, 0, 0, 380, 381, 5, 112, 0, 0, 381, 382, 5, 111, 0, 0, 382, 383, 5, 105, 0, 0, 383, 384, 5, 110, 0, 0, 384, 385, 5, 116, 0, 0, 385, 386, 5, 84, 0, 0, 386, 387, 5, 114, 0, 0, 387, 388, 5, 97, 0, 0, 388, 389, 5, 110, 0, 0, 389, 390, 5, 115, 0, 0, 390, 391, 5, 97, 0, 0, 391, 392, 5, 99, 0, 0, 392, 393, 5, 116, 0, 0, 393, 394, 5, 105, 0, 0, 394, 395, 5, 111, 0, 0, 395, 396, 5, 110, 0, 0, 396, 397, 5, 72, 0, 0, 397, 398, 5, 97, 0, 0, 398, 399, 5, 115, 0, 0, 399, 400, 5, 104, 0, 0, 400, 78, 1, 0, 0, 0, 401, 402, 5, 46, 0, 0, 402, 403, 5, 111, 0, 0, 403, 404, 5, 117, 0, 0, 404, 405, 5, 116, 0, 0, 405, 406, 5, 112, 0, 0, 406, 407, 5, 111, 0, 0, 407, 408, 5, 105, 0, 0, 408, 409, 5, 110, 0, 0, 409, 410, 5, 116, 0, 0, 410, 411, 5, 73, 0, 0, 411, 412, 5, 110, 0, 0, 412, 413, 5, 100, 0, 0, 413, 414, 5, 101, 0, 0, 414, 415, 5, 120, 0, 0, 415, 80, 1, 0, 0, 0, 416, 417, 5, 46, 0, 0, 417, 418, 5, 117, 0, 0, 418, 419, 5, 110, 0, 0, 419, 420, 5, 108, 0, 0, 420, 421, 5, 111, 0, 0, 421, 422, 5, 99, 0, 0, 422, 423, 5, 107, 0, 0, 423, 424, 5, 105, 0, 0, 424, 425, 5, 110, 0, 0, 425, 426, 5, 103, 0, 0, 426, 427, 5, 66, 0, 0, 427, 428, 5, 121, 0, 0, 428, 429, 5, 116, 0, 0, 429, 430, 5, 101, 0, 0, 430, 431, 5, 99, 0, 0, 431, 432, 5, 111, 0, 0, 432, 433, 5, 100, 0, 0, 433, 434, 5, 101, 0, 0, 434, 82, 1, 0, 0, 0, 435, 436, 5, 46, 0, 0, 436, 437, 5, 115, 0, 0, 437, 438, 5, 101, 0, 0, 438, 439, 5, 113, 0, 0, 439, 440, 5, 117, 0, 0, 440, 441, 5, 101, 0, 0, 441, 442, 5, 110, 0, 0, 442, 443, 5, 99, 0, 0, 443, 444, 5, 101, 0, 0, 444, 445, 5, 78, 0, 0, 445, 446, 5, 117, 0, 0, 446, 447, 5, 109, 0, 0, 447, 448, 5, 98, 0, 0, 448, 449, 5, 101, 0, 0, 449, 450, 5, 114, 0, 0, 450, 84, 1, 0, 0, 0, 451, 452, 5, 46, 0, 0, 452, 453, 5, 114, 0, 0, 453, 454, 5, 101, 0, 0, 454, 455, 5, 118, 0, 0, 455, 456, 5, 101, 0, 0, 456, 457, 5, 114, 0, 0, 457, 458, 5, 115, 0, 0, 458, 459, 5, 101, 0, 0, 459, 460, 5, 40, 0, 0, 460, 461, 5, 41, 0, 0, 461, 86, 1, 0, 0, 0, 462, 463, 5, 46, 0, 0, 463, 464, 5, 108, 0, 0, 464, 465, 5, 101, 0, 0, 465, 466, 5, 110, 0, 0, 466, 467, 5, 103, 0, 0, 467, 468, 5, 116, 0, 0, 468, 469, 5, 104, 0, 0, 469, 88, 1, 0, 0, 0, 470, 471, 5, 46, 0, 0, 471, 472, 5, 115, 0, 0, 472, 473, 5, 112, 0, 0, 473, 474, 5, 108, 0, 0, 474, 475, 5, 105, 0, 0, 475, 476, 5, 116, 0, 0, 476, 90, 1, 0, 0, 0, 477, 478, 5, 46, 0, 0, 478, 479, 5, 115, 0, 0, 479, 480, 5, 108, 0, 0, 480, 481, 5, 105, 0, 0, 481, 482, 5, 99, 0, 0, 482, 483, 5, 101, 0, 0, 483, 92, 1, 0, 0, 0, 484, 485, 5, 33, 0, 0, 485, 94, 1, 0, 0, 0, 486, 487, 5, 45, 0, 0, 487, 96, 1, 0, 0, 0, 488, 489, 5, 42, 0, 0, 489, 98, 1, 0, 0, 0, 490, 491, 5, 47, 0, 0, 491, 100, 1, 0, 0, 0, 492, 493, 5, 37, 0, 0, 493, 102, 1, 0, 0, 0, 494, 495, 5, 43, 0, 0, 495, 104, 1, 0, 0, 0, 496, 497, 5, 62, 0, 0, 497, 498, 5, 62, 0, 0, 498, 106, 1, 0, 0, 0, 499, 500, 5, 60, 0, 0, 500, 501, 5, 60, 0, 0, 501, 108, 1, 0, 0, 0, 502, 503, 5, 61, 0, 0, 503, 504, 5, 61, 0, 0, 504, 110, 1, 0, 0, 0, 505, 506, 5, 33, 0, 0, 506, 507, 5, 61, 0, 0, 507, 112, 1, 0, 0, 0, 508, 509, 5, 38, 0, 0, 509, 114, 1, 0, 0, 0, 510, 511, 5, 124, 0, 0, 511, 116, 1, 0, 0, 0, 512, 513, 5, 38, 0, 0, 513, 514, 5, 38, 0, 0, 514, 118, 1, 0, 0, 0, 515, 516, 5, 124, 0, 0, 516, 517, 5, 124, 0, 0, 517, 120, 1, 0, 0, 0, 518, 519, 5, 99, 0, 0, 519, 520, 5, 111, 0, 0, 520, 521, 5, 110, 0, 0, 521, 522, 5, 115, 0, 0, 522, 523, 5, 116, 0, 0, 523, 524, 5, 97, 0, 0, 524, 525, 5, 110, 0, 0, 525, 526, 5, 116, 0, 0, 526, 122, 1, 0, 0, 0, 527, 529, 7, 0, 0, 0, 528, 527, 1, 0, 0, 0, 529, 530, 1, 0, 0, 0, 530, 528, 1, 0, 0, 0, 530, 531, 1, 0, 0, 0, 531, 532, 1, 0, 0, 0, 532, 534, 5, 46, 0, 0, 533, 535, 7, 0, 0, 0, 534, 533, 1, 0, 0, 0, 535, 536, 1, 0, 0, 0, 536, 534, 1, 0, 0, 0, 536, 537, 1, 0, 0, 0, 537, 538, 1, 0, 0, 0, 538, 540, 5, 46, 0, 0, 539, 541, 7, 0, 0, 0, 540, 539, 1, 0, 0, 0, 541, 542, 1, 0, 0, 0, 542, 540, 1, 0, 0, 0, 542, 543, 1, 0, 0, 0, 543, 124, 1, 0, 0, 0, 544, 545, 5, 116, 0, 0, 545, 546, 5, 114, 0, 0, 546, 547, 5, 117, 0, 0, 547, 554, 5, 101, 0, 0, 548, 549, 5, 102, 0, 0, 549, 550, 5, 97, 0, 0, 550, 551, 5, 108, 0, 0, 551, 552, 5, 115, 0, 0, 552, 554, 5, 101, 0, 0, 553, 544, 1, 0, 0, 0, 553, 548, 1, 0, 0, 0, 554, 126, 1, 0, 0, 0, 555, 556, 5, 115, 0, 0, 556, 557, 5, 97, 0, 0, 557, 558, 5, 116, 0, 0, 558, 559, 5, 111, 0, 0, 559, 560, 5, 115, 0, 0, 560, 561, 5, 104, 0, 0, 561, 562, 5, 105, 0, 0, 562, 613, 5, 115, 0, 0, 563, 564, 5, 115, 0, 0, 564, 565, 5, 97, 0, 0, 565, 566, 5, 116, 0, 0, 566, 613, 5, 115, 0, 0, 567, 568, 5, 102, 0, 0, 568, 569, 5, 105, 0, 0, 569, 570, 5, 110, 0, 0, 570, 571, 5, 110, 0, 0, 571, 572, 5, 101, 0, 0, 572, 613, 5, 121, 0, 0, 573, 574, 5, 98, 0, 0, 574, 575, 5, 105, 0, 0, 575, 576, 5, 116, 0, 0, 576, 613, 5, 115, 0, 0, 577, 578, 5, 98, 0, 0, 578, 579, 5, 105, 0, 0, 579, 580, 5, 116, 0, 0, 580, 581, 5, 99, 0, 0, 581, 582, 5, 111, 0, 0, 582, 583, 5, 105, 0, 0, 583, 613, 5, 110, 0, 0, 584, 585, 5, 115, 0, 0, 585, 586, 5, 101, 0, 0, 586, 587, 5, 99, 0, 0, 587, 588, 5, 111, 0, 0, 588, 589, 5, 110, 0, 0, 589, 590, 5, 100, 0, 0, 590, 613, 5, 115, 0, 0, 591, 592, 5, 109, 0, 0, 592, 593, 5, 105, 0, 0, 593, 594, 5, 110, 0, 0, 594, 595, 5, 117, 0, 0, 595, 596, 5, 116, 0, 0, 596, 597, 5, 101, 0, 0, 597, 613, 5, 115, 0, 0, 598, 599, 5, 104, 0, 0, 599, 600, 5, 111, 0, 0, 600, 601, 5, 117, 0, 0, 601, 602, 5, 114, 0, 0, 602, 613, 5, 115, 0, 0, 603, 604, 5, 100, 0, 0, 604, 605, 5, 97, 0, 0, 605, 606, 5, 121, 0, 0, 606, 613, 5, 115, 0, 0, 607, 608, 5, 119, 0, 0, 608, 609, 5, 101, 0, 0, 609, 610, 5, 101, 0, 0, 610, 611, 5, 107, 0, 0, 611, 613, 5, 115, 0, 0, 612, 555, 1, 0, 0, 0, 612, 563, 1, 0, 0, 0, 612, 567, 1, 0, 0, 0, 612, 573, 1, 0, 0, 0, 612, 577, 1, 0, 0, 0, 612, 584, 1, 0, 0, 0, 612, 591, 1, 0, 0, 0, 612, 598, 1, 0, 0, 0, 612, 603, 1, 0, 0, 0, 612, 607, 1, 0, 0, 0, 613, 128, 1, 0, 0, 0, 614, 616, 5, 45, 0, 0, 615, 614, 1, 0, 0, 0, 615, 616, 1, 0, 0, 0, 616, 617, 1, 0, 0, 0, 617, 619, 3, 131, 65, 0, 618, 620, 3, 133, 66, 0, 619, 618, 1, 0, 0, 0, 619, 620, 1, 0, 0, 0, 620, 130, 1, 0, 0, 0, 621, 623, 7, 0, 0, 0, 622, 621, 1, 0, 0, 0, 623, 624, 1, 0, 0, 0, 624, 622, 1, 0, 0, 0, 624, 625, 1, 0, 0, 0, 625, 634, 1, 0, 0, 0, 626, 628, 5, 95, 0, 0, 627, 629, 7, 0, 0, 0, 628, 627, 1, 0, 0, 0, 629, 630, 1, 0, 0, 0, 630, 628, 1, 0, 0, 0, 630, 631, 1, 0, 0, 0, 631, 633, 1, 0, 0, 0, 632, 626, 1, 0, 0, 0, 633, 636, 1, 0, 0, 0, 634, 632, 1, 0, 0, 0, 634, 635, 1, 0, 0, 0, 635, 132, 1, 0, 0, 0, 636, 634, 1, 0, 0, 0, 637, 638, 7, 1, 0, 0, 638, 639, 3, 131, 65, 0, 639, 134, 1, 0, 0, 0, 640, 641, 5, 105, 0, 0, 641, 642, 5, 110, 0, 0, 642, 670, 5, 116, 0, 0, 643, 644, 5, 98, 0, 0, 644, 645, 5, 111, 0, 0, 645, 646, 5, 111, 0, 0, 646, 670, 5, 108, 0, 0, 647, 648, 5, 115, 0, 0, 648, 649, 5, 116, 0, 0, 649, 650, 5, 114, 0, 0, 650, 651, 5, 105, 0, 0, 651, 652, 5, 110, 0, 0, 652, 670, 5, 103, 0, 0, 653, 654, 5, 112, 0, 0, 654, 655, 5, 117, 0, 0, 655, 656, 5, 98, 0, 0, 656, 657, 5, 107, 0, 0, 657, 658, 5, 101, 0, 0, 658, 670, 5, 121, 0, 0, 659, 660, 5, 115, 0, 0, 660, 661, 5, 105, 0, 0, 661, 670, 5, 103, 0, 0, 662, 663, 5, 100, 0, 0, 663, 664, 5, 97, 0, 0, 664, 665, 5, 116, 0, 0, 665, 666, 5, 97, 0, 0, 666, 667, 5, 115, 0, 0, 667, 668, 5, 105, 0, 0, 668, 670, 5, 103, 0, 0, 669, 640, 1, 0, 0, 0, 669, 643, 1, 0, 0, 0, 669, 647, 1, 0, 0, 0, 669, 653, 1, 0, 0, 0, 669, 659, 1, 0, 0, 0, 669, 662, 1, 0, 0, 0, 670, 136, 1, 0, 0, 0, 671, 672, 5, 98, 0, 0, 672, 673, 5, 121, 0, 0, 673, 674, 5, 116, 0, 0, 674, 675, 5, 101, 0, 0, 675, 676, 5, 115, 0, 0, 676, 138, 1, 0, 0, 0, 677, 678, 5, 98, 0, 0, 678, 679, 5, 121, 0, 0, 679, 680, 5, 116, 0, 0, 680, 681, 5, 101, 0, 0, 681, 682, 5, 115, 0, 0, 682, 683, 1, 0, 0, 0, 683, 689, 3, 141, 70, 0, 684, 685, 5, 98, 0, 0, 685, 686, 5, 121, 0, 0, 686, 687, 5, 116, 0, 0, 687, 689, 5, 101, 0, 0, 688, 677, 1, 0, 0, 0, 688, 684, 1, 0, 0, 0, 689, 140, 1, 0, 0, 0, 690, 694, 7, 2, 0, 0, 691, 693, 7, 0, 0, 0, 692, 691, 1, 0, 0, 0, 693, 696, 1, 0, 0, 0, 694, 692, 1, 0, 0, 0, 694, 695, 1, 0, 0, 0, 695, 142, 1, 0, 0, 0, 696, 694, 1, 0, 0, 0, 697, 703, 5, 34, 0, 0, 698, 699, 5, 92, 0, 0, 699, 702, 5, 34, 0, 0, 700, 702, 8, 3, 0, 0, 701, 698, 1, 0, 0, 0, 701, 700, 1, 0, 0, 0, 702, 705, 1, 0, 0, 0, 703, 704, 1, 0, 0, 0, 703, 701, 1, 0, 0, 0, 704, 706, 1, 0, 0, 0, 705, 703, 1, 0, 0, 0, 706, 718, 5, 34, 0, 0, 707, 713, 5, 39, 0, 0, 708, 709, 5, 92, 0, 0, 709, 712, 5, 39, 0, 0, 710, 712, 8, 4, 0, 0, 711, 708, 1, 0, 0, 0, 711, 710, 1, 0, 0, 0, 712, 715, 1, 0, 0, 0, 713, 714, 1, 0, 0, 0, 713, 711, 1, 0, 0, 0, 714, 716, 1, 0, 0, 0, 715, 713, 1, 0, 0, 0, 716, 718, 5, 39, 0, 0, 717, 697, 1, 0, 0, 0, 717, 707, 1, 0, 0, 0, 718, 144, 1, 0, 0, 0, 719, 720, 5, 100, 0, 0, 720, 721, 5, 97, 0, 0, 721, 722, 5, 116, 0, 0, 722, 723, 5, 101, 0, 0, 723, 724, 5, 40, 0, 0, 724, 725, 1, 0, 0, 0, 725, 726, 3, 143, 71, 0, 726, 727, 5, 41, 0, 0, 727, 146, 1, 0, 0, 0, 728, 729, 5, 48, 0, 0, 729, 733, 7, 5, 0, 0, 730, 732, 7, 6, 0, 0, 731, 730, 1, 0, 0, 0, 732, 735, 1, 0, 0, 0, 733, 731, 1, 0, 0, 0, 733, 734, 1, 0, 0, 0, 734, 148, 1, 0, 0, 0, 735, 733, 1, 0, 0, 0, 736, 737, 5, 116, 0, 0, 737, 738, 5, 104, 0, 0, 738, 739, 5, 105, 0, 0, 739, 740, 5, 115, 0, 0, 740, 741, 5, 46, 0, 0, 741, 742, 5, 97, 0, 0, 742, 743, 5, 103, 0, 0, 743, 752, 5, 101, 0, 0, 744, 745, 5, 116, 0, 0, 745, 746, 5, 120, 0, 0, 746, 747, 5, 46, 0, 0, 747, 748, 5, 116, 0, 0, 748, 749, 5, 105, 0, 0, 749, 750, 5, 109, 0, 0, 750, 752, 5, 101, 0, 0, 751, 736, 1, 0, 0, 0, 751, 744, 1, 0, 0, 0, 752, 150, 1, 0, 0, 0, 753, 754, 5, 117, 0, 0, 754, 755, 5, 110, 0, 0, 755, 756, 5, 115, 0, 0, 756, 757, 5, 97, 0, 0, 757, 758, 5, 102, 0, 0, 758, 759, 5, 101, 0, 0, 759, 760, 5, 95, 0, 0, 760, 761, 5, 105, 0, 0, 761, 762, 5, 110, 0, 0, 762, 802, 5, 116, 0, 0, 763, 764, 5, 117, 0, 0, 764, 765, 5, 110, 0, 0, 765, 766, 5, 115, 0, 0, 766, 767, 5, 97, 0, 0, 767, 768, 5, 102, 0, 0, 768, 769, 5, 101, 0, 0, 769, 770, 5, 95, 0, 0, 770, 771, 5, 98, 0, 0, 771, 772, 5, 111, 0, 0, 772, 773, 5, 111, 0, 0, 773, 802, 5, 108, 0, 0, 774, 775, 5, 117, 0, 0, 775, 776, 5, 110, 0, 0, 776, 777, 5, 115, 0, 0, 777, 778, 5, 97, 0, 0, 778, 779, 5, 102, 0, 0, 779, 780, 5, 101, 0, 0, 780, 781, 5, 95, 0, 0, 781, 782, 5, 98, 0, 0, 782, 783, 5, 121, 0, 0, 783, 784, 5, 116, 0, 0, 784, 785, 5, 101, 0, 0, 785, 786, 5, 115, 0, 0, 786, 788, 1, 0, 0, 0, 787, 789, 3, 141, 70, 0, 788, 787, 1, 0, 0, 0, 788, 789, 1, 0, 0, 0, 789, 802, 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, 98, 0, 0, 798, 799, 5, 121, 0, 0, 799, 800, 5, 116, 0, 0, 800, 802, 5, 101, 0, 0, 801, 753, 1, 0, 0, 0, 801, 763, 1, 0, 0, 0, 801, 774, 1, 0, 0, 0, 801, 790, 1, 0, 0, 0, 802, 152, 1, 0, 0, 0, 803, 804, 5, 116, 0, 0, 804, 805, 5, 104, 0, 0, 805, 806, 5, 105, 0, 0, 806, 807, 5, 115, 0, 0, 807, 808, 5, 46, 0, 0, 808, 809, 5, 97, 0, 0, 809, 810, 5, 99, 0, 0, 810, 811, 5, 116, 0, 0, 811, 812, 5, 105, 0, 0, 812, 813, 5, 118, 0, 0, 813, 814, 5, 101, 0, 0, 814, 815, 5, 73, 0, 0, 815, 816, 5, 110, 0, 0, 816, 817, 5, 112, 0, 0, 817, 818, 5, 117, 0, 0, 818, 819, 5, 116, 0, 0, 819, 820, 5, 73, 0, 0, 820, 821, 5, 110, 0, 0, 821, 822, 5, 100, 0, 0, 822, 823, 5, 101, 0, 0, 823, 898, 5, 120, 0, 0, 824, 825, 5, 116, 0, 0, 825, 826, 5, 104, 0, 0, 826, 827, 5, 105, 0, 0, 827, 828, 5, 115, 0, 0, 828, 829, 5, 46, 0, 0, 829, 830, 5, 97, 0, 0, 830, 831, 5, 99, 0, 0, 831, 832, 5, 116, 0, 0, 832, 833, 5, 105, 0, 0, 833, 834, 5, 118, 0, 0, 834, 835, 5, 101, 0, 0, 835, 836, 5, 66, 0, 0, 836, 837, 5, 121, 0, 0, 837, 838, 5, 116, 0, 0, 838, 839, 5, 101, 0, 0, 839, 840, 5, 99, 0, 0, 840, 841, 5, 111, 0, 0, 841, 842, 5, 100, 0, 0, 842, 898, 5, 101, 0, 0, 843, 844, 5, 116, 0, 0, 844, 845, 5, 120, 0, 0, 845, 846, 5, 46, 0, 0, 846, 847, 5, 105, 0, 0, 847, 848, 5, 110, 0, 0, 848, 849, 5, 112, 0, 0, 849, 850, 5, 117, 0, 0, 850, 851, 5, 116, 0, 0, 851, 852, 5, 115, 0, 0, 852, 853, 5, 46, 0, 0, 853, 854, 5, 108, 0, 0, 854, 855, 5, 101, 0, 0, 855, 856, 5, 110, 0, 0, 856, 857, 5, 103, 0, 0, 857, 858, 5, 116, 0, 0, 858, 898, 5, 104, 0, 0, 859, 860, 5, 116, 0, 0, 860, 861, 5, 120, 0, 0, 861, 862, 5, 46, 0, 0, 862, 863, 5, 111, 0, 0, 863, 864, 5, 117, 0, 0, 864, 865, 5, 116, 0, 0, 865, 866, 5, 112, 0, 0, 866, 867, 5, 117, 0, 0, 867, 868, 5, 116, 0, 0, 868, 869, 5, 115, 0, 0, 869, 870, 5, 46, 0, 0, 870, 871, 5, 108, 0, 0, 871, 872, 5, 101, 0, 0, 872, 873, 5, 110, 0, 0, 873, 874, 5, 103, 0, 0, 874, 875, 5, 116, 0, 0, 875, 898, 5, 104, 0, 0, 876, 877, 5, 116, 0, 0, 877, 878, 5, 120, 0, 0, 878, 879, 5, 46, 0, 0, 879, 880, 5, 118, 0, 0, 880, 881, 5, 101, 0, 0, 881, 882, 5, 114, 0, 0, 882, 883, 5, 115, 0, 0, 883, 884, 5, 105, 0, 0, 884, 885, 5, 111, 0, 0, 885, 898, 5, 110, 0, 0, 886, 887, 5, 116, 0, 0, 887, 888, 5, 120, 0, 0, 888, 889, 5, 46, 0, 0, 889, 890, 5, 108, 0, 0, 890, 891, 5, 111, 0, 0, 891, 892, 5, 99, 0, 0, 892, 893, 5, 107, 0, 0, 893, 894, 5, 116, 0, 0, 894, 895, 5, 105, 0, 0, 895, 896, 5, 109, 0, 0, 896, 898, 5, 101, 0, 0, 897, 803, 1, 0, 0, 0, 897, 824, 1, 0, 0, 0, 897, 843, 1, 0, 0, 0, 897, 859, 1, 0, 0, 0, 897, 876, 1, 0, 0, 0, 897, 886, 1, 0, 0, 0, 898, 154, 1, 0, 0, 0, 899, 903, 7, 7, 0, 0, 900, 902, 7, 8, 0, 0, 901, 900, 1, 0, 0, 0, 902, 905, 1, 0, 0, 0, 903, 901, 1, 0, 0, 0, 903, 904, 1, 0, 0, 0, 904, 156, 1, 0, 0, 0, 905, 903, 1, 0, 0, 0, 906, 908, 7, 9, 0, 0, 907, 906, 1, 0, 0, 0, 908, 909, 1, 0, 0, 0, 909, 907, 1, 0, 0, 0, 909, 910, 1, 0, 0, 0, 910, 911, 1, 0, 0, 0, 911, 912, 6, 78, 0, 0, 912, 158, 1, 0, 0, 0, 913, 914, 5, 47, 0, 0, 914, 915, 5, 42, 0, 0, 915, 919, 1, 0, 0, 0, 916, 918, 9, 0, 0, 0, 917, 916, 1, 0, 0, 0, 918, 921, 1, 0, 0, 0, 919, 920, 1, 0, 0, 0, 919, 917, 1, 0, 0, 0, 920, 922, 1, 0, 0, 0, 921, 919, 1, 0, 0, 0, 922, 923, 5, 42, 0, 0, 923, 924, 5, 47, 0, 0, 924, 925, 1, 0, 0, 0, 925, 926, 6, 79, 1, 0, 926, 160, 1, 0, 0, 0, 927, 928, 5, 47, 0, 0, 928, 929, 5, 47, 0, 0, 929, 933, 1, 0, 0, 0, 930, 932, 8, 10, 0, 0, 931, 930, 1, 0, 0, 0, 932, 935, 1, 0, 0, 0, 933, 931, 1, 0, 0, 0, 933, 934, 1, 0, 0, 0, 934, 936, 1, 0, 0, 0, 935, 933, 1, 0, 0, 0, 936, 937, 6, 80, 1, 0, 937, 162, 1, 0, 0, 0, 28, 0, 530, 536, 542, 553, 612, 615, 619, 624, 630, 634, 669, 688, 694, 701, 703, 711, 713, 717, 733, 751, 788, 801, 897, 903, 909, 919, 933, 2, 6, 0, 0, 0, 1, 0] \ No newline at end of file +[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 diff --git a/packages/cashc/src/grammar/CashScriptLexer.tokens b/packages/cashc/src/grammar/CashScriptLexer.tokens index b9cfb61bd..16dc361de 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.tokens +++ b/packages/cashc/src/grammar/CashScriptLexer.tokens @@ -59,26 +59,29 @@ T__57=58 T__58=59 T__59=60 T__60=61 -VersionLiteral=62 -BooleanLiteral=63 -NumberUnit=64 -NumberLiteral=65 -NumberPart=66 -ExponentPart=67 -PrimitiveType=68 -UnboundedBytes=69 -BoundedBytes=70 -Bound=71 -StringLiteral=72 -DateLiteral=73 -HexLiteral=74 -TxVar=75 -UnsafeCast=76 -NullaryOp=77 -Identifier=78 -WHITESPACE=79 -COMMENT=80 -LINE_COMMENT=81 +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 'pragma'=1 ';'=2 'cashscript'=3 @@ -89,55 +92,58 @@ LINE_COMMENT=81 '<'=8 '<='=9 '='=10 -'contract'=11 -'{'=12 -'}'=13 -'function'=14 -'('=15 -','=16 -')'=17 -'+='=18 -'-='=19 -'++'=20 -'--'=21 -'require'=22 -'console.log'=23 -'if'=24 -'else'=25 -'do'=26 -'while'=27 -'for'=28 -'new'=29 -'['=30 -']'=31 -'tx.outputs'=32 -'.value'=33 -'.lockingBytecode'=34 -'.tokenCategory'=35 -'.nftCommitment'=36 -'.tokenAmount'=37 -'tx.inputs'=38 -'.outpointTransactionHash'=39 -'.outpointIndex'=40 -'.unlockingBytecode'=41 -'.sequenceNumber'=42 -'.reverse()'=43 -'.length'=44 -'.split'=45 -'.slice'=46 -'!'=47 -'-'=48 -'*'=49 -'/'=50 -'%'=51 -'+'=52 -'>>'=53 -'<<'=54 -'=='=55 -'!='=56 -'&'=57 -'|'=58 -'&&'=59 -'||'=60 -'constant'=61 -'bytes'=69 +'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 diff --git a/packages/cashc/src/grammar/CashScriptLexer.ts b/packages/cashc/src/grammar/CashScriptLexer.ts index c67a03b5f..0300faedd 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.ts +++ b/packages/cashc/src/grammar/CashScriptLexer.ts @@ -73,26 +73,29 @@ export default class CashScriptLexer extends Lexer { public static readonly T__58 = 59; public static readonly T__59 = 60; public static readonly T__60 = 61; - public static readonly VersionLiteral = 62; - public static readonly BooleanLiteral = 63; - public static readonly NumberUnit = 64; - public static readonly NumberLiteral = 65; - public static readonly NumberPart = 66; - public static readonly ExponentPart = 67; - public static readonly PrimitiveType = 68; - public static readonly UnboundedBytes = 69; - public static readonly BoundedBytes = 70; - public static readonly Bound = 71; - public static readonly StringLiteral = 72; - public static readonly DateLiteral = 73; - public static readonly HexLiteral = 74; - public static readonly TxVar = 75; - public static readonly UnsafeCast = 76; - public static readonly NullaryOp = 77; - public static readonly Identifier = 78; - public static readonly WHITESPACE = 79; - public static readonly COMMENT = 80; - public static readonly LINE_COMMENT = 81; + 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 channelNames: string[] = [ "DEFAULT_TOKEN_CHANNEL", "HIDDEN" ]; @@ -101,13 +104,16 @@ export default class CashScriptLexer extends Lexer { "'^'", "'~'", "'>='", "'>'", "'<'", "'<='", - "'='", "'contract'", - "'{'", "'}'", + "'='", "'import'", "'function'", - "'('", "','", - "')'", "'+='", - "'-='", "'++'", - "'--'", "'require'", + "'returns'", + "'('", "')'", + "'contract'", + "'{'", "'}'", + "','", "'return'", + "'+='", "'-='", + "'++'", "'--'", + "'require'", "'console.log'", "'if'", "'else'", "'do'", "'while'", @@ -171,7 +177,8 @@ export default class CashScriptLexer extends Lexer { null, null, null, null, null, null, - "VersionLiteral", + null, null, + null, "VersionLiteral", "BooleanLiteral", "NumberUnit", "NumberLiteral", @@ -199,11 +206,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", "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", "VersionLiteral", + "BooleanLiteral", "NumberUnit", "NumberLiteral", "NumberPart", "ExponentPart", + "PrimitiveType", "UnboundedBytes", "BoundedBytes", "Bound", "StringLiteral", + "DateLiteral", "HexLiteral", "TxVar", "UnsafeCast", "NullaryOp", "Identifier", + "WHITESPACE", "COMMENT", "LINE_COMMENT", ]; @@ -224,7 +231,7 @@ export default class CashScriptLexer extends Lexer { public get modeNames(): string[] { return CashScriptLexer.modeNames; } - public static readonly _serializedATN: number[] = [4,0,81,938,6,-1,2,0, + public static readonly _serializedATN: number[] = [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, @@ -235,304 +242,313 @@ export default class CashScriptLexer extends Lexer { 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,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,10,1,10,1,11,1,11,1,12,1,12,1,13,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,18,1,18,1,18,1,19,1,19,1,19,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,1,22,1,22,1,22,1,22,1,22,1,22,1, - 22,1,23,1,23,1,23,1,24,1,24,1,24,1,24,1,24,1,25,1,25,1,25,1,26,1,26,1,26, - 1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,28,1,28,1,28,1,28,1,29,1,29,1,30,1, - 30,1,31,1,31,1,31,1,31,1,31,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,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1,33,1, - 33,1,33,1,33,1,33,1,33,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,34,1,34,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,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,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,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,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,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,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,46,1,46,1,47,1,47,1,48,1,48,1, - 49,1,49,1,50,1,50,1,51,1,51,1,52,1,52,1,52,1,53,1,53,1,53,1,54,1,54,1,54, - 1,55,1,55,1,55,1,56,1,56,1,57,1,57,1,58,1,58,1,58,1,59,1,59,1,59,1,60,1, - 60,1,60,1,60,1,60,1,60,1,60,1,60,1,60,1,61,4,61,529,8,61,11,61,12,61,530, - 1,61,1,61,4,61,535,8,61,11,61,12,61,536,1,61,1,61,4,61,541,8,61,11,61,12, - 61,542,1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,62,1,62,3,62,554,8,62,1,63, - 1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1, - 63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63, - 1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1, - 63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,1,63,3,63,613, - 8,63,1,64,3,64,616,8,64,1,64,1,64,3,64,620,8,64,1,65,4,65,623,8,65,11,65, - 12,65,624,1,65,1,65,4,65,629,8,65,11,65,12,65,630,5,65,633,8,65,10,65,12, - 65,636,9,65,1,66,1,66,1,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,3,67,670,8,67,1,68,1,68,1,68,1,68,1,68,1,68, - 1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,1,69,3,69,689,8,69,1, - 70,1,70,5,70,693,8,70,10,70,12,70,696,9,70,1,71,1,71,1,71,1,71,5,71,702, - 8,71,10,71,12,71,705,9,71,1,71,1,71,1,71,1,71,1,71,5,71,712,8,71,10,71, - 12,71,715,9,71,1,71,3,71,718,8,71,1,72,1,72,1,72,1,72,1,72,1,72,1,72,1, - 72,1,72,1,73,1,73,1,73,5,73,732,8,73,10,73,12,73,735,9,73,1,74,1,74,1,74, - 1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,1,74,3,74,752,8, - 74,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75, - 1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1,75,1, - 75,1,75,1,75,1,75,1,75,1,75,1,75,3,75,789,8,75,1,75,1,75,1,75,1,75,1,75, - 1,75,1,75,1,75,1,75,1,75,1,75,3,75,802,8,75,1,76,1,76,1,76,1,76,1,76,1, - 76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76, - 1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1, - 76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76, - 1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1, - 76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76, - 1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1,76,1, - 76,1,76,3,76,898,8,76,1,77,1,77,5,77,902,8,77,10,77,12,77,905,9,77,1,78, - 4,78,908,8,78,11,78,12,78,909,1,78,1,78,1,79,1,79,1,79,1,79,5,79,918,8, - 79,10,79,12,79,921,9,79,1,79,1,79,1,79,1,79,1,79,1,80,1,80,1,80,1,80,5, - 80,932,8,80,10,80,12,80,935,9,80,1,80,1,80,3,703,713,919,0,81,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,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,982,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,1,163,1,0,0, - 0,3,170,1,0,0,0,5,172,1,0,0,0,7,183,1,0,0,0,9,185,1,0,0,0,11,187,1,0,0, - 0,13,190,1,0,0,0,15,192,1,0,0,0,17,194,1,0,0,0,19,197,1,0,0,0,21,199,1, - 0,0,0,23,208,1,0,0,0,25,210,1,0,0,0,27,212,1,0,0,0,29,221,1,0,0,0,31,223, - 1,0,0,0,33,225,1,0,0,0,35,227,1,0,0,0,37,230,1,0,0,0,39,233,1,0,0,0,41, - 236,1,0,0,0,43,239,1,0,0,0,45,247,1,0,0,0,47,259,1,0,0,0,49,262,1,0,0,0, - 51,267,1,0,0,0,53,270,1,0,0,0,55,276,1,0,0,0,57,280,1,0,0,0,59,284,1,0, - 0,0,61,286,1,0,0,0,63,288,1,0,0,0,65,299,1,0,0,0,67,306,1,0,0,0,69,323, - 1,0,0,0,71,338,1,0,0,0,73,353,1,0,0,0,75,366,1,0,0,0,77,376,1,0,0,0,79, - 401,1,0,0,0,81,416,1,0,0,0,83,435,1,0,0,0,85,451,1,0,0,0,87,462,1,0,0,0, - 89,470,1,0,0,0,91,477,1,0,0,0,93,484,1,0,0,0,95,486,1,0,0,0,97,488,1,0, - 0,0,99,490,1,0,0,0,101,492,1,0,0,0,103,494,1,0,0,0,105,496,1,0,0,0,107, - 499,1,0,0,0,109,502,1,0,0,0,111,505,1,0,0,0,113,508,1,0,0,0,115,510,1,0, - 0,0,117,512,1,0,0,0,119,515,1,0,0,0,121,518,1,0,0,0,123,528,1,0,0,0,125, - 553,1,0,0,0,127,612,1,0,0,0,129,615,1,0,0,0,131,622,1,0,0,0,133,637,1,0, - 0,0,135,669,1,0,0,0,137,671,1,0,0,0,139,688,1,0,0,0,141,690,1,0,0,0,143, - 717,1,0,0,0,145,719,1,0,0,0,147,728,1,0,0,0,149,751,1,0,0,0,151,801,1,0, - 0,0,153,897,1,0,0,0,155,899,1,0,0,0,157,907,1,0,0,0,159,913,1,0,0,0,161, - 927,1,0,0,0,163,164,5,112,0,0,164,165,5,114,0,0,165,166,5,97,0,0,166,167, - 5,103,0,0,167,168,5,109,0,0,168,169,5,97,0,0,169,2,1,0,0,0,170,171,5,59, - 0,0,171,4,1,0,0,0,172,173,5,99,0,0,173,174,5,97,0,0,174,175,5,115,0,0,175, - 176,5,104,0,0,176,177,5,115,0,0,177,178,5,99,0,0,178,179,5,114,0,0,179, - 180,5,105,0,0,180,181,5,112,0,0,181,182,5,116,0,0,182,6,1,0,0,0,183,184, - 5,94,0,0,184,8,1,0,0,0,185,186,5,126,0,0,186,10,1,0,0,0,187,188,5,62,0, - 0,188,189,5,61,0,0,189,12,1,0,0,0,190,191,5,62,0,0,191,14,1,0,0,0,192,193, - 5,60,0,0,193,16,1,0,0,0,194,195,5,60,0,0,195,196,5,61,0,0,196,18,1,0,0, - 0,197,198,5,61,0,0,198,20,1,0,0,0,199,200,5,99,0,0,200,201,5,111,0,0,201, - 202,5,110,0,0,202,203,5,116,0,0,203,204,5,114,0,0,204,205,5,97,0,0,205, - 206,5,99,0,0,206,207,5,116,0,0,207,22,1,0,0,0,208,209,5,123,0,0,209,24, - 1,0,0,0,210,211,5,125,0,0,211,26,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,28,1,0,0,0,221,222,5,40,0,0, - 222,30,1,0,0,0,223,224,5,44,0,0,224,32,1,0,0,0,225,226,5,41,0,0,226,34, - 1,0,0,0,227,228,5,43,0,0,228,229,5,61,0,0,229,36,1,0,0,0,230,231,5,45,0, - 0,231,232,5,61,0,0,232,38,1,0,0,0,233,234,5,43,0,0,234,235,5,43,0,0,235, - 40,1,0,0,0,236,237,5,45,0,0,237,238,5,45,0,0,238,42,1,0,0,0,239,240,5,114, - 0,0,240,241,5,101,0,0,241,242,5,113,0,0,242,243,5,117,0,0,243,244,5,105, - 0,0,244,245,5,114,0,0,245,246,5,101,0,0,246,44,1,0,0,0,247,248,5,99,0,0, - 248,249,5,111,0,0,249,250,5,110,0,0,250,251,5,115,0,0,251,252,5,111,0,0, - 252,253,5,108,0,0,253,254,5,101,0,0,254,255,5,46,0,0,255,256,5,108,0,0, - 256,257,5,111,0,0,257,258,5,103,0,0,258,46,1,0,0,0,259,260,5,105,0,0,260, - 261,5,102,0,0,261,48,1,0,0,0,262,263,5,101,0,0,263,264,5,108,0,0,264,265, - 5,115,0,0,265,266,5,101,0,0,266,50,1,0,0,0,267,268,5,100,0,0,268,269,5, - 111,0,0,269,52,1,0,0,0,270,271,5,119,0,0,271,272,5,104,0,0,272,273,5,105, - 0,0,273,274,5,108,0,0,274,275,5,101,0,0,275,54,1,0,0,0,276,277,5,102,0, - 0,277,278,5,111,0,0,278,279,5,114,0,0,279,56,1,0,0,0,280,281,5,110,0,0, - 281,282,5,101,0,0,282,283,5,119,0,0,283,58,1,0,0,0,284,285,5,91,0,0,285, - 60,1,0,0,0,286,287,5,93,0,0,287,62,1,0,0,0,288,289,5,116,0,0,289,290,5, - 120,0,0,290,291,5,46,0,0,291,292,5,111,0,0,292,293,5,117,0,0,293,294,5, - 116,0,0,294,295,5,112,0,0,295,296,5,117,0,0,296,297,5,116,0,0,297,298,5, - 115,0,0,298,64,1,0,0,0,299,300,5,46,0,0,300,301,5,118,0,0,301,302,5,97, - 0,0,302,303,5,108,0,0,303,304,5,117,0,0,304,305,5,101,0,0,305,66,1,0,0, - 0,306,307,5,46,0,0,307,308,5,108,0,0,308,309,5,111,0,0,309,310,5,99,0,0, - 310,311,5,107,0,0,311,312,5,105,0,0,312,313,5,110,0,0,313,314,5,103,0,0, - 314,315,5,66,0,0,315,316,5,121,0,0,316,317,5,116,0,0,317,318,5,101,0,0, - 318,319,5,99,0,0,319,320,5,111,0,0,320,321,5,100,0,0,321,322,5,101,0,0, - 322,68,1,0,0,0,323,324,5,46,0,0,324,325,5,116,0,0,325,326,5,111,0,0,326, - 327,5,107,0,0,327,328,5,101,0,0,328,329,5,110,0,0,329,330,5,67,0,0,330, - 331,5,97,0,0,331,332,5,116,0,0,332,333,5,101,0,0,333,334,5,103,0,0,334, - 335,5,111,0,0,335,336,5,114,0,0,336,337,5,121,0,0,337,70,1,0,0,0,338,339, - 5,46,0,0,339,340,5,110,0,0,340,341,5,102,0,0,341,342,5,116,0,0,342,343, - 5,67,0,0,343,344,5,111,0,0,344,345,5,109,0,0,345,346,5,109,0,0,346,347, - 5,105,0,0,347,348,5,116,0,0,348,349,5,109,0,0,349,350,5,101,0,0,350,351, - 5,110,0,0,351,352,5,116,0,0,352,72,1,0,0,0,353,354,5,46,0,0,354,355,5,116, - 0,0,355,356,5,111,0,0,356,357,5,107,0,0,357,358,5,101,0,0,358,359,5,110, - 0,0,359,360,5,65,0,0,360,361,5,109,0,0,361,362,5,111,0,0,362,363,5,117, - 0,0,363,364,5,110,0,0,364,365,5,116,0,0,365,74,1,0,0,0,366,367,5,116,0, - 0,367,368,5,120,0,0,368,369,5,46,0,0,369,370,5,105,0,0,370,371,5,110,0, - 0,371,372,5,112,0,0,372,373,5,117,0,0,373,374,5,116,0,0,374,375,5,115,0, - 0,375,76,1,0,0,0,376,377,5,46,0,0,377,378,5,111,0,0,378,379,5,117,0,0,379, - 380,5,116,0,0,380,381,5,112,0,0,381,382,5,111,0,0,382,383,5,105,0,0,383, - 384,5,110,0,0,384,385,5,116,0,0,385,386,5,84,0,0,386,387,5,114,0,0,387, - 388,5,97,0,0,388,389,5,110,0,0,389,390,5,115,0,0,390,391,5,97,0,0,391,392, - 5,99,0,0,392,393,5,116,0,0,393,394,5,105,0,0,394,395,5,111,0,0,395,396, - 5,110,0,0,396,397,5,72,0,0,397,398,5,97,0,0,398,399,5,115,0,0,399,400,5, - 104,0,0,400,78,1,0,0,0,401,402,5,46,0,0,402,403,5,111,0,0,403,404,5,117, - 0,0,404,405,5,116,0,0,405,406,5,112,0,0,406,407,5,111,0,0,407,408,5,105, - 0,0,408,409,5,110,0,0,409,410,5,116,0,0,410,411,5,73,0,0,411,412,5,110, - 0,0,412,413,5,100,0,0,413,414,5,101,0,0,414,415,5,120,0,0,415,80,1,0,0, - 0,416,417,5,46,0,0,417,418,5,117,0,0,418,419,5,110,0,0,419,420,5,108,0, - 0,420,421,5,111,0,0,421,422,5,99,0,0,422,423,5,107,0,0,423,424,5,105,0, - 0,424,425,5,110,0,0,425,426,5,103,0,0,426,427,5,66,0,0,427,428,5,121,0, - 0,428,429,5,116,0,0,429,430,5,101,0,0,430,431,5,99,0,0,431,432,5,111,0, - 0,432,433,5,100,0,0,433,434,5,101,0,0,434,82,1,0,0,0,435,436,5,46,0,0,436, - 437,5,115,0,0,437,438,5,101,0,0,438,439,5,113,0,0,439,440,5,117,0,0,440, - 441,5,101,0,0,441,442,5,110,0,0,442,443,5,99,0,0,443,444,5,101,0,0,444, - 445,5,78,0,0,445,446,5,117,0,0,446,447,5,109,0,0,447,448,5,98,0,0,448,449, - 5,101,0,0,449,450,5,114,0,0,450,84,1,0,0,0,451,452,5,46,0,0,452,453,5,114, - 0,0,453,454,5,101,0,0,454,455,5,118,0,0,455,456,5,101,0,0,456,457,5,114, - 0,0,457,458,5,115,0,0,458,459,5,101,0,0,459,460,5,40,0,0,460,461,5,41,0, - 0,461,86,1,0,0,0,462,463,5,46,0,0,463,464,5,108,0,0,464,465,5,101,0,0,465, - 466,5,110,0,0,466,467,5,103,0,0,467,468,5,116,0,0,468,469,5,104,0,0,469, - 88,1,0,0,0,470,471,5,46,0,0,471,472,5,115,0,0,472,473,5,112,0,0,473,474, - 5,108,0,0,474,475,5,105,0,0,475,476,5,116,0,0,476,90,1,0,0,0,477,478,5, - 46,0,0,478,479,5,115,0,0,479,480,5,108,0,0,480,481,5,105,0,0,481,482,5, - 99,0,0,482,483,5,101,0,0,483,92,1,0,0,0,484,485,5,33,0,0,485,94,1,0,0,0, - 486,487,5,45,0,0,487,96,1,0,0,0,488,489,5,42,0,0,489,98,1,0,0,0,490,491, - 5,47,0,0,491,100,1,0,0,0,492,493,5,37,0,0,493,102,1,0,0,0,494,495,5,43, - 0,0,495,104,1,0,0,0,496,497,5,62,0,0,497,498,5,62,0,0,498,106,1,0,0,0,499, - 500,5,60,0,0,500,501,5,60,0,0,501,108,1,0,0,0,502,503,5,61,0,0,503,504, - 5,61,0,0,504,110,1,0,0,0,505,506,5,33,0,0,506,507,5,61,0,0,507,112,1,0, - 0,0,508,509,5,38,0,0,509,114,1,0,0,0,510,511,5,124,0,0,511,116,1,0,0,0, - 512,513,5,38,0,0,513,514,5,38,0,0,514,118,1,0,0,0,515,516,5,124,0,0,516, - 517,5,124,0,0,517,120,1,0,0,0,518,519,5,99,0,0,519,520,5,111,0,0,520,521, - 5,110,0,0,521,522,5,115,0,0,522,523,5,116,0,0,523,524,5,97,0,0,524,525, - 5,110,0,0,525,526,5,116,0,0,526,122,1,0,0,0,527,529,7,0,0,0,528,527,1,0, - 0,0,529,530,1,0,0,0,530,528,1,0,0,0,530,531,1,0,0,0,531,532,1,0,0,0,532, - 534,5,46,0,0,533,535,7,0,0,0,534,533,1,0,0,0,535,536,1,0,0,0,536,534,1, - 0,0,0,536,537,1,0,0,0,537,538,1,0,0,0,538,540,5,46,0,0,539,541,7,0,0,0, - 540,539,1,0,0,0,541,542,1,0,0,0,542,540,1,0,0,0,542,543,1,0,0,0,543,124, - 1,0,0,0,544,545,5,116,0,0,545,546,5,114,0,0,546,547,5,117,0,0,547,554,5, - 101,0,0,548,549,5,102,0,0,549,550,5,97,0,0,550,551,5,108,0,0,551,552,5, - 115,0,0,552,554,5,101,0,0,553,544,1,0,0,0,553,548,1,0,0,0,554,126,1,0,0, - 0,555,556,5,115,0,0,556,557,5,97,0,0,557,558,5,116,0,0,558,559,5,111,0, - 0,559,560,5,115,0,0,560,561,5,104,0,0,561,562,5,105,0,0,562,613,5,115,0, - 0,563,564,5,115,0,0,564,565,5,97,0,0,565,566,5,116,0,0,566,613,5,115,0, - 0,567,568,5,102,0,0,568,569,5,105,0,0,569,570,5,110,0,0,570,571,5,110,0, - 0,571,572,5,101,0,0,572,613,5,121,0,0,573,574,5,98,0,0,574,575,5,105,0, - 0,575,576,5,116,0,0,576,613,5,115,0,0,577,578,5,98,0,0,578,579,5,105,0, - 0,579,580,5,116,0,0,580,581,5,99,0,0,581,582,5,111,0,0,582,583,5,105,0, - 0,583,613,5,110,0,0,584,585,5,115,0,0,585,586,5,101,0,0,586,587,5,99,0, - 0,587,588,5,111,0,0,588,589,5,110,0,0,589,590,5,100,0,0,590,613,5,115,0, - 0,591,592,5,109,0,0,592,593,5,105,0,0,593,594,5,110,0,0,594,595,5,117,0, - 0,595,596,5,116,0,0,596,597,5,101,0,0,597,613,5,115,0,0,598,599,5,104,0, - 0,599,600,5,111,0,0,600,601,5,117,0,0,601,602,5,114,0,0,602,613,5,115,0, - 0,603,604,5,100,0,0,604,605,5,97,0,0,605,606,5,121,0,0,606,613,5,115,0, - 0,607,608,5,119,0,0,608,609,5,101,0,0,609,610,5,101,0,0,610,611,5,107,0, - 0,611,613,5,115,0,0,612,555,1,0,0,0,612,563,1,0,0,0,612,567,1,0,0,0,612, - 573,1,0,0,0,612,577,1,0,0,0,612,584,1,0,0,0,612,591,1,0,0,0,612,598,1,0, - 0,0,612,603,1,0,0,0,612,607,1,0,0,0,613,128,1,0,0,0,614,616,5,45,0,0,615, - 614,1,0,0,0,615,616,1,0,0,0,616,617,1,0,0,0,617,619,3,131,65,0,618,620, - 3,133,66,0,619,618,1,0,0,0,619,620,1,0,0,0,620,130,1,0,0,0,621,623,7,0, - 0,0,622,621,1,0,0,0,623,624,1,0,0,0,624,622,1,0,0,0,624,625,1,0,0,0,625, - 634,1,0,0,0,626,628,5,95,0,0,627,629,7,0,0,0,628,627,1,0,0,0,629,630,1, - 0,0,0,630,628,1,0,0,0,630,631,1,0,0,0,631,633,1,0,0,0,632,626,1,0,0,0,633, - 636,1,0,0,0,634,632,1,0,0,0,634,635,1,0,0,0,635,132,1,0,0,0,636,634,1,0, - 0,0,637,638,7,1,0,0,638,639,3,131,65,0,639,134,1,0,0,0,640,641,5,105,0, - 0,641,642,5,110,0,0,642,670,5,116,0,0,643,644,5,98,0,0,644,645,5,111,0, - 0,645,646,5,111,0,0,646,670,5,108,0,0,647,648,5,115,0,0,648,649,5,116,0, - 0,649,650,5,114,0,0,650,651,5,105,0,0,651,652,5,110,0,0,652,670,5,103,0, - 0,653,654,5,112,0,0,654,655,5,117,0,0,655,656,5,98,0,0,656,657,5,107,0, - 0,657,658,5,101,0,0,658,670,5,121,0,0,659,660,5,115,0,0,660,661,5,105,0, - 0,661,670,5,103,0,0,662,663,5,100,0,0,663,664,5,97,0,0,664,665,5,116,0, - 0,665,666,5,97,0,0,666,667,5,115,0,0,667,668,5,105,0,0,668,670,5,103,0, - 0,669,640,1,0,0,0,669,643,1,0,0,0,669,647,1,0,0,0,669,653,1,0,0,0,669,659, - 1,0,0,0,669,662,1,0,0,0,670,136,1,0,0,0,671,672,5,98,0,0,672,673,5,121, - 0,0,673,674,5,116,0,0,674,675,5,101,0,0,675,676,5,115,0,0,676,138,1,0,0, - 0,677,678,5,98,0,0,678,679,5,121,0,0,679,680,5,116,0,0,680,681,5,101,0, - 0,681,682,5,115,0,0,682,683,1,0,0,0,683,689,3,141,70,0,684,685,5,98,0,0, - 685,686,5,121,0,0,686,687,5,116,0,0,687,689,5,101,0,0,688,677,1,0,0,0,688, - 684,1,0,0,0,689,140,1,0,0,0,690,694,7,2,0,0,691,693,7,0,0,0,692,691,1,0, - 0,0,693,696,1,0,0,0,694,692,1,0,0,0,694,695,1,0,0,0,695,142,1,0,0,0,696, - 694,1,0,0,0,697,703,5,34,0,0,698,699,5,92,0,0,699,702,5,34,0,0,700,702, - 8,3,0,0,701,698,1,0,0,0,701,700,1,0,0,0,702,705,1,0,0,0,703,704,1,0,0,0, - 703,701,1,0,0,0,704,706,1,0,0,0,705,703,1,0,0,0,706,718,5,34,0,0,707,713, - 5,39,0,0,708,709,5,92,0,0,709,712,5,39,0,0,710,712,8,4,0,0,711,708,1,0, - 0,0,711,710,1,0,0,0,712,715,1,0,0,0,713,714,1,0,0,0,713,711,1,0,0,0,714, - 716,1,0,0,0,715,713,1,0,0,0,716,718,5,39,0,0,717,697,1,0,0,0,717,707,1, - 0,0,0,718,144,1,0,0,0,719,720,5,100,0,0,720,721,5,97,0,0,721,722,5,116, - 0,0,722,723,5,101,0,0,723,724,5,40,0,0,724,725,1,0,0,0,725,726,3,143,71, - 0,726,727,5,41,0,0,727,146,1,0,0,0,728,729,5,48,0,0,729,733,7,5,0,0,730, - 732,7,6,0,0,731,730,1,0,0,0,732,735,1,0,0,0,733,731,1,0,0,0,733,734,1,0, - 0,0,734,148,1,0,0,0,735,733,1,0,0,0,736,737,5,116,0,0,737,738,5,104,0,0, - 738,739,5,105,0,0,739,740,5,115,0,0,740,741,5,46,0,0,741,742,5,97,0,0,742, - 743,5,103,0,0,743,752,5,101,0,0,744,745,5,116,0,0,745,746,5,120,0,0,746, - 747,5,46,0,0,747,748,5,116,0,0,748,749,5,105,0,0,749,750,5,109,0,0,750, - 752,5,101,0,0,751,736,1,0,0,0,751,744,1,0,0,0,752,150,1,0,0,0,753,754,5, - 117,0,0,754,755,5,110,0,0,755,756,5,115,0,0,756,757,5,97,0,0,757,758,5, - 102,0,0,758,759,5,101,0,0,759,760,5,95,0,0,760,761,5,105,0,0,761,762,5, - 110,0,0,762,802,5,116,0,0,763,764,5,117,0,0,764,765,5,110,0,0,765,766,5, - 115,0,0,766,767,5,97,0,0,767,768,5,102,0,0,768,769,5,101,0,0,769,770,5, - 95,0,0,770,771,5,98,0,0,771,772,5,111,0,0,772,773,5,111,0,0,773,802,5,108, - 0,0,774,775,5,117,0,0,775,776,5,110,0,0,776,777,5,115,0,0,777,778,5,97, - 0,0,778,779,5,102,0,0,779,780,5,101,0,0,780,781,5,95,0,0,781,782,5,98,0, - 0,782,783,5,121,0,0,783,784,5,116,0,0,784,785,5,101,0,0,785,786,5,115,0, - 0,786,788,1,0,0,0,787,789,3,141,70,0,788,787,1,0,0,0,788,789,1,0,0,0,789, - 802,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, - 98,0,0,798,799,5,121,0,0,799,800,5,116,0,0,800,802,5,101,0,0,801,753,1, - 0,0,0,801,763,1,0,0,0,801,774,1,0,0,0,801,790,1,0,0,0,802,152,1,0,0,0,803, - 804,5,116,0,0,804,805,5,104,0,0,805,806,5,105,0,0,806,807,5,115,0,0,807, - 808,5,46,0,0,808,809,5,97,0,0,809,810,5,99,0,0,810,811,5,116,0,0,811,812, - 5,105,0,0,812,813,5,118,0,0,813,814,5,101,0,0,814,815,5,73,0,0,815,816, - 5,110,0,0,816,817,5,112,0,0,817,818,5,117,0,0,818,819,5,116,0,0,819,820, - 5,73,0,0,820,821,5,110,0,0,821,822,5,100,0,0,822,823,5,101,0,0,823,898, - 5,120,0,0,824,825,5,116,0,0,825,826,5,104,0,0,826,827,5,105,0,0,827,828, - 5,115,0,0,828,829,5,46,0,0,829,830,5,97,0,0,830,831,5,99,0,0,831,832,5, - 116,0,0,832,833,5,105,0,0,833,834,5,118,0,0,834,835,5,101,0,0,835,836,5, - 66,0,0,836,837,5,121,0,0,837,838,5,116,0,0,838,839,5,101,0,0,839,840,5, - 99,0,0,840,841,5,111,0,0,841,842,5,100,0,0,842,898,5,101,0,0,843,844,5, - 116,0,0,844,845,5,120,0,0,845,846,5,46,0,0,846,847,5,105,0,0,847,848,5, - 110,0,0,848,849,5,112,0,0,849,850,5,117,0,0,850,851,5,116,0,0,851,852,5, - 115,0,0,852,853,5,46,0,0,853,854,5,108,0,0,854,855,5,101,0,0,855,856,5, - 110,0,0,856,857,5,103,0,0,857,858,5,116,0,0,858,898,5,104,0,0,859,860,5, - 116,0,0,860,861,5,120,0,0,861,862,5,46,0,0,862,863,5,111,0,0,863,864,5, - 117,0,0,864,865,5,116,0,0,865,866,5,112,0,0,866,867,5,117,0,0,867,868,5, - 116,0,0,868,869,5,115,0,0,869,870,5,46,0,0,870,871,5,108,0,0,871,872,5, - 101,0,0,872,873,5,110,0,0,873,874,5,103,0,0,874,875,5,116,0,0,875,898,5, - 104,0,0,876,877,5,116,0,0,877,878,5,120,0,0,878,879,5,46,0,0,879,880,5, - 118,0,0,880,881,5,101,0,0,881,882,5,114,0,0,882,883,5,115,0,0,883,884,5, - 105,0,0,884,885,5,111,0,0,885,898,5,110,0,0,886,887,5,116,0,0,887,888,5, - 120,0,0,888,889,5,46,0,0,889,890,5,108,0,0,890,891,5,111,0,0,891,892,5, - 99,0,0,892,893,5,107,0,0,893,894,5,116,0,0,894,895,5,105,0,0,895,896,5, - 109,0,0,896,898,5,101,0,0,897,803,1,0,0,0,897,824,1,0,0,0,897,843,1,0,0, - 0,897,859,1,0,0,0,897,876,1,0,0,0,897,886,1,0,0,0,898,154,1,0,0,0,899,903, - 7,7,0,0,900,902,7,8,0,0,901,900,1,0,0,0,902,905,1,0,0,0,903,901,1,0,0,0, - 903,904,1,0,0,0,904,156,1,0,0,0,905,903,1,0,0,0,906,908,7,9,0,0,907,906, - 1,0,0,0,908,909,1,0,0,0,909,907,1,0,0,0,909,910,1,0,0,0,910,911,1,0,0,0, - 911,912,6,78,0,0,912,158,1,0,0,0,913,914,5,47,0,0,914,915,5,42,0,0,915, - 919,1,0,0,0,916,918,9,0,0,0,917,916,1,0,0,0,918,921,1,0,0,0,919,920,1,0, - 0,0,919,917,1,0,0,0,920,922,1,0,0,0,921,919,1,0,0,0,922,923,5,42,0,0,923, - 924,5,47,0,0,924,925,1,0,0,0,925,926,6,79,1,0,926,160,1,0,0,0,927,928,5, - 47,0,0,928,929,5,47,0,0,929,933,1,0,0,0,930,932,8,10,0,0,931,930,1,0,0, - 0,932,935,1,0,0,0,933,931,1,0,0,0,933,934,1,0,0,0,934,936,1,0,0,0,935,933, - 1,0,0,0,936,937,6,80,1,0,937,162,1,0,0,0,28,0,530,536,542,553,612,615,619, - 624,630,634,669,688,694,701,703,711,713,717,733,751,788,801,897,903,909, - 919,933,2,6,0,0,0,1,0]; + 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]; 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 8d8c718dd..0833d80ea 100644 --- a/packages/cashc/src/grammar/CashScriptParser.ts +++ b/packages/cashc/src/grammar/CashScriptParser.ts @@ -79,26 +79,29 @@ export default class CashScriptParser extends Parser { public static readonly T__58 = 59; public static readonly T__59 = 60; public static readonly T__60 = 61; - public static readonly VersionLiteral = 62; - public static readonly BooleanLiteral = 63; - public static readonly NumberUnit = 64; - public static readonly NumberLiteral = 65; - public static readonly NumberPart = 66; - public static readonly ExponentPart = 67; - public static readonly PrimitiveType = 68; - public static readonly UnboundedBytes = 69; - public static readonly BoundedBytes = 70; - public static readonly Bound = 71; - public static readonly StringLiteral = 72; - public static readonly DateLiteral = 73; - public static readonly HexLiteral = 74; - public static readonly TxVar = 75; - public static readonly UnsafeCast = 76; - public static readonly NullaryOp = 77; - public static readonly Identifier = 78; - public static readonly WHITESPACE = 79; - public static readonly COMMENT = 80; - public static readonly LINE_COMMENT = 81; + 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 RULE_sourceFile = 0; public static readonly RULE_pragmaDirective = 1; @@ -106,50 +109,58 @@ export default class CashScriptParser extends Parser { public static readonly RULE_pragmaValue = 3; public static readonly RULE_versionConstraint = 4; public static readonly RULE_versionOperator = 5; - public static readonly RULE_contractDefinition = 6; - public static readonly RULE_functionDefinition = 7; - public static readonly RULE_functionBody = 8; - public static readonly RULE_parameterList = 9; - public static readonly RULE_parameter = 10; - public static readonly RULE_block = 11; - public static readonly RULE_statement = 12; - public static readonly RULE_nonControlStatement = 13; - public static readonly RULE_controlStatement = 14; - public static readonly RULE_variableDefinition = 15; - public static readonly RULE_tupleAssignment = 16; - public static readonly RULE_assignStatement = 17; - public static readonly RULE_timeOpStatement = 18; - public static readonly RULE_requireStatement = 19; - public static readonly RULE_consoleStatement = 20; - public static readonly RULE_ifStatement = 21; - public static readonly RULE_loopStatement = 22; - public static readonly RULE_doWhileStatement = 23; - public static readonly RULE_whileStatement = 24; - public static readonly RULE_forStatement = 25; - public static readonly RULE_forInit = 26; - public static readonly RULE_requireMessage = 27; - public static readonly RULE_consoleParameter = 28; - public static readonly RULE_consoleParameterList = 29; - public static readonly RULE_functionCall = 30; - public static readonly RULE_expressionList = 31; - public static readonly RULE_expression = 32; - public static readonly RULE_modifier = 33; - public static readonly RULE_literal = 34; - public static readonly RULE_numberLiteral = 35; - public static readonly RULE_typeName = 36; - public static readonly RULE_typeCast = 37; + 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 literalNames: (string | null)[] = [ null, "'pragma'", "';'", "'cashscript'", "'^'", "'~'", "'>='", "'>'", "'<'", "'<='", - "'='", "'contract'", - "'{'", "'}'", + "'='", "'import'", "'function'", - "'('", "','", - "')'", "'+='", - "'-='", "'++'", - "'--'", "'require'", + "'returns'", + "'('", "')'", + "'contract'", + "'{'", "'}'", + "','", "'return'", + "'+='", "'-='", + "'++'", "'--'", + "'require'", "'console.log'", "'if'", "'else'", "'do'", "'while'", @@ -213,7 +224,8 @@ export default class CashScriptParser extends Parser { null, null, null, null, null, null, - "VersionLiteral", + null, null, + null, "VersionLiteral", "BooleanLiteral", "NumberUnit", "NumberLiteral", @@ -234,12 +246,13 @@ export default class CashScriptParser extends Parser { // tslint:disable:no-trailing-whitespace public static readonly ruleNames: string[] = [ "sourceFile", "pragmaDirective", "pragmaName", "pragmaValue", "versionConstraint", - "versionOperator", "contractDefinition", "functionDefinition", "functionBody", - "parameterList", "parameter", "block", "statement", "nonControlStatement", - "controlStatement", "variableDefinition", "tupleAssignment", "assignStatement", - "timeOpStatement", "requireStatement", "consoleStatement", "ifStatement", - "loopStatement", "doWhileStatement", "whileStatement", "forStatement", - "forInit", "requireMessage", "consoleParameter", "consoleParameterList", + "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", ]; @@ -265,23 +278,49 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 79; + this.state = 89; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===1) { { { - this.state = 76; + this.state = 86; this.pragmaDirective(); } } - this.state = 81; + this.state = 91; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 95; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===11) { + { + { + this.state = 92; + this.importDirective(); + } + } + this.state = 97; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 82; - this.contractDefinition(); - this.state = 83; + this.state = 101; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===12 || _la===16) { + { + { + this.state = 98; + this.topLevelDefinition(); + } + } + this.state = 103; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 104; this.match(CashScriptParser.EOF); } } @@ -306,13 +345,13 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 85; + this.state = 106; this.match(CashScriptParser.T__0); - this.state = 86; + this.state = 107; this.pragmaName(); - this.state = 87; + this.state = 108; this.pragmaValue(); - this.state = 88; + this.state = 109; this.match(CashScriptParser.T__1); } } @@ -337,7 +376,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 90; + this.state = 111; this.match(CashScriptParser.T__2); } } @@ -363,14 +402,14 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 92; + this.state = 113; this.versionConstraint(); - this.state = 94; + this.state = 115; this._errHandler.sync(this); _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0) || _la===62) { + if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0) || _la===65) { { - this.state = 93; + this.state = 114; this.versionConstraint(); } } @@ -399,17 +438,17 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 97; + this.state = 118; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0)) { { - this.state = 96; + this.state = 117; this.versionOperator(); } } - this.state = 99; + this.state = 120; this.match(CashScriptParser.VersionLiteral); } } @@ -435,7 +474,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 101; + this.state = 122; _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0))) { this._errHandler.recoverInline(this); @@ -461,37 +500,154 @@ export default class CashScriptParser extends Parser { return localctx; } // @RuleVersion(0) + public importDirective(): ImportDirectiveContext { + let localctx: ImportDirectiveContext = new ImportDirectiveContext(this, this._ctx, this.state); + this.enterRule(localctx, 12, CashScriptParser.RULE_importDirective); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 124; + this.match(CashScriptParser.T__10); + this.state = 125; + this.match(CashScriptParser.StringLiteral); + this.state = 126; + 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 topLevelDefinition(): TopLevelDefinitionContext { + let localctx: TopLevelDefinitionContext = new TopLevelDefinitionContext(this, this._ctx, this.state); + this.enterRule(localctx, 14, CashScriptParser.RULE_topLevelDefinition); + try { + this.state = 130; + this._errHandler.sync(this); + switch (this._input.LA(1)) { + case 12: + this.enterOuterAlt(localctx, 1); + { + this.state = 128; + this.globalFunctionDefinition(); + } + break; + case 16: + this.enterOuterAlt(localctx, 2); + { + this.state = 129; + this.contractDefinition(); + } + 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 globalFunctionDefinition(): GlobalFunctionDefinitionContext { + let localctx: GlobalFunctionDefinitionContext = new GlobalFunctionDefinitionContext(this, this._ctx, this.state); + this.enterRule(localctx, 16, CashScriptParser.RULE_globalFunctionDefinition); + let _la: number; + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 132; + this.match(CashScriptParser.T__11); + this.state = 133; + this.match(CashScriptParser.Identifier); + this.state = 134; + this.parameterList(); + this.state = 140; + this._errHandler.sync(this); + _la = this._input.LA(1); + if (_la===13) { + { + this.state = 135; + this.match(CashScriptParser.T__12); + this.state = 136; + this.match(CashScriptParser.T__13); + this.state = 137; + this.typeName(); + this.state = 138; + this.match(CashScriptParser.T__14); + } + } + + this.state = 142; + this.functionBody(); + } + } + 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 contractDefinition(): ContractDefinitionContext { let localctx: ContractDefinitionContext = new ContractDefinitionContext(this, this._ctx, this.state); - this.enterRule(localctx, 12, CashScriptParser.RULE_contractDefinition); + this.enterRule(localctx, 18, CashScriptParser.RULE_contractDefinition); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 103; - this.match(CashScriptParser.T__10); - this.state = 104; + this.state = 144; + this.match(CashScriptParser.T__15); + this.state = 145; this.match(CashScriptParser.Identifier); - this.state = 105; + this.state = 146; this.parameterList(); - this.state = 106; - this.match(CashScriptParser.T__11); - this.state = 110; + this.state = 147; + this.match(CashScriptParser.T__16); + this.state = 151; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===14) { + while (_la===12) { { { - this.state = 107; - this.functionDefinition(); + this.state = 148; + this.contractFunctionDefinition(); } } - this.state = 112; + this.state = 153; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 113; - this.match(CashScriptParser.T__12); + this.state = 154; + this.match(CashScriptParser.T__17); } } catch (re) { @@ -509,19 +665,19 @@ export default class CashScriptParser extends Parser { return localctx; } // @RuleVersion(0) - public functionDefinition(): FunctionDefinitionContext { - let localctx: FunctionDefinitionContext = new FunctionDefinitionContext(this, this._ctx, this.state); - this.enterRule(localctx, 14, CashScriptParser.RULE_functionDefinition); + public contractFunctionDefinition(): ContractFunctionDefinitionContext { + let localctx: ContractFunctionDefinitionContext = new ContractFunctionDefinitionContext(this, this._ctx, this.state); + this.enterRule(localctx, 20, CashScriptParser.RULE_contractFunctionDefinition); try { this.enterOuterAlt(localctx, 1); { - this.state = 115; - this.match(CashScriptParser.T__13); - this.state = 116; + this.state = 156; + this.match(CashScriptParser.T__11); + this.state = 157; this.match(CashScriptParser.Identifier); - this.state = 117; + this.state = 158; this.parameterList(); - this.state = 118; + this.state = 159; this.functionBody(); } } @@ -542,29 +698,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, 16, CashScriptParser.RULE_functionBody); + this.enterRule(localctx, 22, CashScriptParser.RULE_functionBody); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 120; - this.match(CashScriptParser.T__11); - this.state = 124; + this.state = 161; + this.match(CashScriptParser.T__16); + this.state = 165; this._errHandler.sync(this); _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 499122176) !== 0) || ((((_la - 68)) & ~0x1F) === 0 && ((1 << (_la - 68)) & 1031) !== 0)) { + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 3994025984) !== 0) || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 1031) !== 0)) { { { - this.state = 121; + this.state = 162; this.statement(); } } - this.state = 126; + this.state = 167; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 127; - this.match(CashScriptParser.T__12); + this.state = 168; + this.match(CashScriptParser.T__17); } } catch (re) { @@ -584,54 +740,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, 18, CashScriptParser.RULE_parameterList); + this.enterRule(localctx, 24, CashScriptParser.RULE_parameterList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 129; - this.match(CashScriptParser.T__14); - this.state = 141; + this.state = 170; + this.match(CashScriptParser.T__13); + this.state = 182; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 68)) & ~0x1F) === 0 && ((1 << (_la - 68)) & 7) !== 0)) { + if (((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0)) { { - this.state = 130; + this.state = 171; this.parameter(); - this.state = 135; + this.state = 176; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 5, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 9, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 131; - this.match(CashScriptParser.T__15); - this.state = 132; + this.state = 172; + this.match(CashScriptParser.T__18); + this.state = 173; this.parameter(); } } } - this.state = 137; + this.state = 178; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 5, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 9, this._ctx); } - this.state = 139; + this.state = 180; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===16) { + if (_la===19) { { - this.state = 138; - this.match(CashScriptParser.T__15); + this.state = 179; + this.match(CashScriptParser.T__18); } } } } - this.state = 143; - this.match(CashScriptParser.T__16); + this.state = 184; + this.match(CashScriptParser.T__14); } } catch (re) { @@ -651,13 +807,13 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public parameter(): ParameterContext { let localctx: ParameterContext = new ParameterContext(this, this._ctx, this.state); - this.enterRule(localctx, 20, CashScriptParser.RULE_parameter); + this.enterRule(localctx, 26, CashScriptParser.RULE_parameter); try { this.enterOuterAlt(localctx, 1); { - this.state = 145; + this.state = 186; this.typeName(); - this.state = 146; + this.state = 187; this.match(CashScriptParser.Identifier); } } @@ -678,48 +834,49 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public block(): BlockContext { let localctx: BlockContext = new BlockContext(this, this._ctx, this.state); - this.enterRule(localctx, 22, CashScriptParser.RULE_block); + this.enterRule(localctx, 28, CashScriptParser.RULE_block); let _la: number; try { - this.state = 157; + this.state = 198; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 12: + case 17: this.enterOuterAlt(localctx, 1); { - this.state = 148; - this.match(CashScriptParser.T__11); - this.state = 152; + this.state = 189; + this.match(CashScriptParser.T__16); + this.state = 193; this._errHandler.sync(this); _la = this._input.LA(1); - while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 499122176) !== 0) || ((((_la - 68)) & ~0x1F) === 0 && ((1 << (_la - 68)) & 1031) !== 0)) { + while ((((_la) & ~0x1F) === 0 && ((1 << _la) & 3994025984) !== 0) || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 1031) !== 0)) { { { - this.state = 149; + this.state = 190; this.statement(); } } - this.state = 154; + this.state = 195; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 155; - this.match(CashScriptParser.T__12); + this.state = 196; + this.match(CashScriptParser.T__17); } break; - case 22: - case 23: - case 24: + case 20: + case 25: case 26: case 27: - case 28: - case 68: - case 69: - case 70: - case 78: + case 29: + case 30: + case 31: + case 71: + case 72: + case 73: + case 81: this.enterOuterAlt(localctx, 2); { - this.state = 156; + this.state = 197; this.statement(); } break; @@ -744,32 +901,33 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public statement(): StatementContext { let localctx: StatementContext = new StatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 24, CashScriptParser.RULE_statement); + this.enterRule(localctx, 30, CashScriptParser.RULE_statement); try { - this.state = 163; + this.state = 204; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 24: - case 26: case 27: - case 28: + case 29: + case 30: + case 31: this.enterOuterAlt(localctx, 1); { - this.state = 159; + this.state = 200; this.controlStatement(); } break; - case 22: - case 23: - case 68: - case 69: - case 70: - case 78: + case 20: + case 25: + case 26: + case 71: + case 72: + case 73: + case 81: this.enterOuterAlt(localctx, 2); { - this.state = 160; + this.state = 201; this.nonControlStatement(); - this.state = 161; + this.state = 202; this.match(CashScriptParser.T__1); } break; @@ -794,53 +952,119 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public nonControlStatement(): NonControlStatementContext { let localctx: NonControlStatementContext = new NonControlStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 26, CashScriptParser.RULE_nonControlStatement); + this.enterRule(localctx, 32, CashScriptParser.RULE_nonControlStatement); try { - this.state = 171; + this.state = 214; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 11, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 15, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 165; + this.state = 206; this.variableDefinition(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 166; + this.state = 207; this.tupleAssignment(); } break; case 3: this.enterOuterAlt(localctx, 3); { - this.state = 167; + this.state = 208; this.assignStatement(); } break; case 4: this.enterOuterAlt(localctx, 4); { - this.state = 168; + this.state = 209; this.timeOpStatement(); } break; case 5: this.enterOuterAlt(localctx, 5); { - this.state = 169; + this.state = 210; this.requireStatement(); } break; case 6: this.enterOuterAlt(localctx, 6); { - this.state = 170; + this.state = 211; + this.functionCallStatement(); + } + break; + case 7: + this.enterOuterAlt(localctx, 7); + { + this.state = 212; this.consoleStatement(); } break; + case 8: + this.enterOuterAlt(localctx, 8); + { + this.state = 213; + this.returnStatement(); + } + break; + } + } + 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 functionCallStatement(): FunctionCallStatementContext { + let localctx: FunctionCallStatementContext = new FunctionCallStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 34, CashScriptParser.RULE_functionCallStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 216; + this.functionCall(); + } + } + 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 returnStatement(): ReturnStatementContext { + let localctx: ReturnStatementContext = new ReturnStatementContext(this, this._ctx, this.state); + this.enterRule(localctx, 36, CashScriptParser.RULE_returnStatement); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 218; + this.match(CashScriptParser.T__19); + this.state = 219; + this.expression(0); } } catch (re) { @@ -860,24 +1084,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, 28, CashScriptParser.RULE_controlStatement); + this.enterRule(localctx, 38, CashScriptParser.RULE_controlStatement); try { - this.state = 175; + this.state = 223; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 24: + case 27: this.enterOuterAlt(localctx, 1); { - this.state = 173; + this.state = 221; this.ifStatement(); } break; - case 26: - case 27: - case 28: + case 29: + case 30: + case 31: this.enterOuterAlt(localctx, 2); { - this.state = 174; + this.state = 222; this.loopStatement(); } break; @@ -902,32 +1126,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, 30, CashScriptParser.RULE_variableDefinition); + this.enterRule(localctx, 40, CashScriptParser.RULE_variableDefinition); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 177; + this.state = 225; this.typeName(); - this.state = 181; + this.state = 229; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===61) { + while (_la===64) { { { - this.state = 178; + this.state = 226; this.modifier(); } } - this.state = 183; + this.state = 231; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 184; + this.state = 232; this.match(CashScriptParser.Identifier); - this.state = 185; + this.state = 233; this.match(CashScriptParser.T__9); - this.state = 186; + this.state = 234; this.expression(0); } } @@ -948,23 +1172,23 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public tupleAssignment(): TupleAssignmentContext { let localctx: TupleAssignmentContext = new TupleAssignmentContext(this, this._ctx, this.state); - this.enterRule(localctx, 32, CashScriptParser.RULE_tupleAssignment); + this.enterRule(localctx, 42, CashScriptParser.RULE_tupleAssignment); try { this.enterOuterAlt(localctx, 1); { - this.state = 188; + this.state = 236; this.typeName(); - this.state = 189; + this.state = 237; this.match(CashScriptParser.Identifier); - this.state = 190; - this.match(CashScriptParser.T__15); - this.state = 191; + this.state = 238; + this.match(CashScriptParser.T__18); + this.state = 239; this.typeName(); - this.state = 192; + this.state = 240; this.match(CashScriptParser.Identifier); - this.state = 193; + this.state = 241; this.match(CashScriptParser.T__9); - this.state = 194; + this.state = 242; this.expression(0); } } @@ -985,40 +1209,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, 34, CashScriptParser.RULE_assignStatement); + this.enterRule(localctx, 44, CashScriptParser.RULE_assignStatement); let _la: number; try { - this.state = 201; + this.state = 249; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 14, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 18, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 196; + this.state = 244; this.match(CashScriptParser.Identifier); - this.state = 197; + this.state = 245; localctx._op = this._input.LT(1); _la = this._input.LA(1); - if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 787456) !== 0))) { + if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 6292480) !== 0))) { localctx._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 198; + this.state = 246; this.expression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 199; + this.state = 247; this.match(CashScriptParser.Identifier); - this.state = 200; + this.state = 248; localctx._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===20 || _la===21)) { + if(!(_la===23 || _la===24)) { localctx._op = this._errHandler.recoverInline(this); } else { @@ -1046,35 +1270,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, 36, CashScriptParser.RULE_timeOpStatement); + this.enterRule(localctx, 46, CashScriptParser.RULE_timeOpStatement); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 203; - this.match(CashScriptParser.T__21); - this.state = 204; - this.match(CashScriptParser.T__14); - this.state = 205; + this.state = 251; + this.match(CashScriptParser.T__24); + this.state = 252; + this.match(CashScriptParser.T__13); + this.state = 253; this.match(CashScriptParser.TxVar); - this.state = 206; + this.state = 254; this.match(CashScriptParser.T__5); - this.state = 207; + this.state = 255; this.expression(0); - this.state = 210; + this.state = 258; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===16) { + if (_la===19) { { - this.state = 208; - this.match(CashScriptParser.T__15); - this.state = 209; + this.state = 256; + this.match(CashScriptParser.T__18); + this.state = 257; this.requireMessage(); } } - this.state = 212; - this.match(CashScriptParser.T__16); + this.state = 260; + this.match(CashScriptParser.T__14); } } catch (re) { @@ -1094,31 +1318,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, 38, CashScriptParser.RULE_requireStatement); + this.enterRule(localctx, 48, CashScriptParser.RULE_requireStatement); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 214; - this.match(CashScriptParser.T__21); - this.state = 215; - this.match(CashScriptParser.T__14); - this.state = 216; + this.state = 262; + this.match(CashScriptParser.T__24); + this.state = 263; + this.match(CashScriptParser.T__13); + this.state = 264; this.expression(0); - this.state = 219; + this.state = 267; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===16) { + if (_la===19) { { - this.state = 217; - this.match(CashScriptParser.T__15); - this.state = 218; + this.state = 265; + this.match(CashScriptParser.T__18); + this.state = 266; this.requireMessage(); } } - this.state = 221; - this.match(CashScriptParser.T__16); + this.state = 269; + this.match(CashScriptParser.T__14); } } catch (re) { @@ -1138,13 +1362,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, 40, CashScriptParser.RULE_consoleStatement); + this.enterRule(localctx, 50, CashScriptParser.RULE_consoleStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 223; - this.match(CashScriptParser.T__22); - this.state = 224; + this.state = 271; + this.match(CashScriptParser.T__25); + this.state = 272; this.consoleParameterList(); } } @@ -1165,28 +1389,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, 42, CashScriptParser.RULE_ifStatement); + this.enterRule(localctx, 52, CashScriptParser.RULE_ifStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 226; - this.match(CashScriptParser.T__23); - this.state = 227; - this.match(CashScriptParser.T__14); - this.state = 228; + this.state = 274; + this.match(CashScriptParser.T__26); + this.state = 275; + this.match(CashScriptParser.T__13); + this.state = 276; this.expression(0); - this.state = 229; - this.match(CashScriptParser.T__16); - this.state = 230; + this.state = 277; + this.match(CashScriptParser.T__14); + this.state = 278; localctx._ifBlock = this.block(); - this.state = 233; + this.state = 281; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 17, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 21, this._ctx) ) { case 1: { - this.state = 231; - this.match(CashScriptParser.T__24); - this.state = 232; + this.state = 279; + this.match(CashScriptParser.T__27); + this.state = 280; localctx._elseBlock = this.block(); } break; @@ -1210,29 +1434,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, 44, CashScriptParser.RULE_loopStatement); + this.enterRule(localctx, 54, CashScriptParser.RULE_loopStatement); try { - this.state = 238; + this.state = 286; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 26: + case 29: this.enterOuterAlt(localctx, 1); { - this.state = 235; + this.state = 283; this.doWhileStatement(); } break; - case 27: + case 30: this.enterOuterAlt(localctx, 2); { - this.state = 236; + this.state = 284; this.whileStatement(); } break; - case 28: + case 31: this.enterOuterAlt(localctx, 3); { - this.state = 237; + this.state = 285; this.forStatement(); } break; @@ -1257,23 +1481,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, 46, CashScriptParser.RULE_doWhileStatement); + this.enterRule(localctx, 56, CashScriptParser.RULE_doWhileStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 240; - this.match(CashScriptParser.T__25); - this.state = 241; + this.state = 288; + this.match(CashScriptParser.T__28); + this.state = 289; this.block(); - this.state = 242; - this.match(CashScriptParser.T__26); - this.state = 243; - this.match(CashScriptParser.T__14); - this.state = 244; + this.state = 290; + this.match(CashScriptParser.T__29); + this.state = 291; + this.match(CashScriptParser.T__13); + this.state = 292; this.expression(0); - this.state = 245; - this.match(CashScriptParser.T__16); - this.state = 246; + this.state = 293; + this.match(CashScriptParser.T__14); + this.state = 294; this.match(CashScriptParser.T__1); } } @@ -1294,19 +1518,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, 48, CashScriptParser.RULE_whileStatement); + this.enterRule(localctx, 58, CashScriptParser.RULE_whileStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 248; - this.match(CashScriptParser.T__26); - this.state = 249; - this.match(CashScriptParser.T__14); - this.state = 250; + this.state = 296; + this.match(CashScriptParser.T__29); + this.state = 297; + this.match(CashScriptParser.T__13); + this.state = 298; this.expression(0); - this.state = 251; - this.match(CashScriptParser.T__16); - this.state = 252; + this.state = 299; + this.match(CashScriptParser.T__14); + this.state = 300; this.block(); } } @@ -1327,27 +1551,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, 50, CashScriptParser.RULE_forStatement); + this.enterRule(localctx, 60, CashScriptParser.RULE_forStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 254; - this.match(CashScriptParser.T__27); - this.state = 255; - this.match(CashScriptParser.T__14); - this.state = 256; + this.state = 302; + this.match(CashScriptParser.T__30); + this.state = 303; + this.match(CashScriptParser.T__13); + this.state = 304; this.forInit(); - this.state = 257; + this.state = 305; this.match(CashScriptParser.T__1); - this.state = 258; + this.state = 306; this.expression(0); - this.state = 259; + this.state = 307; this.match(CashScriptParser.T__1); - this.state = 260; + this.state = 308; this.assignStatement(); - this.state = 261; - this.match(CashScriptParser.T__16); - this.state = 262; + this.state = 309; + this.match(CashScriptParser.T__14); + this.state = 310; this.block(); } } @@ -1368,24 +1592,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, 52, CashScriptParser.RULE_forInit); + this.enterRule(localctx, 62, CashScriptParser.RULE_forInit); try { - this.state = 266; + this.state = 314; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 68: - case 69: - case 70: + case 71: + case 72: + case 73: this.enterOuterAlt(localctx, 1); { - this.state = 264; + this.state = 312; this.variableDefinition(); } break; - case 78: + case 81: this.enterOuterAlt(localctx, 2); { - this.state = 265; + this.state = 313; this.assignStatement(); } break; @@ -1410,11 +1634,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, 54, CashScriptParser.RULE_requireMessage); + this.enterRule(localctx, 64, CashScriptParser.RULE_requireMessage); try { this.enterOuterAlt(localctx, 1); { - this.state = 268; + this.state = 316; this.match(CashScriptParser.StringLiteral); } } @@ -1435,26 +1659,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, 56, CashScriptParser.RULE_consoleParameter); + this.enterRule(localctx, 66, CashScriptParser.RULE_consoleParameter); try { - this.state = 272; + this.state = 320; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 78: + case 81: this.enterOuterAlt(localctx, 1); { - this.state = 270; + this.state = 318; this.match(CashScriptParser.Identifier); } break; - case 63: - case 65: - case 72: - case 73: - case 74: + case 66: + case 68: + case 75: + case 76: + case 77: this.enterOuterAlt(localctx, 2); { - this.state = 271; + this.state = 319; this.literal(); } break; @@ -1479,54 +1703,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, 58, CashScriptParser.RULE_consoleParameterList); + this.enterRule(localctx, 68, CashScriptParser.RULE_consoleParameterList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 274; - this.match(CashScriptParser.T__14); - this.state = 286; + this.state = 322; + this.match(CashScriptParser.T__13); + this.state = 334; this._errHandler.sync(this); _la = this._input.LA(1); - if (((((_la - 63)) & ~0x1F) === 0 && ((1 << (_la - 63)) & 36357) !== 0)) { + if (((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 36357) !== 0)) { { - this.state = 275; + this.state = 323; this.consoleParameter(); - this.state = 280; + this.state = 328; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 21, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 276; - this.match(CashScriptParser.T__15); - this.state = 277; + this.state = 324; + this.match(CashScriptParser.T__18); + this.state = 325; this.consoleParameter(); } } } - this.state = 282; + this.state = 330; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 21, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); } - this.state = 284; + this.state = 332; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===16) { + if (_la===19) { { - this.state = 283; - this.match(CashScriptParser.T__15); + this.state = 331; + this.match(CashScriptParser.T__18); } } } } - this.state = 288; - this.match(CashScriptParser.T__16); + this.state = 336; + this.match(CashScriptParser.T__14); } } catch (re) { @@ -1546,13 +1770,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, 60, CashScriptParser.RULE_functionCall); + this.enterRule(localctx, 70, CashScriptParser.RULE_functionCall); try { this.enterOuterAlt(localctx, 1); { - this.state = 290; + this.state = 338; this.match(CashScriptParser.Identifier); - this.state = 291; + this.state = 339; this.expressionList(); } } @@ -1573,54 +1797,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, 62, CashScriptParser.RULE_expressionList); + this.enterRule(localctx, 72, CashScriptParser.RULE_expressionList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 293; - this.match(CashScriptParser.T__14); - this.state = 305; + this.state = 341; + this.match(CashScriptParser.T__13); + this.state = 353; this._errHandler.sync(this); _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 1610645536) !== 0) || ((((_la - 32)) & ~0x1F) === 0 && ((1 << (_la - 32)) & 2147582017) !== 0) || ((((_la - 65)) & ~0x1F) === 0 && ((1 << (_la - 65)) & 15257) !== 0)) { + if (_la===5 || _la===14 || ((((_la - 32)) & ~0x1F) === 0 && ((1 << (_la - 32)) & 786955) !== 0) || ((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 61029) !== 0)) { { - this.state = 294; + this.state = 342; this.expression(0); - this.state = 299; + this.state = 347; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 24, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 295; - this.match(CashScriptParser.T__15); - this.state = 296; + this.state = 343; + this.match(CashScriptParser.T__18); + this.state = 344; this.expression(0); } } } - this.state = 301; + this.state = 349; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 24, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); } - this.state = 303; + this.state = 351; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===16) { + if (_la===19) { { - this.state = 302; - this.match(CashScriptParser.T__15); + this.state = 350; + this.match(CashScriptParser.T__18); } } } } - this.state = 307; - this.match(CashScriptParser.T__16); + this.state = 355; + this.match(CashScriptParser.T__14); } } catch (re) { @@ -1650,28 +1874,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 = 64; - this.enterRecursionRule(localctx, 64, CashScriptParser.RULE_expression, _p); + let _startState: number = 74; + this.enterRecursionRule(localctx, 74, CashScriptParser.RULE_expression, _p); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 358; + this.state = 406; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 31, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 35, this._ctx) ) { case 1: { localctx = new ParenthesisedContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 310; - this.match(CashScriptParser.T__14); - this.state = 311; + this.state = 358; + this.match(CashScriptParser.T__13); + this.state = 359; this.expression(0); - this.state = 312; - this.match(CashScriptParser.T__16); + this.state = 360; + this.match(CashScriptParser.T__14); } break; case 2: @@ -1679,24 +1903,24 @@ export default class CashScriptParser extends Parser { localctx = new CastContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 314; + this.state = 362; this.typeCast(); - this.state = 315; - this.match(CashScriptParser.T__14); - this.state = 316; + this.state = 363; + this.match(CashScriptParser.T__13); + this.state = 364; (localctx as CastContext)._castable = this.expression(0); - this.state = 318; + this.state = 366; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===16) { + if (_la===19) { { - this.state = 317; - this.match(CashScriptParser.T__15); + this.state = 365; + this.match(CashScriptParser.T__18); } } - this.state = 320; - this.match(CashScriptParser.T__16); + this.state = 368; + this.match(CashScriptParser.T__14); } break; case 3: @@ -1704,7 +1928,7 @@ export default class CashScriptParser extends Parser { localctx = new FunctionCallExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 322; + this.state = 370; this.functionCall(); } break; @@ -1713,11 +1937,11 @@ export default class CashScriptParser extends Parser { localctx = new InstantiationContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 323; - this.match(CashScriptParser.T__28); - this.state = 324; + this.state = 371; + this.match(CashScriptParser.T__31); + this.state = 372; this.match(CashScriptParser.Identifier); - this.state = 325; + this.state = 373; this.expressionList(); } break; @@ -1726,18 +1950,18 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 326; - (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__31); - this.state = 327; - this.match(CashScriptParser.T__29); - this.state = 328; + 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 = 329; - this.match(CashScriptParser.T__30); - this.state = 330; + this.state = 377; + this.match(CashScriptParser.T__33); + this.state = 378; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 31) !== 0))) { + if(!(((((_la - 36)) & ~0x1F) === 0 && ((1 << (_la - 36)) & 31) !== 0))) { (localctx as UnaryIntrospectionOpContext)._op = this._errHandler.recoverInline(this); } else { @@ -1751,18 +1975,18 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 332; - (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__37); - this.state = 333; - this.match(CashScriptParser.T__29); - this.state = 334; + 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 = 335; - this.match(CashScriptParser.T__30); - this.state = 336; + this.state = 383; + this.match(CashScriptParser.T__33); + this.state = 384; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 991) !== 0))) { + if(!(((((_la - 36)) & ~0x1F) === 0 && ((1 << (_la - 36)) & 991) !== 0))) { (localctx as UnaryIntrospectionOpContext)._op = this._errHandler.recoverInline(this); } else { @@ -1776,17 +2000,17 @@ export default class CashScriptParser extends Parser { localctx = new UnaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 338; + this.state = 386; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===5 || _la===47 || _la===48)) { + if(!(_la===5 || _la===50 || _la===51)) { (localctx as UnaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 339; + this.state = 387; this.expression(15); } break; @@ -1795,48 +2019,48 @@ export default class CashScriptParser extends Parser { localctx = new ArrayContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 340; - this.match(CashScriptParser.T__29); - this.state = 352; + this.state = 388; + this.match(CashScriptParser.T__32); + this.state = 400; this._errHandler.sync(this); _la = this._input.LA(1); - if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 1610645536) !== 0) || ((((_la - 32)) & ~0x1F) === 0 && ((1 << (_la - 32)) & 2147582017) !== 0) || ((((_la - 65)) & ~0x1F) === 0 && ((1 << (_la - 65)) & 15257) !== 0)) { + if (_la===5 || _la===14 || ((((_la - 32)) & ~0x1F) === 0 && ((1 << (_la - 32)) & 786955) !== 0) || ((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 61029) !== 0)) { { - this.state = 341; + this.state = 389; this.expression(0); - this.state = 346; + this.state = 394; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 342; - this.match(CashScriptParser.T__15); - this.state = 343; + this.state = 390; + this.match(CashScriptParser.T__18); + this.state = 391; this.expression(0); } } } - this.state = 348; + this.state = 396; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); } - this.state = 350; + this.state = 398; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===16) { + if (_la===19) { { - this.state = 349; - this.match(CashScriptParser.T__15); + this.state = 397; + this.match(CashScriptParser.T__18); } } } } - this.state = 354; - this.match(CashScriptParser.T__30); + this.state = 402; + this.match(CashScriptParser.T__33); } break; case 9: @@ -1844,7 +2068,7 @@ export default class CashScriptParser extends Parser { localctx = new NullaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 355; + this.state = 403; this.match(CashScriptParser.NullaryOp); } break; @@ -1853,7 +2077,7 @@ export default class CashScriptParser extends Parser { localctx = new IdentifierContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 356; + this.state = 404; this.match(CashScriptParser.Identifier); } break; @@ -1862,15 +2086,15 @@ export default class CashScriptParser extends Parser { localctx = new LiteralExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 357; + this.state = 405; this.literal(); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 412; + this.state = 460; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 33, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 37, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -1878,29 +2102,29 @@ export default class CashScriptParser extends Parser { } _prevctx = localctx; { - this.state = 410; + this.state = 458; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 32, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 36, 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 = 360; + this.state = 408; if (!(this.precpred(this._ctx, 14))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 14)"); } - this.state = 361; + this.state = 409; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(((((_la - 49)) & ~0x1F) === 0 && ((1 << (_la - 49)) & 7) !== 0))) { + if(!(((((_la - 52)) & ~0x1F) === 0 && ((1 << (_la - 52)) & 7) !== 0))) { (localctx as BinaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 362; + this.state = 410; (localctx as BinaryOpContext)._right = this.expression(15); } break; @@ -1909,21 +2133,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 = 363; + this.state = 411; if (!(this.precpred(this._ctx, 13))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 13)"); } - this.state = 364; + this.state = 412; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===48 || _la===52)) { + if(!(_la===51 || _la===55)) { (localctx as BinaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 365; + this.state = 413; (localctx as BinaryOpContext)._right = this.expression(14); } break; @@ -1932,21 +2156,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 = 366; + this.state = 414; if (!(this.precpred(this._ctx, 12))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 12)"); } - this.state = 367; + this.state = 415; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===53 || _la===54)) { + if(!(_la===56 || _la===57)) { (localctx as BinaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 368; + this.state = 416; (localctx as BinaryOpContext)._right = this.expression(13); } break; @@ -1955,11 +2179,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 = 369; + this.state = 417; if (!(this.precpred(this._ctx, 11))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 11)"); } - this.state = 370; + this.state = 418; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 960) !== 0))) { @@ -1969,7 +2193,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 371; + this.state = 419; (localctx as BinaryOpContext)._right = this.expression(12); } break; @@ -1978,21 +2202,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 = 372; + this.state = 420; if (!(this.precpred(this._ctx, 10))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 10)"); } - this.state = 373; + this.state = 421; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===55 || _la===56)) { + if(!(_la===58 || _la===59)) { (localctx as BinaryOpContext)._op = this._errHandler.recoverInline(this); } else { this._errHandler.reportMatch(this); this.consume(); } - this.state = 374; + this.state = 422; (localctx as BinaryOpContext)._right = this.expression(11); } break; @@ -2001,13 +2225,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 = 375; + this.state = 423; if (!(this.precpred(this._ctx, 9))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 9)"); } - this.state = 376; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__56); - this.state = 377; + this.state = 424; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__59); + this.state = 425; (localctx as BinaryOpContext)._right = this.expression(10); } break; @@ -2016,13 +2240,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 = 378; + this.state = 426; if (!(this.precpred(this._ctx, 8))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 8)"); } - this.state = 379; + this.state = 427; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__3); - this.state = 380; + this.state = 428; (localctx as BinaryOpContext)._right = this.expression(9); } break; @@ -2031,13 +2255,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 = 381; + this.state = 429; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 382; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__57); - this.state = 383; + this.state = 430; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); + this.state = 431; (localctx as BinaryOpContext)._right = this.expression(8); } break; @@ -2046,13 +2270,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 = 384; + this.state = 432; if (!(this.precpred(this._ctx, 6))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 6)"); } - this.state = 385; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__58); - this.state = 386; + this.state = 433; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); + this.state = 434; (localctx as BinaryOpContext)._right = this.expression(7); } break; @@ -2061,13 +2285,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 = 387; + this.state = 435; if (!(this.precpred(this._ctx, 5))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 5)"); } - this.state = 388; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__59); - this.state = 389; + this.state = 436; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); + this.state = 437; (localctx as BinaryOpContext)._right = this.expression(6); } break; @@ -2075,30 +2299,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 = 390; + this.state = 438; if (!(this.precpred(this._ctx, 21))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 21)"); } - this.state = 391; - this.match(CashScriptParser.T__29); - this.state = 392; + this.state = 439; + this.match(CashScriptParser.T__32); + this.state = 440; (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); - this.state = 393; - this.match(CashScriptParser.T__30); + this.state = 441; + this.match(CashScriptParser.T__33); } break; case 12: { localctx = new UnaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 394; + this.state = 442; if (!(this.precpred(this._ctx, 18))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 18)"); } - this.state = 395; + this.state = 443; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); - if(!(_la===43 || _la===44)) { + if(!(_la===46 || _la===47)) { (localctx as UnaryOpContext)._op = this._errHandler.recoverInline(this); } else { @@ -2112,18 +2336,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 = 396; + this.state = 444; if (!(this.precpred(this._ctx, 17))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 17)"); } - this.state = 397; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__44); - this.state = 398; - this.match(CashScriptParser.T__14); - this.state = 399; + 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 = 400; - this.match(CashScriptParser.T__16); + this.state = 448; + this.match(CashScriptParser.T__14); } break; case 14: @@ -2131,30 +2355,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 = 402; + this.state = 450; if (!(this.precpred(this._ctx, 16))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 16)"); } - this.state = 403; - this.match(CashScriptParser.T__45); - this.state = 404; - this.match(CashScriptParser.T__14); - this.state = 405; + this.state = 451; + this.match(CashScriptParser.T__48); + this.state = 452; + this.match(CashScriptParser.T__13); + this.state = 453; (localctx as SliceContext)._start = this.expression(0); - this.state = 406; - this.match(CashScriptParser.T__15); - this.state = 407; + this.state = 454; + this.match(CashScriptParser.T__18); + this.state = 455; (localctx as SliceContext)._end = this.expression(0); - this.state = 408; - this.match(CashScriptParser.T__16); + this.state = 456; + this.match(CashScriptParser.T__14); } break; } } } - this.state = 414; + this.state = 462; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 33, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 37, this._ctx); } } } @@ -2175,12 +2399,12 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public modifier(): ModifierContext { let localctx: ModifierContext = new ModifierContext(this, this._ctx, this.state); - this.enterRule(localctx, 66, CashScriptParser.RULE_modifier); + this.enterRule(localctx, 76, CashScriptParser.RULE_modifier); try { this.enterOuterAlt(localctx, 1); { - this.state = 415; - this.match(CashScriptParser.T__60); + this.state = 463; + this.match(CashScriptParser.T__63); } } catch (re) { @@ -2200,43 +2424,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, 68, CashScriptParser.RULE_literal); + this.enterRule(localctx, 78, CashScriptParser.RULE_literal); try { - this.state = 422; + this.state = 470; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 63: + case 66: this.enterOuterAlt(localctx, 1); { - this.state = 417; + this.state = 465; this.match(CashScriptParser.BooleanLiteral); } break; - case 65: + case 68: this.enterOuterAlt(localctx, 2); { - this.state = 418; + this.state = 466; this.numberLiteral(); } break; - case 72: + case 75: this.enterOuterAlt(localctx, 3); { - this.state = 419; + this.state = 467; this.match(CashScriptParser.StringLiteral); } break; - case 73: + case 76: this.enterOuterAlt(localctx, 4); { - this.state = 420; + this.state = 468; this.match(CashScriptParser.DateLiteral); } break; - case 74: + case 77: this.enterOuterAlt(localctx, 5); { - this.state = 421; + this.state = 469; this.match(CashScriptParser.HexLiteral); } break; @@ -2261,18 +2485,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, 70, CashScriptParser.RULE_numberLiteral); + this.enterRule(localctx, 80, CashScriptParser.RULE_numberLiteral); try { this.enterOuterAlt(localctx, 1); { - this.state = 424; + this.state = 472; this.match(CashScriptParser.NumberLiteral); - this.state = 426; + this.state = 474; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 35, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 39, this._ctx) ) { case 1: { - this.state = 425; + this.state = 473; this.match(CashScriptParser.NumberUnit); } break; @@ -2296,14 +2520,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, 72, CashScriptParser.RULE_typeName); + this.enterRule(localctx, 82, CashScriptParser.RULE_typeName); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 428; + this.state = 476; _la = this._input.LA(1); - if(!(((((_la - 68)) & ~0x1F) === 0 && ((1 << (_la - 68)) & 7) !== 0))) { + if(!(((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0))) { this._errHandler.recoverInline(this); } else { @@ -2329,14 +2553,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, 74, CashScriptParser.RULE_typeCast); + this.enterRule(localctx, 84, CashScriptParser.RULE_typeCast); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 430; + this.state = 478; _la = this._input.LA(1); - if(!(((((_la - 68)) & ~0x1F) === 0 && ((1 << (_la - 68)) & 259) !== 0))) { + if(!(((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 259) !== 0))) { this._errHandler.recoverInline(this); } else { @@ -2362,7 +2586,7 @@ export default class CashScriptParser extends Parser { public sempred(localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 32: + case 37: return this.expression_sempred(localctx as ExpressionContext, predIndex); } return true; @@ -2401,149 +2625,165 @@ export default class CashScriptParser extends Parser { return true; } - public static readonly _serializedATN: number[] = [4,1,81,433,2,0,7,0,2, + public static readonly _serializedATN: number[] = [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,1,0,5,0,78, - 8,0,10,0,12,0,81,9,0,1,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,95,8,3,1,4,3,4,98,8,4,1,4,1,4,1,5,1,5,1,6,1,6,1,6,1,6,1,6,5,6,109,8,6, - 10,6,12,6,112,9,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,8,1,8,5,8,123,8,8,10,8, - 12,8,126,9,8,1,8,1,8,1,9,1,9,1,9,1,9,5,9,134,8,9,10,9,12,9,137,9,9,1,9, - 3,9,140,8,9,3,9,142,8,9,1,9,1,9,1,10,1,10,1,10,1,11,1,11,5,11,151,8,11, - 10,11,12,11,154,9,11,1,11,1,11,3,11,158,8,11,1,12,1,12,1,12,1,12,3,12,164, - 8,12,1,13,1,13,1,13,1,13,1,13,1,13,3,13,172,8,13,1,14,1,14,3,14,176,8,14, - 1,15,1,15,5,15,180,8,15,10,15,12,15,183,9,15,1,15,1,15,1,15,1,15,1,16,1, - 16,1,16,1,16,1,16,1,16,1,16,1,16,1,17,1,17,1,17,1,17,1,17,3,17,202,8,17, - 1,18,1,18,1,18,1,18,1,18,1,18,1,18,3,18,211,8,18,1,18,1,18,1,19,1,19,1, - 19,1,19,1,19,3,19,220,8,19,1,19,1,19,1,20,1,20,1,20,1,21,1,21,1,21,1,21, - 1,21,1,21,1,21,3,21,234,8,21,1,22,1,22,1,22,3,22,239,8,22,1,23,1,23,1,23, - 1,23,1,23,1,23,1,23,1,23,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,26,1,26,3,26,267,8,26,1,27,1,27,1,28, - 1,28,3,28,273,8,28,1,29,1,29,1,29,1,29,5,29,279,8,29,10,29,12,29,282,9, - 29,1,29,3,29,285,8,29,3,29,287,8,29,1,29,1,29,1,30,1,30,1,30,1,31,1,31, - 1,31,1,31,5,31,298,8,31,10,31,12,31,301,9,31,1,31,3,31,304,8,31,3,31,306, - 8,31,1,31,1,31,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,3,32,319,8, - 32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32, - 1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,5,32,345,8,32,10,32,12, - 32,348,9,32,1,32,3,32,351,8,32,3,32,353,8,32,1,32,1,32,1,32,1,32,3,32,359, - 8,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1, - 32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32, - 1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,1, - 32,1,32,1,32,1,32,1,32,1,32,1,32,1,32,5,32,411,8,32,10,32,12,32,414,9,32, - 1,33,1,33,1,34,1,34,1,34,1,34,1,34,3,34,423,8,34,1,35,1,35,3,35,427,8,35, - 1,36,1,36,1,37,1,37,1,37,0,1,64,38,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, - 0,14,1,0,4,10,2,0,10,10,18,19,1,0,20,21,1,0,33,37,2,0,33,37,39,42,2,0,5, - 5,47,48,1,0,49,51,2,0,48,48,52,52,1,0,53,54,1,0,6,9,1,0,55,56,1,0,43,44, - 1,0,68,70,2,0,68,69,76,76,459,0,79,1,0,0,0,2,85,1,0,0,0,4,90,1,0,0,0,6, - 92,1,0,0,0,8,97,1,0,0,0,10,101,1,0,0,0,12,103,1,0,0,0,14,115,1,0,0,0,16, - 120,1,0,0,0,18,129,1,0,0,0,20,145,1,0,0,0,22,157,1,0,0,0,24,163,1,0,0,0, - 26,171,1,0,0,0,28,175,1,0,0,0,30,177,1,0,0,0,32,188,1,0,0,0,34,201,1,0, - 0,0,36,203,1,0,0,0,38,214,1,0,0,0,40,223,1,0,0,0,42,226,1,0,0,0,44,238, - 1,0,0,0,46,240,1,0,0,0,48,248,1,0,0,0,50,254,1,0,0,0,52,266,1,0,0,0,54, - 268,1,0,0,0,56,272,1,0,0,0,58,274,1,0,0,0,60,290,1,0,0,0,62,293,1,0,0,0, - 64,358,1,0,0,0,66,415,1,0,0,0,68,422,1,0,0,0,70,424,1,0,0,0,72,428,1,0, - 0,0,74,430,1,0,0,0,76,78,3,2,1,0,77,76,1,0,0,0,78,81,1,0,0,0,79,77,1,0, - 0,0,79,80,1,0,0,0,80,82,1,0,0,0,81,79,1,0,0,0,82,83,3,12,6,0,83,84,5,0, - 0,1,84,1,1,0,0,0,85,86,5,1,0,0,86,87,3,4,2,0,87,88,3,6,3,0,88,89,5,2,0, - 0,89,3,1,0,0,0,90,91,5,3,0,0,91,5,1,0,0,0,92,94,3,8,4,0,93,95,3,8,4,0,94, - 93,1,0,0,0,94,95,1,0,0,0,95,7,1,0,0,0,96,98,3,10,5,0,97,96,1,0,0,0,97,98, - 1,0,0,0,98,99,1,0,0,0,99,100,5,62,0,0,100,9,1,0,0,0,101,102,7,0,0,0,102, - 11,1,0,0,0,103,104,5,11,0,0,104,105,5,78,0,0,105,106,3,18,9,0,106,110,5, - 12,0,0,107,109,3,14,7,0,108,107,1,0,0,0,109,112,1,0,0,0,110,108,1,0,0,0, - 110,111,1,0,0,0,111,113,1,0,0,0,112,110,1,0,0,0,113,114,5,13,0,0,114,13, - 1,0,0,0,115,116,5,14,0,0,116,117,5,78,0,0,117,118,3,18,9,0,118,119,3,16, - 8,0,119,15,1,0,0,0,120,124,5,12,0,0,121,123,3,24,12,0,122,121,1,0,0,0,123, - 126,1,0,0,0,124,122,1,0,0,0,124,125,1,0,0,0,125,127,1,0,0,0,126,124,1,0, - 0,0,127,128,5,13,0,0,128,17,1,0,0,0,129,141,5,15,0,0,130,135,3,20,10,0, - 131,132,5,16,0,0,132,134,3,20,10,0,133,131,1,0,0,0,134,137,1,0,0,0,135, - 133,1,0,0,0,135,136,1,0,0,0,136,139,1,0,0,0,137,135,1,0,0,0,138,140,5,16, - 0,0,139,138,1,0,0,0,139,140,1,0,0,0,140,142,1,0,0,0,141,130,1,0,0,0,141, - 142,1,0,0,0,142,143,1,0,0,0,143,144,5,17,0,0,144,19,1,0,0,0,145,146,3,72, - 36,0,146,147,5,78,0,0,147,21,1,0,0,0,148,152,5,12,0,0,149,151,3,24,12,0, - 150,149,1,0,0,0,151,154,1,0,0,0,152,150,1,0,0,0,152,153,1,0,0,0,153,155, - 1,0,0,0,154,152,1,0,0,0,155,158,5,13,0,0,156,158,3,24,12,0,157,148,1,0, - 0,0,157,156,1,0,0,0,158,23,1,0,0,0,159,164,3,28,14,0,160,161,3,26,13,0, - 161,162,5,2,0,0,162,164,1,0,0,0,163,159,1,0,0,0,163,160,1,0,0,0,164,25, - 1,0,0,0,165,172,3,30,15,0,166,172,3,32,16,0,167,172,3,34,17,0,168,172,3, - 36,18,0,169,172,3,38,19,0,170,172,3,40,20,0,171,165,1,0,0,0,171,166,1,0, - 0,0,171,167,1,0,0,0,171,168,1,0,0,0,171,169,1,0,0,0,171,170,1,0,0,0,172, - 27,1,0,0,0,173,176,3,42,21,0,174,176,3,44,22,0,175,173,1,0,0,0,175,174, - 1,0,0,0,176,29,1,0,0,0,177,181,3,72,36,0,178,180,3,66,33,0,179,178,1,0, - 0,0,180,183,1,0,0,0,181,179,1,0,0,0,181,182,1,0,0,0,182,184,1,0,0,0,183, - 181,1,0,0,0,184,185,5,78,0,0,185,186,5,10,0,0,186,187,3,64,32,0,187,31, - 1,0,0,0,188,189,3,72,36,0,189,190,5,78,0,0,190,191,5,16,0,0,191,192,3,72, - 36,0,192,193,5,78,0,0,193,194,5,10,0,0,194,195,3,64,32,0,195,33,1,0,0,0, - 196,197,5,78,0,0,197,198,7,1,0,0,198,202,3,64,32,0,199,200,5,78,0,0,200, - 202,7,2,0,0,201,196,1,0,0,0,201,199,1,0,0,0,202,35,1,0,0,0,203,204,5,22, - 0,0,204,205,5,15,0,0,205,206,5,75,0,0,206,207,5,6,0,0,207,210,3,64,32,0, - 208,209,5,16,0,0,209,211,3,54,27,0,210,208,1,0,0,0,210,211,1,0,0,0,211, - 212,1,0,0,0,212,213,5,17,0,0,213,37,1,0,0,0,214,215,5,22,0,0,215,216,5, - 15,0,0,216,219,3,64,32,0,217,218,5,16,0,0,218,220,3,54,27,0,219,217,1,0, - 0,0,219,220,1,0,0,0,220,221,1,0,0,0,221,222,5,17,0,0,222,39,1,0,0,0,223, - 224,5,23,0,0,224,225,3,58,29,0,225,41,1,0,0,0,226,227,5,24,0,0,227,228, - 5,15,0,0,228,229,3,64,32,0,229,230,5,17,0,0,230,233,3,22,11,0,231,232,5, - 25,0,0,232,234,3,22,11,0,233,231,1,0,0,0,233,234,1,0,0,0,234,43,1,0,0,0, - 235,239,3,46,23,0,236,239,3,48,24,0,237,239,3,50,25,0,238,235,1,0,0,0,238, - 236,1,0,0,0,238,237,1,0,0,0,239,45,1,0,0,0,240,241,5,26,0,0,241,242,3,22, - 11,0,242,243,5,27,0,0,243,244,5,15,0,0,244,245,3,64,32,0,245,246,5,17,0, - 0,246,247,5,2,0,0,247,47,1,0,0,0,248,249,5,27,0,0,249,250,5,15,0,0,250, - 251,3,64,32,0,251,252,5,17,0,0,252,253,3,22,11,0,253,49,1,0,0,0,254,255, - 5,28,0,0,255,256,5,15,0,0,256,257,3,52,26,0,257,258,5,2,0,0,258,259,3,64, - 32,0,259,260,5,2,0,0,260,261,3,34,17,0,261,262,5,17,0,0,262,263,3,22,11, - 0,263,51,1,0,0,0,264,267,3,30,15,0,265,267,3,34,17,0,266,264,1,0,0,0,266, - 265,1,0,0,0,267,53,1,0,0,0,268,269,5,72,0,0,269,55,1,0,0,0,270,273,5,78, - 0,0,271,273,3,68,34,0,272,270,1,0,0,0,272,271,1,0,0,0,273,57,1,0,0,0,274, - 286,5,15,0,0,275,280,3,56,28,0,276,277,5,16,0,0,277,279,3,56,28,0,278,276, - 1,0,0,0,279,282,1,0,0,0,280,278,1,0,0,0,280,281,1,0,0,0,281,284,1,0,0,0, - 282,280,1,0,0,0,283,285,5,16,0,0,284,283,1,0,0,0,284,285,1,0,0,0,285,287, - 1,0,0,0,286,275,1,0,0,0,286,287,1,0,0,0,287,288,1,0,0,0,288,289,5,17,0, - 0,289,59,1,0,0,0,290,291,5,78,0,0,291,292,3,62,31,0,292,61,1,0,0,0,293, - 305,5,15,0,0,294,299,3,64,32,0,295,296,5,16,0,0,296,298,3,64,32,0,297,295, - 1,0,0,0,298,301,1,0,0,0,299,297,1,0,0,0,299,300,1,0,0,0,300,303,1,0,0,0, - 301,299,1,0,0,0,302,304,5,16,0,0,303,302,1,0,0,0,303,304,1,0,0,0,304,306, - 1,0,0,0,305,294,1,0,0,0,305,306,1,0,0,0,306,307,1,0,0,0,307,308,5,17,0, - 0,308,63,1,0,0,0,309,310,6,32,-1,0,310,311,5,15,0,0,311,312,3,64,32,0,312, - 313,5,17,0,0,313,359,1,0,0,0,314,315,3,74,37,0,315,316,5,15,0,0,316,318, - 3,64,32,0,317,319,5,16,0,0,318,317,1,0,0,0,318,319,1,0,0,0,319,320,1,0, - 0,0,320,321,5,17,0,0,321,359,1,0,0,0,322,359,3,60,30,0,323,324,5,29,0,0, - 324,325,5,78,0,0,325,359,3,62,31,0,326,327,5,32,0,0,327,328,5,30,0,0,328, - 329,3,64,32,0,329,330,5,31,0,0,330,331,7,3,0,0,331,359,1,0,0,0,332,333, - 5,38,0,0,333,334,5,30,0,0,334,335,3,64,32,0,335,336,5,31,0,0,336,337,7, - 4,0,0,337,359,1,0,0,0,338,339,7,5,0,0,339,359,3,64,32,15,340,352,5,30,0, - 0,341,346,3,64,32,0,342,343,5,16,0,0,343,345,3,64,32,0,344,342,1,0,0,0, - 345,348,1,0,0,0,346,344,1,0,0,0,346,347,1,0,0,0,347,350,1,0,0,0,348,346, - 1,0,0,0,349,351,5,16,0,0,350,349,1,0,0,0,350,351,1,0,0,0,351,353,1,0,0, - 0,352,341,1,0,0,0,352,353,1,0,0,0,353,354,1,0,0,0,354,359,5,31,0,0,355, - 359,5,77,0,0,356,359,5,78,0,0,357,359,3,68,34,0,358,309,1,0,0,0,358,314, - 1,0,0,0,358,322,1,0,0,0,358,323,1,0,0,0,358,326,1,0,0,0,358,332,1,0,0,0, - 358,338,1,0,0,0,358,340,1,0,0,0,358,355,1,0,0,0,358,356,1,0,0,0,358,357, - 1,0,0,0,359,412,1,0,0,0,360,361,10,14,0,0,361,362,7,6,0,0,362,411,3,64, - 32,15,363,364,10,13,0,0,364,365,7,7,0,0,365,411,3,64,32,14,366,367,10,12, - 0,0,367,368,7,8,0,0,368,411,3,64,32,13,369,370,10,11,0,0,370,371,7,9,0, - 0,371,411,3,64,32,12,372,373,10,10,0,0,373,374,7,10,0,0,374,411,3,64,32, - 11,375,376,10,9,0,0,376,377,5,57,0,0,377,411,3,64,32,10,378,379,10,8,0, - 0,379,380,5,4,0,0,380,411,3,64,32,9,381,382,10,7,0,0,382,383,5,58,0,0,383, - 411,3,64,32,8,384,385,10,6,0,0,385,386,5,59,0,0,386,411,3,64,32,7,387,388, - 10,5,0,0,388,389,5,60,0,0,389,411,3,64,32,6,390,391,10,21,0,0,391,392,5, - 30,0,0,392,393,5,65,0,0,393,411,5,31,0,0,394,395,10,18,0,0,395,411,7,11, - 0,0,396,397,10,17,0,0,397,398,5,45,0,0,398,399,5,15,0,0,399,400,3,64,32, - 0,400,401,5,17,0,0,401,411,1,0,0,0,402,403,10,16,0,0,403,404,5,46,0,0,404, - 405,5,15,0,0,405,406,3,64,32,0,406,407,5,16,0,0,407,408,3,64,32,0,408,409, - 5,17,0,0,409,411,1,0,0,0,410,360,1,0,0,0,410,363,1,0,0,0,410,366,1,0,0, - 0,410,369,1,0,0,0,410,372,1,0,0,0,410,375,1,0,0,0,410,378,1,0,0,0,410,381, - 1,0,0,0,410,384,1,0,0,0,410,387,1,0,0,0,410,390,1,0,0,0,410,394,1,0,0,0, - 410,396,1,0,0,0,410,402,1,0,0,0,411,414,1,0,0,0,412,410,1,0,0,0,412,413, - 1,0,0,0,413,65,1,0,0,0,414,412,1,0,0,0,415,416,5,61,0,0,416,67,1,0,0,0, - 417,423,5,63,0,0,418,423,3,70,35,0,419,423,5,72,0,0,420,423,5,73,0,0,421, - 423,5,74,0,0,422,417,1,0,0,0,422,418,1,0,0,0,422,419,1,0,0,0,422,420,1, - 0,0,0,422,421,1,0,0,0,423,69,1,0,0,0,424,426,5,65,0,0,425,427,5,64,0,0, - 426,425,1,0,0,0,426,427,1,0,0,0,427,71,1,0,0,0,428,429,7,12,0,0,429,73, - 1,0,0,0,430,431,7,13,0,0,431,75,1,0,0,0,36,79,94,97,110,124,135,139,141, - 152,157,163,171,175,181,201,210,219,233,238,266,272,280,284,286,299,303, - 305,318,346,350,352,358,410,412,422,426]; + 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]; private static __ATN: ATN; public static get _ATN(): ATN { @@ -2564,9 +2804,6 @@ export class SourceFileContext extends ParserRuleContext { super(parent, invokingState); this.parser = parser; } - public contractDefinition(): ContractDefinitionContext { - return this.getTypedRuleContext(ContractDefinitionContext, 0) as ContractDefinitionContext; - } public EOF(): TerminalNode { return this.getToken(CashScriptParser.EOF, 0); } @@ -2576,6 +2813,18 @@ export class SourceFileContext extends ParserRuleContext { public pragmaDirective(i: number): PragmaDirectiveContext { return this.getTypedRuleContext(PragmaDirectiveContext, i) as PragmaDirectiveContext; } + public importDirective_list(): ImportDirectiveContext[] { + return this.getTypedRuleContexts(ImportDirectiveContext) as ImportDirectiveContext[]; + } + public importDirective(i: number): ImportDirectiveContext { + return this.getTypedRuleContext(ImportDirectiveContext, i) as ImportDirectiveContext; + } + public topLevelDefinition_list(): TopLevelDefinitionContext[] { + return this.getTypedRuleContexts(TopLevelDefinitionContext) as TopLevelDefinitionContext[]; + } + public topLevelDefinition(i: number): TopLevelDefinitionContext { + return this.getTypedRuleContext(TopLevelDefinitionContext, i) as TopLevelDefinitionContext; + } public get ruleIndex(): number { return CashScriptParser.RULE_sourceFile; } @@ -2703,6 +2952,84 @@ export class VersionOperatorContext extends ParserRuleContext { } +export class ImportDirectiveContext extends ParserRuleContext { + constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public StringLiteral(): TerminalNode { + return this.getToken(CashScriptParser.StringLiteral, 0); + } + public get ruleIndex(): number { + return CashScriptParser.RULE_importDirective; + } + // @Override + public accept(visitor: CashScriptVisitor): Result { + if (visitor.visitImportDirective) { + return visitor.visitImportDirective(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class TopLevelDefinitionContext extends ParserRuleContext { + constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public globalFunctionDefinition(): GlobalFunctionDefinitionContext { + return this.getTypedRuleContext(GlobalFunctionDefinitionContext, 0) as GlobalFunctionDefinitionContext; + } + public contractDefinition(): ContractDefinitionContext { + return this.getTypedRuleContext(ContractDefinitionContext, 0) as ContractDefinitionContext; + } + public get ruleIndex(): number { + return CashScriptParser.RULE_topLevelDefinition; + } + // @Override + public accept(visitor: CashScriptVisitor): Result { + if (visitor.visitTopLevelDefinition) { + return visitor.visitTopLevelDefinition(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class GlobalFunctionDefinitionContext extends ParserRuleContext { + constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public Identifier(): TerminalNode { + return this.getToken(CashScriptParser.Identifier, 0); + } + public parameterList(): ParameterListContext { + return this.getTypedRuleContext(ParameterListContext, 0) as ParameterListContext; + } + public functionBody(): FunctionBodyContext { + return this.getTypedRuleContext(FunctionBodyContext, 0) as FunctionBodyContext; + } + public typeName(): TypeNameContext { + return this.getTypedRuleContext(TypeNameContext, 0) as TypeNameContext; + } + public get ruleIndex(): number { + return CashScriptParser.RULE_globalFunctionDefinition; + } + // @Override + public accept(visitor: CashScriptVisitor): Result { + if (visitor.visitGlobalFunctionDefinition) { + return visitor.visitGlobalFunctionDefinition(this); + } else { + return visitor.visitChildren(this); + } + } +} + + export class ContractDefinitionContext extends ParserRuleContext { constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { super(parent, invokingState); @@ -2714,11 +3041,11 @@ export class ContractDefinitionContext extends ParserRuleContext { public parameterList(): ParameterListContext { return this.getTypedRuleContext(ParameterListContext, 0) as ParameterListContext; } - public functionDefinition_list(): FunctionDefinitionContext[] { - return this.getTypedRuleContexts(FunctionDefinitionContext) as FunctionDefinitionContext[]; + public contractFunctionDefinition_list(): ContractFunctionDefinitionContext[] { + return this.getTypedRuleContexts(ContractFunctionDefinitionContext) as ContractFunctionDefinitionContext[]; } - public functionDefinition(i: number): FunctionDefinitionContext { - return this.getTypedRuleContext(FunctionDefinitionContext, i) as FunctionDefinitionContext; + public contractFunctionDefinition(i: number): ContractFunctionDefinitionContext { + return this.getTypedRuleContext(ContractFunctionDefinitionContext, i) as ContractFunctionDefinitionContext; } public get ruleIndex(): number { return CashScriptParser.RULE_contractDefinition; @@ -2734,7 +3061,7 @@ export class ContractDefinitionContext extends ParserRuleContext { } -export class FunctionDefinitionContext extends ParserRuleContext { +export class ContractFunctionDefinitionContext extends ParserRuleContext { constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { super(parent, invokingState); this.parser = parser; @@ -2749,12 +3076,12 @@ export class FunctionDefinitionContext extends ParserRuleContext { return this.getTypedRuleContext(FunctionBodyContext, 0) as FunctionBodyContext; } public get ruleIndex(): number { - return CashScriptParser.RULE_functionDefinition; + return CashScriptParser.RULE_contractFunctionDefinition; } // @Override public accept(visitor: CashScriptVisitor): Result { - if (visitor.visitFunctionDefinition) { - return visitor.visitFunctionDefinition(this); + if (visitor.visitContractFunctionDefinition) { + return visitor.visitContractFunctionDefinition(this); } else { return visitor.visitChildren(this); } @@ -2907,9 +3234,15 @@ export class NonControlStatementContext extends ParserRuleContext { public requireStatement(): RequireStatementContext { return this.getTypedRuleContext(RequireStatementContext, 0) as RequireStatementContext; } + public functionCallStatement(): FunctionCallStatementContext { + return this.getTypedRuleContext(FunctionCallStatementContext, 0) as FunctionCallStatementContext; + } public consoleStatement(): ConsoleStatementContext { return this.getTypedRuleContext(ConsoleStatementContext, 0) as ConsoleStatementContext; } + public returnStatement(): ReturnStatementContext { + return this.getTypedRuleContext(ReturnStatementContext, 0) as ReturnStatementContext; + } public get ruleIndex(): number { return CashScriptParser.RULE_nonControlStatement; } @@ -2924,6 +3257,50 @@ export class NonControlStatementContext extends ParserRuleContext { } +export class FunctionCallStatementContext extends ParserRuleContext { + constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public functionCall(): FunctionCallContext { + return this.getTypedRuleContext(FunctionCallContext, 0) as FunctionCallContext; + } + public get ruleIndex(): number { + return CashScriptParser.RULE_functionCallStatement; + } + // @Override + public accept(visitor: CashScriptVisitor): Result { + if (visitor.visitFunctionCallStatement) { + return visitor.visitFunctionCallStatement(this); + } else { + return visitor.visitChildren(this); + } + } +} + + +export class ReturnStatementContext extends ParserRuleContext { + constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { + super(parent, invokingState); + this.parser = parser; + } + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; + } + public get ruleIndex(): number { + return CashScriptParser.RULE_returnStatement; + } + // @Override + public accept(visitor: CashScriptVisitor): Result { + if (visitor.visitReturnStatement) { + return visitor.visitReturnStatement(this); + } else { + return visitor.visitChildren(this); + } + } +} + + export class ControlStatementContext extends ParserRuleContext { constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { super(parent, invokingState); diff --git a/packages/cashc/src/grammar/CashScriptVisitor.ts b/packages/cashc/src/grammar/CashScriptVisitor.ts index ffb8f081c..6b47aa00a 100644 --- a/packages/cashc/src/grammar/CashScriptVisitor.ts +++ b/packages/cashc/src/grammar/CashScriptVisitor.ts @@ -9,14 +9,19 @@ import { PragmaNameContext } from "./CashScriptParser.js"; import { PragmaValueContext } from "./CashScriptParser.js"; import { VersionConstraintContext } from "./CashScriptParser.js"; import { VersionOperatorContext } from "./CashScriptParser.js"; +import { ImportDirectiveContext } from "./CashScriptParser.js"; +import { TopLevelDefinitionContext } from "./CashScriptParser.js"; +import { GlobalFunctionDefinitionContext } from "./CashScriptParser.js"; import { ContractDefinitionContext } from "./CashScriptParser.js"; -import { FunctionDefinitionContext } from "./CashScriptParser.js"; +import { ContractFunctionDefinitionContext } from "./CashScriptParser.js"; import { FunctionBodyContext } from "./CashScriptParser.js"; import { ParameterListContext } from "./CashScriptParser.js"; import { ParameterContext } from "./CashScriptParser.js"; import { BlockContext } from "./CashScriptParser.js"; import { StatementContext } from "./CashScriptParser.js"; import { NonControlStatementContext } from "./CashScriptParser.js"; +import { FunctionCallStatementContext } from "./CashScriptParser.js"; +import { ReturnStatementContext } from "./CashScriptParser.js"; import { ControlStatementContext } from "./CashScriptParser.js"; import { VariableDefinitionContext } from "./CashScriptParser.js"; import { TupleAssignmentContext } from "./CashScriptParser.js"; @@ -99,6 +104,24 @@ export default class CashScriptVisitor extends ParseTreeVisitor * @return the visitor result */ visitVersionOperator?: (ctx: VersionOperatorContext) => Result; + /** + * Visit a parse tree produced by `CashScriptParser.importDirective`. + * @param ctx the parse tree + * @return the visitor result + */ + visitImportDirective?: (ctx: ImportDirectiveContext) => Result; + /** + * Visit a parse tree produced by `CashScriptParser.topLevelDefinition`. + * @param ctx the parse tree + * @return the visitor result + */ + visitTopLevelDefinition?: (ctx: TopLevelDefinitionContext) => Result; + /** + * Visit a parse tree produced by `CashScriptParser.globalFunctionDefinition`. + * @param ctx the parse tree + * @return the visitor result + */ + visitGlobalFunctionDefinition?: (ctx: GlobalFunctionDefinitionContext) => Result; /** * Visit a parse tree produced by `CashScriptParser.contractDefinition`. * @param ctx the parse tree @@ -106,11 +129,11 @@ export default class CashScriptVisitor extends ParseTreeVisitor */ visitContractDefinition?: (ctx: ContractDefinitionContext) => Result; /** - * Visit a parse tree produced by `CashScriptParser.functionDefinition`. + * Visit a parse tree produced by `CashScriptParser.contractFunctionDefinition`. * @param ctx the parse tree * @return the visitor result */ - visitFunctionDefinition?: (ctx: FunctionDefinitionContext) => Result; + visitContractFunctionDefinition?: (ctx: ContractFunctionDefinitionContext) => Result; /** * Visit a parse tree produced by `CashScriptParser.functionBody`. * @param ctx the parse tree @@ -147,6 +170,18 @@ export default class CashScriptVisitor extends ParseTreeVisitor * @return the visitor result */ visitNonControlStatement?: (ctx: NonControlStatementContext) => Result; + /** + * Visit a parse tree produced by `CashScriptParser.functionCallStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitFunctionCallStatement?: (ctx: FunctionCallStatementContext) => Result; + /** + * Visit a parse tree produced by `CashScriptParser.returnStatement`. + * @param ctx the parse tree + * @return the visitor result + */ + visitReturnStatement?: (ctx: ReturnStatementContext) => Result; /** * Visit a parse tree produced by `CashScriptParser.controlStatement`. * @param ctx the parse tree diff --git a/packages/cashc/src/parser.ts b/packages/cashc/src/parser.ts new file mode 100644 index 000000000..e7e0e799d --- /dev/null +++ b/packages/cashc/src/parser.ts @@ -0,0 +1,30 @@ +import { CharStream, CommonTokenStream } from 'antlr4'; +import { Ast } from './ast/AST.js'; +import AstBuilder from './ast/AstBuilder.js'; +import { ThrowingErrorListener, CashScriptErrorListener, ForwardingErrorListener } from './ast/error-listeners.js'; +import CashScriptLexer from './grammar/CashScriptLexer.js'; +import CashScriptParser from './grammar/CashScriptParser.js'; + +export function parseCode( + code: string, + errorListener: CashScriptErrorListener = ThrowingErrorListener.INSTANCE, +): Ast { + const syntaxErrorListener = new ForwardingErrorListener(errorListener); + + // Lexing (throwing on errors) + const inputStream = new CharStream(code); + const lexer = new CashScriptLexer(inputStream); + lexer.removeErrorListeners(); + lexer.addErrorListener(syntaxErrorListener); + const tokenStream = new CommonTokenStream(lexer); + + // Parsing (throwing on errors) + const parser = new CashScriptParser(tokenStream); + parser.removeErrorListeners(); + parser.addErrorListener(syntaxErrorListener); + const parseTree = parser.sourceFile(); + syntaxErrorListener.throwFirstError(); + + // AST building + return new AstBuilder(parseTree).build() as Ast; +} diff --git a/packages/cashc/src/print/OutputSourceCodeTraversal.ts b/packages/cashc/src/print/OutputSourceCodeTraversal.ts index 70f62db2c..7f703f8a9 100644 --- a/packages/cashc/src/print/OutputSourceCodeTraversal.ts +++ b/packages/cashc/src/print/OutputSourceCodeTraversal.ts @@ -2,6 +2,8 @@ import { binToHex } from '@bitauth/libauth'; import { SymbolTable } from '../ast/SymbolTable.js'; import { Node, + SourceFileNode, + ImportNode, ContractNode, ParameterNode, VariableDefinitionNode, @@ -22,11 +24,13 @@ import { ArrayNode, TupleIndexOpNode, RequireNode, + ReturnNode, InstantiationNode, TupleAssignmentNode, NullaryOpNode, ConsoleStatementNode, ConsoleParameterNode, + FunctionCallStatementNode, SliceNode, DoWhileNode, WhileNode, @@ -61,6 +65,18 @@ export default class OutputSourceCodeTraversal extends AstTraversal { this.addOutput(` --> ST: ${symbolTable}`); } + visitSourceFile(node: SourceFileNode): Node { + node.imports = this.visitList(node.imports) as ImportNode[]; + node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; + if (node.contract) node.contract = this.visit(node.contract) as ContractNode; + return node; + } + + visitImport(node: ImportNode): Node { + this.addOutput(`import "${node.path}";\n`, true); + return node; + } + visitContract(node: ContractNode): Node { this.addOutput(`contract ${node.name}(`, true); node.parameters = this.visitCommaList(node.parameters) as ParameterNode[]; @@ -80,6 +96,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})`); this.outputSymbolTable(node.symbolTable); this.addOutput(' '); @@ -147,6 +164,18 @@ export default class OutputSourceCodeTraversal extends AstTraversal { return node; } + visitReturn(node: ReturnNode): Node { + this.addOutput('return ', true); + node.expression = this.visit(node.expression); + return node; + } + + visitFunctionCallStatement(node: FunctionCallStatementNode): Node { + this.addOutput('', true); + node.functionCall = this.visit(node.functionCall) as FunctionCallNode; + return node; + } + visitConsoleStatement(node: ConsoleStatementNode): Node { this.addOutput('console.log(', true); node.parameters = this.visitCommaList(node.parameters) as ConsoleParameterNode[]; diff --git a/packages/cashc/src/semantic/DeadCodeEliminationTraversal.ts b/packages/cashc/src/semantic/DeadCodeEliminationTraversal.ts new file mode 100644 index 000000000..657414902 --- /dev/null +++ b/packages/cashc/src/semantic/DeadCodeEliminationTraversal.ts @@ -0,0 +1,40 @@ +import { + FunctionCallNode, + FunctionDefinitionNode, + Node, + SourceFileNode, +} from '../ast/AST.js'; +import AstTraversal from '../ast/AstTraversal.js'; + +export default class DeadCodeEliminationTraversal extends AstTraversal { + private reachableFunctions = new Set(); + + visitSourceFile(node: SourceFileNode): Node { + super.visitOptional(node.contract); + + // Set the node.functions to the reachable functions and re-index functionIds, the order is based on insertion + // into the set, which is most stable for the functionId as it is based on contract structure rather than + // name or order of declaration. + node.functions = [...this.reachableFunctions]; + node.functions.forEach((func, index) => { + node.symbolTable!.getFromThis(func.name)!.setFunctionId(index); + }); + + return node; + } + + visitFunctionCall(node: FunctionCallNode): Node { + node = super.visitFunctionCall(node) as FunctionCallNode; + + const functionDefinition = node.identifier.symbol?.definition; + if (!functionDefinition || !(functionDefinition instanceof FunctionDefinitionNode)) return node; + + // Only descend into a function the first time it is reached to prevent infinite recursion. + if (!this.reachableFunctions.has(functionDefinition)) { + this.reachableFunctions.add(functionDefinition); + this.visit(functionDefinition.body); + } + + return node; + } +} diff --git a/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts b/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts index 2974f16cb..e5d9115f8 100644 --- a/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts +++ b/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts @@ -2,7 +2,9 @@ import { ContractNode, ParameterNode, FunctionDefinitionNode, + FunctionKind, RequireNode, + ReturnNode, TimeOpNode, BranchNode, ConsoleStatementNode, @@ -10,9 +12,17 @@ import { WhileNode, ForNode, BlockNode, + StatementNode, + Node, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; -import { EmptyContractError, EmptyFunctionError, FinalRequireStatementError } from '../Errors.js'; +import { + EmptyContractError, + EmptyFunctionError, + FinalRequireStatementError, + MissingReturnError, + MisplacedReturnError, +} from '../Errors.js'; export default class EnsureFinalRequireTraversal extends AstTraversal { visitContract(node: ContractNode): ContractNode { @@ -34,12 +44,57 @@ export default class EnsureFinalRequireTraversal extends AstTraversal { throw new EmptyFunctionError(node); } - ensureFinalStatementIsRequire(node.body); + if (node.kind === FunctionKind.CONTRACT) { + ensureFinalStatementIsRequire(node.body); + } else if (node.returnType !== undefined) { + ensureSingleTailReturn(node.body); + } return node; } } +// TODO: This code is a bit convoluted, but we're likely to make changes to allow early returns before a mainline release, +// so we're leaving this code as-is for now. + +function ensureSingleTailReturn(body: BlockNode): void { + const statements = body.statements ?? []; + const finalStatement = statements[statements.length - 1]; + if (!(finalStatement instanceof ReturnNode)) { + throw new MissingReturnError(finalStatement ?? body); + } + + const stray = findReturn(statements.slice(0, -1)); + if (stray) throw new MisplacedReturnError(stray); +} + +function findReturn(statements: StatementNode[]): ReturnNode | undefined { + for (const statement of statements) { + if (statement instanceof ReturnNode) return statement; + for (const list of nestedStatementLists(statement)) { + const found = findReturn(list); + if (found) return found; + } + } + return undefined; +} + +function nestedStatementLists(statement: StatementNode): StatementNode[][] { + const asStatements = (block?: Node): StatementNode[] => { + if (!block) return []; + if (block instanceof BlockNode) return block.statements ?? []; + return [block as StatementNode]; + }; + + if (statement instanceof BranchNode) { + return [asStatements(statement.ifBlock), asStatements(statement.elseBlock)]; + } + if (statement instanceof DoWhileNode || statement instanceof WhileNode || statement instanceof ForNode) { + return [asStatements(statement.block)]; + } + return []; +} + function ensureFinalStatementIsRequire(block: BlockNode): void { const statementsWithoutLogs = (block.statements ?? []).filter((statement) => !(statement instanceof ConsoleStatementNode)); const finalStatement = statementsWithoutLogs[statementsWithoutLogs.length - 1]; diff --git a/packages/cashc/src/semantic/EnsureFunctionsSafeTraversal.ts b/packages/cashc/src/semantic/EnsureFunctionsSafeTraversal.ts new file mode 100644 index 000000000..dabd9ab4e --- /dev/null +++ b/packages/cashc/src/semantic/EnsureFunctionsSafeTraversal.ts @@ -0,0 +1,46 @@ +import { + FunctionCallNode, + FunctionDefinitionNode, + FunctionKind, + Node, + NullaryOpNode, +} from '../ast/AST.js'; +import AstTraversal from '../ast/AstTraversal.js'; +import { GlobalFunction } from '../ast/Globals.js'; +import { NullaryOperator } from '../ast/Operator.js'; +import { UnsafeFunctionOperationError } from '../Errors.js'; + +// checkSig and checkMultisig, as well as this.activeBytecode use the function's bytecode instead of the contract's. +// This is almost never what a developer would expect, so we reject using these inside global functions altogether. +export default class EnsureFunctionsSafeTraversal extends AstTraversal { + private insideGlobalFunction = false; + + visitFunctionDefinition(node: FunctionDefinitionNode): Node { + const enclosingInsideGlobalFunction = this.insideGlobalFunction; + this.insideGlobalFunction = node.kind === FunctionKind.GLOBAL; + + node = super.visitFunctionDefinition(node) as FunctionDefinitionNode; + + this.insideGlobalFunction = enclosingInsideGlobalFunction; + return node; + } + + visitNullaryOp(node: NullaryOpNode): Node { + if (this.insideGlobalFunction && node.operator === NullaryOperator.BYTECODE) { + throw new UnsafeFunctionOperationError(node, node.operator); + } + + return node; + } + + visitFunctionCall(node: FunctionCallNode): Node { + node = super.visitFunctionCall(node) as FunctionCallNode; + + const UNSAFE_FUNCTIONS: string[] = [GlobalFunction.CHECKSIG, GlobalFunction.CHECKMULTISIG]; + if (this.insideGlobalFunction && UNSAFE_FUNCTIONS.includes(node.identifier.name)) { + throw new UnsafeFunctionOperationError(node, node.identifier.name); + } + + return node; + } +} diff --git a/packages/cashc/src/semantic/InjectLocktimeGuardTraversal.ts b/packages/cashc/src/semantic/InjectLocktimeGuardTraversal.ts index 1aa0983f4..6137d6e3c 100644 --- a/packages/cashc/src/semantic/InjectLocktimeGuardTraversal.ts +++ b/packages/cashc/src/semantic/InjectLocktimeGuardTraversal.ts @@ -1,10 +1,13 @@ import { PrimitiveType } from '@cashscript/utils'; import { BlockNode, + ContractNode, + FunctionCallNode, FunctionDefinitionNode, IntLiteralNode, Node, NullaryOpNode, + SourceFileNode, TimeOpNode, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; @@ -12,45 +15,90 @@ import { TimeOp } from '../ast/Globals.js'; import { Location } from '../ast/Location.js'; import { NullaryOperator } from '../ast/Operator.js'; -// Per BCH consensus, `tx.locktime` is only protocol-enforced if at least one input has a non-final sequence number -// If a require(tx.time >= ...) check or a require(this.age >= ...) with a compile-time int literal below 2^31 is -// present, then `tx.locktime` is protocol-enforced. If no such check is present, then we add a -// synthetic require(tx.time >= tx.locktime) check. +// Per BCH consensus, `tx.locktime` is only protocol-enforced if at least one input has a non-final +// sequence number. A require(tx.time >= ...) check — or a require(this.age >= ...) with a compile-time +// int literal below 2^31 — forces that non-finality. When a spending path uses `tx.locktime` without +// such a check, we inject a synthetic require(tx.time >= tx.locktime) guard at the start of the function. export default class InjectLocktimeGuardTraversal extends AstTraversal { - private hasTimeCheckOnPath = false; - private functionNeedsGuard = false; + // Keep track of which global functions require a locktime guard when called. + private globalFunctionRequiresLocktimeGuard = new Map(); - visitFunctionDefinition(node: FunctionDefinitionNode): Node { - this.hasTimeCheckOnPath = false; - this.functionNeedsGuard = false; - - super.visitFunctionDefinition(node); + visitSourceFile(node: SourceFileNode): Node { + // Only contract spending functions are traversed (and guarded); globals are analysed on demand. + node.contract = this.visitOptional(node.contract) as ContractNode | undefined; + return node; + } - if (this.functionNeedsGuard) { + visitFunctionDefinition(node: FunctionDefinitionNode): Node { + if (this.requiresLocktimeGuard(node.body)) { node.body.statements = [createLocktimeGuard(node), ...(node.body.statements ?? [])]; } return node; } + private requiresLocktimeGuard(body: BlockNode): boolean { + const analyser = new LocktimeGuardRequirementAnalyser((func) => this.checkGlobalFunctionRequiresLocktimeGuard(func)); + analyser.visit(body); + return analyser.requiresLocktimeGuard; + } + + // Memoised, cycle-safe analysis of a single global function. + private checkGlobalFunctionRequiresLocktimeGuard(func: FunctionDefinitionNode): boolean { + const memoised = this.globalFunctionRequiresLocktimeGuard.get(func); + if (memoised !== undefined) return memoised; + + this.globalFunctionRequiresLocktimeGuard.set(func, false); // seed: a re-entrant (cyclic) call contributes nothing + const requiresLocktimeGuard = this.requiresLocktimeGuard(func.body); + this.globalFunctionRequiresLocktimeGuard.set(func, requiresLocktimeGuard); + return requiresLocktimeGuard; + } +} + +class LocktimeGuardRequirementAnalyser extends AstTraversal { + requiresLocktimeGuard = false; + private isAlreadyCovered = false; + + constructor( + private checkGlobalFunctionRequiresLocktimeGuard: (func: FunctionDefinitionNode) => boolean, + ) { + super(); + } + visitBlock(node: BlockNode): Node { - const previous = this.hasTimeCheckOnPath; + const enclosingIsAlreadyCovered = this.isAlreadyCovered; - // Check whether there are any locktime checks on the same execution path, BEFORE entering the block body. - // So even if there are locktime checks after the `tx.locktime` access, it counts as a locktime check + // A time check anywhere in this block covers the whole block (order within the block is irrelevant); + // a sibling branch's check does not, since each branch body is its own block. if (node.statements?.some(isLocktimeCheck)) { - this.hasTimeCheckOnPath = true; + this.isAlreadyCovered = true; } + super.visitBlock(node); - this.hasTimeCheckOnPath = previous; + + this.isAlreadyCovered = enclosingIsAlreadyCovered; return node; } visitNullaryOp(node: NullaryOpNode): Node { - if (node.operator === NullaryOperator.LOCKTIME && !this.hasTimeCheckOnPath) { - this.functionNeedsGuard = true; + if (node.operator === NullaryOperator.LOCKTIME && !this.isAlreadyCovered) { + this.requiresLocktimeGuard = true; } return node; } + + visitFunctionCall(node: FunctionCallNode): Node { + node = super.visitFunctionCall(node) as FunctionCallNode; + if (this.isAlreadyCovered) return node; + + const functionDefinition = node.identifier.symbol?.definition; + if (!functionDefinition || !(functionDefinition instanceof FunctionDefinitionNode)) return node; + + if (this.checkGlobalFunctionRequiresLocktimeGuard(functionDefinition)) { + this.requiresLocktimeGuard = true; + } + + return node; + } } // Note that `require(tx.time >= ...)` checks are always sufficient to enforce the non-finality of the spending input, diff --git a/packages/cashc/src/semantic/SymbolTableTraversal.ts b/packages/cashc/src/semantic/SymbolTableTraversal.ts index 8b980b497..41b49cd45 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -1,9 +1,11 @@ import { GLOBAL_SYMBOL_TABLE, Modifier } from '../ast/Globals.js'; import { + SourceFileNode, ContractNode, ParameterNode, VariableDefinitionNode, FunctionDefinitionNode, + FunctionKind, IdentifierNode, StatementNode, BlockNode, @@ -29,11 +31,32 @@ import { export default class SymbolTableTraversal extends AstTraversal { private symbolTables: SymbolTable[] = [GLOBAL_SYMBOL_TABLE]; - private functionNames: Map = new Map(); + private contractFunctionNames: Map = new Map(); private currentFunction: FunctionDefinitionNode; private expectedSymbolType: SymbolType = SymbolType.VARIABLE; private insideConsoleStatement: boolean = false; + visitSourceFile(node: SourceFileNode): Node { + const globalFunctionTable = new SymbolTable(this.symbolTables[0]); + + node.functions.forEach((functionNode, functionId) => { + if (globalFunctionTable.get(functionNode.name)) { + throw new FunctionRedefinitionError(functionNode); + } + const symbol = Symbol.userFunction(functionNode, functionId); + globalFunctionTable.set(symbol); + }); + + node.symbolTable = globalFunctionTable; + this.symbolTables.unshift(globalFunctionTable); + + node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; + node.contract = this.visitOptional(node.contract) as ContractNode | undefined; + + this.symbolTables.shift(); + return node; + } + visitContract(node: ContractNode): Node { node.symbolTable = new SymbolTable(this.symbolTables[0]); this.symbolTables.unshift(node.symbolTable); @@ -62,12 +85,12 @@ export default class SymbolTableTraversal extends AstTraversal { visitFunctionDefinition(node: FunctionDefinitionNode): Node { this.currentFunction = node; - // Checked for function redefinition, but they are not included in the - // symbol table, as internal function calls are not supported. - if (this.functionNames.get(node.name)) { - throw new FunctionRedefinitionError(node); + if (node.kind === FunctionKind.CONTRACT) { + if (this.contractFunctionNames.get(node.name)) { + throw new FunctionRedefinitionError(node); + } + this.contractFunctionNames.set(node.name, true); } - this.functionNames.set(node.name, true); node.symbolTable = new SymbolTable(this.symbolTables[0]); this.symbolTables.unshift(node.symbolTable); @@ -185,17 +208,17 @@ export default class SymbolTableTraversal extends AstTraversal { } visitIdentifier(node: IdentifierNode): Node { - const definition = this.symbolTables[0].get(node.name); - if (!definition) { + const symbol = this.symbolTables[0].get(node.name); + if (!symbol) { throw new UndefinedReferenceError(node); } - if (definition.symbolType !== this.expectedSymbolType) { + if (symbol.symbolType !== this.expectedSymbolType) { throw new InvalidSymbolTypeError(node, this.expectedSymbolType); } - node.definition = definition; - node.definition.references.push(node); + node.symbol = symbol; + node.symbol.references.push(node); // Keep track of final use of variables for code generation (excluding console statements) if (!this.insideConsoleStatement) { diff --git a/packages/cashc/src/semantic/TypeCheckTraversal.ts b/packages/cashc/src/semantic/TypeCheckTraversal.ts index 5e6742c97..4c5d120c1 100644 --- a/packages/cashc/src/semantic/TypeCheckTraversal.ts +++ b/packages/cashc/src/semantic/TypeCheckTraversal.ts @@ -14,6 +14,9 @@ import { BranchNode, CastNode, FunctionCallNode, + FunctionCallStatementNode, + FunctionDefinitionNode, + ParameterNode, UnaryOpNode, BinaryOpNode, IdentifierNode, @@ -22,6 +25,7 @@ import { ArrayNode, TupleIndexOpNode, RequireNode, + ReturnNode, Node, InstantiationNode, TupleAssignmentNode, @@ -47,6 +51,8 @@ import { IndexOutOfBoundsError, TupleAssignmentError, BitshiftBitcountNegativeError, + UnusedFunctionReturnError, + ReturnTypeError, } from '../Errors.js'; import { BinaryOperator, NullaryOperator, UnaryOperator } from '../ast/Operator.js'; import { GlobalFunction } from '../ast/Globals.js'; @@ -54,6 +60,8 @@ import { Symbol } from '../ast/SymbolTable.js'; import { resultingTypeForBinaryOp } from '../utils.js'; export default class TypeCheckTraversal extends AstTraversal { + private currentFunctionReturnType: Type = PrimitiveType.VOID; + visitVariableDefinition(node: VariableDefinitionNode): Node { node.expression = this.visit(node.expression); expectAssignable(node, node.expression.type, node.type); @@ -178,15 +186,38 @@ export default class TypeCheckTraversal extends AstTraversal { return node; } + visitFunctionCallStatement(node: FunctionCallStatementNode): Node { + node.functionCall = this.visit(node.functionCall) as FunctionCallNode; + if (node.functionCall.type !== PrimitiveType.VOID) { + throw new UnusedFunctionReturnError(node.functionCall); + } + return node; + } + + visitFunctionDefinition(node: FunctionDefinitionNode): Node { + this.currentFunctionReturnType = node.returnType ?? PrimitiveType.VOID; + 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); + } + return node; + } + visitFunctionCall(node: FunctionCallNode): Node { node.identifier = this.visit(node.identifier) as IdentifierNode; node.parameters = this.visitList(node.parameters); - const { definition, type } = node.identifier; - if (!definition || !definition.parameters) return node; // already checked in symbol table + const { symbol, type } = node.identifier; + if (!symbol || !symbol.parameters) return node; // already checked in symbol table const parameterTypes = node.parameters.map((p) => p.type!); - expectParameters(node, parameterTypes, definition.parameters); + expectParameters(node, parameterTypes, symbol.parameters); // Additional array length check for checkMultiSig if (node.identifier.name === GlobalFunction.CHECKMULTISIG) { @@ -211,11 +242,11 @@ export default class TypeCheckTraversal extends AstTraversal { node.identifier = this.visit(node.identifier) as IdentifierNode; node.parameters = this.visitList(node.parameters); - const { definition, type } = node.identifier; - if (!definition || !definition.parameters) return node; // already checked in symbol table + const { symbol, type } = node.identifier; + if (!symbol || !symbol.parameters) return node; // already checked in symbol table const parameterTypes = node.parameters.map((p) => p.type!); - expectParameters(node, parameterTypes, definition.parameters); + expectParameters(node, parameterTypes, symbol.parameters); node.type = type; return node; @@ -405,8 +436,8 @@ export default class TypeCheckTraversal extends AstTraversal { } visitIdentifier(node: IdentifierNode): Node { - if (!node.definition) return node; - node.type = node.definition.type; + if (!node.symbol) return node; + node.type = node.symbol.type; return node; } } @@ -599,13 +630,13 @@ function extractSingleBytesNarrowing(expr: BinaryOpNode): Narrowing | undefined const { sizeNode, literalNode } = match; if (!(sizeNode.expression instanceof IdentifierNode)) return undefined; - const { definition } = sizeNode.expression; - if (!definition || !(definition.type instanceof BytesType) || definition.type.bound !== undefined) return undefined; + const { symbol } = sizeNode.expression; + if (!symbol || !(symbol.type instanceof BytesType) || symbol.type.bound !== undefined) return undefined; const bound = Number(literalNode.value); if (bound <= 0) return undefined; - return { symbol: definition, bound }; + return { symbol, bound }; } // Matches expr.length N or N expr.length, returning the SIZE node and int literal. diff --git a/packages/cashc/test/ast/AST.test.ts b/packages/cashc/test/ast/AST.test.ts index 7a7c0076e..a9d0deb11 100644 --- a/packages/cashc/test/ast/AST.test.ts +++ b/packages/cashc/test/ast/AST.test.ts @@ -12,7 +12,7 @@ import fs from 'fs'; import { URL } from 'url'; import { fixtures } from './fixtures.js'; -import { parseCode } from '../../src/compiler.js'; +import { parseCode } from '../../src/parser.js'; import { readCashFiles } from '../test-utils.js'; import { Ast } from '../../src/ast/AST.js'; import OutputSourceCodeTraversal from '../../src/print/OutputSourceCodeTraversal.js'; diff --git a/packages/cashc/test/ast/Location.test.ts b/packages/cashc/test/ast/Location.test.ts index 4f7d94187..65894d305 100644 --- a/packages/cashc/test/ast/Location.test.ts +++ b/packages/cashc/test/ast/Location.test.ts @@ -1,6 +1,7 @@ import fs from 'fs'; import { URL } from 'url'; -import { compileString, parseCode } from '../../src/compiler.js'; +import { compileString } from '../../src/compiler.js'; +import { parseCode } from '../../src/parser.js'; import { buildLineToAsmMap, bytecodeToAsm, bytecodeToScript } from '@cashscript/utils'; import { hexToBin } from '@bitauth/libauth'; @@ -9,7 +10,7 @@ describe('Location', () => { const code = fs.readFileSync(new URL('../valid-contract-files/simple_functions.cash', import.meta.url), { encoding: 'utf-8' }); const ast = parseCode(code); - const f = ast.contract.functions[0]; + const f = ast.contract!.functions[0]; expect(f.location).toBeDefined(); expect((f.location).text(code)).toEqual('function hello(sig s, pubkey pk) {\n require(checkSig(s, pk));\n }'); @@ -84,7 +85,7 @@ contract test() { const code = fs.readFileSync(new URL('../valid-contract-files/simple_functions.cash', import.meta.url), { encoding: 'utf-8' }); const ast = parseCode(code); - const secondFunction = ast.contract.functions[1]; + const secondFunction = ast.contract!.functions[1]; expect(secondFunction.location).toBeDefined(); expect(secondFunction.location.start).toEqual({ line: 6, column: 4 }); diff --git a/packages/cashc/test/ast/fixtures.ts b/packages/cashc/test/ast/fixtures.ts index 12cc323cd..c54d2a0f5 100644 --- a/packages/cashc/test/ast/fixtures.ts +++ b/packages/cashc/test/ast/fixtures.ts @@ -6,6 +6,7 @@ import { Ast, ParameterNode, FunctionDefinitionNode, + FunctionKind, BlockNode, RequireNode, BinaryOpNode, @@ -45,6 +46,7 @@ export const fixtures: Fixture[] = [ 'P2PKH', [new ParameterNode(new BytesType(20), 'pkh')], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'spend', [ new ParameterNode(PrimitiveType.PUBKEY, 'pk'), @@ -76,6 +78,7 @@ export const fixtures: Fixture[] = [ 'Reassignment', [new ParameterNode(PrimitiveType.INT, 'x'), new ParameterNode(PrimitiveType.STRING, 'y')], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'hello', [new ParameterNode(PrimitiveType.PUBKEY, 'pk'), new ParameterNode(PrimitiveType.SIG, 's')], new BlockNode([ @@ -150,6 +153,7 @@ export const fixtures: Fixture[] = [ [new ParameterNode(PrimitiveType.INT, 'x'), new ParameterNode(PrimitiveType.INT, 'y')], [ new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'transfer', [new ParameterNode(PrimitiveType.INT, 'a'), new ParameterNode(PrimitiveType.INT, 'b')], new BlockNode([ @@ -233,6 +237,7 @@ export const fixtures: Fixture[] = [ ]), ), new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'timeout', [new ParameterNode(PrimitiveType.INT, 'b')], new BlockNode([ @@ -312,6 +317,7 @@ export const fixtures: Fixture[] = [ new ParameterNode(PrimitiveType.PUBKEY, 'pk3'), ], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'spend', [ new ParameterNode(PrimitiveType.SIG, 's1'), @@ -351,6 +357,7 @@ export const fixtures: Fixture[] = [ new ParameterNode(PrimitiveType.INT, 'priceTarget'), ], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'spend', [ new ParameterNode(PrimitiveType.SIG, 'ownerSig'), @@ -436,6 +443,7 @@ export const fixtures: Fixture[] = [ 'Covenant', [], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'spend', [], new BlockNode([ @@ -651,6 +659,7 @@ export const fixtures: Fixture[] = [ ], [ new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'receive', [], new BlockNode([ @@ -772,6 +781,7 @@ export const fixtures: Fixture[] = [ ]), ), new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'reclaim', [ new ParameterNode(PrimitiveType.PUBKEY, 'pk'), @@ -810,6 +820,7 @@ export const fixtures: Fixture[] = [ 'Announcement', [], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'announce', [], new BlockNode([ @@ -913,6 +924,7 @@ export const fixtures: Fixture[] = [ [], [ new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'spend', [new ParameterNode(PrimitiveType.INT, 'value')], new BlockNode([ @@ -957,6 +969,7 @@ export const fixtures: Fixture[] = [ 'Loopy', [], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'doLoop', [], new BlockNode([ @@ -1005,6 +1018,7 @@ export const fixtures: Fixture[] = [ 'WhileLoopBasic', [], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'spend', [], new BlockNode([ @@ -1050,6 +1064,7 @@ export const fixtures: Fixture[] = [ 'ForLoopBasic', [], [new FunctionDefinitionNode( + FunctionKind.CONTRACT, 'spend', [], new BlockNode([ diff --git a/packages/cashc/test/compiler/AssignTypeError/void_function_as_value.cash b/packages/cashc/test/compiler/AssignTypeError/void_function_as_value.cash new file mode 100644 index 000000000..f4a16022d --- /dev/null +++ b/packages/cashc/test/compiler/AssignTypeError/void_function_as_value.cash @@ -0,0 +1,10 @@ +function check(int a) { + require(a > 0); +} + +contract Test() { + function spend(int x) { + int y = check(x); + require(y == 0); + } +} diff --git a/packages/cashc/test/compiler/MisplacedReturnError/conditional_return.cash b/packages/cashc/test/compiler/MisplacedReturnError/conditional_return.cash new file mode 100644 index 000000000..db96fdca9 --- /dev/null +++ b/packages/cashc/test/compiler/MisplacedReturnError/conditional_return.cash @@ -0,0 +1,12 @@ +function clamp(int a) returns (int) { + if (a > 10) { + return 10; + } + return a; +} + +contract Test() { + function spend(int x) { + require(clamp(x) == 5); + } +} diff --git a/packages/cashc/test/compiler/MissingReturnError/global_function_missing_return.cash b/packages/cashc/test/compiler/MissingReturnError/global_function_missing_return.cash new file mode 100644 index 000000000..33c5843f9 --- /dev/null +++ b/packages/cashc/test/compiler/MissingReturnError/global_function_missing_return.cash @@ -0,0 +1,10 @@ +function broken(int a) returns (int) { + int b = a + 1; + require(b > 0); +} + +contract Test() { + function spend(int x) { + require(broken(x) == 2); + } +} diff --git a/packages/cashc/test/compiler/ParseError/import_after_contract.cash b/packages/cashc/test/compiler/ParseError/import_after_contract.cash new file mode 100644 index 000000000..33b18164a --- /dev/null +++ b/packages/cashc/test/compiler/ParseError/import_after_contract.cash @@ -0,0 +1,7 @@ +contract Test() { + function spend() { + require(true); + } +} + +import "./helpers.cash"; diff --git a/packages/cashc/test/compiler/ParseError/import_after_function.cash b/packages/cashc/test/compiler/ParseError/import_after_function.cash new file mode 100644 index 000000000..ee2d7c601 --- /dev/null +++ b/packages/cashc/test/compiler/ParseError/import_after_function.cash @@ -0,0 +1,11 @@ +function helper(int a) returns (int) { + return a + 1; +} + +import "./other.cash"; + +contract Test() { + function spend(int x) { + require(helper(x) == 2); + } +} diff --git a/packages/cashc/test/compiler/RedefinitionError/duplicate_global_function.cash b/packages/cashc/test/compiler/RedefinitionError/duplicate_global_function.cash new file mode 100644 index 000000000..41ed861d0 --- /dev/null +++ b/packages/cashc/test/compiler/RedefinitionError/duplicate_global_function.cash @@ -0,0 +1,13 @@ +function foo(int a) returns (int) { + return a + 1; +} + +function foo(int a) returns (int) { + return a + 2; +} + +contract DuplicateGlobalFunction() { + function spend() { + require(foo(1) == 2); + } +} diff --git a/packages/cashc/test/compiler/ReturnTypeError/return_in_contract_function.cash b/packages/cashc/test/compiler/ReturnTypeError/return_in_contract_function.cash new file mode 100644 index 000000000..1f7c67b97 --- /dev/null +++ b/packages/cashc/test/compiler/ReturnTypeError/return_in_contract_function.cash @@ -0,0 +1,5 @@ +contract Test() { + function spend(int x) { + return x; + } +} diff --git a/packages/cashc/test/compiler/ReturnTypeError/wrong_return_type.cash b/packages/cashc/test/compiler/ReturnTypeError/wrong_return_type.cash new file mode 100644 index 000000000..e3cb3efad --- /dev/null +++ b/packages/cashc/test/compiler/ReturnTypeError/wrong_return_type.cash @@ -0,0 +1,9 @@ +function toBytes(int a) returns (bytes32) { + return a; +} + +contract Test() { + function spend(int x) { + require(toBytes(x) == 0x0000000000000000000000000000000000000000000000000000000000000000); + } +} diff --git a/packages/cashc/test/compiler/UnsafeFunctionOperationError/active_bytecode_in_function.cash b/packages/cashc/test/compiler/UnsafeFunctionOperationError/active_bytecode_in_function.cash new file mode 100644 index 000000000..52af373c3 --- /dev/null +++ b/packages/cashc/test/compiler/UnsafeFunctionOperationError/active_bytecode_in_function.cash @@ -0,0 +1,9 @@ +function bodyMatches(bytes expected) returns (bool) { + return this.activeBytecode == expected; +} + +contract Test() { + function spend(bytes expected) { + require(bodyMatches(expected)); + } +} diff --git a/packages/cashc/test/compiler/UnsafeFunctionOperationError/checkmultisig_in_function.cash b/packages/cashc/test/compiler/UnsafeFunctionOperationError/checkmultisig_in_function.cash new file mode 100644 index 000000000..d2a200870 --- /dev/null +++ b/packages/cashc/test/compiler/UnsafeFunctionOperationError/checkmultisig_in_function.cash @@ -0,0 +1,9 @@ +function verifyMulti(sig s1, sig s2, pubkey pk1, pubkey pk2) returns (bool) { + return checkMultiSig([s1, s2], [pk1, pk2]); +} + +contract Test() { + function spend(sig s1, sig s2, pubkey pk1, pubkey pk2) { + require(verifyMulti(s1, s2, pk1, pk2)); + } +} diff --git a/packages/cashc/test/compiler/UnsafeFunctionOperationError/checksig_in_function.cash b/packages/cashc/test/compiler/UnsafeFunctionOperationError/checksig_in_function.cash new file mode 100644 index 000000000..ddd69039b --- /dev/null +++ b/packages/cashc/test/compiler/UnsafeFunctionOperationError/checksig_in_function.cash @@ -0,0 +1,9 @@ +function verify(sig s, pubkey pk) returns (bool) { + return checkSig(s, pk); +} + +contract Test() { + function spend(sig s, pubkey pk) { + require(verify(s, pk)); + } +} diff --git a/packages/cashc/test/compiler/ParseError/nonvoid_function_call.cash b/packages/cashc/test/compiler/UnusedFunctionReturnError/nonvoid_function_call.cash similarity index 100% rename from packages/cashc/test/compiler/ParseError/nonvoid_function_call.cash rename to packages/cashc/test/compiler/UnusedFunctionReturnError/nonvoid_function_call.cash diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash b/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash new file mode 100644 index 000000000..a37120dd3 --- /dev/null +++ b/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash @@ -0,0 +1,10 @@ +function withUnusedLocal(int a) returns (int) { + int unused = a + 1; + return a; +} + +contract UnusedGlobalFunctionLocal() { + function spend() { + require(withUnusedLocal(1) == 1); + } +} diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_parameter.cash b/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_parameter.cash new file mode 100644 index 000000000..815d952ea --- /dev/null +++ b/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_parameter.cash @@ -0,0 +1,9 @@ +function withUnusedParameter(int a, int b) returns (int) { + return a; +} + +contract UnusedGlobalFunctionParameter() { + function spend() { + require(withUnusedParameter(1, 2) == 1); + } +} diff --git a/packages/cashc/test/dead-code-elimination.test.ts b/packages/cashc/test/dead-code-elimination.test.ts new file mode 100644 index 000000000..6a493e01d --- /dev/null +++ b/packages/cashc/test/dead-code-elimination.test.ts @@ -0,0 +1,162 @@ +import { fileURLToPath } from 'url'; +import { compileString } from '../src/index.js'; + +const fixtureDir = fileURLToPath(new URL('./import-fixtures/', import.meta.url)); +const countOpDefines = (bytecode: string): number => [...bytecode.matchAll(/OP_DEFINE/g)].length; + +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; } + + contract Test() { + function spend(int x) { + require(used(x) == 6); + } + }`; + + const artifact = compileString(code); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + expect(artifact.bytecode).toContain('OP_INVOKE'); + }); + + it('eliminates functions that are only reachable through other dead functions', () => { + const code = ` + function used(int a) returns (int) { return a + 1; } + function deadCaller(int a) returns (int) { return deadLeaf(a); } + function deadLeaf(int a) returns (int) { return a * 2; } + + contract Test() { + function spend(int x) { + require(used(x) == 6); + } + }`; + + // Only `used` is reachable; both `deadCaller` and the function it calls (`deadLeaf`) are dropped. + const artifact = compileString(code); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('keeps a function that is only reachable transitively', () => { + const code = ` + function outer(int a) returns (int) { return inner(a) + 1; } + function inner(int a) returns (int) { return a * 2; } + + contract Test() { + function spend(int x) { + require(outer(x) == 7); + } + }`; + + // `outer` is called directly and `inner` only through `outer` — both must be defined. + const artifact = compileString(code); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + }); + + it('keeps a recursive function without looping forever', () => { + const code = ` + function f(int n) returns (int) { return f(n); } + + contract Test() { + function spend(int x) { + require(f(x) == 0); + } + }`; + + const artifact = compileString(code); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('keeps mutually recursive functions that are reachable', () => { + const code = ` + function a(int n) returns (int) { return b(n); } + function b(int n) returns (int) { return a(n); } + + contract Test() { + function spend(int x) { + require(a(x) == 0); + } + }`; + + const artifact = compileString(code); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + }); + + it('eliminates a mutually recursive cycle that is never reached', () => { + const code = ` + function used(int n) returns (int) { return n + 1; } + function deadA(int n) returns (int) { return deadB(n); } + function deadB(int n) returns (int) { return deadA(n); } + + contract Test() { + function spend(int x) { + require(used(x) == 1); + } + }`; + + // deadA <-> deadB form a cycle but neither is reachable, so both are dropped. + const artifact = compileString(code); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('eliminates an unused imported function', () => { + // math.cash exports both `addOne` and `double`; only `double` is used here, so `addOne` is dropped. + const code = 'import "./math.cash";\ncontract Test() { function spend(int x) { require(double(x) == 8); } }'; + + const artifact = compileString(code, { basePath: fixtureDir }); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); +}); + +describe('Stable function id assignment', () => { + it('reordering function declarations does not change the bytecode', () => { + const ordered = ` + function a(int n) returns (int) { return n + 1; } + function b(int n) returns (int) { return n * 2; } + + contract Test() { + function spend(int x) { + require(b(x) + a(x) == 10); + } + }`; + + const reordered = ` + function b(int n) returns (int) { return n * 2; } + function a(int n) returns (int) { return n + 1; } + + contract Test() { + function spend(int x) { + require(b(x) + a(x) == 10); + } + }`; + + // functionIds follow call order (b, then a) rather than declaration order, so swapping the two + // declarations produces byte-identical output. + expect(compileString(reordered).bytecode).toEqual(compileString(ordered).bytecode); + }); + + it('renaming a function does not change the bytecode', () => { + const original = ` + function apple(int n) returns (int) { return n + 1; } + function mango(int n) returns (int) { return n * 2; } + + contract Test() { + function spend(int x) { + require(mango(x) + apple(x) == 10); + } + }`; + + const renamed = ` + function zebra(int n) returns (int) { return n + 1; } + function mango(int n) returns (int) { return n * 2; } + + contract Test() { + function spend(int x) { + require(mango(x) + zebra(x) == 10); + } + }`; + + expect(compileString(renamed).bytecode).toEqual(compileString(original).bytecode); + }); +}); diff --git a/packages/cashc/test/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts index c03ac203d..a8a6c2eca 100644 --- a/packages/cashc/test/generation/fixtures.ts +++ b/packages/cashc/test/generation/fixtures.ts @@ -1408,4 +1408,143 @@ export const fixtures: Fixture[] = [ fingerprint: '606e540c38f161868964b683aeb0ddf93094dc36607397ef9b9f507f9028bc37', }, }, + { + // A single global function — the basic OP_DEFINE / OP_INVOKE calling convention. + fn: 'global_function_simple.cash', + artifact: { + contractName: 'GlobalFunctionSimple', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // OP_DEFINE double (id 0): return a * 2 + '5295 OP_0 OP_DEFINE ' + // require(double(x) == 6) + + 'OP_0 OP_INVOKE OP_6 OP_NUMEQUAL', + debug: { + bytecode: '0252950089008a569c', + logs: [], + requires: [ + { ip: 7, line: 7 }, + ], + sourceMap: '1::3:1;;::::1;7:16:7:25;;:29::30:0;:8::32:1', + }, + source: fs.readFileSync(new URL('../valid-contract-files/global_function_simple.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: 'ef6dd7819e66a430286fe16f3d6dad7e026cf1970eda6bc620be7e7a3bdd2a4d', + }, + }, + { + // 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', + 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', + debug: { + bytecode: '019400897c008a579c', + logs: [], + requires: [ + { ip: 8, line: 7 }, + ], + sourceMap: '1::3:1;;::::1;7:23:7:24:0;:16::25:1;;:29::30:0;:8::32:1', + }, + source: fs.readFileSync(new URL('../valid-contract-files/global_function_multi_param.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: '8fc72a3f89ee3238266d6dd9ad3919f7238c8d6a31296cc8925968a31c78c7dc', + }, + }, + { + // A void global function called as a statement — no return value, and the void stack-cleanup path. + fn: 'global_function_void.cash', + artifact: { + contractName: 'GlobalFunctionVoid', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // OP_DEFINE requirePositive (id 0): require(a > 0) + '00a069 OP_0 OP_DEFINE ' + // requirePositive(x); require(x < 100) + + 'OP_DUP OP_0 OP_INVOKE 64 OP_LESSTHAN', + debug: { + bytecode: '0300a069008976008a01649f', + logs: [], + requires: [ + { ip: 8, line: 8 }, + ], + sourceMap: '1::3:1;;::::1;7:24:7:25:0;:8::26:1;;8:20:8:23:0;:8::25:1', + }, + source: fs.readFileSync(new URL('../valid-contract-files/global_function_void.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: '4d5e07b068e501eb26e61aab0d53214aa42590858253b1106d6074d494fde557', + }, + }, + { + // 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', + artifact: { + contractName: 'Diamond', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // Functions are defined in call order (DFS from the contract), so m1 is id 0, leaf id 1, m2 id 2. + // OP_DEFINE m1 (id 0): return leaf(a) * 2 + '518a5295 OP_0 OP_DEFINE ' + // OP_DEFINE leaf (id 1): return a + 1 + + '8b OP_1 OP_DEFINE ' + // OP_DEFINE m2 (id 2): return leaf(a) + 3 + + '518a5393 OP_2 OP_DEFINE ' + // require(m1(x) + m2(x) == 18) + + 'OP_DUP OP_0 OP_INVOKE OP_SWAP OP_2 OP_INVOKE OP_ADD 12 OP_NUMEQUAL', + debug: { + bytecode: '04518a52950089018b518904518a5393528976008a7c528a9301129c', + logs: [], + requires: [ + { ip: 18, line: 6 }, + ], + sourceMap: '2::4:1;;::::1;1::3::0;;::::1;2::4::0;;::::1;6:19:6:20:0;:16::21:1;;:27::28:0;:24::29:1;;:16;:33::35:0;:8::37:1', + }, + source: fs.readFileSync(new URL('../import-fixtures/diamond.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: '316a3305152ec0695bf80303736c79dd1f9cc2f1dbccf57d9965094401363307', + }, + }, ]; diff --git a/packages/cashc/test/import-fixtures/cycle_a.cash b/packages/cashc/test/import-fixtures/cycle_a.cash new file mode 100644 index 000000000..5197f26ec --- /dev/null +++ b/packages/cashc/test/import-fixtures/cycle_a.cash @@ -0,0 +1,5 @@ +import "./cycle_b.cash"; + +function a(int n) returns (int) { + return n + 1; +} diff --git a/packages/cashc/test/import-fixtures/cycle_b.cash b/packages/cashc/test/import-fixtures/cycle_b.cash new file mode 100644 index 000000000..da059e51b --- /dev/null +++ b/packages/cashc/test/import-fixtures/cycle_b.cash @@ -0,0 +1,5 @@ +import "./cycle_a.cash"; + +function b(int n) returns (int) { + return n * 2; +} diff --git a/packages/cashc/test/import-fixtures/cycle_main.cash b/packages/cashc/test/import-fixtures/cycle_main.cash new file mode 100644 index 000000000..6f54878b7 --- /dev/null +++ b/packages/cashc/test/import-fixtures/cycle_main.cash @@ -0,0 +1,7 @@ +import "./cycle_a.cash"; + +contract Cycle() { + function spend(int x) { + require(a(x) + b(x) == 7); + } +} diff --git a/packages/cashc/test/import-fixtures/diamond.cash b/packages/cashc/test/import-fixtures/diamond.cash new file mode 100644 index 000000000..e3629cb4d --- /dev/null +++ b/packages/cashc/test/import-fixtures/diamond.cash @@ -0,0 +1,8 @@ +import "./mid1.cash"; +import "./mid2.cash"; + +contract Diamond() { + function spend(int x) { + require(m1(x) + m2(x) == 18); + } +} diff --git a/packages/cashc/test/import-fixtures/duplicate_import_helper.cash b/packages/cashc/test/import-fixtures/duplicate_import_helper.cash new file mode 100644 index 000000000..03a29aa07 --- /dev/null +++ b/packages/cashc/test/import-fixtures/duplicate_import_helper.cash @@ -0,0 +1,3 @@ +function shared(int a) returns (int) { + return a + 99; +} diff --git a/packages/cashc/test/import-fixtures/duplicate_import_main.cash b/packages/cashc/test/import-fixtures/duplicate_import_main.cash new file mode 100644 index 000000000..2ec046823 --- /dev/null +++ b/packages/cashc/test/import-fixtures/duplicate_import_main.cash @@ -0,0 +1,11 @@ +import "./duplicate_import_helper.cash"; + +function shared(int a) returns (int) { + return a + 1; +} + +contract DuplicateImport() { + function spend() { + require(shared(1) == 2); + } +} diff --git a/packages/cashc/test/import-fixtures/leaf.cash b/packages/cashc/test/import-fixtures/leaf.cash new file mode 100644 index 000000000..c3d21091a --- /dev/null +++ b/packages/cashc/test/import-fixtures/leaf.cash @@ -0,0 +1,3 @@ +function leaf(int a) returns (int) { + return a + 1; +} diff --git a/packages/cashc/test/import-fixtures/main.cash b/packages/cashc/test/import-fixtures/main.cash new file mode 100644 index 000000000..f9c1a552b --- /dev/null +++ b/packages/cashc/test/import-fixtures/main.cash @@ -0,0 +1,7 @@ +import "./math.cash"; + +contract Main() { + function spend(int x) { + require(double(addOne(x)) == 8); + } +} diff --git a/packages/cashc/test/import-fixtures/math.cash b/packages/cashc/test/import-fixtures/math.cash new file mode 100644 index 000000000..9d74e6923 --- /dev/null +++ b/packages/cashc/test/import-fixtures/math.cash @@ -0,0 +1,7 @@ +function addOne(int a) returns (int) { + return a + 1; +} + +function double(int a) returns (int) { + return a * 2; +} diff --git a/packages/cashc/test/import-fixtures/mid1.cash b/packages/cashc/test/import-fixtures/mid1.cash new file mode 100644 index 000000000..096decc5a --- /dev/null +++ b/packages/cashc/test/import-fixtures/mid1.cash @@ -0,0 +1,4 @@ +import "./leaf.cash"; +function m1(int a) returns (int) { + return leaf(a) * 2; +} diff --git a/packages/cashc/test/import-fixtures/mid2.cash b/packages/cashc/test/import-fixtures/mid2.cash new file mode 100644 index 000000000..cdc964c0c --- /dev/null +++ b/packages/cashc/test/import-fixtures/mid2.cash @@ -0,0 +1,4 @@ +import "./leaf.cash"; +function m2(int a) returns (int) { + return leaf(a) + 3; +} diff --git a/packages/cashc/test/imports.test.ts b/packages/cashc/test/imports.test.ts new file mode 100644 index 000000000..4eb960fcf --- /dev/null +++ b/packages/cashc/test/imports.test.ts @@ -0,0 +1,46 @@ +import { fileURLToPath } from 'url'; +import { compileFile, compileString } from '../src/index.js'; +import { ImportResolutionError, FunctionRedefinitionError } from '../src/Errors.js'; + +const fixture = (name: string): string => fileURLToPath(new URL(`./import-fixtures/${name}`, import.meta.url)); + +describe('Imports', () => { + it('merges global functions from an imported file', () => { + const artifact = compileFile(fixture('main.cash')); + expect(artifact.contractName).toEqual('Main'); + expect(artifact.bytecode).toContain('OP_INVOKE'); + // both imported functions are defined (one OP_DEFINE each) + expect([...artifact.bytecode.matchAll(/OP_DEFINE/g)]).toHaveLength(2); + }); + + 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')); + expect(artifact.contractName).toEqual('Diamond'); + expect([...artifact.bytecode.matchAll(/OP_DEFINE/g)]).toHaveLength(3); + }); + + it('throws when compiling a string with imports but no base path', () => { + const code = 'import "./math.cash";\ncontract C() { function spend() { require(true); } }'; + expect(() => compileString(code)).toThrow(ImportResolutionError); + }); + + it('throws when an imported file cannot be found', () => { + const code = 'import "./does-not-exist.cash";\ncontract C() { function spend() { require(true); } }'; + expect(() => compileString(code, { basePath: fixture('') })).toThrow(ImportResolutionError); + }); + + it('throws when an imported function collides with a local function of the same name', () => { + // duplicate_import_main defines `shared` and imports a file that also defines `shared`. + expect(() => compileFile(fixture('duplicate_import_main.cash'))).toThrow(FunctionRedefinitionError); + }); + + it('resolves a cyclic import without infinite looping', () => { + // cycle_a imports cycle_b which imports cycle_a back; de-duplication by absolute path breaks the + // cycle, and both functions (a and b) end up defined exactly once. + const artifact = compileFile(fixture('cycle_main.cash')); + expect(artifact.contractName).toEqual('Cycle'); + expect([...artifact.bytecode.matchAll(/OP_DEFINE/g)]).toHaveLength(2); + }); +}); diff --git a/packages/cashc/test/semantic/InjectLocktimeGuardTraversal.test.ts b/packages/cashc/test/semantic/InjectLocktimeGuardTraversal.test.ts index fc89f420b..c99f91139 100644 --- a/packages/cashc/test/semantic/InjectLocktimeGuardTraversal.test.ts +++ b/packages/cashc/test/semantic/InjectLocktimeGuardTraversal.test.ts @@ -213,3 +213,102 @@ describe('InjectLocktimeGuardTraversal', () => { expect(compileString(src, { enforceLocktimeGuard: false }).bytecode.startsWith(GUARD_PREFIX)).toBe(false); }); }); + +// The guard is only injected into contract spending functions, never into global functions (non-finality +// is a transaction-wide property, so a single guard on the spending path covers any tx.locktime accessed +// inside invoked global functions). Whether a contract function needs the guard is therefore decided by +// looking through the global functions it (transitively) invokes. The injected guard is a require with a +// distinctive message, which is detectable even when the OP_DEFINE prologue precedes the contract body. +describe('InjectLocktimeGuardTraversal — global functions', () => { + const GUARD_MESSAGE = 'non-final sequence number'; + const guardInjected = (src: string): boolean => (compileString(src).debug?.requires ?? []) + .some((statement) => statement.message?.includes(GUARD_MESSAGE)); + + it('injects guard in the contract when an invoked global uses tx.locktime', () => { + const src = ` + function usesLocktime() returns (int) { return tx.locktime; } + contract T() { + function spend() { + require(usesLocktime() >= 100); + } + }`; + expect(guardInjected(src)).toBe(true); + }); + + it('does not inject when the contract has a tx.time check before invoking the global', () => { + const src = ` + function usesLocktime() returns (int) { return tx.locktime; } + contract T() { + function spend() { + require(tx.time >= 100); + require(usesLocktime() >= 100); + } + }`; + expect(guardInjected(src)).toBe(false); + }); + + it('does not inject when the invoked global covers its own tx.locktime with a tx.time check', () => { + const src = ` + function usesLocktime() returns (int) { require(tx.time >= 100); return tx.locktime; } + contract T() { + function spend() { + require(usesLocktime() >= 0); + } + }`; + expect(guardInjected(src)).toBe(false); + }); + + it('injects guard for tx.locktime reached transitively through nested global invocations', () => { + const src = ` + function inner() returns (int) { return tx.locktime; } + function outer() returns (int) { return inner(); } + contract T() { + function spend() { + require(outer() >= 100); + } + }`; + expect(guardInjected(src)).toBe(true); + }); + + it('does not inject when a caller global covers the callee with its own tx.time check', () => { + const src = ` + function inner() returns (int) { return tx.locktime; } + function outer() returns (int) { require(tx.time >= 100); return inner(); } + contract T() { + function spend() { + require(outer() >= 0); + } + }`; + expect(guardInjected(src)).toBe(false); + }); + + it('injects guard when an invoked global only uses tx.locktime inside a branch', () => { + const src = ` + function maybeLocktime(int a) { + if (a > 0) { + int x = tx.locktime; + require(x >= 100); + } else { + require(a == 0); + } + } + contract T() { + function spend(int x) { + maybeLocktime(x); + require(x >= 0); + } + }`; + expect(guardInjected(src)).toBe(true); + }); + + it('does not inject when an invoked global does not use tx.locktime', () => { + const src = ` + function double(int a) returns (int) { return a * 2; } + contract T() { + function spend(int x) { + require(double(x) >= 2); + } + }`; + expect(guardInjected(src)).toBe(false); + }); +}); diff --git a/packages/cashc/test/valid-contract-files/checkdatasig_in_function.cash b/packages/cashc/test/valid-contract-files/checkdatasig_in_function.cash new file mode 100644 index 000000000..0ba76f2e2 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/checkdatasig_in_function.cash @@ -0,0 +1,9 @@ +function verifyData(datasig s, bytes message, pubkey pk) returns (bool) { + return checkDataSig(s, message, pk); +} + +contract Test() { + function spend(datasig s, bytes message, pubkey pk) { + require(verifyData(s, message, pk)); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_function_in_control_flow.cash b/packages/cashc/test/valid-contract-files/global_function_in_control_flow.cash new file mode 100644 index 000000000..9d9d6a4b0 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_in_control_flow.cash @@ -0,0 +1,17 @@ +function triple(int a) returns (int) { + return a * 3; +} + +contract GlobalFunctionInControlFlow() { + function spend(int x, bool useLoop) { + int total = 0; + if (useLoop) { + for (int i = 0; i < 3; i = i + 1) { + total = total + triple(x); + } + } else { + total = triple(x); + } + require(total == 9); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_function_multi_param.cash b/packages/cashc/test/valid-contract-files/global_function_multi_param.cash new file mode 100644 index 000000000..badac11dc --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_multi_param.cash @@ -0,0 +1,9 @@ +function sub(int a, int b) returns (int) { + return a - b; +} + +contract GlobalFunctionMultiParam() { + function spend(int x, int y) { + require(sub(x, y) == 7); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_function_nested.cash b/packages/cashc/test/valid-contract-files/global_function_nested.cash new file mode 100644 index 000000000..cc350bcb9 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_nested.cash @@ -0,0 +1,13 @@ +function addOne(int a) returns (int) { + return a + 1; +} + +function doubleIncremented(int a) returns (int) { + return addOne(a) * 2; +} + +contract GlobalFunctionNested() { + function spend(int x) { + require(doubleIncremented(x) == 8); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_function_simple.cash b/packages/cashc/test/valid-contract-files/global_function_simple.cash new file mode 100644 index 000000000..851f6cd7f --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_simple.cash @@ -0,0 +1,9 @@ +function double(int a) returns (int) { + return a * 2; +} + +contract GlobalFunctionSimple() { + function spend(int x) { + require(double(x) == 6); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_function_void.cash b/packages/cashc/test/valid-contract-files/global_function_void.cash new file mode 100644 index 000000000..945569f73 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_void.cash @@ -0,0 +1,10 @@ +function requirePositive(int a) { + require(a > 0); +} + +contract GlobalFunctionVoid() { + function spend(int x) { + requirePositive(x); + require(x < 100); + } +} diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index 3215217dc..63c519377 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -46,6 +46,7 @@ export enum PrimitiveType { SIG = 'sig', DATASIG = 'datasig', ANY = 'any', + VOID = 'void', } const ExplicitlyCastableTo: { [key in PrimitiveType]: PrimitiveType[] } = { @@ -56,11 +57,15 @@ const ExplicitlyCastableTo: { [key in PrimitiveType]: PrimitiveType[] } = { [PrimitiveType.SIG]: [PrimitiveType.SIG], [PrimitiveType.DATASIG]: [PrimitiveType.DATASIG], [PrimitiveType.ANY]: [], + [PrimitiveType.VOID]: [], }; export function explicitlyCastable(from?: Type, to?: Type): boolean { if (!from || !to) return false; + // `void` is not a real value type, so it can never participate in a cast + if (from === PrimitiveType.VOID || to === PrimitiveType.VOID) return false; + // Tuples can't be cast if (from instanceof TupleType || to instanceof TupleType) return false; @@ -111,6 +116,9 @@ export function explicitlyCastable(from?: Type, to?: Type): boolean { export function implicitlyCastable(actual?: Type, expected?: Type): boolean { if (!actual || !expected) return false; + // `void` is not a real value type, so it can never be assigned to or from (not even to `any`) + if (actual === PrimitiveType.VOID || expected === PrimitiveType.VOID) return false; + if (actual instanceof TupleType && expected instanceof TupleType) { const leftIsCompatible = implicitlyCastable(actual.leftType, expected.leftType); const rightIsCompatible = implicitlyCastable(actual.rightType, expected.rightType); diff --git a/website/docs/compiler/compiler.md b/website/docs/compiler/compiler.md index de6e48c89..f5de753d9 100644 --- a/website/docs/compiler/compiler.md +++ b/website/docs/compiler/compiler.md @@ -82,6 +82,10 @@ Compiles a CashScript contract from a source file. This compile method is handy const P2PKH = compileFile(new URL('p2pkh.cash', import.meta.url)); ``` +:::note +If the contract uses `import` directives to pull in [user-defined functions](/docs/language/contracts#user-defined-functions) from other files, `compileFile` resolves those imports relative to the source file's directory automatically. +::: + ### compileString() ```ts compileString(sourceCode: string, compilerOptions?: CompilerOptions): Artifact @@ -97,6 +101,10 @@ const source = await result.text(); const P2PKH = compileString(source); ``` +:::note +`compileString` has no source file to resolve `import` directives against. To compile a contract that imports [user-defined functions](/docs/language/contracts#user-defined-functions) from other files, use [`compileFile`](#compilefile) instead. +::: + ### Compiler Options ```ts interface CompilerOptions { diff --git a/website/docs/compiler/grammar.md b/website/docs/compiler/grammar.md index 93f5d8d7d..060931884 100644 --- a/website/docs/compiler/grammar.md +++ b/website/docs/compiler/grammar.md @@ -7,7 +7,7 @@ description: ANTLR4 language grammar for CashScript grammar CashScript; sourceFile - : pragmaDirective* contractDefinition EOF + : pragmaDirective* importDirective* topLevelDefinition* EOF ; pragmaDirective @@ -30,11 +30,24 @@ versionOperator : '^' | '~' | '>=' | '>' | '<' | '<=' | '=' ; +importDirective + : 'import' StringLiteral ';' + ; + +topLevelDefinition + : globalFunctionDefinition + | contractDefinition + ; + +globalFunctionDefinition + : 'function' Identifier parameterList ('returns' '(' typeName ')')? functionBody + ; + contractDefinition - : 'contract' Identifier parameterList '{' functionDefinition* '}' + : 'contract' Identifier parameterList '{' contractFunctionDefinition* '}' ; -functionDefinition +contractFunctionDefinition : 'function' Identifier parameterList functionBody ; @@ -66,7 +79,17 @@ nonControlStatement | assignStatement | timeOpStatement | requireStatement + | functionCallStatement | consoleStatement + | returnStatement + ; + +functionCallStatement + : functionCall + ; + +returnStatement + : 'return' expression ; controlStatement @@ -140,7 +163,7 @@ consoleParameterList ; functionCall - : Identifier expressionList // Only built-in functions are accepted + : Identifier expressionList // Built-in global functions and user-defined global functions ; expressionList diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index b6e45949c..e160d30a2 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -60,7 +60,7 @@ contract TransferWithTimeout(pubkey sender, pubkey recipient, int timeout) { ``` :::note -The functions described here are top-level contract functions, which act as the entry points for spending from the contract. CashScript does not yet support user-defined reusable functions that can be called from within other functions. Callable functions are likely coming in CashScript v0.14, which would also allow function calls inside loops and loops inside reusable functions. +The functions described here are top-level contract functions, which act as the entry points for spending from the contract. CashScript also supports user-defined reusable functions that are declared at the top level of a file (outside the contract) and can be called from contract functions and from each other. See [User-defined functions](#user-defined-functions) below. ::: ### Function Arguments @@ -79,6 +79,83 @@ In CashScript the types for the function arguments are **not** enforced automati The typings for function arguments are enforced by default for boolean values and bounded bytes types such as `bytes20` and `bytes32`. ::: +## User-defined functions +Reusable functions are declared at the **top level** of a `.cash` file, outside the contract. They are compiled to the BCH VM's native function opcodes (`OP_DEFINE`/`OP_INVOKE`, available since the May 2026 upgrade), so a function's body is stored once and shared across every call site rather than duplicated. + +A function may return a **single value** using a `returns (T)` clause, and is called from contract functions or from other top-level functions: + +```solidity +pragma cashscript ^0.14.0; + +function double(int a) returns (int) { + return a * 2; +} + +function addThenDouble(int a, int b) returns (int) { + return double(a + b); +} + +contract Example() { + function spend(int x) { + require(addThenDouble(x, 1) == 8); + } +} +``` + +A function without a `returns` clause is a **void** function — it performs only `require` checks and is called as a statement: + +```solidity +function requirePositive(int a) { + require(a > 0); +} + +contract Example() { + function spend(int x) { + requirePositive(x); + require(x < 100); + } +} +``` + +### Importing functions from other files +Top-level functions can be split across files and pulled in with an `import` directive, which makes the imported file's functions available as if they were declared locally. All `import` directives must appear at the **top of the file** — after any `pragma` directives and before any function or contract definitions. Imports are resolved relative to the importing file, so they require compiling from a file (`compileFile`): + +```solidity +// math.cash +function double(int a) returns (int) { + return a * 2; +} +``` + +```solidity +// main.cash +pragma cashscript ^0.14.0; +import "./math.cash"; + +contract Main() { + function spend(int x) { + require(double(x) == 8); + } +} +``` + +Imported function names share a single global namespace, so a name may only be defined once across the whole import graph. Files reached through more than one import path (diamond imports) are resolved once. + +:::info +`checkSig`, `checkMultiSig` and `this.activeBytecode` cannot be used inside a user-defined function, since they would apply to the function body rather than the contract. Use them in a contract function instead (`checkDataSig` is allowed). +::: + +### Limitations +This first version of user-defined functions is intentionally limited in scope: + +- Functions return **at most one value** (no multiple/tuple returns), and a value-returning function must end with a single `return` statement (no early or conditional returns — compute into a variable and return it at the end). +- No advanced optimisations are performed yet on user-defined functions. +- The local debugging tools in the SDK don't properly support user-defined functions yet. + +:::note +Recursive and mutually recursive functions are allowed and compile fine. At runtime the VM control stack is limited to 100 entries, shared between recursion depth and nested `if` and loop blocks, so excessively deep recursion will fail when the contract gets spent. +::: + ## Statements CashScript functions are made up of a collection of statements that determine whether money may be spent from the contract. diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 12b56417e..160d49f80 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -2,6 +2,14 @@ title: Release Notes --- +## v0.14.0-next.0 + +⚠️ Note that this is a pre-release version and is not yet stable. There will likely be breaking changes to the APIs and compiler output in subsequent pre-releases. + +#### cashc compiler +- :sparkles: Add support for user-defined reusable functions. +- :sparkles: Add support for `import` directives to share user-defined functions across files. + ## v0.13.2 #### cashc compiler From 790d4a2c608ef492a9a1f886b1489d2e4ffe95e2 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Fri, 26 Jun 2026 16:09:56 +0200 Subject: [PATCH 02/37] Bump version to 0.14.0-next.0 --- examples/package.json | 6 +++--- examples/testing-suite/package.json | 6 +++--- packages/cashc/package.json | 4 ++-- packages/cashc/src/index.ts | 2 +- packages/cashscript/package.json | 4 ++-- packages/cashscript/test/e2e/LocktimeGuard.test.ts | 2 +- packages/utils/package.json | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/package.json b/examples/package.json index 0dd0edb75..43a9e0313 100644 --- a/examples/package.json +++ b/examples/package.json @@ -1,7 +1,7 @@ { "name": "cashscript-examples", "private": true, - "version": "0.13.2", + "version": "0.14.0-next.0", "description": "Usage examples of the CashScript SDK", "main": "p2pkh.js", "type": "module", @@ -13,8 +13,8 @@ "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", "@types/node": "^22.17.0", - "cashc": "^0.13.2", - "cashscript": "^0.13.2", + "cashc": "^0.14.0-next.0", + "cashscript": "^0.14.0-next.0", "eslint": "^8.56.0", "typescript": "^5.9.2" } diff --git a/examples/testing-suite/package.json b/examples/testing-suite/package.json index a931cec80..1fb4f4ea4 100644 --- a/examples/testing-suite/package.json +++ b/examples/testing-suite/package.json @@ -1,6 +1,6 @@ { "name": "testing-suite", - "version": "0.13.2", + "version": "0.14.0-next.0", "description": "Example project to develop and test CashScript contracts", "main": "index.js", "type": "module", @@ -18,8 +18,8 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "cashc": "^0.13.2", - "cashscript": "^0.13.2" + "cashc": "^0.14.0-next.0", + "cashscript": "^0.14.0-next.0" }, "devDependencies": { "tsx": "^4.20.3", diff --git a/packages/cashc/package.json b/packages/cashc/package.json index 713a783b4..a1d9c1088 100644 --- a/packages/cashc/package.json +++ b/packages/cashc/package.json @@ -1,6 +1,6 @@ { "name": "cashc", - "version": "0.13.2", + "version": "0.14.0-next.0", "description": "Compile Bitcoin Cash contracts to Bitcoin Cash Script or artifacts", "keywords": [ "bitcoin", @@ -48,7 +48,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.13.2", + "@cashscript/utils": "^0.14.0-next.0", "antlr4": "^4.13.2", "commander": "^14.0.0", "semver": "^7.7.2" diff --git a/packages/cashc/src/index.ts b/packages/cashc/src/index.ts index 178adeaa7..d8761f026 100644 --- a/packages/cashc/src/index.ts +++ b/packages/cashc/src/index.ts @@ -4,4 +4,4 @@ export { compileFile, compileString, type CompileOptions } from './compiler.js'; export * from './ast/Location.js'; export * from './ast/error-listeners.js'; -export const version = '0.13.2'; +export const version = '0.14.0-next.0'; diff --git a/packages/cashscript/package.json b/packages/cashscript/package.json index 1e8351f94..7358763fa 100644 --- a/packages/cashscript/package.json +++ b/packages/cashscript/package.json @@ -1,6 +1,6 @@ { "name": "cashscript", - "version": "0.13.2", + "version": "0.14.0-next.0", "description": "Easily write and interact with Bitcoin Cash contracts", "keywords": [ "bitcoin cash", @@ -42,7 +42,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.13.2", + "@cashscript/utils": "^0.14.0-next.0", "@electrum-cash/network": "^4.1.3", "fflate": "^0.8.2", "semver": "^7.7.2" diff --git a/packages/cashscript/test/e2e/LocktimeGuard.test.ts b/packages/cashscript/test/e2e/LocktimeGuard.test.ts index 76e4ac96a..8503aef93 100644 --- a/packages/cashscript/test/e2e/LocktimeGuard.test.ts +++ b/packages/cashscript/test/e2e/LocktimeGuard.test.ts @@ -59,7 +59,7 @@ describe('Locktime Guard with function parameters', () => { const provider = new MockNetworkProvider(); const artifactWithParameter = compileString(` - pragma cashscript ^0.13.0; + pragma cashscript ^0.14.0; contract ParameterizedLocktimeGuard() { function spend( diff --git a/packages/utils/package.json b/packages/utils/package.json index 36b169a5c..fb576d8e9 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@cashscript/utils", - "version": "0.13.2", + "version": "0.14.0-next.0", "description": "CashScript utilities and types", "keywords": [ "bitcoin cash", From 7bcaf86dc381578e765fec7f260521d72537f75d Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 7 Jul 2026 10:33:27 +0200 Subject: [PATCH 03/37] Add SDK debugging support for user-defined functions (#418) --- .cspell.json | 3 + packages/cashc/src/ast/AST.ts | 4 + packages/cashc/src/compiler.ts | 1 + packages/cashc/src/dependency-resolution.ts | 10 +- .../src/generation/GenerateTargetTraversal.ts | 27 +- packages/cashc/test/ast/Location.test.ts | 68 ---- packages/cashc/test/generation/fixtures.ts | 68 ++++ packages/cashscript/src/Errors.ts | 38 +- packages/cashscript/src/debug-frame.ts | 45 +++ packages/cashscript/src/debugging.ts | 53 +-- .../cashscript/src/libauth-template/utils.ts | 10 +- packages/cashscript/test/debugging.test.ts | 89 ++++- .../fixture/debugging/debugging_contracts.ts | 36 +- .../fixture/debugging/function_helpers.cash | 3 + .../fixture/debugging/function_importer.cash | 8 + packages/utils/src/artifact.ts | 14 + packages/utils/src/bitauth-script.ts | 347 +++++++++++++----- packages/utils/test/bitauth-script.test.ts | 75 +++- .../test/fixtures/bitauth-script.fixture.ts | 252 ++++++++----- .../fixtures/function-imports/helpers.cash | 9 + .../fixtures/function-imports/importer.cash | 8 + 21 files changed, 849 insertions(+), 319 deletions(-) create mode 100644 packages/cashscript/src/debug-frame.ts create mode 100644 packages/cashscript/test/fixture/debugging/function_helpers.cash create mode 100644 packages/cashscript/test/fixture/debugging/function_importer.cash create mode 100644 packages/utils/test/fixtures/function-imports/helpers.cash create mode 100644 packages/utils/test/fixtures/function-imports/importer.cash diff --git a/.cspell.json b/.cspell.json index 56f78ca2b..b38edf2f0 100644 --- a/.cspell.json +++ b/.cspell.json @@ -48,6 +48,9 @@ "chipnet", "cleanstack", "cleanup", + "cleanups", + "remappings", + "codegen", "cryptocurrency", "collateralized", "datasig", diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index 8d0970232..fd43eca09 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -75,6 +75,10 @@ export class FunctionDefinitionNode extends Node implements Named { symbolTable?: SymbolTable; opRolls: Map = new Map(); + // Source provenance for debugging. Set on imported functions, left undefined for functions in the contract's own file. + sourceCode?: string; + sourceFile?: string; + constructor( public kind: FunctionKind, public name: string, diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index efdb98591..04a164252 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -99,6 +99,7 @@ export function compileString(code: string, compilerOptions: CompileOptions = {} logs: optimisationResult.logs, requires: optimisationResult.requires, ...(sourceTags ? { sourceTags } : {}), + ...(traversal.frames.length > 0 ? { functions: traversal.frames } : {}), }; const fingerprint = computeBytecodeFingerprintWithConstructorArgs(optimisationResult.script, constructorParamLength); diff --git a/packages/cashc/src/dependency-resolution.ts b/packages/cashc/src/dependency-resolution.ts index c182d5095..7a0246b24 100644 --- a/packages/cashc/src/dependency-resolution.ts +++ b/packages/cashc/src/dependency-resolution.ts @@ -36,7 +36,15 @@ function collectImports( if (visitedPaths.has(absolutePath)) return []; visitedPaths.add(absolutePath); - const importedAst = parseCode(readImportedFile(importNode, absolutePath), options.errorListener); + const importedSource = readImportedFile(importNode, absolutePath); + const importedAst = parseCode(importedSource, options.errorListener); + + // Record source provenance so debug frames can attribute to the imported file + importedAst.functions.forEach((func) => { + func.sourceCode = importedSource; + func.sourceFile = path.basename(absolutePath); + }); + return [...collect(importedAst.imports, path.dirname(absolutePath)), ...importedAst.functions]; }); diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index 73e7e5e2c..07654a0ce 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -1,4 +1,4 @@ -import { hexToBin } from '@bitauth/libauth'; +import { binToHex, hexToBin } from '@bitauth/libauth'; import { asmToScript, encodeBool, @@ -12,7 +12,9 @@ import { scriptToBytecode, optimiseBytecode, generateSourceMap, + generateSourceTags, FullLocationData, + DebugFrame, LogEntry, RequireStatement, PositionHint, @@ -77,6 +79,7 @@ export default class GenerateTargetTraversal extends AstTraversal { consoleLogs: LogEntry[] = []; requires: RequireStatement[] = []; sourceTags: SourceTagEntry[] = []; + frames: DebugFrame[] = []; finalStackUsage: Record = {}; private scopeDepth = 0; @@ -151,7 +154,7 @@ export default class GenerateTargetTraversal extends AstTraversal { private defineGlobalFunctions(node: SourceFileNode): void { node.functions.forEach((func) => { const { functionId } = node.symbolTable!.getFromThis(func.name)!; - const bodyBytecode = this.compileGlobalFunctionBody(func); + const bodyBytecode = this.compileGlobalFunctionBody(func, functionId!); const locationData = { location: func.location, positionHint: PositionHint.START }; this.emit(bodyBytecode, locationData); // @@ -160,7 +163,7 @@ export default class GenerateTargetTraversal extends AstTraversal { }); } - private compileGlobalFunctionBody(node: FunctionDefinitionNode): Uint8Array { + private compileGlobalFunctionBody(node: FunctionDefinitionNode, functionId: number): Uint8Array { const bodyTraversal = new GenerateTargetTraversal(this.compilerOptions); bodyTraversal.currentFunction = node; bodyTraversal.constructorParameterCount = 0; @@ -183,7 +186,23 @@ export default class GenerateTargetTraversal extends AstTraversal { 0, ); - return scriptToBytecode(optimised.script); + 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; } cleanGlobalFunctionStack(node: FunctionDefinitionNode): void { diff --git a/packages/cashc/test/ast/Location.test.ts b/packages/cashc/test/ast/Location.test.ts index 65894d305..ebae658fa 100644 --- a/packages/cashc/test/ast/Location.test.ts +++ b/packages/cashc/test/ast/Location.test.ts @@ -1,9 +1,6 @@ import fs from 'fs'; import { URL } from 'url'; -import { compileString } from '../../src/compiler.js'; import { parseCode } from '../../src/parser.js'; -import { buildLineToAsmMap, bytecodeToAsm, bytecodeToScript } from '@cashscript/utils'; -import { hexToBin } from '@bitauth/libauth'; describe('Location', () => { it('should retrieve correct text from location', () => { @@ -16,71 +13,6 @@ describe('Location', () => { expect((f.location).text(code)).toEqual('function hello(sig s, pubkey pk) {\n require(checkSig(s, pk));\n }'); }); - const wrap = (code: string): string => { - return ` -contract test() { - function test() { - require(${code}); - } -}`; - }; - - describe('Line to ASM map generation', () => { - const blocks = [ - '1 < 1', '1 <= 1', '1 == 1', '1 != 1', '1 > 1', '1 >= 1', - '(1 - 1) == 1', '(1 + 1) == 1', '(1 * 1) == 1', '(1 / 1) == 1', - '(true && true) == true', '(true || true) == true', - '(0x01 & 0x01) == 0x01', '(0x01 | 0x01) == 0x01', '(0x01 ^ 0x01) == 0x01', - '"1" + "1" == "1"', '"1" + "1" != "1"', '"11".split(1)[0] == "1"', '"11".split(1)[1] == "1"', - '"1".reverse() == "1"', '"1".length == 1', '0x01.length == 1', '-333 == 1', - 'tx.inputs[0].tokenAmount == 1', - 'this.activeInputIndex == 1', 'tx.version == 1', - 'abs(-1) == 1', 'within(1,1,1) == true', 'bytes(sha256(1)) == bytes(0x01)', - 'checkSig(sig(0x00), pubkey(0x00))', 'checkMultiSig([sig(0x00), sig(0x00)], [pubkey(0x00), pubkey(0x00)])', - 'checkDataSig(datasig(0x00), 0x00, pubkey(0x00))', - 'tx.time >= 1', 'this.age >= 1', - 'bytes(1) == 0x01', 'int(0x01) == 1', - ]; - - blocks.forEach(block => { - it(`it should generate the same bytecode using line-to-asm map as the regular compiler for: ${block}`, () => { - { - const source = wrap(block); - - // Compile the source code using regular CashScript compilation - const artifact = compileString(source); - const expected = bytecodeToAsm(hexToBin(artifact.debug!.bytecode)); - - // Generate the line-to-asm map from the source code - const opCodeMap = buildLineToAsmMap( - bytecodeToScript(hexToBin(artifact.debug!.bytecode)), artifact.debug!.sourceMap, - ); - - // Convert the line-to-asm map to CashScript bytecode to make sure that the generated opcode map matches the - // bytecode generated by CashScript - const received = Object.values(opCodeMap).join(' ') - .replaceAll('<0x', '').replaceAll('>', '').replace(/\s+/g, ' '); - expect(received).toBe(expected); - } - - // Repeat the tests with the source code modified to test the position hint functionality - { - const source = wrap(block.replaceAll(' ', '\n').replaceAll(')', '\n)')) - .replaceAll('(\n)', '()').replace(/\((?!\))/g, '(\n'); - const artifact = compileString(source); - const expected = bytecodeToAsm(hexToBin(artifact.debug!.bytecode)); - const opCodeMap = buildLineToAsmMap( - bytecodeToScript(hexToBin(artifact.debug!.bytecode)), artifact.debug!.sourceMap, - ); - - const received = Object.values(opCodeMap).join(' ') - .replaceAll('<0x', '').replaceAll('>', '').replace(/\s+/g, ' '); - expect(received).toBe(expected); - } - }); - }); - }); - it('should set the correct location points', () => { const code = fs.readFileSync(new URL('../valid-contract-files/simple_functions.cash', import.meta.url), { encoding: 'utf-8' }); const ast = parseCode(code); diff --git a/packages/cashc/test/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts index a8a6c2eca..a22d77437 100644 --- a/packages/cashc/test/generation/fixtures.ts +++ b/packages/cashc/test/generation/fixtures.ts @@ -1427,6 +1427,17 @@ export const fixtures: Fixture[] = [ { ip: 7, line: 7 }, ], sourceMap: '1::3:1;;::::1;7:16:7:25;;:29::30:0;:8::32:1', + functions: [ + { + id: 0, + name: 'double', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '5295', + sourceMap: '2:15:2:16;:11:::1', + logs: [], + requires: [], + }, + ], }, source: fs.readFileSync(new URL('../valid-contract-files/global_function_simple.cash', import.meta.url), { encoding: 'utf-8' }), compiler: { @@ -1461,6 +1472,17 @@ export const fixtures: Fixture[] = [ { ip: 8, line: 7 }, ], sourceMap: '1::3:1;;::::1;7:23:7:24:0;:16::25:1;;: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', + logs: [], + requires: [], + }, + ], }, source: fs.readFileSync(new URL('../valid-contract-files/global_function_multi_param.cash', import.meta.url), { encoding: 'utf-8' }), compiler: { @@ -1494,6 +1516,17 @@ export const fixtures: Fixture[] = [ { ip: 8, line: 8 }, ], sourceMap: '1::3:1;;::::1;7:24:7:25:0;:8::26:1;;8:20:8:23:0;:8::25:1', + functions: [ + { + id: 0, + name: 'requirePositive', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '00a069', + sourceMap: '2:16:2:17;:12:::1;:4::19', + logs: [], + requires: [{ ip: 2, line: 2 }], + }, + ], }, source: fs.readFileSync(new URL('../valid-contract-files/global_function_void.cash', import.meta.url), { encoding: 'utf-8' }), compiler: { @@ -1533,6 +1566,41 @@ export const fixtures: Fixture[] = [ { ip: 18, line: 6 }, ], sourceMap: '2::4:1;;::::1;1::3::0;;::::1;2::4::0;;::::1;6:19:6:20:0;:16::21:1;;:27::28:0;:24::29:1;;:16;:33::35:0;:8::37:1', + functions: [ + { + id: 0, + name: 'm1', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '518a5295', + sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', + logs: [], + requires: [], + source: fs.readFileSync(new URL('../import-fixtures/mid1.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'mid1.cash', + }, + { + id: 1, + name: 'leaf', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '8b', + sourceMap: '2:11:2:16:1', + logs: [], + requires: [], + source: fs.readFileSync(new URL('../import-fixtures/leaf.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'leaf.cash', + }, + { + id: 2, + name: 'm2', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '518a5393', + sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', + logs: [], + requires: [], + source: fs.readFileSync(new URL('../import-fixtures/mid2.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'mid2.cash', + }, + ], }, source: fs.readFileSync(new URL('../import-fixtures/diamond.cash', import.meta.url), { encoding: 'utf-8' }), compiler: { diff --git a/packages/cashscript/src/Errors.ts b/packages/cashscript/src/Errors.ts index d23e45f91..85740c714 100644 --- a/packages/cashscript/src/Errors.ts +++ b/packages/cashscript/src/Errors.ts @@ -1,4 +1,5 @@ import { Artifact, RequireStatement, sourceMapToLocationData, Type } from '@cashscript/utils'; +import { ResolvedFrame, rootFrame } from './debug-frame.js'; export class TypeError extends Error { constructor(actual: string, expected: Type) { @@ -134,12 +135,15 @@ export class FailedTransactionEvaluationError extends FailedTransactionError { public inputIndex: number, public bitauthUri: string, public libauthErrorMessage: string, + frame?: ResolvedFrame, ) { let message = `${artifact.contractName}.cash Error in transaction at input ${inputIndex} in contract ${artifact.contractName}.cash.\nReason: ${libauthErrorMessage}`; if (artifact.debug) { - const { statement, lineNumber } = getLocationDataForInstructionPointer(artifact, failingInstructionPointer); - message = `${artifact.contractName}.cash:${lineNumber} Error in transaction at input ${inputIndex} in contract ${artifact.contractName}.cash at line ${lineNumber}.\nReason: ${libauthErrorMessage}\nFailing statement: ${statement}`; + const resolvedFrame = frame ?? rootFrame(artifact); + const { statement, lineNumber } = getLocationDataForFrame(resolvedFrame, failingInstructionPointer); + const context = formatFrameContext(resolvedFrame, artifact.contractName, lineNumber); + message = `${resolvedFrame.sourceName}:${lineNumber} Error in transaction at input ${inputIndex} ${context}.\nReason: ${libauthErrorMessage}\nFailing statement: ${statement}`; } super(message, bitauthUri); @@ -154,10 +158,13 @@ export class FailedRequireError extends FailedTransactionError { public inputIndex: number, public bitauthUri: string, public libauthErrorMessage?: string, + frame?: ResolvedFrame, ) { - const { statement, lineNumber } = getLocationDataForInstructionPointer(artifact, failingInstructionPointer); + const resolvedFrame = frame ?? rootFrame(artifact); + const { statement, lineNumber } = getLocationDataForFrame(resolvedFrame, failingInstructionPointer); + const context = formatFrameContext(resolvedFrame, artifact.contractName, lineNumber); - const baseMessage = `${artifact.contractName}.cash:${lineNumber} Require statement failed at input ${inputIndex} in contract ${artifact.contractName}.cash at line ${lineNumber}`; + const baseMessage = `${resolvedFrame.sourceName}:${lineNumber} Require statement failed at input ${inputIndex} ${context}`; const baseMessageWithRequireMessage = `${baseMessage} with the following message: ${requireStatement.message}`; const headline = `${requireStatement.message ? baseMessageWithRequireMessage : baseMessage}.`; @@ -169,19 +176,28 @@ export class FailedRequireError extends FailedTransactionError { } } -const getLocationDataForInstructionPointer = ( - artifact: Artifact, +const formatFrameContext = (frame: ResolvedFrame, contractName: string, lineNumber: number): string => { + if (frame.functionName) { + return `in contract ${contractName}, function ${frame.functionName} (${frame.sourceName}, line ${lineNumber})`; + } + + return `in contract ${contractName}.cash at line ${lineNumber}`; +}; + +const getLocationDataForFrame = ( + frame: ResolvedFrame, instructionPointer: number, ): { lineNumber: number, statement: string } => { - const locationData = sourceMapToLocationData(artifact.debug!.sourceMap); + const locationData = sourceMapToLocationData(frame.sourceMap); - // We subtract the constructor inputs because these are present in the evaluation (and thus the instruction pointer) - // but they are not present in the source code (and thus the location data) - const modifiedInstructionPointer = instructionPointer - artifact.constructorInputs.length; + // We subtract the frame's ip offset (the constructor-arg prefix for the root frame, 0 for helper + // frames) because those pushes are present in the evaluation (and thus the instruction pointer) but + // not in the source code (and thus the location data). + const modifiedInstructionPointer = instructionPointer - frame.ipOffset; const { location } = locationData[modifiedInstructionPointer]; - const failingLines = artifact.source.split('\n').slice(location.start.line - 1, location.end.line); + const failingLines = frame.source.split('\n').slice(location.start.line - 1, location.end.line); // Slice off the start and end of the statement's start and end lines to only return the failing part // Note that we first slice off the end, to avoid shifting the end column index diff --git a/packages/cashscript/src/debug-frame.ts b/packages/cashscript/src/debug-frame.ts new file mode 100644 index 000000000..5ec61c830 --- /dev/null +++ b/packages/cashscript/src/debug-frame.ts @@ -0,0 +1,45 @@ +import { AuthenticationProgramStateCommon, binToHex, encodeAuthenticationInstructions } from '@bitauth/libauth'; +import { Artifact, LogEntry, RequireStatement } from '@cashscript/utils'; + +export interface ResolvedFrame { + sourceMap: string; + source: string; + sourceName: string; + ipOffset: number; + requires: readonly RequireStatement[]; + logs: readonly LogEntry[]; + functionName?: string; +} + +export const rootFrame = (artifact: Artifact): ResolvedFrame => ({ + sourceMap: artifact.debug?.sourceMap ?? '', + source: artifact.source, + sourceName: `${artifact.contractName}.cash`, + ipOffset: artifact.constructorInputs.length, + requires: artifact.debug?.requires ?? [], + logs: artifact.debug?.logs ?? [], +}); + +export const getActiveBytecode = (step: AuthenticationProgramStateCommon): string => + binToHex(encodeAuthenticationInstructions(step.instructions)); + +export const resolveFrame = ( + artifact: Artifact, + step: AuthenticationProgramStateCommon, +): ResolvedFrame => { + const frames = artifact.debug?.functions ?? []; + const activeBytecode = frames.length > 0 ? getActiveBytecode(step) : undefined; + const frame = frames.find((candidate) => candidate.bytecode === activeBytecode); + + if (!frame) return rootFrame(artifact); + + return { + sourceMap: frame.sourceMap, + source: frame.source ?? artifact.source, + sourceName: frame.sourceFile ?? `${artifact.contractName}.cash`, + ipOffset: 0, // function bodies have no constructor-arg prefix; their ips start at 0 + requires: frame.requires, + logs: frame.logs, + ...(frame.sourceFile !== undefined ? { functionName: frame.name } : {}), + }; +}; diff --git a/packages/cashscript/src/debugging.ts b/packages/cashscript/src/debugging.ts index d5bf39918..cbbeb4bc6 100644 --- a/packages/cashscript/src/debugging.ts +++ b/packages/cashscript/src/debugging.ts @@ -2,6 +2,7 @@ import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationPro import { Artifact, LogData, LogEntry, Op, PrimitiveType, StackItem, asmToBytecode, bytecodeToAsm, decodeBool, decodeInt, decodeString } from '@cashscript/utils'; import { findLastIndex, toRegExp } from './utils.js'; import { FailedRequireError, FailedTransactionError, FailedTransactionEvaluationError } from './Errors.js'; +import { getActiveBytecode, resolveFrame } from './debug-frame.js'; import { getBitauthUri } from './libauth-template/LibauthTemplate.js'; import { VmTarget } from './interfaces.js'; @@ -72,7 +73,11 @@ const debugSingleScenario = ( // P2SH executions have 3 phases, we only want the last one (locking script execution) // https://libauth.org/types/AuthenticationVirtualMachine.html#__type.debug - const lockingScriptDebugResult = fullDebugSteps.slice(findLastIndex(fullDebugSteps, (state) => state.ip === 0)); + // We additionally require an empty control stack: an invoked function body (OP_INVOKE) also starts at + // ip 0, but always with a saved return frame on the control stack. + const lockingScriptDebugResult = fullDebugSteps.slice( + findLastIndex(fullDebugSteps, (state) => state.ip === 0 && state.controlStack.length === 0), + ); // The controlStack determines whether the current debug step is in the executed branch // It also tracks loop / function usage, but for the purpose of determining whether a step was executed, @@ -84,26 +89,29 @@ const debugSingleScenario = ( // P2PKH inputs do not have an artifact, so we skip the console.log handling if (artifact) { - // Try to match each executed debug step to a log entry if it exists. Note that inside loops, - // the same log statement may be executed multiple times in different debug steps - // Also note that multiple log statements may exist for the same ip, so we need to handle all of them + // Try to match each executed debug step to a log entry if it exists. Notes: + // - inside loops, the same log statement may be executed multiple times in different debug steps + // - the same ip may be executed by multiple function frames, so they are matched against the active frame's logs. + // - multiple log statements may exist for the same ip, so we need to handle all of them. const executedLogs = executedDebugSteps .flatMap((debugStep, index) => { - const logEntries = artifact.debug?.logs?.filter((log) => log.ip === debugStep.ip); - if (!logEntries || logEntries.length === 0) return []; + const frame = resolveFrame(artifact, debugStep); + const logEntries = frame.logs.filter((log) => log.ip === debugStep.ip); + if (logEntries.length === 0) return []; const reversedPriorDebugSteps = executedDebugSteps.slice(0, index + 1).reverse(); + const frameBytecode = getActiveBytecode(debugStep); return logEntries.map((logEntry) => { const decodedLogData = logEntry.data - .map((dataEntry) => decodeLogDataEntry(dataEntry, reversedPriorDebugSteps, vm)); - return { logEntry, decodedLogData }; + .map((dataEntry) => decodeLogDataEntry(dataEntry, reversedPriorDebugSteps, vm, frameBytecode)); + return { logEntry, decodedLogData, sourceName: frame.sourceName }; }); }); - for (const { logEntry, decodedLogData } of executedLogs) { + for (const { logEntry, decodedLogData, sourceName } of executedLogs) { const inputIndex = extractInputIndexFromScenario(scenarioId); - logConsoleLogStatement(logEntry, decodedLogData, artifact.contractName, inputIndex); + logConsoleLogStatement(logEntry, decodedLogData, sourceName, inputIndex); } } @@ -135,19 +143,19 @@ const debugSingleScenario = ( throw new FailedTransactionError(error, getBitauthUri(template)); } - const requireStatement = (artifact.debug?.requires ?? []) - .find((statement) => statement.ip === requireStatementIp); + const frame = resolveFrame(artifact, lastExecutedDebugStep); + const requireStatement = frame.requires.find((statement) => statement.ip === requireStatementIp); if (requireStatement) { // Note that we use failingIp here rather than requireStatementIp, see comment above throw new FailedRequireError( - artifact, failingIp, requireStatement, inputIndex, getBitauthUri(template), error, + artifact, failingIp, requireStatement, inputIndex, getBitauthUri(template), error, frame, ); } // Note that we use failingIp here rather than requireStatementIp, see comment above throw new FailedTransactionEvaluationError( - artifact, failingIp, inputIndex, getBitauthUri(template), error, + artifact, failingIp, inputIndex, getBitauthUri(template), error, frame, ); } @@ -175,17 +183,17 @@ const debugSingleScenario = ( throw new FailedTransactionError(evaluationResult, getBitauthUri(template)); } - const requireStatement = (artifact.debug?.requires ?? []) - .find((message) => message.ip === finalExecutedVerifyIp); + const frame = resolveFrame(artifact, lastExecutedDebugStep); + const requireStatement = frame.requires.find((message) => message.ip === finalExecutedVerifyIp); if (requireStatement) { throw new FailedRequireError( - artifact, sourcemapInstructionPointer, requireStatement, inputIndex, getBitauthUri(template), + artifact, sourcemapInstructionPointer, requireStatement, inputIndex, getBitauthUri(template), undefined, frame, ); } throw new FailedTransactionEvaluationError( - artifact, sourcemapInstructionPointer, inputIndex, getBitauthUri(template), evaluationResult, + artifact, sourcemapInstructionPointer, inputIndex, getBitauthUri(template), evaluationResult, frame, ); } @@ -236,20 +244,23 @@ const createProgram = (template: WalletTemplate, unlockingScriptId: string, scen const logConsoleLogStatement = ( log: LogEntry, decodedLogData: Array, - contractName: string, + sourceName: string, inputIndex: number, ): void => { - console.log(`[Input #${inputIndex}] ${contractName}.cash:${log.line} ${decodedLogData.join(' ')}`); + console.log(`[Input #${inputIndex}] ${sourceName}:${log.line} ${decodedLogData.join(' ')}`); }; const decodeLogDataEntry = ( dataEntry: LogData, reversedPriorDebugSteps: AuthenticationProgramStateCommon[], vm: VM, + frameBytecode: string, ): string | bigint | boolean => { if (typeof dataEntry === 'string') return dataEntry; - const dataEntryDebugStep = reversedPriorDebugSteps.find((step) => step.ip === dataEntry.ip); + const dataEntryDebugStep = reversedPriorDebugSteps.find( + (step) => step.ip === dataEntry.ip && getActiveBytecode(step) === frameBytecode, + ); if (!dataEntryDebugStep) { throw new Error(`Should not happen: corresponding data entry debug step not found for entry at ip ${dataEntry.ip}`); diff --git a/packages/cashscript/src/libauth-template/utils.ts b/packages/cashscript/src/libauth-template/utils.ts index df817f3aa..a987e61d8 100644 --- a/packages/cashscript/src/libauth-template/utils.ts +++ b/packages/cashscript/src/libauth-template/utils.ts @@ -1,4 +1,4 @@ -import { AbiFunction, AbiInput, Artifact, bytecodeToScript, formatBitAuthScript, sha256 } from '@cashscript/utils'; +import { AbiFunction, AbiInput, Artifact, formatBitAuthScript, sha256 } from '@cashscript/utils'; import { HashType, LibauthTokenDetails, SignatureAlgorithm, TokenDetails, VmTarget } from '../interfaces.js'; import { hexToBin, binToHex, isHex, decodeCashAddress, Input, assertSuccess, decodeAuthenticationInstructions, AuthenticationInstructionPush } from '@bitauth/libauth'; import { EncodedFunctionArgument } from '../Argument.js'; @@ -77,6 +77,7 @@ export const formatParametersForDebugging = (types: readonly AbiInput[], args: E }; export const formatBytecodeForDebugging = (artifact: Artifact): string => { + // Old artifacts carry no debug information, so we render the raw bytecode in execution order if (!artifact.debug) { return artifact.bytecode .split(' ') @@ -84,12 +85,7 @@ export const formatBytecodeForDebugging = (artifact: Artifact): string => { .join('\n'); } - return formatBitAuthScript( - bytecodeToScript(hexToBin(artifact.debug.bytecode)), - artifact.debug.sourceMap, - artifact.source, - artifact.debug.sourceTags, - ); + return formatBitAuthScript(artifact.debug, artifact.source); }; export const serialiseTokenDetails = ( diff --git a/packages/cashscript/test/debugging.test.ts b/packages/cashscript/test/debugging.test.ts index 441afcabd..408109291 100644 --- a/packages/cashscript/test/debugging.test.ts +++ b/packages/cashscript/test/debugging.test.ts @@ -1,5 +1,5 @@ import { Contract, FailedTransactionError, MockNetworkProvider, SignatureAlgorithm, SignatureTemplate, TransactionBuilder, VmTarget } from '../src/index.js'; -import { DEFAULT_VM_TARGET } from '../src/libauth-template/utils.js'; +import { DEFAULT_VM_TARGET, getLockScriptName } from '../src/libauth-template/utils.js'; import { aliceAddress, alicePriv, alicePub, bobPriv, bobPub } from './fixture/vars.js'; import { randomUtxo } from '../src/utils.js'; import { AuthenticationErrorCommon, binToHex, hexToBin } from '@bitauth/libauth'; @@ -14,6 +14,9 @@ import { artifactTestZeroHandling, artifactTestRequireInsideLoop, artifactTestLogInsideLoop, + artifactTestFunctionDebugging, + artifactTestFunctionIntermediateResults, + artifactTestImportedFunctionDebugging, } from './fixture/debugging/debugging_contracts.js'; import { sha256 } from '@cashscript/utils'; @@ -814,3 +817,87 @@ describe('VM Resources', () => { expect(vmUsage[2]?.hashDigestIterations).toBeGreaterThan(0); }); }); + +describe('Debugging tests - user-defined function frames', () => { + const provider = new MockNetworkProvider(); + + 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()); + + it('attributes a console.log inside a function to the function source line', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(contractUtxo, contract.unlock.spend(5n)) + .addOutput({ to: contract.address, amount: 10000n }); + + expect(transaction).toLog(new RegExp('^\\[Input #0] Test.cash:3 checking 5$')); + }); + + it('attributes a require failing inside a function to the function source line', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(contractUtxo, contract.unlock.spend(0n)) + .addOutput({ to: contract.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('still attributes a contract-level require to the contract source line', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(contractUtxo, contract.unlock.spend(100n)) + .addOutput({ to: contract.address, amount: 10000n }); + + expect(transaction).toFailRequireWith('Test.cash:10 Require statement failed at input 0 in contract Test.cash at line 10 with the following message: x must be small.'); + 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', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(importedUtxo, importedContract.unlock.spend(0n)) + .addOutput({ to: importedContract.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")'); + }); + + it('logs intermediate results that get optimised out inside a function', () => { + const intermediateContract = new Contract(artifactTestFunctionIntermediateResults, [alicePub], { provider }); + const intermediateUtxo = provider.addUtxo(intermediateContract.address, randomUtxo()); + + const transaction = new TransactionBuilder({ provider }) + .addInput(intermediateUtxo, intermediateContract.unlock.spend()) + .addOutput({ to: intermediateContract.address, amount: 10000n }); + + const expectedHash = binToHex(sha256(alicePub)); + expect(transaction).toLog(new RegExp(`^\\[Input #0] Test.cash:4 0x${expectedHash}$`)); + }); + + 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 }); + + const template = transaction.getLibauthTemplate(); + const lockScript = template.scripts[getLockScriptName(contract)].script; + + // The function body is rendered as a `<...>` push group annotated with its own source lines + expect(lockScript).toContain('/* function checkValue(int value) {'); + expect(lockScript).toContain('> OP_0 OP_DEFINE'); + expect(lockScript).toContain('OP_0 OP_INVOKE'); + }); + + 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 }); + + const template = transaction.getLibauthTemplate(); + const lockScript = template.scripts[getLockScriptName(importedContract)].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'); + }); +}); diff --git a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts index be048ef29..a54f7604d 100644 --- a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts +++ b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts @@ -1,4 +1,33 @@ -import { compileString } from 'cashc'; +import { compileFile, compileString } from 'cashc'; + +const CONTRACT_TEST_FUNCTION_DEBUGGING = ` +function checkValue(int value) { + console.log("checking", value); + require(value > 0, "value must be positive"); +} + +contract Test() { + function spend(int x) { + checkValue(x); + require(x < 100, "x must be small"); + } +} +`; + +const CONTRACT_TEST_FUNCTION_INTERMEDIATE_RESULTS = ` +function hashTwice(pubkey pk) returns (bytes32) { + bytes32 singleHash = sha256(pk); + console.log(singleHash); + bytes32 doubleHash = sha256(singleHash); + return doubleHash; +} + +contract Test(pubkey owner) { + function spend() { + require(hashTwice(owner).length == 32, "should be 32 bytes"); + } +} +`; const CONTRACT_TEST_REQUIRES = ` contract Test() { @@ -437,3 +466,8 @@ export const artifactTestMultipleLogs = compileString(CONTRACT_TEST_MULTIPLE_LOG export const artifactTestMultipleConstructorParameters = compileString(CONTRACT_TEST_MULTIPLE_CONSTRUCTOR_PARAMETERS); export const artifactTestRequireInsideLoop = compileString(CONTRACT_TEST_REQUIRE_INSIDE_LOOP); export const artifactTestLogInsideLoop = compileString(CONTRACT_TEST_LOG_INSIDE_LOOP); +export const artifactTestFunctionDebugging = compileString(CONTRACT_TEST_FUNCTION_DEBUGGING); +export const artifactTestFunctionIntermediateResults = compileString(CONTRACT_TEST_FUNCTION_INTERMEDIATE_RESULTS); + +// 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)); diff --git a/packages/cashscript/test/fixture/debugging/function_helpers.cash b/packages/cashscript/test/fixture/debugging/function_helpers.cash new file mode 100644 index 000000000..f031f25c0 --- /dev/null +++ b/packages/cashscript/test/fixture/debugging/function_helpers.cash @@ -0,0 +1,3 @@ +function assertPositive(int value) { + require(value > 0, "value must be positive"); +} diff --git a/packages/cashscript/test/fixture/debugging/function_importer.cash b/packages/cashscript/test/fixture/debugging/function_importer.cash new file mode 100644 index 000000000..eac2e4b41 --- /dev/null +++ b/packages/cashscript/test/fixture/debugging/function_importer.cash @@ -0,0 +1,8 @@ +import "./function_helpers.cash"; + +contract Test() { + function spend(int x) { + assertPositive(x); + require(x < 100, "x must be small"); + } +} diff --git a/packages/utils/src/artifact.ts b/packages/utils/src/artifact.ts index 733a67618..040c3b474 100644 --- a/packages/utils/src/artifact.ts +++ b/packages/utils/src/artifact.ts @@ -19,6 +19,20 @@ export interface DebugInformation { logs: readonly LogEntry[]; // log entries generated from `console.log` statements requires: readonly RequireStatement[]; // messages for failing `require` statements sourceTags?: string; // semantic tags for opcodes (e.g. loop update/condition ranges) + functions?: readonly DebugFrame[]; // Debug metadata for each user-defined function +} + +export interface DebugFrame { + id: number; // the function's id, as used with OP_DEFINE and OP_INVOKE in the bytecode + name: string; // the function's name + inputs: readonly AbiInput[]; // the function's parameters (name and type), mirroring the ABI; for reference + bytecode: string; // hex of the function body bytecode (exactly what OP_DEFINE stores and the VM runs) + sourceMap: string; // frame-local source map (ips starting from 0) + sourceTags?: string; // frame-local semantic tags for opcodes (e.g. loop update/condition ranges) + source?: string; // full text of the defining file; absent means the function lives in the contract's own source file + sourceFile?: string; // originating file name for imported functions; absent means the contract's file + logs: readonly LogEntry[]; // frame-local log entries + requires: readonly RequireStatement[]; // frame-local require statements } export interface LogEntry { diff --git a/packages/utils/src/bitauth-script.ts b/packages/utils/src/bitauth-script.ts index 9cd3aab5e..b2aee008e 100644 --- a/packages/utils/src/bitauth-script.ts +++ b/packages/utils/src/bitauth-script.ts @@ -1,60 +1,263 @@ -import { range } from './data.js'; -import { Script, scriptToBitAuthAsm } from './script.js'; +import { hexToBin } from '@bitauth/libauth'; +import { DebugFrame, DebugInformation } from './artifact.js'; +import { encodeInt, range } from './data.js'; +import { Op, Script, bytecodeToScript, scriptToBitAuthAsm } from './script.js'; import { parseSourceTags, sourceMapToLocationData } from './source-map.js'; -import { FullLocationData, PositionHint, SingleLocationData, SourceTagEntry, SourceTagKind } from './types.js'; +import { FullLocationData, LocationI, PositionHint, SingleLocationData, SourceTagEntry, SourceTagKind } from './types.js'; -export type LineToOpcodesMap = Record; -export type LineToAsmMap = Record; +export function formatBitAuthScript(debug: DebugInformation, sourceCode: string): string { + const sourceLines = sourceCode.split('\n'); -export function buildLineToOpcodesMap( - bytecode: Script, - sourceMapOrLocationData: string | FullLocationData, -): LineToOpcodesMap { - const locationData = typeof sourceMapOrLocationData === 'string' ? sourceMapToLocationData(sourceMapOrLocationData) : sourceMapOrLocationData; + const rows = walkScript({ + script: bytecodeToScript(hexToBin(debug.bytecode)), + sourceMap: debug.sourceMap, + sourceTags: debug.sourceTags, + functions: debug.functions, + sourceLines, + startLine: 1, + endLine: sourceLines.length, + asmIndent: '', + }); - return locationData.reduce((lineToOpcodeMap, singleLocation, index) => { - const opcode = bytecode[index]; - const line = getDisplayLine(singleLocation); + return renderRows(rows); +} - return { - ...lineToOpcodeMap, - [line]: [...(lineToOpcodeMap[line] || []), opcode], - }; - }, {}); +interface WalkParams { + script: Script; + sourceMap: string; + sourceTags?: string; + functions?: readonly DebugFrame[]; + sourceLines: string[]; + startLine: number; + endLine: number; + asmIndent: string; +} + +function walkScript(params: WalkParams): Row[] { + const segments = segmentScript(params); + return renderSegments(segments, params); +} + +interface LineGroupSegment { + kind: 'lineGroup'; + asm: string; + line: number; +} + +interface AnnotationSegment { + kind: 'annotation'; + asm: string; + comment: string; + insertAfterLine: number; +} + +interface FunctionDefinitionSegment { + kind: 'functionDefinition'; + frame: DebugFrame; + location: LocationI; +} + +type Segment = LineGroupSegment | AnnotationSegment | FunctionDefinitionSegment; + +function segmentScript(params: WalkParams): Segment[] { + const { script, sourceLines } = params; + const locationData = sourceMapToLocationData(params.sourceMap); + const tags = parseSourceTags(params.sourceTags ?? ''); + const frames = params.functions ?? []; + + const segments: Segment[] = []; + let index = 0; + + while (index < script.length) { + // Function definitions are always at the start of the script in sets of three: ` OP_DEFINE` per frame + if (index < frames.length * 3) { + segments.push({ kind: 'functionDefinition', frame: frames[index / 3], location: locationData[index].location }); + index += 3; + continue; + } + + const tag = findTagAt(tags, index); + if (tag) { + segments.push(annotationSegment(script, tag, tags, locationData, sourceLines)); + index = tag.endIndex + 1; + continue; + } + + const endIndex = findLineGroupEnd(script, index, locationData, tags); + segments.push({ kind: 'lineGroup', asm: scriptToBitAuthAsm(script.slice(index, endIndex)), line: getDisplayLine(locationData[index]) }); + index = endIndex; + } + + return segments; +} + +function annotationSegment( + script: Script, + tag: SourceTagEntry, + tags: SourceTagEntry[], + locationData: FullLocationData, + sourceLines: string[], +): AnnotationSegment { + const { insertAfterLine, indent } = deriveAnchor(tag, tags, locationData, sourceLines); + + return { + kind: 'annotation', + asm: scriptToBitAuthAsm(script.slice(tag.startIndex, tag.endIndex + 1)), + comment: `${indent}${tagDescription(tag, locationData, sourceLines)}`, + insertAfterLine, + }; +} + +// A line group runs until the next opcode that belongs to a tagged range or maps to a different source line +function findLineGroupEnd(script: Script, start: number, locationData: FullLocationData, tags: SourceTagEntry[]): number { + const line = getDisplayLine(locationData[start]); + const nextBoundary = range(start + 1, script.length - 1).find((index) => ( + getDisplayLine(locationData[index]) !== line || findTagAt(tags, index) !== undefined + )); + + return nextBoundary ?? script.length; +} + +function findTagAt(tags: SourceTagEntry[], index: number): SourceTagEntry | undefined { + return tags.find((tag) => index >= tag.startIndex && index <= tag.endIndex); +} + +interface Row { + asm: string; + comment: string; } -export function buildLineToAsmMap(bytecode: Script, sourceMapOrLocationData: string | FullLocationData): LineToAsmMap { - const lineToOpcodesMap = buildLineToOpcodesMap(bytecode, sourceMapOrLocationData); +interface RenderState { + rows: Row[]; + lastRenderedLine: number; // the last source line that has been rendered +} + +type RenderContext = WalkParams & { + functionSectionLines: Set; // source lines rendered inside function sections, never as filler +}; + +const BLANK_ROW: Row = { asm: '', comment: '' }; + +function renderSegments(segments: Segment[], params: WalkParams): Row[] { + const context: RenderContext = { + ...params, + functionSectionLines: deriveFunctionSectionLines(segments, params.sourceLines), + }; + + const initialState: RenderState = { rows: [], lastRenderedLine: params.startLine - 1 }; + const finalState = segments.reduce((state, segment) => renderSegment(state, segment, context), initialState); + + // After the last opcode, fill in the remaining source lines (e.g. the contract's closing braces) + return [...finalState.rows, ...fillerRows(finalState.lastRenderedLine, params.endLine, context)]; +} - return Object.fromEntries( - Object.entries(lineToOpcodesMap).map(([lineNumber, opcodeList]) => [lineNumber, scriptToBitAuthAsm(opcodeList)]), +function deriveFunctionSectionLines(segments: Segment[], sourceLines: string[]): Set { + const localFunctionSegments = segments.filter( + (segment): segment is FunctionDefinitionSegment => segment.kind === 'functionDefinition' && segment.frame.source === undefined, ); + + return new Set(localFunctionSegments.flatMap(({ location }) => { + let lastLine = location.end.line; + while (lastLine < sourceLines.length && sourceLines[lastLine].trim() === '') lastLine += 1; + return range(location.start.line, lastLine); + })); } -export function formatBitAuthScript(bytecode: Script, sourceMap: string, sourceCode: string, sourceTags?: string): string { - const locationData = sourceMapToLocationData(sourceMap); - const sourceLines = sourceCode.split('\n'); +function renderSegment(state: RenderState, segment: Segment, context: RenderContext): RenderState { + if (segment.kind === 'functionDefinition') return renderFunctionDefinition(state, segment, context); + if (segment.kind === 'annotation') return renderAnnotation(state, segment, context); + return renderLineGroup(state, segment, context); +} + +// The group's row renders its own source line, after filling in the opcode-less lines above it +function renderLineGroup(state: RenderState, segment: LineGroupSegment, context: RenderContext): RenderState { + return { + rows: [ + ...state.rows, + ...fillerRows(state.lastRenderedLine, segment.line - 1, context), + { asm: context.asmIndent + segment.asm, comment: context.sourceLines[segment.line - 1] }, + ], + lastRenderedLine: advanceTo(state.lastRenderedLine, segment.line, context), + }; +} + +// The `>>>` annotation row lands right after its anchor line +function renderAnnotation(state: RenderState, segment: AnnotationSegment, context: RenderContext): RenderState { + return { + rows: [ + ...state.rows, + ...fillerRows(state.lastRenderedLine, segment.insertAfterLine, context), + { asm: context.asmIndent + segment.asm, comment: segment.comment }, + ], + lastRenderedLine: advanceTo(state.lastRenderedLine, segment.insertAfterLine, context), + }; +} + +function renderFunctionDefinition( + state: RenderState, + segment: FunctionDefinitionSegment, + context: RenderContext, +): RenderState { + const { frame, location } = segment; + const isImported = frame.sourceFile !== undefined; + const sourceLines = isImported ? frame.source!.split('\n') : context.sourceLines; + + const headerRows = isImported + ? [{ asm: '', comment: `>>> function ${frame.name} (imported from ${frame.sourceFile})` }] + : []; + + return { + rows: [...state.rows, ...headerRows, ...buildFunctionSection(frame, location, sourceLines), BLANK_ROW], + lastRenderedLine: state.lastRenderedLine, + }; +} + +function buildFunctionSection(frame: DebugFrame, location: LocationI, sourceLines: string[]): Row[] { + const bodyScript = bytecodeToScript(hexToBin(frame.bytecode)); + const defineAsm = scriptToBitAuthAsm([encodeInt(BigInt(frame.id)), Op.OP_DEFINE]); + const { start, end } = location; - // Splice synthetic annotation lines (e.g. for-loop updates) into source and remap opcode lines - const insertions = buildInsertions(locationData, sourceLines, sourceTags); - const splicedSourceLines = spliceSyntheticSourceLines(sourceLines, insertions); - const splicedLocationData = updateLocationData(locationData, insertions); + if (end.line === start.line) { + const asm = ['<', scriptToBitAuthAsm(bodyScript), '>', defineAsm].filter((part) => part !== '').join(' '); + return [{ asm, comment: sourceLines[start.line - 1] }]; + } + + const bodyRows = walkScript({ + script: bodyScript, + sourceMap: frame.sourceMap, + sourceTags: frame.sourceTags, + sourceLines, + startLine: start.line + 1, + endLine: end.line - 1, + asmIndent: ' ', + }); - // Group opcodes by display line and convert to ASM - const lineToAsm = buildLineToAsmMap(bytecode, splicedLocationData); + return [ + { asm: '<', comment: sourceLines[start.line - 1] }, + ...bodyRows, + { asm: `> ${defineAsm}`, comment: sourceLines[end.line - 1] }, + ]; +} - // Format output - const escapedLines = splicedSourceLines.map(escapeCommentChars); - const maxAsmLen = Math.max(...escapedLines.map((_, i) => (lineToAsm[i + 1] || '').length)); - const maxSrcLen = Math.max(...escapedLines.map((l) => l.length)); +function fillerRows(afterLine: number, throughLine: number, context: RenderContext): Row[] { + return range(afterLine + 1, Math.min(throughLine, context.endLine)) + .filter((line) => !context.functionSectionLines.has(line)) + .map((line) => ({ asm: '', comment: context.sourceLines[line - 1] })); +} - return escapedLines.map((src, i) => { - const asm = lineToAsm[i + 1] || ''; - return `${asm.padEnd(maxAsmLen)} /* ${src.padEnd(maxSrcLen)} */`; - }).join('\n'); +function advanceTo(renderedLine: number, line: number, context: RenderContext): number { + return Math.max(renderedLine, Math.min(line, context.endLine)); } -// --- Helpers --- +function renderRows(rows: Row[]): string { + const escapedRows = rows.map((row) => ({ asm: row.asm, comment: escapeCommentChars(row.comment) })); + const maxAsmLength = Math.max(...escapedRows.map((row) => row.asm.length)); + const maxCommentLength = Math.max(...escapedRows.map((row) => row.comment.length)); + + return escapedRows + .map((row) => `${row.asm.padEnd(maxAsmLength)} /* ${row.comment.padEnd(maxCommentLength)} */`) + .join('\n'); +} function getDisplayLine(singleLocation: SingleLocationData): number { const { location, positionHint } = singleLocation; @@ -65,16 +268,6 @@ function escapeCommentChars(text: string): string { return text.replaceAll('/*', '\\/*').replaceAll('*/', '*\\/'); } -// --- Source tag handling (for-loop update annotations) --- - -interface Insertion { - insertAfterLine: number; - annotation: string; - startIndex: number; - endIndex: number; -} - -// Where a synthetic annotation line is spliced, and the indentation it's rendered with. interface Anchor { insertAfterLine: number; indent: string; @@ -92,20 +285,6 @@ const EPILOGUE_KINDS = [ SourceTagKind.LOOP_CONDITION, ]; -function buildInsertions( - locationData: FullLocationData, - sourceLines: string[], - sourceTags?: string, -): Insertion[] { - const tags = (sourceTags ? parseSourceTags(sourceTags) : []); - - return tags.map((tag) => { - const { insertAfterLine, indent } = deriveAnchor(tag, tags, locationData, sourceLines); - const annotation = `${indent}${tagDescription(tag, locationData, sourceLines)}`; - return { insertAfterLine, annotation, startIndex: tag.startIndex, endIndex: tag.endIndex }; - }); -} - function deriveAnchor( tag: SourceTagEntry, tags: SourceTagEntry[], @@ -120,15 +299,15 @@ function deriveAnchor( const firstBodyOpcode = lastPrologueOpcode + 1; const firstBodyLine = getDisplayLine(locationData[firstBodyOpcode]); + // `insertAfterLine` of `firstBodyLine - 1` lands all the prologue annotations directly above the + // first body statement, at its indentation. return { - // `insertAfterLine` splices *after* a line, so `firstBodyLine - 1` lands all the prologue - // annotations directly above the first body statement, at its indentation. insertAfterLine: firstBodyLine - 1, indent: lineIndent(sourceLines, firstBodyLine), }; } - // Scope cleanup and loop-back condition tags always get inserted right before the scope's closing brace. + // Scope cleanup and loop-back condition tags always land right before the scope's closing brace. if (EPILOGUE_KINDS.includes(tag.kind)) { const braceLine = getDisplayLine(locationData[tag.startIndex]); return { @@ -143,40 +322,6 @@ function deriveAnchor( }; } -function spliceSyntheticSourceLines(sourceLines: string[], insertions: Insertion[]): string[] { - return insertions.reduceRight( - (lines, ins) => [...lines.slice(0, ins.insertAfterLine), ins.annotation, ...lines.slice(ins.insertAfterLine)], - sourceLines, - ); -} - -function updateLocationData(locationData: FullLocationData, insertions: Insertion[]): FullLocationData { - return insertions.reduceRight((location, insertion) => { - return location.map((entry, opcodeIndex) => { - const currentLineNumber = getDisplayLine(location[opcodeIndex]); - const updatedLineNumber = getUpdatedLineNumber(currentLineNumber, insertion, opcodeIndex); - if (updatedLineNumber === currentLineNumber) return entry; - - return { - location: { - start: { line: updatedLineNumber, column: 0 }, - end: { line: updatedLineNumber, column: 0 }, - }, - positionHint: PositionHint.START, - }; - }); - }, locationData); -} - -const getUpdatedLineNumber = (currentLineNumber: number, insertion: Insertion, opcodeIndex: number): number => { - const newLineNumber = insertion.insertAfterLine + 1; - const inTagRange = opcodeIndex >= insertion.startIndex && opcodeIndex <= insertion.endIndex; - - if (inTagRange) return newLineNumber; - if (currentLineNumber > insertion.insertAfterLine) return currentLineNumber + 1; - return currentLineNumber; -}; - // e.g. ">>> for-loop update (i = i + 1)" function tagDescription(tag: SourceTagEntry, locationData: FullLocationData, sourceLines: string[]): string { switch (tag.kind) { diff --git a/packages/utils/test/bitauth-script.test.ts b/packages/utils/test/bitauth-script.test.ts index 97d59b241..06e1a7820 100644 --- a/packages/utils/test/bitauth-script.test.ts +++ b/packages/utils/test/bitauth-script.test.ts @@ -1,7 +1,9 @@ -import { asmToScript } from '../src/script.js'; -import { buildLineToAsmMap, formatBitAuthScript } from '../src/bitauth-script.js'; -import { fixtures } from './fixtures/bitauth-script.fixture.js'; -import { compileString } from 'cashc'; +import { binToHex, createCompilerBch } from '@bitauth/libauth'; +import { Artifact } from '../src/artifact.js'; +import { asmToScript, scriptToBytecode } from '../src/script.js'; +import { formatBitAuthScript } from '../src/bitauth-script.js'; +import { FunctionFixture, fixtures, functionFixtures } from './fixtures/bitauth-script.fixture.js'; +import { compileFile, compileString } from 'cashc'; describe('Libauth Script formatting', () => { fixtures.forEach((fixture) => { @@ -16,17 +18,68 @@ describe('Libauth Script formatting', () => { expect(artifact.bytecode).toEqual(fixture.asmBytecode); }); - it('should build a line-to-asm map', () => { - expect(buildLineToAsmMap(scriptBytecode, fixture.sourceMap)).toEqual(fixture.expectedLineToAsmMap); - }); - it('should format script as debugging output for BitAuth IDE', () => { const expectedBitAuthScript = fixture.expectedBitAuthScript.replace(/^\n+/, '').replace(/\n+$/, ''); - const formattedBitAuthScript = formatBitAuthScript( - scriptBytecode, fixture.sourceMap, fixture.sourceCode, fixture.sourceTags, - ); + const debugInformation = { + bytecode: binToHex(scriptToBytecode(scriptBytecode)), + sourceMap: fixture.sourceMap, + logs: [], + requires: [], + ...(fixture.sourceTags ? { sourceTags: fixture.sourceTags } : {}), + }; + const formattedBitAuthScript = formatBitAuthScript(debugInformation, fixture.sourceCode); expect(formattedBitAuthScript).toBe(expectedBitAuthScript); + expectBitAuthScriptToCompileTo(formattedBitAuthScript, debugInformation.bytecode); + }); + }); + }); + + describe('Bytecode order preservation', () => { + it('should emit opcodes in bytecode order even for non-monotonic source maps', () => { + // OP_3 maps back to line 3 after line-4 opcodes — grouping by source line would reorder execution. + // The formatted output is executed, so bytecode order must win over source-line grouping. + const scriptBytecode = asmToScript('OP_1 OP_2 OP_ADD OP_3 OP_NUMEQUAL'); + const debugInformation = { + bytecode: binToHex(scriptToBytecode(scriptBytecode)), + sourceMap: '3:8:3:9;4:8:4:9;:12::13;3:12:3:13;5:8:5:9', + logs: [], + requires: [], + }; + const sourceCode = 'line 1\nline 2\nline 3\nline 4\nline 5'; + + const formattedBitAuthScript = formatBitAuthScript(debugInformation, sourceCode); + expectBitAuthScriptToCompileTo(formattedBitAuthScript, debugInformation.bytecode); + }); + }); + + describe('User-defined function formatting', () => { + const compileFixture = (fixture: FunctionFixture): Artifact => (fixture.file + ? compileFile(new URL(`./fixtures/${fixture.file}`, import.meta.url)) + : compileString(fixture.sourceCode!)); + + functionFixtures.forEach((fixture) => { + describe(fixture.name, () => { + it('should format function definitions as source-mapped push groups', () => { + const artifact = compileFixture(fixture); + const expectedBitAuthScript = fixture.expectedBitAuthScript.replace(/^\n+/, '').replace(/\n+$/, ''); + expect(formatBitAuthScript(artifact.debug!, artifact.source)).toBe(expectedBitAuthScript); + }); + + it('should compile back to the exact original bytecode', () => { + const artifact = compileFixture(fixture); + const formattedBitAuthScript = formatBitAuthScript(artifact.debug!, artifact.source); + expectBitAuthScriptToCompileTo(formattedBitAuthScript, artifact.debug!.bytecode); + }); }); }); }); }); + +// The formatted output is executed by the BitAuth IDE (and hashed into the P2SH address), so it must +// compile back to the exact bytecode it was generated from +function expectBitAuthScriptToCompileTo(bitAuthScript: string, expectedBytecodeHex: string): void { + const compiler = createCompilerBch({ scripts: { formatted: bitAuthScript } }); + const result = compiler.generateBytecode({ scriptId: 'formatted', data: {} }); + if (!result.success) throw new Error(`BitAuth Script failed to compile: ${JSON.stringify(result.errors)}`); + expect(binToHex(result.bytecode)).toBe(expectedBytecodeHex); +} diff --git a/packages/utils/test/fixtures/bitauth-script.fixture.ts b/packages/utils/test/fixtures/bitauth-script.fixture.ts index 3150831ca..97bbb9b9f 100644 --- a/packages/utils/test/fixtures/bitauth-script.fixture.ts +++ b/packages/utils/test/fixtures/bitauth-script.fixture.ts @@ -6,7 +6,6 @@ export interface Fixture { asmBytecode: string; sourceMap: string; sourceTags?: string; - expectedLineToAsmMap: Record; expectedBitAuthScript: string; } @@ -33,22 +32,6 @@ contract TransferWithTimeout(bytes20 senderPkh, bytes20 recipientPkh, int timeou asmBytecode: 'OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_5 OP_ROLL OP_5 OP_PICK OP_CHECKSIGVERIFY OP_4 OP_ROLL OP_HASH160 OP_ROT OP_EQUAL OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY OP_DUP deadbeefdeadbeefdeadbeefdeadbeefdeadbeef OP_EQUALVERIFY OP_2 OP_PICK OP_3 OP_PICK OP_NUMEQUALVERIFY OP_4 OP_PICK OP_5 OP_PICK OP_EQUALVERIFY OP_3 OP_PICK OP_4 OP_PICK OP_EQUALVERIFY OP_4 OP_ROLL OP_4 OP_PICK OP_CHECKSIGVERIFY OP_3 OP_ROLL OP_HASH160 OP_EQUALVERIFY OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_2DROP OP_1 OP_ENDIF', sourceMap: '3:2:6:3;;;;;4:21:4:22;;:24::33;;:4::36:1;5:20:5:29:0;;:12::30:1;:34::46:0;:4::48:1;3:45:6:3;;;:2;8::16::0;;;;9:12:9:21;:25::67;:4::69:1;10:12:10:19:0;;:23::30;;:4::32:1;11:12:11:13:0;;:17::18;;:4::20:1;12:12:12:21:0;;:25::34;;:4::36:1;13:21:13:22:0;;:24::33;;:4::36:1;14:20:14:29:0;;:12::30:1;:4::45;15:23:15:30:0;:4::32:1;8:44:16:3;;2:0:17:1', sourceTags: '15:17:sc', - expectedLineToAsmMap: { - 3: 'OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF', - 4: 'OP_5 OP_ROLL OP_5 OP_PICK OP_CHECKSIGVERIFY', - 5: 'OP_4 OP_ROLL OP_HASH160 OP_ROT OP_EQUAL', - 6: 'OP_NIP OP_NIP OP_NIP OP_ELSE', - 8: 'OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY', - 9: 'OP_DUP <0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef> OP_EQUALVERIFY', - 10: 'OP_2 OP_PICK OP_3 OP_PICK OP_NUMEQUALVERIFY', - 11: 'OP_4 OP_PICK OP_5 OP_PICK OP_EQUALVERIFY', - 12: 'OP_3 OP_PICK OP_4 OP_PICK OP_EQUALVERIFY', - 13: 'OP_4 OP_ROLL OP_4 OP_PICK OP_CHECKSIGVERIFY', - 14: 'OP_3 OP_ROLL OP_HASH160 OP_EQUALVERIFY', - 15: 'OP_SWAP OP_CHECKLOCKTIMEVERIFY', - 16: 'OP_2DROP OP_1', - 17: 'OP_ENDIF', - }, expectedBitAuthScript: ` /* */ /* contract TransferWithTimeout(bytes20 senderPkh, bytes20 recipientPkh, int timeout) { */ @@ -110,26 +93,6 @@ contract Mecenas(bytes20 recipient, bytes20 funder, int pledge/*, int period */) asmBytecode: 'OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_0 OP_OUTPUTBYTECODE 76a914 OP_ROT OP_CAT 88ac OP_CAT OP_EQUALVERIFY e803 OP_INPUTINDEX OP_UTXOVALUE OP_DUP OP_4 OP_PICK OP_SUB OP_2 OP_PICK OP_SUB OP_DUP OP_5 OP_PICK OP_4 OP_PICK OP_ADD OP_LESSTHANOREQUAL OP_IF OP_0 OP_OUTPUTVALUE OP_2OVER OP_SWAP OP_SUB OP_NUMEQUALVERIFY OP_ELSE OP_0 OP_OUTPUTVALUE OP_5 OP_PICK OP_NUMEQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY OP_ENDIF OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY OP_3 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_2SWAP OP_CHECKSIG OP_NIP OP_NIP OP_ENDIF', sourceMap: '9:4:28:5;;;;;13:27:13:28;:16::45:1;:49::84:0;:74::83;:49::84:1;;;:8::86;15:23:15:27:0;16:37:16:58;:27::65:1;17:26:17:38:0;:41::47;;:26:::1;:50::58:0;;:26:::1;21:12:21:23:0;:27::33;;:36::44;;:27:::1;:12;:46:23:9:0;22:31:22:32;:20::39:1;:43::66:0;;::::1;:12::68;23:15:27:9:0;24:31:24:32;:20::39:1;:43::49:0;;:12::51:1;25:31:25:32:0;:20::49:1;:63::84:0;:53::101:1;:12::103;26:31:26:32:0;:20::39:1;:43::54:0;:12::56:1;23:15:27:9;9:23:28:5;;;;:4;30::33::0;;;;31:24:31:26;;:16::27:1;:31::37:0;:8::39:1;32:25:32:30:0;:8::33:1;30:39:33:5;;8:0:34:1', sourceTags: '69:70:sc', - expectedLineToAsmMap: { - 9: 'OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF', - 13: 'OP_0 OP_OUTPUTBYTECODE <0x76a914> OP_ROT OP_CAT <0x88ac> OP_CAT OP_EQUALVERIFY', - 15: '<0xe803>', - 16: 'OP_INPUTINDEX OP_UTXOVALUE', - 17: 'OP_DUP OP_4 OP_PICK OP_SUB OP_2 OP_PICK OP_SUB', - 21: 'OP_DUP OP_5 OP_PICK OP_4 OP_PICK OP_ADD OP_LESSTHANOREQUAL OP_IF', - 22: 'OP_0 OP_OUTPUTVALUE OP_2OVER OP_SWAP OP_SUB OP_NUMEQUALVERIFY', - 23: 'OP_ELSE', - 24: 'OP_0 OP_OUTPUTVALUE OP_5 OP_PICK OP_NUMEQUALVERIFY', - 25: 'OP_1 OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUALVERIFY', - 26: 'OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY', - 27: 'OP_ENDIF', - 28: 'OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE', - 30: 'OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY', - 31: 'OP_3 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY', - 32: 'OP_2SWAP OP_CHECKSIG', - 33: 'OP_NIP OP_NIP', - 34: 'OP_ENDIF', - }, expectedBitAuthScript: ` /* pragma cashscript >=0.8.0; */ /* */ @@ -208,17 +171,6 @@ contract HodlVault( asmBytecode: 'OP_6 OP_ROLL OP_SIZE OP_8 OP_EQUALVERIFY OP_DUP OP_4 OP_SPLIT OP_SWAP OP_BIN2NUM OP_SWAP OP_BIN2NUM OP_OVER OP_6 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_DROP OP_4 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY OP_4 OP_ROLL OP_SWAP OP_3 OP_ROLL OP_CHECKDATASIGVERIFY OP_CHECKSIG', sourceMap: '15:8:15:28;;;;;18:49:18:62;:69::70;:49::71:1;19:30:19:44:0;:26::45:1;20:24:20:32:0;:20::33:1;23:16:23:27:0;:31::39;;:16:::1;:8::41;24:27:24:38:0;:8::40:1;;27:25:27:36:0;;:16:::1;:8::38;30:29:30::0;;:40::53;:55::63;;:8::66:1;31::31:45', sourceTags: '0:4:pv', - expectedLineToAsmMap: { - 15: 'OP_6 OP_ROLL OP_SIZE OP_8 OP_EQUALVERIFY', - 18: 'OP_DUP OP_4 OP_SPLIT', - 19: 'OP_SWAP OP_BIN2NUM', - 20: 'OP_SWAP OP_BIN2NUM', - 23: 'OP_OVER OP_6 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY', - 24: 'OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_DROP', - 27: 'OP_4 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY', - 30: 'OP_4 OP_ROLL OP_SWAP OP_3 OP_ROLL OP_CHECKDATASIGVERIFY', - 31: 'OP_CHECKSIG', - }, expectedBitAuthScript: ` /* // This contract forces HODLing until a certain price target has been reached */ /* // A minimum block is provided to ensure that oracle price entries from before this block are disregarded */ @@ -280,17 +232,6 @@ contract ForWhileNested() { asmBytecode: 'OP_0 OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_2 OP_PICK OP_2 OP_PICK OP_ADD OP_OVER OP_ADD OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_4 OP_NUMEQUAL', sourceMap: '3:18:3:19;5:21:5:22;:8:13:9;:24:5:25;:28::29;:24:::1;;;:42:13:9:0;6:20:6:21;8:12:12:13;:19:8:20;:23::24;:19:::1;;;:26:12:13:0;9:22:9:25;;:28::29;;:22:::1;:32::33:0;:22:::1;:16::34;;;;;;;10:20:10:21:0;:::25:1;:16::26;8:26:12:13;;:12;;5:35:5:36:0;:::40:1;:31;;::13:9;:42;;:8;;;15:23:15:24:0;:8::26:1', sourceTags: '34:37:lc;38:42:fu;43:46:lc;47:47:sc', - expectedLineToAsmMap: { - 3: 'OP_0', - 5: 'OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_1ADD OP_ROT OP_DROP', - 6: 'OP_0', - 8: 'OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF', - 9: 'OP_2 OP_PICK OP_2 OP_PICK OP_ADD OP_OVER OP_ADD OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK', - 10: 'OP_DUP OP_1ADD OP_NIP', - 12: 'OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL', - 13: 'OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP', - 15: 'OP_4 OP_NUMEQUAL', - }, expectedBitAuthScript: ` /* contract ForWhileNested() { */ /* function spend() { */ @@ -339,20 +280,6 @@ OP_4 OP_NUMEQUAL asmBytecode: 'OP_0 OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_2 OP_PICK OP_2 OP_PICK OP_ADD OP_OVER OP_ADD OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_0 OP_BEGIN OP_DUP OP_1ADD OP_NIP OP_DUP OP_3 OP_GREATERTHANOREQUAL OP_UNTIL OP_ADD OP_12 OP_NUMEQUAL', sourceMap: '3:20:3:21;5:21:5:22;:8:10:9;:24:5:25;:28::29;:24:::1;;;6:19:10:9:0;7:25:7:26;:12:9:13;:28:7:29;:32::33;:28:::1;;;:46:9:13:0;8:24:8:29;;:32::33;;:24:::1;:36::37:0;:24:::1;:16::38;;;;;;;7:39:7:40:0;:::44:1;:35;:46:9:13;;:12;;;6::6::0;:::17:1;5:31;6:19:10:9;;5:8;;;12:20:12:21:0;13:8:15:28;14:20:14:25;:::29:1;:12::30;15:17:15:22:0;:25::26;13:8::28:1;;17:16:17:29;:33::35:0;:8::37:1', sourceTags: '31:33:fu;34:37:lc;38:38:sc;39:41:fu;42:45:lc;46:46:sc', - expectedLineToAsmMap: { - 3: 'OP_0', - 5: 'OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK', - 6: 'OP_IF OP_DUP OP_1ADD OP_NIP', - 7: 'OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_DUP OP_1ADD OP_NIP', - 8: 'OP_2 OP_PICK OP_2 OP_PICK OP_ADD OP_OVER OP_ADD OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK', - 9: 'OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP', - 10: 'OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP', - 12: 'OP_0', - 13: 'OP_BEGIN', - 14: 'OP_DUP OP_1ADD OP_NIP', - 15: 'OP_DUP OP_3 OP_GREATERTHANOREQUAL OP_UNTIL', - 17: 'OP_ADD OP_12 OP_NUMEQUAL', - }, expectedBitAuthScript: ` /* contract NestedForWithDoWhile() { */ /* function spend() { */ @@ -393,10 +320,6 @@ OP_ADD OP_12 OP_NUMEQUAL asmBytecode: 'OP_SIZE OP_8 OP_EQUALVERIFY OP_SIZE OP_NIP OP_8 OP_NUMEQUAL', sourceMap: '3:8:3:18;;;5:16:5:26:1;;:30::31:0;:8::33:1', sourceTags: '0:2:pv', - expectedLineToAsmMap: { - 3: 'OP_SIZE OP_8 OP_EQUALVERIFY', - 5: 'OP_SIZE OP_NIP OP_8 OP_NUMEQUAL', - }, expectedBitAuthScript: ` /* contract ParameterCheck() { */ /* function spend( */ @@ -418,10 +341,6 @@ OP_SIZE OP_NIP OP_8 OP_NUMEQUAL /* require(tag.length == 8); asmBytecode: 'OP_TXLOCKTIME OP_CHECKLOCKTIMEVERIFY OP_DROP OP_TXLOCKTIME OP_1 OP_GREATERTHANOREQUAL', sourceMap: '2:21:2:21;::::1;;3:16:3:27:0;:31::32;:8::34:1', sourceTags: '0:2:lg', - expectedLineToAsmMap: { - 2: 'OP_TXLOCKTIME OP_CHECKLOCKTIMEVERIFY OP_DROP', - 3: 'OP_TXLOCKTIME OP_1 OP_GREATERTHANOREQUAL', - }, expectedBitAuthScript: ` /* contract LocktimeGuard() { */ /* function spend() { */ @@ -442,11 +361,6 @@ OP_TXLOCKTIME OP_1 OP_GREATERTHANOREQUAL /* require(tx.locktime >= 1 asmBytecode: 'OP_SIZE OP_8 OP_EQUALVERIFY OP_TXLOCKTIME OP_CHECKLOCKTIMEVERIFY OP_DROP OP_SIZE OP_NIP OP_8 OP_NUMEQUALVERIFY OP_TXLOCKTIME OP_1 OP_GREATERTHANOREQUAL', sourceMap: '2:19:2:29;;;:31::31;::::1;;3:16:3:26;;:30::31:0;:8::33:1;4:16:4:27:0;:31::32;:8::34:1', sourceTags: '0:2:pv;3:5:lg', - expectedLineToAsmMap: { - 2: 'OP_SIZE OP_8 OP_EQUALVERIFY OP_TXLOCKTIME OP_CHECKLOCKTIMEVERIFY OP_DROP', - 3: 'OP_SIZE OP_NIP OP_8 OP_NUMEQUALVERIFY', - 4: 'OP_TXLOCKTIME OP_1 OP_GREATERTHANOREQUAL', - }, expectedBitAuthScript: ` /* contract ParameterLocktimeGuard() { */ /* function spend(bytes8 tag) { */ @@ -472,13 +386,6 @@ OP_TXLOCKTIME OP_1 OP_GREATERTHANOREQUAL /* require(tx.locktime >= 1 asmBytecode: 'OP_DUP OP_0 OP_GREATERTHAN OP_IF OP_DUP OP_1ADD OP_DUP OP_0 OP_GREATERTHAN OP_VERIFY OP_DROP OP_ENDIF OP_0 OP_GREATERTHAN', sourceMap: '3:12:3:13;:16::17;:12:::1;:19:6:9:0;4:20:4:21;:::25:1;5::5:21:0;:24::25;:20:::1;:12::27;3:19:6:9;;7:20:7:21:0;:8::23:1', sourceTags: '10:10:sc', - expectedLineToAsmMap: { - 3: 'OP_DUP OP_0 OP_GREATERTHAN OP_IF', - 4: 'OP_DUP OP_1ADD', - 5: 'OP_DUP OP_0 OP_GREATERTHAN OP_VERIFY', - 6: 'OP_DROP OP_ENDIF', - 7: 'OP_0 OP_GREATERTHAN', - }, expectedBitAuthScript: ` /* contract ScopeCleanup() { */ /* function spend(int x) { */ @@ -493,3 +400,162 @@ OP_0 OP_GREATERTHAN /* require(x > 0); */ `.replace(/^\n+/, '').replace(/\n+$/, ''), }, ]; + +// Contracts with user-defined functions render each definition as a source-mapped `<...>` push group. +// These fixtures are compiled at test time (compileString for same-file functions, compileFile for imports). +export interface FunctionFixture { + name: string; + sourceCode?: string; // compiled with compileString when set + file?: string; // compiled with compileFile, relative to this fixtures directory (used for imports) + expectedBitAuthScript: string; +} + +export const functionFixtures: FunctionFixture[] = [ + { + name: 'LocalFunctions (same-file functions with loop + recursion)', + sourceCode: ` +function sumTo(int n) returns (int) { + int sum = 0; + for (int i = 0; i < n; i = i + 1) { + sum = sum + i; + } + return sum; +} + +function fib(int n) returns (int) { + int result = n; + if (n >= 2) { + result = fib(n - 1) + fib(n - 2); + } + return result; +} + +contract LocalFunctions() { + function spend() { + require(sumTo(5) == 10, 'sum mismatch'); + require(fib(7) == 13, 'fib mismatch'); + } +} +`.replace(/^\n+/, '').replace(/\n+$/, ''), + expectedBitAuthScript: ` +< /* function sumTo(int n) returns (int) { */ + OP_0 /* int sum = 0; */ + OP_0 OP_BEGIN OP_DUP OP_3 OP_PICK OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF /* for (int i = 0; i < n; i = i + 1) { */ + OP_2DUP OP_ADD OP_ROT OP_DROP OP_SWAP /* sum = sum + i; */ + OP_DUP OP_1ADD OP_NIP /* >>> for-loop update (i = i + 1) */ + OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL /* >>> loop condition check */ + OP_DROP /* >>> scope cleanup */ + /* } */ + /* return sum; */ + OP_NIP /* >>> scope cleanup */ +> OP_0 OP_DEFINE /* } */ + /* */ +< /* function fib(int n) returns (int) { */ + OP_DUP OP_DUP /* int result = n; */ + OP_2 OP_GREATERTHANOREQUAL OP_IF /* if (n >= 2) { */ + OP_OVER OP_1SUB OP_1 OP_INVOKE OP_2 OP_PICK OP_2 OP_SUB OP_1 OP_INVOKE OP_ADD OP_NIP /* result = fib(n - 1) + fib(n - 2); */ + OP_ENDIF /* } */ + /* return result; */ + OP_NIP /* >>> scope cleanup */ +> OP_1 OP_DEFINE /* } */ + /* */ + /* contract LocalFunctions() { */ + /* function spend() { */ +OP_5 OP_0 OP_INVOKE OP_10 OP_NUMEQUALVERIFY /* require(sumTo(5) == 10, 'sum mismatch'); */ +OP_7 OP_1 OP_INVOKE OP_13 OP_NUMEQUAL /* require(fib(7) == 13, 'fib mismatch'); */ + /* } */ + /* } */ +`.replace(/^\n+/, '').replace(/\n+$/, ''), + }, + { + name: 'ImportedFunctions (two imported functions from one file)', + file: 'function-imports/importer.cash', + expectedBitAuthScript: ` + /* >>> function double (imported from helpers.cash) */ +< /* function double(int x) returns (int) { */ + OP_2 OP_MUL /* return x * 2; */ +> OP_0 OP_DEFINE /* } */ + /* */ + /* >>> 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_GREATERTHANOREQUAL OP_VERIFY /* require(sum >= a, "overflow"); */ + /* return sum; */ +> OP_1 OP_DEFINE /* } */ + /* */ + /* import "./helpers.cash"; */ + /* */ + /* 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"); */ + /* } */ + /* } */ + /* */ +`.replace(/^\n+/, '').replace(/\n+$/, ''), + }, + { + // The single-byte 0x81 body (lone OP_BIN2NUM) gets minimally encoded as the opcode OP_1NEGATE at the + // define site, so it must be matched to its frame by push-data equality rather than element shape. + name: 'MinimalBody (single-byte function body, minimally encoded define site)', + sourceCode: ` +function toInt(bytes b) returns (int) { + return int(b); +} + +function double(int x) returns (int) { + return x * 2; +} + +contract MinimalBody() { + function spend(bytes8 b) { + require(toInt(b) > 0, 'not positive'); + require(double(3) == 6, 'bad double'); + } +} +`.replace(/^\n+/, '').replace(/\n+$/, ''), + expectedBitAuthScript: ` +< /* function toInt(bytes b) returns (int) { */ + OP_BIN2NUM /* return int(b); */ +> OP_0 OP_DEFINE /* } */ + /* */ +< /* function double(int x) returns (int) { */ + OP_2 OP_MUL /* return x * 2; */ +> OP_1 OP_DEFINE /* } */ + /* */ + /* contract MinimalBody() { */ + /* function spend(bytes8 b) { */ +OP_SIZE OP_8 OP_EQUALVERIFY /* >>> parameter type check (bytes8 b) */ +OP_0 OP_INVOKE OP_0 OP_GREATERTHAN OP_VERIFY /* require(toInt(b) > 0, 'not positive'); */ +OP_3 OP_1 OP_INVOKE OP_6 OP_NUMEQUAL /* require(double(3) == 6, 'bad double'); */ + /* } */ + /* } */ +`.replace(/^\n+/, '').replace(/\n+$/, ''), + }, + { + name: 'AfterContract (function defined below the contract in the same file)', + sourceCode: ` +contract AfterContract() { + function spend(int x) { + require(double(x) == 10, 'mismatch'); + } +} + +function double(int a) returns (int) { + return a * 2; +} +`.replace(/^\n+/, '').replace(/\n+$/, ''), + expectedBitAuthScript: ` +< /* function double(int a) returns (int) { */ + OP_2 OP_MUL /* return a * 2; */ +> OP_0 OP_DEFINE /* } */ + /* */ + /* contract AfterContract() { */ + /* function spend(int x) { */ +OP_0 OP_INVOKE OP_10 OP_NUMEQUAL /* require(double(x) == 10, 'mismatch'); */ + /* } */ + /* } */ + /* */ +`.replace(/^\n+/, '').replace(/\n+$/, ''), + }, +]; diff --git a/packages/utils/test/fixtures/function-imports/helpers.cash b/packages/utils/test/fixtures/function-imports/helpers.cash new file mode 100644 index 000000000..9ca385c15 --- /dev/null +++ b/packages/utils/test/fixtures/function-imports/helpers.cash @@ -0,0 +1,9 @@ +function double(int x) returns (int) { + return x * 2; +} + +function addChecked(int a, int b) returns (int) { + int sum = a + b; + require(sum >= a, "overflow"); + return sum; +} diff --git a/packages/utils/test/fixtures/function-imports/importer.cash b/packages/utils/test/fixtures/function-imports/importer.cash new file mode 100644 index 000000000..c2834589e --- /dev/null +++ b/packages/utils/test/fixtures/function-imports/importer.cash @@ -0,0 +1,8 @@ +import "./helpers.cash"; + +contract ImportedFunctions() { + function spend(int x) { + int doubled = double(x); + require(addChecked(doubled, x) == 15, "sum mismatch"); + } +} From 425e9bd66cd6ee0846c216d64d8c0ef6e8086575 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 7 Jul 2026 10:50:44 +0200 Subject: [PATCH 04/37] Add OP_SWAP OP_MUL optimisation --- packages/utils/src/cashproof-optimisations.ts | 1 + packages/utils/src/optimisations.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/packages/utils/src/cashproof-optimisations.ts b/packages/utils/src/cashproof-optimisations.ts index 59f64d040..85181ce85 100644 --- a/packages/utils/src/cashproof-optimisations.ts +++ b/packages/utils/src/cashproof-optimisations.ts @@ -57,6 +57,7 @@ OP_CHECKDATASIG OP_VERIFY <=> OP_CHECKDATASIGVERIFY; # OP_SWAP OP_OR <=> OP_OR; # OP_SWAP OP_XOR <=> OP_XOR; OP_SWAP OP_ADD <=> OP_ADD; +OP_SWAP OP_MUL <=> OP_MUL; OP_SWAP OP_EQUAL <=> OP_EQUAL; OP_SWAP OP_NUMEQUAL <=> OP_NUMEQUAL; OP_SWAP OP_NUMNOTEQUAL <=> OP_NUMNOTEQUAL; diff --git a/packages/utils/src/optimisations.ts b/packages/utils/src/optimisations.ts index 651a682e3..e22e702f0 100644 --- a/packages/utils/src/optimisations.ts +++ b/packages/utils/src/optimisations.ts @@ -49,6 +49,7 @@ const provableOptimisations = [ // Remove/replace extraneous OP_SWAP ['OP_SWAP OP_ADD', 'OP_ADD'], + ['OP_SWAP OP_MUL', 'OP_MUL'], // This was added to keep the old behaviour while explicitly disallowing partial matches in the optimisation regex ['OP_SWAP OP_EQUALVERIFY', 'OP_EQUALVERIFY'], ['OP_SWAP OP_EQUAL', 'OP_EQUAL'], From 3a9b337a7bd09937006476480b068b83c6b489de Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 7 Jul 2026 10:52:17 +0200 Subject: [PATCH 05/37] Add includePrerelease to debug compiler version check --- packages/cashscript/src/TransactionBuilder.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cashscript/src/TransactionBuilder.ts b/packages/cashscript/src/TransactionBuilder.ts index bddbb2985..ad959babe 100644 --- a/packages/cashscript/src/TransactionBuilder.ts +++ b/packages/cashscript/src/TransactionBuilder.ts @@ -384,7 +384,7 @@ export class TransactionBuilder { .map((input) => 'contract' in input.unlocker ? input.unlocker.contract.artifact.compiler.version : null) .filter((version) => version !== null); - if (!contractVersions.every((version) => semver.satisfies(version, '>=0.11.0'))) { + if (!contractVersions.every((version) => semver.satisfies(version, '>=0.11.0', { includePrerelease: true }))) { console.warn('For the best debugging experience, please recompile your contract with cashc version 0.11.0 or newer.'); } From b3471bbdd3c6bf815a802efaf2a337d1d6e29dc1 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 7 Jul 2026 11:17:20 +0200 Subject: [PATCH 06/37] Update compileString to work with in-memory import resolution --- packages/cashc/src/compiler.ts | 62 ++++++--- packages/cashc/src/dependency-resolution.ts | 103 ++++++++++---- packages/cashc/src/index.ts | 4 +- .../cashc/test/dead-code-elimination.test.ts | 8 +- .../test/import-fixtures/complex/lib/a.cash | 6 + .../test/import-fixtures/complex/lib/b.cash | 5 + .../complex/lib/util/leaf.cash | 3 + .../test/import-fixtures/complex/main.cash | 9 ++ .../import-fixtures/missing_import_main.cash | 7 + .../test/import-fixtures/nested/helper.cash | 3 + .../test/import-fixtures/nested_main.cash | 7 + .../cashc/test/import-fixtures/shared.cash | 3 + packages/cashc/test/imports.test.ts | 126 ++++++++++++++++-- 13 files changed, 280 insertions(+), 66 deletions(-) create mode 100644 packages/cashc/test/import-fixtures/complex/lib/a.cash create mode 100644 packages/cashc/test/import-fixtures/complex/lib/b.cash create mode 100644 packages/cashc/test/import-fixtures/complex/lib/util/leaf.cash create mode 100644 packages/cashc/test/import-fixtures/complex/main.cash create mode 100644 packages/cashc/test/import-fixtures/missing_import_main.cash create mode 100644 packages/cashc/test/import-fixtures/nested/helper.cash create mode 100644 packages/cashc/test/import-fixtures/nested_main.cash create mode 100644 packages/cashc/test/import-fixtures/shared.cash diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index 04a164252..012c145bc 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -19,7 +19,12 @@ import { Ast } from './ast/AST.js'; import { CashScriptErrorListener } from './ast/error-listeners.js'; import { MissingContractError } from './Errors.js'; import { parseCode } from './parser.js'; -import { resolveDependencies } from './dependency-resolution.js'; +import { + createDiskResolver, + createMemoryResolver, + ImportResolver, + resolveDependencies, +} from './dependency-resolution.js'; import GenerateTargetTraversal from './generation/GenerateTargetTraversal.js'; import SymbolTableTraversal from './semantic/SymbolTableTraversal.js'; import TypeCheckTraversal from './semantic/TypeCheckTraversal.js'; @@ -35,7 +40,10 @@ export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = { export interface CompileOptions extends CompilerOptions { errorListener?: CashScriptErrorListener; - basePath?: string; +} + +export interface CompileStringOptions extends CompileOptions { + files?: Record; } /** @@ -44,16 +52,43 @@ export interface CompileOptions extends CompilerOptions { * @param code - The CashScript source code to compile. * @param compilerOptions - Optional compiler options that override the defaults. * @returns The compiled CashScript artifact, including ABI, bytecode and debug information. - * @throws If the source code contains a syntax, semantic, or type error. + * @throws If the source code contains a syntax, semantic, or type error, or an import cannot be resolved. + */ +export function compileString(code: string, compilerOptions: CompileStringOptions = {}): Artifact { + const { files, ...remainingOptions } = compilerOptions; + const resolver = createMemoryResolver(files ?? {}); + return compileCode(code, resolver, remainingOptions); +} + +/** + * Read a `.cash` source file from disk and compile it to an `Artifact`. + * + * Import directives are resolved from the filesystem, relative to the importing file's directory. + * + * @param codeFile - The path to the `.cash` source file. + * @param compilerOptions - Optional compiler options that override the defaults. + * @returns The compiled CashScript artifact. + * @throws If the file cannot be read, or if the source contains a compilation error. */ -export function compileString(code: string, compilerOptions: CompileOptions = {}): Artifact { - const { errorListener, basePath, ...artifactCompilerOptions } = compilerOptions; +export function compileFile(codeFile: PathLike, compilerOptions: CompileOptions = {}): Artifact { + const filePath = codeFile instanceof URL ? fileURLToPath(codeFile) : codeFile.toString(); + const code = fs.readFileSync(filePath, { encoding: 'utf-8' }); + const resolver = createDiskResolver(path.dirname(filePath)); + return compileCode(code, resolver, compilerOptions); +} + +function compileCode( + code: string, + resolver: ImportResolver, + compilerOptions: CompileOptions, +): Artifact { + const { errorListener, ...artifactCompilerOptions } = compilerOptions; const mergedCompilerOptions = { ...DEFAULT_COMPILER_OPTIONS, ...artifactCompilerOptions }; // Lexing + parsing let ast = parseCode(code, errorListener); - ast = resolveDependencies(ast, { basePath, errorListener }) as Ast; + ast = resolveDependencies(ast, resolver, errorListener) as Ast; if (!ast.contract) throw new MissingContractError(); const constructorParamLength = ast.contract.parameters.length; @@ -106,18 +141,3 @@ export function compileString(code: string, compilerOptions: CompileOptions = {} return generateArtifact(ast, optimisationResult.script, code, debug, mergedCompilerOptions, fingerprint); } - -/** - * Read a `.cash` source file from disk and compile it to an `Artifact`. - * - * @param codeFile - The path to the `.cash` source file. - * @param compilerOptions - Optional compiler options that override the defaults. - * @returns The compiled CashScript artifact. - * @throws If the file cannot be read, or if the source contains a compilation error. - */ -export function compileFile(codeFile: PathLike, compilerOptions: CompileOptions = {}): Artifact { - const filePath = codeFile instanceof URL ? fileURLToPath(codeFile) : codeFile.toString(); - const code = fs.readFileSync(filePath, { encoding: 'utf-8' }); - const basePath = compilerOptions.basePath ?? path.dirname(filePath); - return compileString(code, { ...compilerOptions, basePath }); -} diff --git a/packages/cashc/src/dependency-resolution.ts b/packages/cashc/src/dependency-resolution.ts index 7a0246b24..db51a8b69 100644 --- a/packages/cashc/src/dependency-resolution.ts +++ b/packages/cashc/src/dependency-resolution.ts @@ -1,14 +1,67 @@ import fs from 'fs'; import path from 'path'; import { SourceFileNode, FunctionDefinitionNode, ImportNode } from './ast/AST.js'; -import type { CompileOptions } from './compiler.js'; +import type { CashScriptErrorListener } from './ast/error-listeners.js'; import { ImportResolutionError } from './Errors.js'; import { parseCode } from './parser.js'; -export function resolveDependencies(ast: SourceFileNode, options: CompileOptions): SourceFileNode { +// A minimal virtual filesystem used to resolve import directives. Canonical paths are opaque keys: +// absolute filesystem paths for the disk resolver, normalised POSIX paths relative to the main +// source for the in-memory resolver. +export interface ImportResolver { + rootDir: string; + resolve(fromDir: string, importPath: string): string; + read(canonicalPath: string): string | undefined; + dirname(canonicalPath: string): string; + sourceName(canonicalPath: string): string; +} + +export function createDiskResolver(rootDir: string): ImportResolver { + return { + rootDir, + resolve: (fromDir, importPath) => path.resolve(fromDir, importPath), + read: (canonicalPath) => { + try { + return fs.readFileSync(canonicalPath, { encoding: 'utf-8' }); + } catch { + return undefined; + } + }, + dirname: (canonicalPath) => path.dirname(canonicalPath), + sourceName: (canonicalPath) => path.relative(rootDir, canonicalPath).split(path.sep).join(path.posix.sep), + }; +} + +export function createMemoryResolver(files: Record): ImportResolver { + // Normalise keys so that './utils.cash' and 'utils.cash' address the same file + const normalisedFiles = Object.fromEntries( + Object.entries(files).map(([filePath, source]) => [path.posix.normalize(filePath), source]), + ); + + return { + rootDir: '.', + resolve: (fromDir, importPath) => path.posix.normalize(path.posix.join(fromDir, importPath)), + read: (canonicalPath) => normalisedFiles[canonicalPath], + dirname: (canonicalPath) => path.posix.dirname(canonicalPath), + sourceName: (canonicalPath) => canonicalPath, + }; +} + +export function resolveDependencies( + ast: SourceFileNode, + resolver: ImportResolver | undefined, + errorListener?: CashScriptErrorListener, +): SourceFileNode { if (ast.imports.length === 0) return ast; - const importedFunctions = collectImports(ast.imports, options.basePath, options); + if (resolver === undefined) { + throw new ImportResolutionError( + ast.imports[0], + 'Cannot resolve imports when compiling from a string, pass in the imported sources using the "files" option or compile from the filesystem using compileFile', + ); + } + + const importedFunctions = collectImports(ast.imports, resolver, errorListener); ast.functions = [...importedFunctions, ...ast.functions]; ast.imports = []; @@ -16,48 +69,40 @@ export function resolveDependencies(ast: SourceFileNode, options: CompileOptions } // Depth-first walk of the import graph, returning every global function it reaches. `visitedPaths` is -// internal bookkeeping that de-duplicates files by absolute path — collapsing diamonds (a file reached +// 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[], - fileDir: string | undefined, - options: CompileOptions, + resolver: ImportResolver, + errorListener?: CashScriptErrorListener, ): FunctionDefinitionNode[] { const visitedPaths = new Set(); - const collect = (currentImports: ImportNode[], currentDir: string | undefined): FunctionDefinitionNode[] => + const collect = (currentImports: ImportNode[], currentDir: string): FunctionDefinitionNode[] => currentImports.flatMap((importNode) => { - if (currentDir === undefined) { - throw new ImportResolutionError(importNode, 'Cannot resolve imports without a base path (compile from a file)'); - } + const canonicalPath = resolver.resolve(currentDir, importNode.path); + if (visitedPaths.has(canonicalPath)) return []; + visitedPaths.add(canonicalPath); - const absolutePath = path.resolve(currentDir, importNode.path); - if (visitedPaths.has(absolutePath)) return []; - visitedPaths.add(absolutePath); + const importedSource = resolver.read(canonicalPath); + if (importedSource === undefined) { + throw new ImportResolutionError( + importNode, + `Could not read imported file '${importNode.path}' (resolved to '${canonicalPath}')`, + ); + } - const importedSource = readImportedFile(importNode, absolutePath); - const importedAst = parseCode(importedSource, options.errorListener); + const importedAst = parseCode(importedSource, errorListener); // Record source provenance so debug frames can attribute to the imported file importedAst.functions.forEach((func) => { func.sourceCode = importedSource; - func.sourceFile = path.basename(absolutePath); + func.sourceFile = resolver.sourceName(canonicalPath); }); - return [...collect(importedAst.imports, path.dirname(absolutePath)), ...importedAst.functions]; + return [...collect(importedAst.imports, resolver.dirname(canonicalPath)), ...importedAst.functions]; }); - return collect(imports, fileDir); -} - -function readImportedFile(importNode: ImportNode, absolutePath: string): string { - try { - return fs.readFileSync(absolutePath, { encoding: 'utf-8' }); - } catch { - throw new ImportResolutionError( - importNode, - `Could not read imported file '${importNode.path}' (resolved to ${absolutePath})`, - ); - } + return collect(imports, resolver.rootDir); } diff --git a/packages/cashc/src/index.ts b/packages/cashc/src/index.ts index d8761f026..1e8f8e02a 100644 --- a/packages/cashc/src/index.ts +++ b/packages/cashc/src/index.ts @@ -1,6 +1,8 @@ export * from './Errors.js'; export * as utils from '@cashscript/utils'; -export { compileFile, compileString, type CompileOptions } from './compiler.js'; +export { + compileFile, compileString, type CompileOptions, type CompileStringOptions, +} from './compiler.js'; export * from './ast/Location.js'; export * from './ast/error-listeners.js'; diff --git a/packages/cashc/test/dead-code-elimination.test.ts b/packages/cashc/test/dead-code-elimination.test.ts index 6a493e01d..1665bdc05 100644 --- a/packages/cashc/test/dead-code-elimination.test.ts +++ b/packages/cashc/test/dead-code-elimination.test.ts @@ -1,7 +1,5 @@ -import { fileURLToPath } from 'url'; import { compileString } from '../src/index.js'; -const fixtureDir = fileURLToPath(new URL('./import-fixtures/', import.meta.url)); const countOpDefines = (bytecode: string): number => [...bytecode.matchAll(/OP_DEFINE/g)].length; describe('Dead-code elimination', () => { @@ -103,8 +101,12 @@ describe('Dead-code elimination', () => { it('eliminates an unused imported function', () => { // math.cash exports both `addOne` and `double`; only `double` is used here, so `addOne` is dropped. const code = 'import "./math.cash";\ncontract Test() { function spend(int x) { require(double(x) == 8); } }'; + const mathSource = ` + function addOne(int a) returns (int) { return a + 1; } + function double(int a) returns (int) { return a * 2; } + `; - const artifact = compileString(code, { basePath: fixtureDir }); + const artifact = compileString(code, { files: { './math.cash': mathSource } }); expect(countOpDefines(artifact.bytecode)).toEqual(1); }); }); diff --git a/packages/cashc/test/import-fixtures/complex/lib/a.cash b/packages/cashc/test/import-fixtures/complex/lib/a.cash new file mode 100644 index 000000000..d7e12e52f --- /dev/null +++ b/packages/cashc/test/import-fixtures/complex/lib/a.cash @@ -0,0 +1,6 @@ +import "./util/leaf.cash"; +import "../../shared.cash"; + +function alpha(int n) returns (int) { + return leaf(n) + shared(n); +} diff --git a/packages/cashc/test/import-fixtures/complex/lib/b.cash b/packages/cashc/test/import-fixtures/complex/lib/b.cash new file mode 100644 index 000000000..073fd06bf --- /dev/null +++ b/packages/cashc/test/import-fixtures/complex/lib/b.cash @@ -0,0 +1,5 @@ +import "./util/leaf.cash"; + +function beta(int n) returns (int) { + return leaf(n) * 2; +} diff --git a/packages/cashc/test/import-fixtures/complex/lib/util/leaf.cash b/packages/cashc/test/import-fixtures/complex/lib/util/leaf.cash new file mode 100644 index 000000000..b940a4bce --- /dev/null +++ b/packages/cashc/test/import-fixtures/complex/lib/util/leaf.cash @@ -0,0 +1,3 @@ +function leaf(int n) returns (int) { + return n + 1; +} diff --git a/packages/cashc/test/import-fixtures/complex/main.cash b/packages/cashc/test/import-fixtures/complex/main.cash new file mode 100644 index 000000000..4ae3d51d1 --- /dev/null +++ b/packages/cashc/test/import-fixtures/complex/main.cash @@ -0,0 +1,9 @@ +import "./lib/a.cash"; +import "./lib/b.cash"; +import "../shared.cash"; + +contract Complex() { + function spend(int x) { + require(alpha(x) + beta(x) + shared(x) == 42); + } +} diff --git a/packages/cashc/test/import-fixtures/missing_import_main.cash b/packages/cashc/test/import-fixtures/missing_import_main.cash new file mode 100644 index 000000000..4f6871147 --- /dev/null +++ b/packages/cashc/test/import-fixtures/missing_import_main.cash @@ -0,0 +1,7 @@ +import "./does-not-exist.cash"; + +contract Missing() { + function spend() { + require(true); + } +} diff --git a/packages/cashc/test/import-fixtures/nested/helper.cash b/packages/cashc/test/import-fixtures/nested/helper.cash new file mode 100644 index 000000000..29096badf --- /dev/null +++ b/packages/cashc/test/import-fixtures/nested/helper.cash @@ -0,0 +1,3 @@ +function nestedHelper(int a) returns (int) { + return a + 5; +} diff --git a/packages/cashc/test/import-fixtures/nested_main.cash b/packages/cashc/test/import-fixtures/nested_main.cash new file mode 100644 index 000000000..54ed6ab94 --- /dev/null +++ b/packages/cashc/test/import-fixtures/nested_main.cash @@ -0,0 +1,7 @@ +import "./nested/helper.cash"; + +contract Nested() { + function spend(int x) { + require(nestedHelper(x) == 8); + } +} diff --git a/packages/cashc/test/import-fixtures/shared.cash b/packages/cashc/test/import-fixtures/shared.cash new file mode 100644 index 000000000..9aa4ca0d2 --- /dev/null +++ b/packages/cashc/test/import-fixtures/shared.cash @@ -0,0 +1,3 @@ +function shared(int a) returns (int) { + return a + 10; +} diff --git a/packages/cashc/test/imports.test.ts b/packages/cashc/test/imports.test.ts index 4eb960fcf..3c7b11c29 100644 --- a/packages/cashc/test/imports.test.ts +++ b/packages/cashc/test/imports.test.ts @@ -1,16 +1,21 @@ +import fs from 'fs'; import { fileURLToPath } from 'url'; import { compileFile, compileString } from '../src/index.js'; import { ImportResolutionError, FunctionRedefinitionError } from '../src/Errors.js'; const fixture = (name: string): string => fileURLToPath(new URL(`./import-fixtures/${name}`, import.meta.url)); -describe('Imports', () => { +const readFixture = (name: string): string => fs.readFileSync(fixture(name), { encoding: 'utf-8' }); + +const countOpDefines = (bytecode: string): number => [...bytecode.matchAll(/OP_DEFINE/g)].length; + +describe('Imports from the filesystem (compileFile)', () => { it('merges global functions from an imported file', () => { const artifact = compileFile(fixture('main.cash')); expect(artifact.contractName).toEqual('Main'); expect(artifact.bytecode).toContain('OP_INVOKE'); // both imported functions are defined (one OP_DEFINE each) - expect([...artifact.bytecode.matchAll(/OP_DEFINE/g)]).toHaveLength(2); + expect(countOpDefines(artifact.bytecode)).toEqual(2); }); it('de-duplicates a diamond import so a shared leaf is defined once', () => { @@ -18,17 +23,11 @@ describe('Imports', () => { // (otherwise it would be a redefinition): leaf, m1, m2 = 3 OP_DEFINEs. const artifact = compileFile(fixture('diamond.cash')); expect(artifact.contractName).toEqual('Diamond'); - expect([...artifact.bytecode.matchAll(/OP_DEFINE/g)]).toHaveLength(3); - }); - - it('throws when compiling a string with imports but no base path', () => { - const code = 'import "./math.cash";\ncontract C() { function spend() { require(true); } }'; - expect(() => compileString(code)).toThrow(ImportResolutionError); + expect(countOpDefines(artifact.bytecode)).toEqual(3); }); it('throws when an imported file cannot be found', () => { - const code = 'import "./does-not-exist.cash";\ncontract C() { function spend() { require(true); } }'; - expect(() => compileString(code, { basePath: fixture('') })).toThrow(ImportResolutionError); + expect(() => compileFile(fixture('missing_import_main.cash'))).toThrow(ImportResolutionError); }); it('throws when an imported function collides with a local function of the same name', () => { @@ -37,10 +36,113 @@ describe('Imports', () => { }); it('resolves a cyclic import without infinite looping', () => { - // cycle_a imports cycle_b which imports cycle_a back; de-duplication by absolute path breaks the + // 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')); expect(artifact.contractName).toEqual('Cycle'); - expect([...artifact.bytecode.matchAll(/OP_DEFINE/g)]).toHaveLength(2); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + }); + + it('records provenance as the path relative to the main file', () => { + const artifact = compileFile(fixture('nested_main.cash')); + expect(artifact.debug?.functions?.map((func) => func.sourceFile)).toEqual(['nested/helper.cash']); + }); +}); + +describe('Imports from in-memory files (compileString)', () => { + const mathSource = ` + function addOne(int a) returns (int) { return a + 1; } + function double(int a) returns (int) { return a * 2; } + `; + + 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 } }); + 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 } }); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + }); + + it('resolves transitive imports relative to the importing file', () => { + // lib/a.cash imports './b.cash', which is relative to lib/ — so its key is 'lib/b.cash' + const code = 'import "./lib/a.cash";\ncontract C() { function spend(int x) { require(a(x) == 7); } }'; + const files = { + 'lib/a.cash': 'import "./b.cash";\nfunction a(int n) returns (int) { return b(n) + 1; }', + 'lib/b.cash': 'function b(int n) returns (int) { return n * 3; }', + }; + + const artifact = compileString(code, { files }); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + expect(artifact.debug?.functions?.map((func) => func.sourceFile).sort()).toEqual(['lib/a.cash', 'lib/b.cash']); + }); + + it('supports files with the same basename in different directories', () => { + const code = 'import "./a/helper.cash";\nimport "./b/helper.cash";\n' + + 'contract C() { function spend(int x) { require(helperA(x) + helperB(x) == 10); } }'; + const files = { + 'a/helper.cash': 'function helperA(int n) returns (int) { return n + 1; }', + 'b/helper.cash': 'function helperB(int n) returns (int) { return n * 2; }', + }; + + const artifact = compileString(code, { files }); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + }); + + it('de-duplicates a diamond import so a shared leaf is defined once', () => { + const code = 'import "./mid1.cash";\nimport "./mid2.cash";\n' + + 'contract Diamond() { function spend(int x) { require(m1(x) + m2(x) == 18); } }'; + const files = { + 'mid1.cash': 'import "./leaf.cash";\nfunction m1(int a) returns (int) { return leaf(a) * 2; }', + 'mid2.cash': 'import "./leaf.cash";\nfunction m2(int a) returns (int) { return leaf(a) + 3; }', + 'leaf.cash': 'function leaf(int a) returns (int) { return a + 1; }', + }; + + const artifact = compileString(code, { files }); + expect(countOpDefines(artifact.bytecode)).toEqual(3); + }); + + it('resolves parent-directory imports', () => { + 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 }); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('throws when compiling a string with imports without providing files', () => { + expect(() => compileString(mainCode)).toThrow(ImportResolutionError); + }); + + it('throws when an import is missing from the provided files', () => { + expect(() => compileString(mainCode, { files: {} })).toThrow(ImportResolutionError); + }); +}); + +describe('compileFile / compileString equivalence', () => { + it('compiles a complex import graph to the exact same artifact from disk and from memory', () => { + // complex/main.cash exercises nested directories, a diamond (a and b both import util/leaf), + // 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')); + + const files = { + 'lib/a.cash': readFixture('complex/lib/a.cash'), + 'lib/b.cash': readFixture('complex/lib/b.cash'), + 'lib/util/leaf.cash': readFixture('complex/lib/util/leaf.cash'), + '../shared.cash': readFixture('shared.cash'), + }; + const fromString = compileString(readFixture('complex/main.cash'), { files }); + + // sanity-check the fixture actually pulls in all four imported functions + expect(countOpDefines(fromDisk.bytecode)).toEqual(4); + + expect(fromString).toEqual({ ...fromDisk, updatedAt: expect.any(String) }); }); }); From 79efcf08ed5816a0be56a5b4c1c1b2b131c79da0 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 7 Jul 2026 11:56:27 +0200 Subject: [PATCH 07/37] Improve pragma version handling for imported files --- packages/cashc/src/Errors.ts | 8 +++-- packages/cashc/src/ast/AST.ts | 1 + packages/cashc/src/ast/AstBuilder.ts | 22 ++++--------- packages/cashc/src/ast/Pragma.ts | 14 ++++++++ packages/cashc/src/compiler.ts | 2 ++ packages/cashc/src/dependency-resolution.ts | 2 ++ packages/cashc/test/ast/fixtures.ts | 3 ++ .../import-fixtures/bad_pragma_helper.cash | 5 +++ .../test/import-fixtures/bad_pragma_main.cash | 7 ++++ packages/cashc/test/imports.test.ts | 32 ++++++++++++++++++- 10 files changed, 76 insertions(+), 20 deletions(-) create mode 100644 packages/cashc/test/import-fixtures/bad_pragma_helper.cash create mode 100644 packages/cashc/test/import-fixtures/bad_pragma_main.cash diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index 7ff6b4096..af1f28143 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -337,10 +337,12 @@ export class BitshiftBitcountNegativeError extends CashScriptError { export class VersionError extends Error { constructor( - actual: string, - constraint: string, + readonly actual: string, + readonly constraint: string, + readonly sourceFile?: string, ) { - const message = `cashc version ${actual} does not satisfy version constraint ${constraint}`; + const provenance = sourceFile ? ` (from pragma in imported file '${sourceFile}')` : ''; + const message = `cashc version ${actual} does not satisfy version constraint ${constraint}${provenance}`; super(message); this.name = this.constructor.name; diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index fd43eca09..645b319c3 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -34,6 +34,7 @@ export class SourceFileNode extends Node { public contract?: ContractNode, public functions: FunctionDefinitionNode[] = [], public imports: ImportNode[] = [], + public pragmas: string[] = [], ) { super(); } diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index c2bdd0e37..a88c186b1 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -1,7 +1,6 @@ import { ParseTree, ParseTreeVisitor } from 'antlr4'; import { hexToBin } from '@bitauth/libauth'; import { parseType, Type } from '@cashscript/utils'; -import semver from 'semver'; import { Node, SourceFileNode, @@ -95,8 +94,7 @@ import { TimeOp, } from './Globals.js'; import { getPragmaName, PragmaName, getVersionOpFromCtx } from './Pragma.js'; -import { version } from '../index.js'; -import { ParseError, VersionError } from '../Errors.js'; +import { ParseError } from '../Errors.js'; export default class AstBuilder extends ParseTreeVisitor @@ -114,9 +112,7 @@ export default class AstBuilder } visitSourceFile(ctx: SourceFileContext): SourceFileNode { - ctx.pragmaDirective_list().forEach((pragma) => { - this.processPragma(pragma); - }); + const pragmas = ctx.pragmaDirective_list().flatMap((pragma) => this.extractVersionConstraints(pragma)); const imports = ctx.importDirective_list().map((directive) => this.visit(directive) as ImportNode); @@ -134,7 +130,7 @@ export default class AstBuilder } }); - const sourceFileNode = new SourceFileNode(contract, functions, imports); + const sourceFileNode = new SourceFileNode(contract, functions, imports, pragmas); sourceFileNode.location = Location.fromCtx(ctx); return sourceFileNode; } @@ -146,19 +142,13 @@ export default class AstBuilder return importNode; } - processPragma(ctx: PragmaDirectiveContext): void { + extractVersionConstraints(ctx: PragmaDirectiveContext): string[] { const pragmaName = getPragmaName(ctx.pragmaName().getText()); if (pragmaName !== PragmaName.CASHSCRIPT) throw new Error(); // Shouldn't happen - // Strip any -beta tags - const actualVersion = version.replace(/-.*/g, ''); - - ctx.pragmaValue().versionConstraint_list().forEach((constraint) => { + return ctx.pragmaValue().versionConstraint_list().map((constraint) => { const op = getVersionOpFromCtx(constraint.versionOperator()); - const versionConstraint = `${op}${constraint.VersionLiteral().getText()}`; - if (!semver.satisfies(actualVersion, versionConstraint)) { - throw new VersionError(actualVersion, versionConstraint); - } + return `${op}${constraint.VersionLiteral().getText()}`; }); } diff --git a/packages/cashc/src/ast/Pragma.ts b/packages/cashc/src/ast/Pragma.ts index be0c9b19d..2db187823 100644 --- a/packages/cashc/src/ast/Pragma.ts +++ b/packages/cashc/src/ast/Pragma.ts @@ -1,4 +1,7 @@ +import semver from 'semver'; import type { VersionOperatorContext } from '../grammar/CashScriptParser.js'; +import { version } from '../index.js'; +import { VersionError } from '../Errors.js'; export enum PragmaName { CASHSCRIPT = 'cashscript', @@ -21,3 +24,14 @@ export function getPragmaName(name: string): PragmaName { export function getVersionOpFromCtx(ctx?: VersionOperatorContext): VersionOp { return (ctx ? ctx.getText() : '='); } + +export function checkVersionConstraints(constraints: string[], sourceFile?: string): void { + // Strip any prerelease tags + const actualVersion = version.replace(/-.*/g, ''); + + constraints.forEach((constraint) => { + if (!semver.satisfies(actualVersion, constraint)) { + throw new VersionError(actualVersion, constraint, sourceFile); + } + }); +} diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index 012c145bc..a46a4fa06 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -16,6 +16,7 @@ import path from 'path'; import { fileURLToPath } from 'url'; import { generateArtifact } from './artifact/Artifact.js'; import { Ast } from './ast/AST.js'; +import { checkVersionConstraints } from './ast/Pragma.js'; import { CashScriptErrorListener } from './ast/error-listeners.js'; import { MissingContractError } from './Errors.js'; import { parseCode } from './parser.js'; @@ -87,6 +88,7 @@ function compileCode( // Lexing + parsing let ast = parseCode(code, errorListener); + checkVersionConstraints(ast.pragmas); ast = resolveDependencies(ast, resolver, errorListener) as Ast; if (!ast.contract) throw new MissingContractError(); diff --git a/packages/cashc/src/dependency-resolution.ts b/packages/cashc/src/dependency-resolution.ts index db51a8b69..5c8b96e2f 100644 --- a/packages/cashc/src/dependency-resolution.ts +++ b/packages/cashc/src/dependency-resolution.ts @@ -1,6 +1,7 @@ import fs from 'fs'; import path from 'path'; import { SourceFileNode, FunctionDefinitionNode, ImportNode } from './ast/AST.js'; +import { checkVersionConstraints } from './ast/Pragma.js'; import type { CashScriptErrorListener } from './ast/error-listeners.js'; import { ImportResolutionError } from './Errors.js'; import { parseCode } from './parser.js'; @@ -94,6 +95,7 @@ function collectImports( } const importedAst = parseCode(importedSource, errorListener); + checkVersionConstraints(importedAst.pragmas, resolver.sourceName(canonicalPath)); // Record source provenance so debug frames can attribute to the imported file importedAst.functions.forEach((func) => { diff --git a/packages/cashc/test/ast/fixtures.ts b/packages/cashc/test/ast/fixtures.ts index c54d2a0f5..55f856a56 100644 --- a/packages/cashc/test/ast/fixtures.ts +++ b/packages/cashc/test/ast/fixtures.ts @@ -914,6 +914,9 @@ export const fixtures: Fixture[] = [ ]), )], ), + [], + [], + ['>=0.8.0'], ), }, { diff --git a/packages/cashc/test/import-fixtures/bad_pragma_helper.cash b/packages/cashc/test/import-fixtures/bad_pragma_helper.cash new file mode 100644 index 000000000..45fd237a4 --- /dev/null +++ b/packages/cashc/test/import-fixtures/bad_pragma_helper.cash @@ -0,0 +1,5 @@ +pragma cashscript >=999.0.0; + +function bump(int a) returns (int) { + return a + 1; +} diff --git a/packages/cashc/test/import-fixtures/bad_pragma_main.cash b/packages/cashc/test/import-fixtures/bad_pragma_main.cash new file mode 100644 index 000000000..61c705d88 --- /dev/null +++ b/packages/cashc/test/import-fixtures/bad_pragma_main.cash @@ -0,0 +1,7 @@ +import "./bad_pragma_helper.cash"; + +contract BadPragma() { + function spend(int x) { + require(bump(x) == 5); + } +} diff --git a/packages/cashc/test/imports.test.ts b/packages/cashc/test/imports.test.ts index 3c7b11c29..f797016e9 100644 --- a/packages/cashc/test/imports.test.ts +++ b/packages/cashc/test/imports.test.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import { fileURLToPath } from 'url'; import { compileFile, compileString } from '../src/index.js'; -import { ImportResolutionError, FunctionRedefinitionError } from '../src/Errors.js'; +import { ImportResolutionError, FunctionRedefinitionError, VersionError } from '../src/Errors.js'; const fixture = (name: string): string => fileURLToPath(new URL(`./import-fixtures/${name}`, import.meta.url)); @@ -47,6 +47,11 @@ describe('Imports from the filesystem (compileFile)', () => { const artifact = compileFile(fixture('nested_main.cash')); expect(artifact.debug?.functions?.map((func) => func.sourceFile)).toEqual(['nested/helper.cash']); }); + + it('throws when an imported file has a pragma that the compiler version does not satisfy', () => { + expect(() => compileFile(fixture('bad_pragma_main.cash'))).toThrow(VersionError); + expect(() => compileFile(fixture('bad_pragma_main.cash'))).toThrow(/bad_pragma_helper\.cash/); + }); }); describe('Imports from in-memory files (compileString)', () => { @@ -122,6 +127,31 @@ describe('Imports from in-memory files (compileString)', () => { it('throws when an import is missing from the provided files', () => { expect(() => compileString(mainCode, { files: {} })).toThrow(ImportResolutionError); }); + + 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 }); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + }); + + it('throws a VersionError naming the imported file when its pragma is not satisfied', () => { + const files = { './math.cash': `pragma cashscript >=999.0.0;\n${mathSource}` }; + expect(() => compileString(mainCode, { files })).toThrow(VersionError); + expect(() => compileString(mainCode, { files })).toThrow( + /cashc version .* does not satisfy version constraint >=999\.0\.0 \(from pragma in imported file 'math\.cash'\)/, + ); + }); + + it('enforces the pragma of a transitively imported file', () => { + const code = 'import "./lib/a.cash";\ncontract C() { function spend(int x) { require(a(x) == 7); } }'; + const files = { + 'lib/a.cash': 'import "./b.cash";\nfunction a(int n) returns (int) { return b(n) + 1; }', + 'lib/b.cash': 'pragma cashscript >=999.0.0;\nfunction b(int n) returns (int) { return n * 3; }', + }; + + expect(() => compileString(code, { files })).toThrow(VersionError); + expect(() => compileString(code, { files })).toThrow(/lib\/b\.cash/); + }); }); describe('compileFile / compileString equivalence', () => { From 53bee2336f417ace9785788df2f3ab27cf420bbb Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 7 Jul 2026 11:56:42 +0200 Subject: [PATCH 08/37] Update docs and release notes --- website/docs/compiler/artifacts.md | 14 ++++++++ website/docs/compiler/compiler.md | 26 ++++++++++++-- website/docs/guides/debugging.md | 50 ++++++++++++++++---------- website/docs/language/contracts.md | 7 ++-- website/docs/releases/release-notes.md | 7 +++- 5 files changed, 80 insertions(+), 24 deletions(-) diff --git a/website/docs/compiler/artifacts.md b/website/docs/compiler/artifacts.md index fc5cfcb1a..d56f93dbc 100644 --- a/website/docs/compiler/artifacts.md +++ b/website/docs/compiler/artifacts.md @@ -27,6 +27,7 @@ interface Artifact { logs: LogEntry[] // log entries generated from `console.log` statements requires: RequireStatement[] // messages for failing `require` statements sourceTags?: string // semantic tags for opcodes (e.g. loop update/condition ranges) + functions?: DebugFrame[] // debug metadata for each user-defined function } updatedAt: string // Last datetime this artifact was updated (in ISO format) fingerprint?: string // SHA256 of the normalized bytecode pattern (BCH bytecode fingerprinting standard) @@ -61,6 +62,19 @@ interface RequireStatement { message?: string; // custom message for failing `require` statement } +interface DebugFrame { + id: number; // the function's id, as used with OP_DEFINE / OP_INVOKE in the bytecode + name: string; // the function's name + inputs: AbiInput[]; // the function's parameters (name and type) + bytecode: string; // hex-encoded bytecode of the function body (exactly what OP_DEFINE stores) + sourceMap: string; // source map of the function body (instruction pointers starting from 0) + sourceTags?: string; // semantic tags for opcodes within the function body + source?: string; // full source code of the defining file (only present for imported functions) + sourceFile?: string; // file name the function is imported from (absent for the contract's own file) + logs: LogEntry[]; // log entries within the function body + requires: RequireStatement[]; // messages for failing `require` statements within the function body +} + interface CompilerOptions { enforceFunctionParameterTypes?: boolean; // Enforce function parameter types (default: true) enforceLocktimeGuard?: boolean; // Enforce the tx.locktime guard (default: true) diff --git a/website/docs/compiler/compiler.md b/website/docs/compiler/compiler.md index f5de753d9..ca261d986 100644 --- a/website/docs/compiler/compiler.md +++ b/website/docs/compiler/compiler.md @@ -88,7 +88,7 @@ If the contract uses `import` directives to pull in [user-defined functions](/do ### compileString() ```ts -compileString(sourceCode: string, compilerOptions?: CompilerOptions): Artifact +compileString(sourceCode: string, compilerOptions?: CompilerOptions & { files?: Record }): Artifact ``` Compiles a CashScript contract from a source code string. This compile method is handy in a browser compilation setting like the [CashScript Playground](https://playground.cashscript.org/) where testing contracts can be quickly compiled and discarded. The method is also useful if no source file is locally available (e.g. the source code is retrieved with a REST API). @@ -101,8 +101,30 @@ const source = await result.text(); const P2PKH = compileString(source); ``` +`compileString` never reads from the filesystem, so `import` directives that pull in [user-defined functions](/docs/language/contracts#user-defined-functions) are resolved from the `files` compiler option instead. Its keys are the import paths relative to the main source (using forward slashes), and its values are the corresponding source code strings. + +```ts +const mathSource = ` +function double(int a) returns (int) { + return a * 2; +} +`; + +const source = ` +import "./math.cash"; + +contract Doubler() { + function spend(int x) { + require(double(x) == 8); + } +} +`; + +const Doubler = compileString(source, { files: { './math.cash': mathSource } }); +``` + :::note -`compileString` has no source file to resolve `import` directives against. To compile a contract that imports [user-defined functions](/docs/language/contracts#user-defined-functions) from other files, use [`compileFile`](#compilefile) instead. +Imports inside imported files are resolved relative to the *importing* file, but their keys in `files` remain relative to the main source. For example, if `lib/a.cash` contains `import "./b.cash";`, that file must be provided under the key `lib/b.cash`. ::: ### Compiler Options diff --git a/website/docs/guides/debugging.md b/website/docs/guides/debugging.md index daa4131a9..17f4cf28f 100644 --- a/website/docs/guides/debugging.md +++ b/website/docs/guides/debugging.md @@ -52,31 +52,43 @@ const uri = transactionBuilder.getBitauthUri(); It is unsafe to debug transactions on mainnet using the BitAuth IDE as private keys will be exposed to BitAuth IDE and transmitted over the network. ::: -The Bitauth IDE will show you the two-way mapping between the CashScript contract code generated opcodes. Here is [a Bitauth IDE link][BitauthIDE] for the basic `TransferWithTimeout` contract as an example: +The Bitauth IDE will show you the two-way mapping between the CashScript contract code and the generated opcodes. User-defined functions are included with the same mapping: each function definition is rendered as a push group annotated with the function's own source lines, and imported functions are annotated with the file they are imported from. + +Here is [a Bitauth IDE link][BitauthIDE] for an example `HalfTimeVault` contract, which uses a `half()` function imported from `math.cash`. Note the source-mapped function definition (`OP_DEFINE`) at the top, the `OP_INVOKE` call sites, and the `>>>` annotation rows: ```js -// "TransferWithTimeout" contract constructor parameters +// "HalfTimeVault" contract constructor parameters // int = <0x90d003> - // pubkey = <0x038f55548d7f3d183cebb8ee77036feeb408f4a5030fb486717659bb944fe5eb4c> - // pubkey = <0x0218d4166169298d42c1f763e243e4b5bc3df8e11690aa953b17a6e02902625f90> + // pubkey = <0x034f355bdcb7cc0af728ef3cceb9615d90684bb5b2ca5f859ab0f0b704075871aa> // bytecode - /* pragma cashscript ~0.11.0; */ - /* */ - /* contract TransferWithTimeout(pubkey sender, pubkey recipient, int timeout) { */ - /* // Require recipient's signature to match */ -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF /* function transfer(sig recipientSig) { */ -OP_4 OP_ROLL OP_ROT OP_CHECKSIG /* require(checkSig(recipientSig, recipient)); */ -OP_NIP OP_NIP OP_NIP OP_ELSE /* } */ - /* */ - /* // Require timeout time to be reached and sender's signature to match */ -OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY /* function timeout(sig senderSig) { */ -OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY /* require(checkSig(senderSig, sender)); */ -OP_SWAP OP_CHECKLOCKTIMEVERIFY /* require(tx.time >= timeout); */ -OP_2DROP OP_1 /* } */ -OP_ENDIF /* } */ + /* >>> function half (imported from math.cash) */ +< /* function half(int amount) returns (int) { */ + OP_2 OP_DIV /* return amount / 2; */ +> OP_0 OP_DEFINE /* } */ + /* */ + /* pragma cashscript ^0.14.0; */ + /* */ + /* import "./math.cash"; */ + /* */ + /* contract HalfTimeVault(pubkey owner, int timeout) { */ + /* // Early claims must leave half the coins in the vault */ +OP_2 OP_PICK OP_0 OP_NUMEQUAL OP_IF /* function claimEarly(sig ownerSig) { */ +OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY /* require(checkSig(ownerSig, owner)); */ +OP_0 OP_INVOKE OP_CHECKLOCKTIMEVERIFY OP_DROP /* require(tx.time >= half(timeout)); */ +OP_INPUTINDEX OP_UTXOVALUE /* int vaultValue = tx.inputs[this.activeInputIndex].value; */ +OP_0 OP_OUTPUTVALUE OP_SWAP OP_0 OP_INVOKE OP_GREATERTHANOREQUAL /* require(tx.outputs[0].value >= half(vaultValue)); */ +OP_NIP /* >>> scope cleanup */ +OP_ELSE /* } */ + /* */ + /* // After the full timeout, the owner can claim everything */ +OP_ROT OP_1 OP_NUMEQUALVERIFY /* function claim(sig ownerSig) { */ +OP_ROT OP_SWAP OP_CHECKSIGVERIFY /* require(checkSig(ownerSig, owner)); */ +OP_CHECKLOCKTIMEVERIFY OP_DROP /* require(tx.time >= timeout); */ +OP_1 /* } */ +OP_ENDIF /* } */ ``` -[BitauthIDE]: https://ide.bitauth.com/import-template/eJzFWAtv2zYQ_isCN2BJ4drUW8raAK3jNkbSJEvcFUMdGBR1stXakidRWYIg--07SrIk23LgDhlGBKEiHu-7x3fUMY_k55TPYMHIEZkJsUyPer3Qh64XCpaJWZfHi558gEiEnIkwjl4LWCznTMDrO9ot9na_pXFEOsSHlCfhUkqhuuFiGScCfCVI4oXCWTorVlEwYgtAiT6-u8nfKR8hgoRJ6RPwsuk0jKbKqATCDWm2LJSRo6_kff90olHNnFCT3HbIHSRpjkg7RJopQkjJ0SMZJSxKA0i-hGI2ChcQZ2ISRstM0MmSJWiBwI1ScN3sfhyJhHGh8ARyhxUWoQ9ZxPM_GlsrP1qQlIMcSvmJHkrzc_2pNL7NqnnMv6NU25JYNzyLclnpNUtC5s0LV1OIfEhuwum2O-N6cUxq65U4qH0akxJmTGqnap0dIh6W8tUZPJCnTrmyG2oTR8zCVOFlWDcBau1f2HwO4oQJJkES4OEyxHy24VSLe0LVynaglf63YVWh2QtppWgHzirkmE8f7rfhymqoMpOLKSJW4B54lpdCCbShqRUPR4N77RXRTjAUXrI0hZ2U3dgGd2yeyVK93YxEWyHgaq_XZF1beY2jNxUF5TkTxUkyScNpxESWQBfdnOBeVJ1O5HMm7uP0WEG9KDOOxhE-bYQxjKqEofL1AOY7w0gob5U36vFYnmZFKNL2-i5q9qm9aFchlDMeZKMiM0stnenas6fGVoRaZDBavDqi4igVScZFnKxHroxs0yt671KfUh2de1PVQy6wzLzv8FDIUN0JTNM0HN8OdF91dA6e5wDYNtWtAMAzqBMYzKQ6DTzDsWzVtkzX81zDCMDEZX5cJW5buaY6vqFalmq5mouPGlcD29JBM3QwPNPjuh84oOIyZcw1dU-1mQVUc6lmaWbg0uMys96DAB77MI6U_UbvlbJM2HTBGh8i5W_aVdUu_XVPHc3xqvcj0C86fgy64koLlQ7K5BTp6qxyVbGjk3On5NKh8vgvvMZcXcOfWZhArfaXVKnqWJ5tCyb4bB-vL68muoK_rob9MzlT-evi86fBb5_fncvn4YcGdFX9ovT8AFFrK_BYkS7tMUpoQyJcX56fF_NITv3TQf_sZvhxw2s5ksLtA-yQ-HcEO2gid2o7Dg-f4V8JfTG8UramwfnNYDvgT_t4tK_Xe4r-vwzPp5pmq--OnCW7PMk8hlnw80au4PpOCjZptsq12qTZ74Pr4Yc_GtA1zcqikiyrvlx7UmwX9M2Xd1dNnpXoz9Gsgu6UVjxLsDXoNbTzy_7ZaPhpUDvcDHgTWtx382Afv63Oiv2P1BJaO7m-vCqCvXP8FwyXdXRxUpwbzwyEfjHYFfSeoi9fXKRoCyHCK0S8b2NYdXgoXjYwg_JV26dFaW3_1pvddxG2tQzveKCU2mUZ_TUDWZOyvS4_00XvW3SHsiftSk2ywUVTVo1AfQtCxS_RaZC1Kwh5ic6INO4ZZNWOke1LAVFlY8mzJEHs97KJPIVwOsNd2vprGWtypNqGhViaa3QIfr7zhC6T8A4zc1b-2bgfEstwLddjhqepaJvuO6pl2hq1uUZdz0HjTUvXLIeCYXsAGmO2a_HA9j3K8YfbJL9V5N9UxotMPpI8yfKy8EhkUx5j3zAsnEGjVm9G9Z5TbMLQFgBuBa5lqrYWcNc3HGrqAQ-Au6aqqtRmjgm6r_nUU33VBWmyjUmjlu5z3fAC2S_jIQQRh4ts4cnkGxgH17LzaBQdPHbg7yuWfCXpPBbk9gkvKnJR5CHUTIqjsHTlx9ZWYlvMVQ1HM1Xug61xmfvA9wPbMTBArmcyZpgOhs-2ASzHYTLjkthww0ScIqMxWdRFpKfmvy00WY1xlnC4fA5-ZXmbSsNxnm4xL_8AUE0PwQ== +[BitauthIDE]: https://ide.bitauth.com/import-template/eJzdWG1z2jgQ_isa331IOhSMwYDTlhlKaMMkhRwhaW9Cj5GFHHw1ts-WaTKZ_vfblV_AvKTQJDc38YfE2NLuo2dXj9Z7r_wesimfUeVImQrhh0elkj3hRdMWNBLTIvNmJbzhrrAZFbbnvhZ85jtU8NdztRjPLf4deq5SUCY8ZIHt4ygw1535XiD4hFiBNyOMhtP4LQx06YzDiDY8u5DPyEfu8gCMTsgxN6ObG9u9IcPEEUwIIz82phxdK-_bJ2NN1WpjVVe-FpQ5D0LpUS0oCFPYPFSO7pUT6lhDe8avaOSIse36kVDHPg3At4ApOCQPuO25IqBMEBZwuVRCXUAfuUz-WJqarSDngxxIJ-Q39RAhS8vg5noFSa1S12tlatXVqmGZrMpptc40A_7TSpUaNa1crWs1GFFnVFet2qQ20alhVmsN1axUzerY8dg3cJC3yhxqzzo0cO7SpUauHIgM0cCmphPT4n0Hpi_sm_X1j7J3I2WxWuJZCw5GysLPSFnwkBktKOLOxyen_E75UYhfbHW16kdM7ZCwJAwr1hemP1PH4eKYCooeBFDgRWKTj-TVjl5SQ1v8pBwAvRN-u-4uSeSMKjmMCI_wW84imcWJoxVLG_3BtZRCq8m8Ndgw0qdhiJFeTbv1OXxOnQj3F6RIAm0xaFMyw4BSaSUHNu2Pkfs2TQhUCNcLgnFo37hURAEvwirHwDMYD8d4H4lbL2wSsAxjRu7IhbsVFm03ixfYzvMnZ9quIO_IW7U5Qh2KyQAOnmXnQWCewyyEDv-D8A3jdPC1cFrRtmjNWkxybyEsKV94E4ogYsIL8iFK8j3H362hTlS1AjTGEZQv_cj8xu_i92qlalV03Zwws86YCovWGtyqMMZNo1bWJ4Zaa1RNUzc1WKvV0A1qqpZqAjVqXW_Uy5SCbRli805w5k34yCWPvUqvSLPZXCTNFLiA_M2dPzOKpxkcOIebbbwqwZqfAEgOBOwhQejMi1xxSAIO6e-GuLHg1_02GwiEkP75WMM_x92rXwSCV-wyQUBKRHuzhw0E0kQMqgTS-dDtdX4FyI-9J21k5JFXwsj_Aogf0JsZXSqJyF9qsVwtqruG58UxEu9VkLFiKduoI2WfbH15nGQKnpP2g0SNpTwXpHAnQr6mKU_JCAh2XBbIsz8ksygUxOF0zmO1hS8EAGyDvMFZjT_msiJeAEkF7bzbPs1EpXf5qfPHZesM77sfdgKS6euiCDmAuiHmAwqOB5Q1A1JBf4P-mfR78bl1jv_bJ5326UX341Vn0P3w5245EvB_IjvgB_AVxL6B84MURSHGc3i4JYUTIJKEbu-qf9rJIJz126fD7qdOggOld9A_3xGIuC1iNpDmu_j8SVNjG44USLd3fjns9o47X9Dh5fBL_6p1drmr3C8BwXyUob-C2pJDzQCIZCEZXmPZXYR8tue8i0-6WL19LWIRyt_kGOlfDgFOjGApQitsfRx0WsPOYHjS6vUHcRptZiQpNq_VxFnGzgLoEkEJkF53I-f7M4KVScg8H_YH7Bc38ne1kQDpnF3sf-yuAnnUGfzilDURtJaFH4QoVlbkOKmMFuQTuX3hhE50hnDoMtxBBkNbYhGaQX-IiVhelrKfysfDgra7lskrD2RvKXtyQdtTwfYStFTLHq4KEiDlHdw9_67B7ds7_tnJ9jCQl1Q-Q18Dv1u5Cw0pb6e-RtajgLHJd3AneZSvi5bqgXzrIt-labnQj6HQV-SwpaUd3HrfpzzgcV8oKcjjpk3c1sB-ShEtYWcGcKRfrni_2hVSVBiYNL2Up_hcxvZQ2uECg_H3OfYgoAiUDPqBPQc2oN-20t5Tyo-8sAsF3gPqhnhsI3_3SnyYQ3sJXMG5CiVffJArRzosPHkyXMw5gUoesGhs0rAMQ6tNrIrJjWpZNynnRoVrDd1Sdd3grFHWGKyt0mjUaB1IME3e4Gq5DsQZNex3gCRwl_FeNDOR3iq0WIxaHf6mHR9Q5_dZbK6V0PGE8vUHdLfwJbKoHJU1XVWhUZzUBHIda1PvF72V52ndenCaBNBmlxFbTqf_IHMwprIMuqDCCyHllSPDAE6Qp6yVruE-9aKA8f5DRKUcr1ksg0E0Cd7-BdDnHZk= diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index e160d30a2..aa3f80391 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -118,7 +118,9 @@ contract Example() { ``` ### Importing functions from other files -Top-level functions can be split across files and pulled in with an `import` directive, which makes the imported file's functions available as if they were declared locally. All `import` directives must appear at the **top of the file** — after any `pragma` directives and before any function or contract definitions. Imports are resolved relative to the importing file, so they require compiling from a file (`compileFile`): +Top-level functions can be split across files and pulled in with an `import` directive, which makes the imported file's functions available as if they were declared locally. All `import` directives must appear at the **top of the file** after any `pragma` directives and before any function or contract definitions. + +Imports are resolved relative to the importing file: from the filesystem when compiling with [`compileFile`](/docs/compiler#compilefile), or from the `files` compiler option when using [`compileString`](/docs/compiler#compilestring). ```solidity // math.cash @@ -141,6 +143,8 @@ contract Main() { Imported function names share a single global namespace, so a name may only be defined once across the whole import graph. Files reached through more than one import path (diamond imports) are resolved once. +Imported files can declare their own [`pragma` directives](#pragma), and every pragma across the whole import graph — the main file and all (transitively) imported files — must be satisfied by the compiler version. + :::info `checkSig`, `checkMultiSig` and `this.activeBytecode` cannot be used inside a user-defined function, since they would apply to the function body rather than the contract. Use them in a contract function instead (`checkDataSig` is allowed). ::: @@ -150,7 +154,6 @@ This first version of user-defined functions is intentionally limited in scope: - Functions return **at most one value** (no multiple/tuple returns), and a value-returning function must end with a single `return` statement (no early or conditional returns — compute into a variable and return it at the end). - No advanced optimisations are performed yet on user-defined functions. -- The local debugging tools in the SDK don't properly support user-defined functions yet. :::note Recursive and mutually recursive functions are allowed and compile fine. At runtime the VM control stack is limited to 100 entries, shared between recursion depth and nested `if` and loop blocks, so excessively deep recursion will fail when the contract gets spent. diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 160d49f80..6b01601cc 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -2,13 +2,18 @@ title: Release Notes --- -## v0.14.0-next.0 +## v0.14.0-next.1 ⚠️ Note that this is a pre-release version and is not yet stable. There will likely be breaking changes to the APIs and compiler output in subsequent pre-releases. #### cashc compiler - :sparkles: Add support for user-defined reusable functions. - :sparkles: Add support for `import` directives to share user-defined functions across files. +- :hammer_and_wrench: Update `compileString` to take an optional `files` object for filesystem-free import resolution. +- :racehorse: Add new `OP_SWAP OP_MUL` optimisation. + +#### CashScript SDK +- :sparkles: Add support for debugging user-defined functions. ## v0.13.2 From 2fe39181a098c7c1139705d84c2065542f21f634 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 7 Jul 2026 11:57:15 +0200 Subject: [PATCH 09/37] Bump version to 0.14.0-next.1 --- examples/package.json | 6 +++--- examples/testing-suite/package.json | 6 +++--- packages/cashc/package.json | 4 ++-- packages/cashc/src/index.ts | 2 +- packages/cashscript/package.json | 4 ++-- packages/utils/package.json | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/package.json b/examples/package.json index 43a9e0313..d29356661 100644 --- a/examples/package.json +++ b/examples/package.json @@ -1,7 +1,7 @@ { "name": "cashscript-examples", "private": true, - "version": "0.14.0-next.0", + "version": "0.14.0-next.1", "description": "Usage examples of the CashScript SDK", "main": "p2pkh.js", "type": "module", @@ -13,8 +13,8 @@ "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", "@types/node": "^22.17.0", - "cashc": "^0.14.0-next.0", - "cashscript": "^0.14.0-next.0", + "cashc": "^0.14.0-next.1", + "cashscript": "^0.14.0-next.1", "eslint": "^8.56.0", "typescript": "^5.9.2" } diff --git a/examples/testing-suite/package.json b/examples/testing-suite/package.json index 1fb4f4ea4..a21bfdeae 100644 --- a/examples/testing-suite/package.json +++ b/examples/testing-suite/package.json @@ -1,6 +1,6 @@ { "name": "testing-suite", - "version": "0.14.0-next.0", + "version": "0.14.0-next.1", "description": "Example project to develop and test CashScript contracts", "main": "index.js", "type": "module", @@ -18,8 +18,8 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "cashc": "^0.14.0-next.0", - "cashscript": "^0.14.0-next.0" + "cashc": "^0.14.0-next.1", + "cashscript": "^0.14.0-next.1" }, "devDependencies": { "tsx": "^4.20.3", diff --git a/packages/cashc/package.json b/packages/cashc/package.json index a1d9c1088..4ba502900 100644 --- a/packages/cashc/package.json +++ b/packages/cashc/package.json @@ -1,6 +1,6 @@ { "name": "cashc", - "version": "0.14.0-next.0", + "version": "0.14.0-next.1", "description": "Compile Bitcoin Cash contracts to Bitcoin Cash Script or artifacts", "keywords": [ "bitcoin", @@ -48,7 +48,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.0", + "@cashscript/utils": "^0.14.0-next.1", "antlr4": "^4.13.2", "commander": "^14.0.0", "semver": "^7.7.2" diff --git a/packages/cashc/src/index.ts b/packages/cashc/src/index.ts index 1e8f8e02a..6b4a48d80 100644 --- a/packages/cashc/src/index.ts +++ b/packages/cashc/src/index.ts @@ -6,4 +6,4 @@ export { export * from './ast/Location.js'; export * from './ast/error-listeners.js'; -export const version = '0.14.0-next.0'; +export const version = '0.14.0-next.1'; diff --git a/packages/cashscript/package.json b/packages/cashscript/package.json index 7358763fa..6dd7e128b 100644 --- a/packages/cashscript/package.json +++ b/packages/cashscript/package.json @@ -1,6 +1,6 @@ { "name": "cashscript", - "version": "0.14.0-next.0", + "version": "0.14.0-next.1", "description": "Easily write and interact with Bitcoin Cash contracts", "keywords": [ "bitcoin cash", @@ -42,7 +42,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.0", + "@cashscript/utils": "^0.14.0-next.1", "@electrum-cash/network": "^4.1.3", "fflate": "^0.8.2", "semver": "^7.7.2" diff --git a/packages/utils/package.json b/packages/utils/package.json index fb576d8e9..4b7e079a8 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@cashscript/utils", - "version": "0.14.0-next.0", + "version": "0.14.0-next.1", "description": "CashScript utilities and types", "keywords": [ "bitcoin cash", From 3a6cfd2452e573d0f75d8bddc8b34a37a732810e Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 14 Jul 2026 10:18:03 +0200 Subject: [PATCH 10/37] Add multi return values to user-defined functions (#423) --- .cspell.json | 2 + AGENTS.md | 2 + packages/cashc/src/Errors.ts | 9 - packages/cashc/src/ast/AST.ts | 14 +- packages/cashc/src/ast/AstBuilder.ts | 19 +- packages/cashc/src/ast/AstTraversal.ts | 2 +- packages/cashc/src/ast/SymbolTable.ts | 6 +- .../src/generation/GenerateTargetTraversal.ts | 51 +- packages/cashc/src/grammar/CashScript.g4 | 6 +- packages/cashc/src/grammar/CashScript.interp | 4 +- packages/cashc/src/grammar/CashScript.tokens | 10 +- .../cashc/src/grammar/CashScriptLexer.interp | 4 +- .../cashc/src/grammar/CashScriptLexer.tokens | 10 +- packages/cashc/src/grammar/CashScriptLexer.ts | 30 +- .../cashc/src/grammar/CashScriptParser.ts | 1018 +++++++++-------- .../cashc/src/grammar/CashScriptVisitor.ts | 2 +- .../src/print/OutputSourceCodeTraversal.ts | 8 +- .../semantic/EnsureFinalRequireTraversal.ts | 2 +- .../src/semantic/SymbolTableTraversal.ts | 5 +- .../cashc/src/semantic/TypeCheckTraversal.ts | 64 +- packages/cashc/src/utils.ts | 8 +- packages/cashc/test/ast/fixtures.ts | 6 +- .../destructure_count_mismatch.cash | 11 + .../unpack_not_tuple.cash | 0 .../too_many_return_values.cash | 10 + .../multi_return_tuple_comparison.cash | 11 + .../multi_return_tuple_forwarding.cash | 15 + .../TypeError/multi_return_tuple_index.cash | 11 + .../multi_return_used_as_single_value.cash | 9 + .../multi_return_nested_in_split_rhs.cash | 12 + packages/cashc/test/generation/fixtures.ts | 46 + .../import-fixtures/multi_return_lib.cash | 3 + .../import-fixtures/multi_return_main.cash | 9 + packages/cashc/test/imports.test.ts | 9 + .../global_function_altstack_cleanup.cash | 20 + .../global_function_multi_return.cash | 11 + .../global_function_multi_return_three.cash | 12 + packages/cashscript/test/debugging.test.ts | 20 + .../fixture/debugging/debugging_contracts.ts | 18 + packages/utils/src/types.ts | 10 +- website/docs/language/contracts.md | 18 +- website/docs/releases/release-notes.md | 1 + 42 files changed, 938 insertions(+), 600 deletions(-) create mode 100644 packages/cashc/test/compiler/AssignTypeError/destructure_count_mismatch.cash rename packages/cashc/test/compiler/{TupleAssignmentError => AssignTypeError}/unpack_not_tuple.cash (100%) create mode 100644 packages/cashc/test/compiler/ReturnTypeError/too_many_return_values.cash create mode 100644 packages/cashc/test/compiler/TypeError/multi_return_tuple_comparison.cash create mode 100644 packages/cashc/test/compiler/TypeError/multi_return_tuple_forwarding.cash create mode 100644 packages/cashc/test/compiler/TypeError/multi_return_tuple_index.cash create mode 100644 packages/cashc/test/compiler/UnequalTypeError/multi_return_used_as_single_value.cash create mode 100644 packages/cashc/test/compiler/UnsupportedTypeError/multi_return_nested_in_split_rhs.cash create mode 100644 packages/cashc/test/import-fixtures/multi_return_lib.cash create mode 100644 packages/cashc/test/import-fixtures/multi_return_main.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_altstack_cleanup.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_multi_return.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_multi_return_three.cash diff --git a/.cspell.json b/.cspell.json index b38edf2f0..9165d42ac 100644 --- a/.cspell.json +++ b/.cspell.json @@ -56,6 +56,8 @@ "datasig", "defi", "deserialisation", + "destructures", + "divmod", "docblock", "electroncash", "electrum", diff --git a/AGENTS.md b/AGENTS.md index 489da0c1e..9d0c302a9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,5 +1,7 @@ # CLAUDE.md +NEVER stage changes, just leave them in the working directory. + This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index af1f28143..072cb95af 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -19,7 +19,6 @@ import { InstantiationNode, StatementNode, ContractNode, - ExpressionNode, SliceNode, IntLiteralNode, } from './ast/AST.js'; @@ -272,14 +271,6 @@ export class AssignTypeError extends TypeError { } } -export class TupleAssignmentError extends CashScriptError { - constructor( - node: ExpressionNode, - ) { - super(node, 'Expression must return a tuple to use destructuring'); - } -} - export class ConstantConditionError extends CashScriptError { constructor( node: BranchNode | RequireNode, diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index 645b319c3..4c898d0a0 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -85,7 +85,7 @@ export class FunctionDefinitionNode extends Node implements Named { public name: string, public parameters: ParameterNode[], public body: BlockNode, - public returnType?: Type, + public returnTypes?: Type[], ) { super(); } @@ -127,11 +127,15 @@ export class VariableDefinitionNode extends NonControlStatementNode implements N } } +export interface TupleAssignmentTarget { + name: string; + type: Type; +} + 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: TupleAssignmentTarget[], public tuple: ExpressionNode, ) { super(); @@ -211,7 +215,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 a88c186b1..077ece6dd 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -167,19 +167,21 @@ export default class AstBuilder } visitGlobalFunctionDefinition(ctx: GlobalFunctionDefinitionContext): FunctionDefinitionNode { - const returnType = ctx.typeName() ? parseType(ctx.typeName().getText()) : undefined; - return this.buildFunctionDefinition(ctx, FunctionKind.GLOBAL, returnType); + 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; } @@ -231,13 +233,12 @@ 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) => ({ + const targets = ctx.Identifier_list().map((name, i) => ({ name: name.getText(), type: parseType(types[i].getText()), })); - const tupleAssignment = new TupleAssignmentNode(var1, var2, expression); + const tupleAssignment = new TupleAssignmentNode(targets, expression); tupleAssignment.location = Location.fromCtx(ctx); return tupleAssignment; } @@ -295,8 +296,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 bd428132c..65a4c3b74 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/SymbolTable.ts b/packages/cashc/src/ast/SymbolTable.ts index 36a25525b..f06dce04f 100644 --- a/packages/cashc/src/ast/SymbolTable.ts +++ b/packages/cashc/src/ast/SymbolTable.ts @@ -1,4 +1,4 @@ -import { Type, PrimitiveType, Script, Op, encodeInt } from '@cashscript/utils'; +import { Type, Script, Op, encodeInt } from '@cashscript/utils'; import { VariableDefinitionNode, ParameterNode, @@ -6,6 +6,7 @@ import { IdentifierNode, Node, } from './AST.js'; +import { functionReturnType } from '../utils.js'; export class Symbol { references: IdentifierNode[] = []; @@ -34,8 +35,7 @@ export class 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 symbol = new Symbol(node.name, functionReturnType(node.returnTypes), SymbolType.FUNCTION, node, parameterTypes); symbol.setFunctionId(functionId); return symbol; } diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index 07654a0ce..778ad80f8 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -21,6 +21,7 @@ import { SingleLocationData, StackItem, BytesType, + TupleType, CompilerOptions, SourceTagEntry, SourceTagKind, @@ -206,11 +207,8 @@ export default class GenerateTargetTraversal extends AstTraversal { } cleanGlobalFunctionStack(node: FunctionDefinitionNode): void { - if (node.returnType === undefined) { - 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 - } + // Drop everything below the return values on top (or the entire frame for a void function) + this.cleanStack(node.body, node.returnTypes?.length ?? 0); } visitContract(node: ContractNode): Node { @@ -319,14 +317,24 @@ export default class GenerateTargetTraversal extends AstTraversal { } } - cleanStack(functionBodyNode: Node): void { - // Keep final verification value, OP_NIP the other stack values + // Keep only 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. + cleanStack(functionBodyNode: Node, keepCount: number = 1): void { + this.dropFromStack(functionBodyNode, keepCount, this.stack.length - keepCount); + } + + private dropFromStack(node: Node, keepCount: number, dropCount: number): void { 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: node.location, positionHint: PositionHint.END }; + + // Note that in case of keepCount = 1, this gets optimised to just OP_NIP, or for keepCount = 0 to OP_DROP + for (let i = 0; i < dropCount; i += 1) { + this.emit(encodeInt(BigInt(keepCount)), locationData); + this.emit(Op.OP_ROLL, locationData); + this.emit(Op.OP_DROP, locationData); + this.removeFromStack(keepCount); } + this.tagScopeCleanup(tagStartIndex); } @@ -389,9 +397,8 @@ export default class GenerateTargetTraversal extends AstTraversal { visitTupleAssignment(node: TupleAssignmentNode): Node { node.tuple = this.visit(node.tuple); - this.popFromStack(2); - this.pushToStack(node.left.name); - this.pushToStack(node.right.name); + this.popFromStack(node.targets.length); + node.targets.forEach((target) => this.pushToStack(target.name)); return node; } @@ -625,14 +632,9 @@ export default class GenerateTargetTraversal extends AstTraversal { }); } + // Drop the values that a scope (a branch or loop body) added on top of the pre-scope stack. removeScopedVariables(depthBeforeScope: number, node: Node): void { - const tagStartIndex = this.output.length; - const dropCount = this.stack.length - depthBeforeScope; - for (let i = 0; i < dropCount; i += 1) { - this.emit(Op.OP_DROP, { location: node.location, positionHint: PositionHint.END }); - this.popFromStack(); - } - this.tagScopeCleanup(tagStartIndex); + this.dropFromStack(node, 0, this.stack.length - depthBeforeScope); } private tagScopeCleanup(tagStartIndex: number): void { @@ -665,7 +667,12 @@ export default class GenerateTargetTraversal extends AstTraversal { node.parameters = this.visitList(node.parameters); this.emit(symbol.bytecode!, { location: node.location, positionHint: PositionHint.END }); 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 (a TupleType) are subsequently bound by visitTupleAssignment. + const returnValueCount = symbol.type === PrimitiveType.VOID ? 0 + : symbol.type instanceof TupleType ? symbol.type.elementTypes.length : 1; + for (let i = 0; i < returnValueCount; i += 1) this.pushToStack('(value)'); return node; } diff --git a/packages/cashc/src/grammar/CashScript.g4 b/packages/cashc/src/grammar/CashScript.g4 index c221b077a..c980df8fd 100644 --- a/packages/cashc/src/grammar/CashScript.g4 +++ b/packages/cashc/src/grammar/CashScript.g4 @@ -34,7 +34,7 @@ topLevelDefinition ; globalFunctionDefinition - : 'function' Identifier parameterList ('returns' '(' typeName ')')? functionBody + : 'function' Identifier parameterList ('returns' '(' typeName (',' typeName)* ')')? functionBody ; contractDefinition @@ -83,7 +83,7 @@ functionCallStatement ; returnStatement - : 'return' expression + : 'return' expression (',' expression)* ; controlStatement @@ -96,7 +96,7 @@ variableDefinition ; tupleAssignment - : typeName Identifier ',' typeName Identifier '=' expression + : typeName Identifier (',' typeName Identifier)+ '=' expression ; assignStatement diff --git a/packages/cashc/src/grammar/CashScript.interp b/packages/cashc/src/grammar/CashScript.interp index 30fbbbcdf..5a9ef9b58 100644 --- a/packages/cashc/src/grammar/CashScript.interp +++ b/packages/cashc/src/grammar/CashScript.interp @@ -14,11 +14,11 @@ null 'function' 'returns' '(' +',' ')' 'contract' '{' '}' -',' 'return' '+=' '-=' @@ -219,4 +219,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, 84, 499, 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, 5, 8, 141, 8, 8, 10, 8, 12, 8, 144, 9, 8, 1, 8, 1, 8, 3, 8, 148, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 5, 9, 157, 8, 9, 10, 9, 12, 9, 160, 9, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 5, 11, 171, 8, 11, 10, 11, 12, 11, 174, 9, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 182, 8, 12, 10, 12, 12, 12, 185, 9, 12, 1, 12, 3, 12, 188, 8, 12, 3, 12, 190, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 199, 8, 14, 10, 14, 12, 14, 202, 9, 14, 1, 14, 1, 14, 3, 14, 206, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 212, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 222, 8, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 230, 8, 18, 10, 18, 12, 18, 233, 9, 18, 1, 19, 1, 19, 3, 19, 237, 8, 19, 1, 20, 1, 20, 5, 20, 241, 8, 20, 10, 20, 12, 20, 244, 9, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 4, 21, 256, 8, 21, 11, 21, 12, 21, 257, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 268, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 277, 8, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 286, 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, 300, 8, 26, 1, 27, 1, 27, 1, 27, 3, 27, 305, 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, 333, 8, 31, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 339, 8, 33, 1, 34, 1, 34, 1, 34, 1, 34, 5, 34, 345, 8, 34, 10, 34, 12, 34, 348, 9, 34, 1, 34, 3, 34, 351, 8, 34, 3, 34, 353, 8, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 364, 8, 36, 10, 36, 12, 36, 367, 9, 36, 1, 36, 3, 36, 370, 8, 36, 3, 36, 372, 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, 385, 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, 411, 8, 37, 10, 37, 12, 37, 414, 9, 37, 1, 37, 3, 37, 417, 8, 37, 3, 37, 419, 8, 37, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 425, 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, 477, 8, 37, 10, 37, 12, 37, 480, 9, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 489, 8, 39, 1, 40, 1, 40, 3, 40, 493, 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, 529, 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, 151, 1, 0, 0, 0, 20, 163, 1, 0, 0, 0, 22, 168, 1, 0, 0, 0, 24, 177, 1, 0, 0, 0, 26, 193, 1, 0, 0, 0, 28, 205, 1, 0, 0, 0, 30, 211, 1, 0, 0, 0, 32, 221, 1, 0, 0, 0, 34, 223, 1, 0, 0, 0, 36, 225, 1, 0, 0, 0, 38, 236, 1, 0, 0, 0, 40, 238, 1, 0, 0, 0, 42, 249, 1, 0, 0, 0, 44, 267, 1, 0, 0, 0, 46, 269, 1, 0, 0, 0, 48, 280, 1, 0, 0, 0, 50, 289, 1, 0, 0, 0, 52, 292, 1, 0, 0, 0, 54, 304, 1, 0, 0, 0, 56, 306, 1, 0, 0, 0, 58, 314, 1, 0, 0, 0, 60, 320, 1, 0, 0, 0, 62, 332, 1, 0, 0, 0, 64, 334, 1, 0, 0, 0, 66, 338, 1, 0, 0, 0, 68, 340, 1, 0, 0, 0, 70, 356, 1, 0, 0, 0, 72, 359, 1, 0, 0, 0, 74, 424, 1, 0, 0, 0, 76, 481, 1, 0, 0, 0, 78, 488, 1, 0, 0, 0, 80, 490, 1, 0, 0, 0, 82, 494, 1, 0, 0, 0, 84, 496, 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, 147, 3, 24, 12, 0, 135, 136, 5, 13, 0, 0, 136, 137, 5, 14, 0, 0, 137, 142, 3, 82, 41, 0, 138, 139, 5, 15, 0, 0, 139, 141, 3, 82, 41, 0, 140, 138, 1, 0, 0, 0, 141, 144, 1, 0, 0, 0, 142, 140, 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 145, 1, 0, 0, 0, 144, 142, 1, 0, 0, 0, 145, 146, 5, 16, 0, 0, 146, 148, 1, 0, 0, 0, 147, 135, 1, 0, 0, 0, 147, 148, 1, 0, 0, 0, 148, 149, 1, 0, 0, 0, 149, 150, 3, 22, 11, 0, 150, 17, 1, 0, 0, 0, 151, 152, 5, 17, 0, 0, 152, 153, 5, 81, 0, 0, 153, 154, 3, 24, 12, 0, 154, 158, 5, 18, 0, 0, 155, 157, 3, 20, 10, 0, 156, 155, 1, 0, 0, 0, 157, 160, 1, 0, 0, 0, 158, 156, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 161, 1, 0, 0, 0, 160, 158, 1, 0, 0, 0, 161, 162, 5, 19, 0, 0, 162, 19, 1, 0, 0, 0, 163, 164, 5, 12, 0, 0, 164, 165, 5, 81, 0, 0, 165, 166, 3, 24, 12, 0, 166, 167, 3, 22, 11, 0, 167, 21, 1, 0, 0, 0, 168, 172, 5, 18, 0, 0, 169, 171, 3, 30, 15, 0, 170, 169, 1, 0, 0, 0, 171, 174, 1, 0, 0, 0, 172, 170, 1, 0, 0, 0, 172, 173, 1, 0, 0, 0, 173, 175, 1, 0, 0, 0, 174, 172, 1, 0, 0, 0, 175, 176, 5, 19, 0, 0, 176, 23, 1, 0, 0, 0, 177, 189, 5, 14, 0, 0, 178, 183, 3, 26, 13, 0, 179, 180, 5, 15, 0, 0, 180, 182, 3, 26, 13, 0, 181, 179, 1, 0, 0, 0, 182, 185, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 187, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 186, 188, 5, 15, 0, 0, 187, 186, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 190, 1, 0, 0, 0, 189, 178, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 191, 1, 0, 0, 0, 191, 192, 5, 16, 0, 0, 192, 25, 1, 0, 0, 0, 193, 194, 3, 82, 41, 0, 194, 195, 5, 81, 0, 0, 195, 27, 1, 0, 0, 0, 196, 200, 5, 18, 0, 0, 197, 199, 3, 30, 15, 0, 198, 197, 1, 0, 0, 0, 199, 202, 1, 0, 0, 0, 200, 198, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, 203, 1, 0, 0, 0, 202, 200, 1, 0, 0, 0, 203, 206, 5, 19, 0, 0, 204, 206, 3, 30, 15, 0, 205, 196, 1, 0, 0, 0, 205, 204, 1, 0, 0, 0, 206, 29, 1, 0, 0, 0, 207, 212, 3, 38, 19, 0, 208, 209, 3, 32, 16, 0, 209, 210, 5, 2, 0, 0, 210, 212, 1, 0, 0, 0, 211, 207, 1, 0, 0, 0, 211, 208, 1, 0, 0, 0, 212, 31, 1, 0, 0, 0, 213, 222, 3, 40, 20, 0, 214, 222, 3, 42, 21, 0, 215, 222, 3, 44, 22, 0, 216, 222, 3, 46, 23, 0, 217, 222, 3, 48, 24, 0, 218, 222, 3, 34, 17, 0, 219, 222, 3, 50, 25, 0, 220, 222, 3, 36, 18, 0, 221, 213, 1, 0, 0, 0, 221, 214, 1, 0, 0, 0, 221, 215, 1, 0, 0, 0, 221, 216, 1, 0, 0, 0, 221, 217, 1, 0, 0, 0, 221, 218, 1, 0, 0, 0, 221, 219, 1, 0, 0, 0, 221, 220, 1, 0, 0, 0, 222, 33, 1, 0, 0, 0, 223, 224, 3, 70, 35, 0, 224, 35, 1, 0, 0, 0, 225, 226, 5, 20, 0, 0, 226, 231, 3, 74, 37, 0, 227, 228, 5, 15, 0, 0, 228, 230, 3, 74, 37, 0, 229, 227, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 37, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 234, 237, 3, 52, 26, 0, 235, 237, 3, 54, 27, 0, 236, 234, 1, 0, 0, 0, 236, 235, 1, 0, 0, 0, 237, 39, 1, 0, 0, 0, 238, 242, 3, 82, 41, 0, 239, 241, 3, 76, 38, 0, 240, 239, 1, 0, 0, 0, 241, 244, 1, 0, 0, 0, 242, 240, 1, 0, 0, 0, 242, 243, 1, 0, 0, 0, 243, 245, 1, 0, 0, 0, 244, 242, 1, 0, 0, 0, 245, 246, 5, 81, 0, 0, 246, 247, 5, 10, 0, 0, 247, 248, 3, 74, 37, 0, 248, 41, 1, 0, 0, 0, 249, 250, 3, 82, 41, 0, 250, 255, 5, 81, 0, 0, 251, 252, 5, 15, 0, 0, 252, 253, 3, 82, 41, 0, 253, 254, 5, 81, 0, 0, 254, 256, 1, 0, 0, 0, 255, 251, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 5, 10, 0, 0, 260, 261, 3, 74, 37, 0, 261, 43, 1, 0, 0, 0, 262, 263, 5, 81, 0, 0, 263, 264, 7, 1, 0, 0, 264, 268, 3, 74, 37, 0, 265, 266, 5, 81, 0, 0, 266, 268, 7, 2, 0, 0, 267, 262, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 45, 1, 0, 0, 0, 269, 270, 5, 25, 0, 0, 270, 271, 5, 14, 0, 0, 271, 272, 5, 78, 0, 0, 272, 273, 5, 6, 0, 0, 273, 276, 3, 74, 37, 0, 274, 275, 5, 15, 0, 0, 275, 277, 3, 64, 32, 0, 276, 274, 1, 0, 0, 0, 276, 277, 1, 0, 0, 0, 277, 278, 1, 0, 0, 0, 278, 279, 5, 16, 0, 0, 279, 47, 1, 0, 0, 0, 280, 281, 5, 25, 0, 0, 281, 282, 5, 14, 0, 0, 282, 285, 3, 74, 37, 0, 283, 284, 5, 15, 0, 0, 284, 286, 3, 64, 32, 0, 285, 283, 1, 0, 0, 0, 285, 286, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 288, 5, 16, 0, 0, 288, 49, 1, 0, 0, 0, 289, 290, 5, 26, 0, 0, 290, 291, 3, 68, 34, 0, 291, 51, 1, 0, 0, 0, 292, 293, 5, 27, 0, 0, 293, 294, 5, 14, 0, 0, 294, 295, 3, 74, 37, 0, 295, 296, 5, 16, 0, 0, 296, 299, 3, 28, 14, 0, 297, 298, 5, 28, 0, 0, 298, 300, 3, 28, 14, 0, 299, 297, 1, 0, 0, 0, 299, 300, 1, 0, 0, 0, 300, 53, 1, 0, 0, 0, 301, 305, 3, 56, 28, 0, 302, 305, 3, 58, 29, 0, 303, 305, 3, 60, 30, 0, 304, 301, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 303, 1, 0, 0, 0, 305, 55, 1, 0, 0, 0, 306, 307, 5, 29, 0, 0, 307, 308, 3, 28, 14, 0, 308, 309, 5, 30, 0, 0, 309, 310, 5, 14, 0, 0, 310, 311, 3, 74, 37, 0, 311, 312, 5, 16, 0, 0, 312, 313, 5, 2, 0, 0, 313, 57, 1, 0, 0, 0, 314, 315, 5, 30, 0, 0, 315, 316, 5, 14, 0, 0, 316, 317, 3, 74, 37, 0, 317, 318, 5, 16, 0, 0, 318, 319, 3, 28, 14, 0, 319, 59, 1, 0, 0, 0, 320, 321, 5, 31, 0, 0, 321, 322, 5, 14, 0, 0, 322, 323, 3, 62, 31, 0, 323, 324, 5, 2, 0, 0, 324, 325, 3, 74, 37, 0, 325, 326, 5, 2, 0, 0, 326, 327, 3, 44, 22, 0, 327, 328, 5, 16, 0, 0, 328, 329, 3, 28, 14, 0, 329, 61, 1, 0, 0, 0, 330, 333, 3, 40, 20, 0, 331, 333, 3, 44, 22, 0, 332, 330, 1, 0, 0, 0, 332, 331, 1, 0, 0, 0, 333, 63, 1, 0, 0, 0, 334, 335, 5, 75, 0, 0, 335, 65, 1, 0, 0, 0, 336, 339, 5, 81, 0, 0, 337, 339, 3, 78, 39, 0, 338, 336, 1, 0, 0, 0, 338, 337, 1, 0, 0, 0, 339, 67, 1, 0, 0, 0, 340, 352, 5, 14, 0, 0, 341, 346, 3, 66, 33, 0, 342, 343, 5, 15, 0, 0, 343, 345, 3, 66, 33, 0, 344, 342, 1, 0, 0, 0, 345, 348, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 347, 350, 1, 0, 0, 0, 348, 346, 1, 0, 0, 0, 349, 351, 5, 15, 0, 0, 350, 349, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 351, 353, 1, 0, 0, 0, 352, 341, 1, 0, 0, 0, 352, 353, 1, 0, 0, 0, 353, 354, 1, 0, 0, 0, 354, 355, 5, 16, 0, 0, 355, 69, 1, 0, 0, 0, 356, 357, 5, 81, 0, 0, 357, 358, 3, 72, 36, 0, 358, 71, 1, 0, 0, 0, 359, 371, 5, 14, 0, 0, 360, 365, 3, 74, 37, 0, 361, 362, 5, 15, 0, 0, 362, 364, 3, 74, 37, 0, 363, 361, 1, 0, 0, 0, 364, 367, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 366, 1, 0, 0, 0, 366, 369, 1, 0, 0, 0, 367, 365, 1, 0, 0, 0, 368, 370, 5, 15, 0, 0, 369, 368, 1, 0, 0, 0, 369, 370, 1, 0, 0, 0, 370, 372, 1, 0, 0, 0, 371, 360, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, 372, 373, 1, 0, 0, 0, 373, 374, 5, 16, 0, 0, 374, 73, 1, 0, 0, 0, 375, 376, 6, 37, -1, 0, 376, 377, 5, 14, 0, 0, 377, 378, 3, 74, 37, 0, 378, 379, 5, 16, 0, 0, 379, 425, 1, 0, 0, 0, 380, 381, 3, 84, 42, 0, 381, 382, 5, 14, 0, 0, 382, 384, 3, 74, 37, 0, 383, 385, 5, 15, 0, 0, 384, 383, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 387, 5, 16, 0, 0, 387, 425, 1, 0, 0, 0, 388, 425, 3, 70, 35, 0, 389, 390, 5, 32, 0, 0, 390, 391, 5, 81, 0, 0, 391, 425, 3, 72, 36, 0, 392, 393, 5, 35, 0, 0, 393, 394, 5, 33, 0, 0, 394, 395, 3, 74, 37, 0, 395, 396, 5, 34, 0, 0, 396, 397, 7, 3, 0, 0, 397, 425, 1, 0, 0, 0, 398, 399, 5, 41, 0, 0, 399, 400, 5, 33, 0, 0, 400, 401, 3, 74, 37, 0, 401, 402, 5, 34, 0, 0, 402, 403, 7, 4, 0, 0, 403, 425, 1, 0, 0, 0, 404, 405, 7, 5, 0, 0, 405, 425, 3, 74, 37, 15, 406, 418, 5, 33, 0, 0, 407, 412, 3, 74, 37, 0, 408, 409, 5, 15, 0, 0, 409, 411, 3, 74, 37, 0, 410, 408, 1, 0, 0, 0, 411, 414, 1, 0, 0, 0, 412, 410, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 416, 1, 0, 0, 0, 414, 412, 1, 0, 0, 0, 415, 417, 5, 15, 0, 0, 416, 415, 1, 0, 0, 0, 416, 417, 1, 0, 0, 0, 417, 419, 1, 0, 0, 0, 418, 407, 1, 0, 0, 0, 418, 419, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 420, 425, 5, 34, 0, 0, 421, 425, 5, 80, 0, 0, 422, 425, 5, 81, 0, 0, 423, 425, 3, 78, 39, 0, 424, 375, 1, 0, 0, 0, 424, 380, 1, 0, 0, 0, 424, 388, 1, 0, 0, 0, 424, 389, 1, 0, 0, 0, 424, 392, 1, 0, 0, 0, 424, 398, 1, 0, 0, 0, 424, 404, 1, 0, 0, 0, 424, 406, 1, 0, 0, 0, 424, 421, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 424, 423, 1, 0, 0, 0, 425, 478, 1, 0, 0, 0, 426, 427, 10, 14, 0, 0, 427, 428, 7, 6, 0, 0, 428, 477, 3, 74, 37, 15, 429, 430, 10, 13, 0, 0, 430, 431, 7, 7, 0, 0, 431, 477, 3, 74, 37, 14, 432, 433, 10, 12, 0, 0, 433, 434, 7, 8, 0, 0, 434, 477, 3, 74, 37, 13, 435, 436, 10, 11, 0, 0, 436, 437, 7, 9, 0, 0, 437, 477, 3, 74, 37, 12, 438, 439, 10, 10, 0, 0, 439, 440, 7, 10, 0, 0, 440, 477, 3, 74, 37, 11, 441, 442, 10, 9, 0, 0, 442, 443, 5, 60, 0, 0, 443, 477, 3, 74, 37, 10, 444, 445, 10, 8, 0, 0, 445, 446, 5, 4, 0, 0, 446, 477, 3, 74, 37, 9, 447, 448, 10, 7, 0, 0, 448, 449, 5, 61, 0, 0, 449, 477, 3, 74, 37, 8, 450, 451, 10, 6, 0, 0, 451, 452, 5, 62, 0, 0, 452, 477, 3, 74, 37, 7, 453, 454, 10, 5, 0, 0, 454, 455, 5, 63, 0, 0, 455, 477, 3, 74, 37, 6, 456, 457, 10, 21, 0, 0, 457, 458, 5, 33, 0, 0, 458, 459, 5, 68, 0, 0, 459, 477, 5, 34, 0, 0, 460, 461, 10, 18, 0, 0, 461, 477, 7, 11, 0, 0, 462, 463, 10, 17, 0, 0, 463, 464, 5, 48, 0, 0, 464, 465, 5, 14, 0, 0, 465, 466, 3, 74, 37, 0, 466, 467, 5, 16, 0, 0, 467, 477, 1, 0, 0, 0, 468, 469, 10, 16, 0, 0, 469, 470, 5, 49, 0, 0, 470, 471, 5, 14, 0, 0, 471, 472, 3, 74, 37, 0, 472, 473, 5, 15, 0, 0, 473, 474, 3, 74, 37, 0, 474, 475, 5, 16, 0, 0, 475, 477, 1, 0, 0, 0, 476, 426, 1, 0, 0, 0, 476, 429, 1, 0, 0, 0, 476, 432, 1, 0, 0, 0, 476, 435, 1, 0, 0, 0, 476, 438, 1, 0, 0, 0, 476, 441, 1, 0, 0, 0, 476, 444, 1, 0, 0, 0, 476, 447, 1, 0, 0, 0, 476, 450, 1, 0, 0, 0, 476, 453, 1, 0, 0, 0, 476, 456, 1, 0, 0, 0, 476, 460, 1, 0, 0, 0, 476, 462, 1, 0, 0, 0, 476, 468, 1, 0, 0, 0, 477, 480, 1, 0, 0, 0, 478, 476, 1, 0, 0, 0, 478, 479, 1, 0, 0, 0, 479, 75, 1, 0, 0, 0, 480, 478, 1, 0, 0, 0, 481, 482, 5, 64, 0, 0, 482, 77, 1, 0, 0, 0, 483, 489, 5, 66, 0, 0, 484, 489, 3, 80, 40, 0, 485, 489, 5, 75, 0, 0, 486, 489, 5, 76, 0, 0, 487, 489, 5, 77, 0, 0, 488, 483, 1, 0, 0, 0, 488, 484, 1, 0, 0, 0, 488, 485, 1, 0, 0, 0, 488, 486, 1, 0, 0, 0, 488, 487, 1, 0, 0, 0, 489, 79, 1, 0, 0, 0, 490, 492, 5, 68, 0, 0, 491, 493, 5, 67, 0, 0, 492, 491, 1, 0, 0, 0, 492, 493, 1, 0, 0, 0, 493, 81, 1, 0, 0, 0, 494, 495, 7, 12, 0, 0, 495, 83, 1, 0, 0, 0, 496, 497, 7, 13, 0, 0, 497, 85, 1, 0, 0, 0, 43, 89, 95, 101, 115, 118, 130, 142, 147, 158, 172, 183, 187, 189, 200, 205, 211, 221, 231, 236, 242, 257, 267, 276, 285, 299, 304, 332, 338, 346, 350, 352, 365, 369, 371, 384, 412, 416, 418, 424, 476, 478, 488, 492] \ No newline at end of file diff --git a/packages/cashc/src/grammar/CashScript.tokens b/packages/cashc/src/grammar/CashScript.tokens index 16dc361de..14524e521 100644 --- a/packages/cashc/src/grammar/CashScript.tokens +++ b/packages/cashc/src/grammar/CashScript.tokens @@ -96,11 +96,11 @@ LINE_COMMENT=84 'function'=12 'returns'=13 '('=14 -')'=15 -'contract'=16 -'{'=17 -'}'=18 -','=19 +','=15 +')'=16 +'contract'=17 +'{'=18 +'}'=19 'return'=20 '+='=21 '-='=22 diff --git a/packages/cashc/src/grammar/CashScriptLexer.interp b/packages/cashc/src/grammar/CashScriptLexer.interp index d394bd0e5..24b54e13f 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.interp +++ b/packages/cashc/src/grammar/CashScriptLexer.interp @@ -14,11 +14,11 @@ null 'function' 'returns' '(' +',' ')' 'contract' '{' '}' -',' 'return' '+=' '-=' @@ -266,4 +266,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, 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, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 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, 235, 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, 44, 0, 0, 232, 30, 1, 0, 0, 0, 233, 234, 5, 41, 0, 0, 234, 32, 1, 0, 0, 0, 235, 236, 5, 99, 0, 0, 236, 237, 5, 111, 0, 0, 237, 238, 5, 110, 0, 0, 238, 239, 5, 116, 0, 0, 239, 240, 5, 114, 0, 0, 240, 241, 5, 97, 0, 0, 241, 242, 5, 99, 0, 0, 242, 243, 5, 116, 0, 0, 243, 34, 1, 0, 0, 0, 244, 245, 5, 123, 0, 0, 245, 36, 1, 0, 0, 0, 246, 247, 5, 125, 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 diff --git a/packages/cashc/src/grammar/CashScriptLexer.tokens b/packages/cashc/src/grammar/CashScriptLexer.tokens index 16dc361de..14524e521 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.tokens +++ b/packages/cashc/src/grammar/CashScriptLexer.tokens @@ -96,11 +96,11 @@ LINE_COMMENT=84 'function'=12 'returns'=13 '('=14 -')'=15 -'contract'=16 -'{'=17 -'}'=18 -','=19 +','=15 +')'=16 +'contract'=17 +'{'=18 +'}'=19 'return'=20 '+='=21 '-='=22 diff --git a/packages/cashc/src/grammar/CashScriptLexer.ts b/packages/cashc/src/grammar/CashScriptLexer.ts index 0300faedd..52ab29538 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 src/grammar/CashScript.g4 by ANTLR 4.13.2 // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { ATN, @@ -107,10 +107,10 @@ export default class CashScriptLexer extends Lexer { "'='", "'import'", "'function'", "'returns'", - "'('", "')'", - "'contract'", + "'('", "','", + "')'", "'contract'", "'{'", "'}'", - "','", "'return'", + "'return'", "'+='", "'-='", "'++'", "'--'", "'require'", @@ -247,7 +247,7 @@ export default class CashScriptLexer extends Lexer { 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, + 1,13,1,14,1,14,1,15,1,15,1,16,1,16,1,16,1,16,1,16,1,16,1,16,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, @@ -329,7 +329,7 @@ export default class CashScriptLexer extends Lexer { 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, + 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,235, 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, @@ -359,15 +359,15 @@ export default class CashScriptLexer extends Lexer { 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, + 0,0,230,28,1,0,0,0,231,232,5,44,0,0,232,30,1,0,0,0,233,234,5,41,0,0,234, + 32,1,0,0,0,235,236,5,99,0,0,236,237,5,111,0,0,237,238,5,110,0,0,238,239, + 5,116,0,0,239,240,5,114,0,0,240,241,5,97,0,0,241,242,5,99,0,0,242,243,5, + 116,0,0,243,34,1,0,0,0,244,245,5,123,0,0,245,36,1,0,0,0,246,247,5,125,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, diff --git a/packages/cashc/src/grammar/CashScriptParser.ts b/packages/cashc/src/grammar/CashScriptParser.ts index 0833d80ea..ae797cf80 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 src/grammar/CashScript.g4 by ANTLR 4.13.2 // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { @@ -102,7 +102,7 @@ export default class CashScriptParser extends Parser { public static readonly WHITESPACE = 82; public static readonly COMMENT = 83; public static readonly LINE_COMMENT = 84; - public static readonly EOF = Token.EOF; + 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; @@ -154,10 +154,10 @@ export default class CashScriptParser extends Parser { "'='", "'import'", "'function'", "'returns'", - "'('", "')'", - "'contract'", + "'('", "','", + "')'", "'contract'", "'{'", "'}'", - "','", "'return'", + "'return'", "'+='", "'-='", "'++'", "'--'", "'require'", @@ -309,7 +309,7 @@ export default class CashScriptParser extends Parser { this.state = 101; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===12 || _la===16) { + while (_la===12 || _la===17) { { { this.state = 98; @@ -543,7 +543,7 @@ export default class CashScriptParser extends Parser { this.globalFunctionDefinition(); } break; - case 16: + case 17: this.enterOuterAlt(localctx, 2); { this.state = 129; @@ -582,7 +582,7 @@ export default class CashScriptParser extends Parser { this.match(CashScriptParser.Identifier); this.state = 134; this.parameterList(); - this.state = 140; + this.state = 147; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===13) { @@ -593,12 +593,28 @@ export default class CashScriptParser extends Parser { this.match(CashScriptParser.T__13); this.state = 137; this.typeName(); - this.state = 138; - this.match(CashScriptParser.T__14); + this.state = 142; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===15) { + { + { + this.state = 138; + this.match(CashScriptParser.T__14); + this.state = 139; + this.typeName(); + } + } + this.state = 144; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 145; + this.match(CashScriptParser.T__15); } } - this.state = 142; + this.state = 149; this.functionBody(); } } @@ -624,30 +640,30 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 144; - this.match(CashScriptParser.T__15); - this.state = 145; + this.state = 151; + this.match(CashScriptParser.T__16); + this.state = 152; this.match(CashScriptParser.Identifier); - this.state = 146; + this.state = 153; this.parameterList(); - this.state = 147; - this.match(CashScriptParser.T__16); - this.state = 151; + this.state = 154; + this.match(CashScriptParser.T__17); + this.state = 158; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===12) { { { - this.state = 148; + this.state = 155; this.contractFunctionDefinition(); } } - this.state = 153; + this.state = 160; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 154; - this.match(CashScriptParser.T__17); + this.state = 161; + this.match(CashScriptParser.T__18); } } catch (re) { @@ -671,13 +687,13 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 156; + this.state = 163; this.match(CashScriptParser.T__11); - this.state = 157; + this.state = 164; this.match(CashScriptParser.Identifier); - this.state = 158; + this.state = 165; this.parameterList(); - this.state = 159; + this.state = 166; this.functionBody(); } } @@ -703,24 +719,24 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 161; - this.match(CashScriptParser.T__16); - this.state = 165; + this.state = 168; + this.match(CashScriptParser.T__17); + this.state = 172; 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)) { { { - this.state = 162; + this.state = 169; this.statement(); } } - this.state = 167; + this.state = 174; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 168; - this.match(CashScriptParser.T__17); + this.state = 175; + this.match(CashScriptParser.T__18); } } catch (re) { @@ -746,48 +762,48 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 170; + this.state = 177; this.match(CashScriptParser.T__13); - this.state = 182; + this.state = 189; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0)) { { - this.state = 171; + this.state = 178; this.parameter(); - this.state = 176; + this.state = 183; 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 = 179; + this.match(CashScriptParser.T__14); + this.state = 180; this.parameter(); } } } - this.state = 178; + this.state = 185; 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 = 187; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===15) { { - this.state = 179; - this.match(CashScriptParser.T__18); + this.state = 186; + this.match(CashScriptParser.T__14); } } } } - this.state = 184; - this.match(CashScriptParser.T__14); + this.state = 191; + this.match(CashScriptParser.T__15); } } catch (re) { @@ -811,9 +827,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 186; + this.state = 193; this.typeName(); - this.state = 187; + this.state = 194; this.match(CashScriptParser.Identifier); } } @@ -837,30 +853,30 @@ export default class CashScriptParser extends Parser { this.enterRule(localctx, 28, CashScriptParser.RULE_block); let _la: number; try { - this.state = 198; + this.state = 205; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 17: + case 18: this.enterOuterAlt(localctx, 1); { - this.state = 189; - this.match(CashScriptParser.T__16); - this.state = 193; + this.state = 196; + this.match(CashScriptParser.T__17); + this.state = 200; 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)) { { { - this.state = 190; + this.state = 197; this.statement(); } } - this.state = 195; + this.state = 202; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 196; - this.match(CashScriptParser.T__17); + this.state = 203; + this.match(CashScriptParser.T__18); } break; case 20: @@ -876,7 +892,7 @@ export default class CashScriptParser extends Parser { case 81: this.enterOuterAlt(localctx, 2); { - this.state = 197; + this.state = 204; this.statement(); } break; @@ -903,7 +919,7 @@ export default class CashScriptParser extends Parser { let localctx: StatementContext = new StatementContext(this, this._ctx, this.state); this.enterRule(localctx, 30, CashScriptParser.RULE_statement); try { - this.state = 204; + this.state = 211; this._errHandler.sync(this); switch (this._input.LA(1)) { case 27: @@ -912,7 +928,7 @@ export default class CashScriptParser extends Parser { case 31: this.enterOuterAlt(localctx, 1); { - this.state = 200; + this.state = 207; this.controlStatement(); } break; @@ -925,9 +941,9 @@ export default class CashScriptParser extends Parser { case 81: this.enterOuterAlt(localctx, 2); { - this.state = 201; + this.state = 208; this.nonControlStatement(); - this.state = 202; + this.state = 209; this.match(CashScriptParser.T__1); } break; @@ -954,62 +970,62 @@ export default class CashScriptParser extends Parser { let localctx: NonControlStatementContext = new NonControlStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 32, CashScriptParser.RULE_nonControlStatement); try { - this.state = 214; + this.state = 221; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 15, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 16, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 206; + this.state = 213; this.variableDefinition(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 207; + this.state = 214; this.tupleAssignment(); } break; case 3: this.enterOuterAlt(localctx, 3); { - this.state = 208; + this.state = 215; this.assignStatement(); } break; case 4: this.enterOuterAlt(localctx, 4); { - this.state = 209; + this.state = 216; this.timeOpStatement(); } break; case 5: this.enterOuterAlt(localctx, 5); { - this.state = 210; + this.state = 217; this.requireStatement(); } break; case 6: this.enterOuterAlt(localctx, 6); { - this.state = 211; + this.state = 218; this.functionCallStatement(); } break; case 7: this.enterOuterAlt(localctx, 7); { - this.state = 212; + this.state = 219; this.consoleStatement(); } break; case 8: this.enterOuterAlt(localctx, 8); { - this.state = 213; + this.state = 220; this.returnStatement(); } break; @@ -1036,7 +1052,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 216; + this.state = 223; this.functionCall(); } } @@ -1058,13 +1074,30 @@ export default class CashScriptParser extends Parser { public returnStatement(): ReturnStatementContext { let localctx: ReturnStatementContext = new ReturnStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 36, CashScriptParser.RULE_returnStatement); + let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 218; + this.state = 225; this.match(CashScriptParser.T__19); - this.state = 219; + this.state = 226; this.expression(0); + this.state = 231; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===15) { + { + { + this.state = 227; + this.match(CashScriptParser.T__14); + this.state = 228; + this.expression(0); + } + } + this.state = 233; + this._errHandler.sync(this); + _la = this._input.LA(1); + } } } catch (re) { @@ -1086,13 +1119,13 @@ export default class CashScriptParser extends Parser { let localctx: ControlStatementContext = new ControlStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 38, CashScriptParser.RULE_controlStatement); try { - this.state = 223; + this.state = 236; this._errHandler.sync(this); switch (this._input.LA(1)) { case 27: this.enterOuterAlt(localctx, 1); { - this.state = 221; + this.state = 234; this.ifStatement(); } break; @@ -1101,7 +1134,7 @@ export default class CashScriptParser extends Parser { case 31: this.enterOuterAlt(localctx, 2); { - this.state = 222; + this.state = 235; this.loopStatement(); } break; @@ -1131,27 +1164,27 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 225; + this.state = 238; this.typeName(); - this.state = 229; + this.state = 242; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===64) { { { - this.state = 226; + this.state = 239; this.modifier(); } } - this.state = 231; + this.state = 244; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 232; + this.state = 245; this.match(CashScriptParser.Identifier); - this.state = 233; + this.state = 246; this.match(CashScriptParser.T__9); - this.state = 234; + this.state = 247; this.expression(0); } } @@ -1173,22 +1206,35 @@ export default class CashScriptParser extends Parser { public tupleAssignment(): TupleAssignmentContext { let localctx: TupleAssignmentContext = new TupleAssignmentContext(this, this._ctx, this.state); this.enterRule(localctx, 42, 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.state = 249; this.typeName(); - this.state = 240; + this.state = 250; this.match(CashScriptParser.Identifier); - this.state = 241; + this.state = 255; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 251; + this.match(CashScriptParser.T__14); + this.state = 252; + this.typeName(); + this.state = 253; + this.match(CashScriptParser.Identifier); + } + } + this.state = 257; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la===15); + this.state = 259; this.match(CashScriptParser.T__9); - this.state = 242; + this.state = 260; this.expression(0); } } @@ -1212,15 +1258,15 @@ export default class CashScriptParser extends Parser { this.enterRule(localctx, 44, CashScriptParser.RULE_assignStatement); let _la: number; try { - this.state = 249; + this.state = 267; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 18, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 21, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 244; + this.state = 262; this.match(CashScriptParser.Identifier); - this.state = 245; + this.state = 263; localctx._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 6292480) !== 0))) { @@ -1230,16 +1276,16 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 246; + this.state = 264; this.expression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 247; + this.state = 265; this.match(CashScriptParser.Identifier); - this.state = 248; + this.state = 266; localctx._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===23 || _la===24)) { @@ -1275,30 +1321,30 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 251; + this.state = 269; this.match(CashScriptParser.T__24); - this.state = 252; + this.state = 270; this.match(CashScriptParser.T__13); - this.state = 253; + this.state = 271; this.match(CashScriptParser.TxVar); - this.state = 254; + this.state = 272; this.match(CashScriptParser.T__5); - this.state = 255; + this.state = 273; this.expression(0); - this.state = 258; + this.state = 276; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===15) { { - this.state = 256; - this.match(CashScriptParser.T__18); - this.state = 257; + this.state = 274; + this.match(CashScriptParser.T__14); + this.state = 275; this.requireMessage(); } } - this.state = 260; - this.match(CashScriptParser.T__14); + this.state = 278; + this.match(CashScriptParser.T__15); } } catch (re) { @@ -1323,26 +1369,26 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 262; + this.state = 280; this.match(CashScriptParser.T__24); - this.state = 263; + this.state = 281; this.match(CashScriptParser.T__13); - this.state = 264; + this.state = 282; this.expression(0); - this.state = 267; + this.state = 285; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===15) { { - this.state = 265; - this.match(CashScriptParser.T__18); - this.state = 266; + this.state = 283; + this.match(CashScriptParser.T__14); + this.state = 284; this.requireMessage(); } } - this.state = 269; - this.match(CashScriptParser.T__14); + this.state = 287; + this.match(CashScriptParser.T__15); } } catch (re) { @@ -1366,9 +1412,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 271; + this.state = 289; this.match(CashScriptParser.T__25); - this.state = 272; + this.state = 290; this.consoleParameterList(); } } @@ -1393,24 +1439,24 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 274; + this.state = 292; this.match(CashScriptParser.T__26); - this.state = 275; + this.state = 293; this.match(CashScriptParser.T__13); - this.state = 276; + this.state = 294; this.expression(0); - this.state = 277; - this.match(CashScriptParser.T__14); - this.state = 278; + this.state = 295; + this.match(CashScriptParser.T__15); + this.state = 296; localctx._ifBlock = this.block(); - this.state = 281; + this.state = 299; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 21, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 24, this._ctx) ) { case 1: { - this.state = 279; + this.state = 297; this.match(CashScriptParser.T__27); - this.state = 280; + this.state = 298; localctx._elseBlock = this.block(); } break; @@ -1436,27 +1482,27 @@ export default class CashScriptParser extends Parser { let localctx: LoopStatementContext = new LoopStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 54, CashScriptParser.RULE_loopStatement); try { - this.state = 286; + this.state = 304; this._errHandler.sync(this); switch (this._input.LA(1)) { case 29: this.enterOuterAlt(localctx, 1); { - this.state = 283; + this.state = 301; this.doWhileStatement(); } break; case 30: this.enterOuterAlt(localctx, 2); { - this.state = 284; + this.state = 302; this.whileStatement(); } break; case 31: this.enterOuterAlt(localctx, 3); { - this.state = 285; + this.state = 303; this.forStatement(); } break; @@ -1485,19 +1531,19 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 288; + this.state = 306; this.match(CashScriptParser.T__28); - this.state = 289; + this.state = 307; this.block(); - this.state = 290; + this.state = 308; this.match(CashScriptParser.T__29); - this.state = 291; + this.state = 309; this.match(CashScriptParser.T__13); - this.state = 292; + this.state = 310; this.expression(0); - this.state = 293; - this.match(CashScriptParser.T__14); - this.state = 294; + this.state = 311; + this.match(CashScriptParser.T__15); + this.state = 312; this.match(CashScriptParser.T__1); } } @@ -1522,15 +1568,15 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 296; + this.state = 314; this.match(CashScriptParser.T__29); - this.state = 297; + this.state = 315; this.match(CashScriptParser.T__13); - this.state = 298; + this.state = 316; this.expression(0); - this.state = 299; - this.match(CashScriptParser.T__14); - this.state = 300; + this.state = 317; + this.match(CashScriptParser.T__15); + this.state = 318; this.block(); } } @@ -1555,23 +1601,23 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 302; + this.state = 320; this.match(CashScriptParser.T__30); - this.state = 303; + this.state = 321; this.match(CashScriptParser.T__13); - this.state = 304; + this.state = 322; this.forInit(); - this.state = 305; + this.state = 323; this.match(CashScriptParser.T__1); - this.state = 306; + this.state = 324; this.expression(0); - this.state = 307; + this.state = 325; this.match(CashScriptParser.T__1); - this.state = 308; + this.state = 326; this.assignStatement(); - this.state = 309; - this.match(CashScriptParser.T__14); - this.state = 310; + this.state = 327; + this.match(CashScriptParser.T__15); + this.state = 328; this.block(); } } @@ -1594,7 +1640,7 @@ export default class CashScriptParser extends Parser { let localctx: ForInitContext = new ForInitContext(this, this._ctx, this.state); this.enterRule(localctx, 62, CashScriptParser.RULE_forInit); try { - this.state = 314; + this.state = 332; this._errHandler.sync(this); switch (this._input.LA(1)) { case 71: @@ -1602,14 +1648,14 @@ export default class CashScriptParser extends Parser { case 73: this.enterOuterAlt(localctx, 1); { - this.state = 312; + this.state = 330; this.variableDefinition(); } break; case 81: this.enterOuterAlt(localctx, 2); { - this.state = 313; + this.state = 331; this.assignStatement(); } break; @@ -1638,7 +1684,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 316; + this.state = 334; this.match(CashScriptParser.StringLiteral); } } @@ -1661,13 +1707,13 @@ export default class CashScriptParser extends Parser { let localctx: ConsoleParameterContext = new ConsoleParameterContext(this, this._ctx, this.state); this.enterRule(localctx, 66, CashScriptParser.RULE_consoleParameter); try { - this.state = 320; + this.state = 338; this._errHandler.sync(this); switch (this._input.LA(1)) { case 81: this.enterOuterAlt(localctx, 1); { - this.state = 318; + this.state = 336; this.match(CashScriptParser.Identifier); } break; @@ -1678,7 +1724,7 @@ export default class CashScriptParser extends Parser { case 77: this.enterOuterAlt(localctx, 2); { - this.state = 319; + this.state = 337; this.literal(); } break; @@ -1709,48 +1755,48 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 322; + this.state = 340; this.match(CashScriptParser.T__13); - this.state = 334; + this.state = 352; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 36357) !== 0)) { { - this.state = 323; + this.state = 341; this.consoleParameter(); - this.state = 328; + this.state = 346; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 28, 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 = 342; + this.match(CashScriptParser.T__14); + this.state = 343; this.consoleParameter(); } } } - this.state = 330; + this.state = 348; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 25, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); } - this.state = 332; + this.state = 350; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===15) { { - this.state = 331; - this.match(CashScriptParser.T__18); + this.state = 349; + this.match(CashScriptParser.T__14); } } } } - this.state = 336; - this.match(CashScriptParser.T__14); + this.state = 354; + this.match(CashScriptParser.T__15); } } catch (re) { @@ -1774,9 +1820,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 338; + this.state = 356; this.match(CashScriptParser.Identifier); - this.state = 339; + this.state = 357; this.expressionList(); } } @@ -1803,48 +1849,48 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 341; + this.state = 359; this.match(CashScriptParser.T__13); - this.state = 353; + this.state = 371; 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)) { { - this.state = 342; + this.state = 360; this.expression(0); - this.state = 347; + this.state = 365; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 31, 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 = 361; + this.match(CashScriptParser.T__14); + this.state = 362; this.expression(0); } } } - this.state = 349; + this.state = 367; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 31, this._ctx); } - this.state = 351; + this.state = 369; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===15) { { - this.state = 350; - this.match(CashScriptParser.T__18); + this.state = 368; + this.match(CashScriptParser.T__14); } } } } - this.state = 355; - this.match(CashScriptParser.T__14); + this.state = 373; + this.match(CashScriptParser.T__15); } } catch (re) { @@ -1881,21 +1927,21 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 406; + this.state = 424; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 35, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 38, this._ctx) ) { case 1: { localctx = new ParenthesisedContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 358; + this.state = 376; this.match(CashScriptParser.T__13); - this.state = 359; + this.state = 377; this.expression(0); - this.state = 360; - this.match(CashScriptParser.T__14); + this.state = 378; + this.match(CashScriptParser.T__15); } break; case 2: @@ -1903,24 +1949,24 @@ export default class CashScriptParser extends Parser { localctx = new CastContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 362; + this.state = 380; this.typeCast(); - this.state = 363; + this.state = 381; this.match(CashScriptParser.T__13); - this.state = 364; + this.state = 382; (localctx as CastContext)._castable = this.expression(0); - this.state = 366; + this.state = 384; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===15) { { - this.state = 365; - this.match(CashScriptParser.T__18); + this.state = 383; + this.match(CashScriptParser.T__14); } } - this.state = 368; - this.match(CashScriptParser.T__14); + this.state = 386; + this.match(CashScriptParser.T__15); } break; case 3: @@ -1928,7 +1974,7 @@ export default class CashScriptParser extends Parser { localctx = new FunctionCallExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 370; + this.state = 388; this.functionCall(); } break; @@ -1937,11 +1983,11 @@ export default class CashScriptParser extends Parser { localctx = new InstantiationContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 371; + this.state = 389; this.match(CashScriptParser.T__31); - this.state = 372; + this.state = 390; this.match(CashScriptParser.Identifier); - this.state = 373; + this.state = 391; this.expressionList(); } break; @@ -1950,15 +1996,15 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 374; + this.state = 392; (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__34); - this.state = 375; + this.state = 393; this.match(CashScriptParser.T__32); - this.state = 376; + this.state = 394; this.expression(0); - this.state = 377; + this.state = 395; this.match(CashScriptParser.T__33); - this.state = 378; + this.state = 396; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 36)) & ~0x1F) === 0 && ((1 << (_la - 36)) & 31) !== 0))) { @@ -1975,15 +2021,15 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 380; + this.state = 398; (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__40); - this.state = 381; + this.state = 399; this.match(CashScriptParser.T__32); - this.state = 382; + this.state = 400; this.expression(0); - this.state = 383; + this.state = 401; this.match(CashScriptParser.T__33); - this.state = 384; + this.state = 402; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 36)) & ~0x1F) === 0 && ((1 << (_la - 36)) & 991) !== 0))) { @@ -2000,7 +2046,7 @@ export default class CashScriptParser extends Parser { localctx = new UnaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 386; + this.state = 404; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===5 || _la===50 || _la===51)) { @@ -2010,7 +2056,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 387; + this.state = 405; this.expression(15); } break; @@ -2019,47 +2065,47 @@ export default class CashScriptParser extends Parser { localctx = new ArrayContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 388; + this.state = 406; this.match(CashScriptParser.T__32); - this.state = 400; + this.state = 418; 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)) { { - this.state = 389; + this.state = 407; this.expression(0); - this.state = 394; + this.state = 412; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 35, 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 = 408; + this.match(CashScriptParser.T__14); + this.state = 409; this.expression(0); } } } - this.state = 396; + this.state = 414; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); } - this.state = 398; + this.state = 416; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===19) { + if (_la===15) { { - this.state = 397; - this.match(CashScriptParser.T__18); + this.state = 415; + this.match(CashScriptParser.T__14); } } } } - this.state = 402; + this.state = 420; this.match(CashScriptParser.T__33); } break; @@ -2068,7 +2114,7 @@ export default class CashScriptParser extends Parser { localctx = new NullaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 403; + this.state = 421; this.match(CashScriptParser.NullaryOp); } break; @@ -2077,7 +2123,7 @@ export default class CashScriptParser extends Parser { localctx = new IdentifierContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 404; + this.state = 422; this.match(CashScriptParser.Identifier); } break; @@ -2086,15 +2132,15 @@ export default class CashScriptParser extends Parser { localctx = new LiteralExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 405; + this.state = 423; this.literal(); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 460; + this.state = 478; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 37, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -2102,19 +2148,19 @@ export default class CashScriptParser extends Parser { } _prevctx = localctx; { - this.state = 458; + this.state = 476; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 36, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 39, 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 = 426; if (!(this.precpred(this._ctx, 14))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 14)"); } - this.state = 409; + this.state = 427; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 52)) & ~0x1F) === 0 && ((1 << (_la - 52)) & 7) !== 0))) { @@ -2124,7 +2170,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 410; + this.state = 428; (localctx as BinaryOpContext)._right = this.expression(15); } break; @@ -2133,11 +2179,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 = 411; + this.state = 429; if (!(this.precpred(this._ctx, 13))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 13)"); } - this.state = 412; + this.state = 430; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===51 || _la===55)) { @@ -2147,7 +2193,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 413; + this.state = 431; (localctx as BinaryOpContext)._right = this.expression(14); } break; @@ -2156,11 +2202,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 = 414; + this.state = 432; if (!(this.precpred(this._ctx, 12))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 12)"); } - this.state = 415; + this.state = 433; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===56 || _la===57)) { @@ -2170,7 +2216,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 416; + this.state = 434; (localctx as BinaryOpContext)._right = this.expression(13); } break; @@ -2179,11 +2225,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 = 435; if (!(this.precpred(this._ctx, 11))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 11)"); } - this.state = 418; + this.state = 436; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 960) !== 0))) { @@ -2193,7 +2239,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 419; + this.state = 437; (localctx as BinaryOpContext)._right = this.expression(12); } break; @@ -2202,11 +2248,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 = 420; + this.state = 438; if (!(this.precpred(this._ctx, 10))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 10)"); } - this.state = 421; + this.state = 439; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===58 || _la===59)) { @@ -2216,7 +2262,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 422; + this.state = 440; (localctx as BinaryOpContext)._right = this.expression(11); } break; @@ -2225,13 +2271,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 = 441; if (!(this.precpred(this._ctx, 9))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 9)"); } - this.state = 424; + this.state = 442; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__59); - this.state = 425; + this.state = 443; (localctx as BinaryOpContext)._right = this.expression(10); } break; @@ -2240,13 +2286,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 = 444; if (!(this.precpred(this._ctx, 8))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 8)"); } - this.state = 427; + this.state = 445; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__3); - this.state = 428; + this.state = 446; (localctx as BinaryOpContext)._right = this.expression(9); } break; @@ -2255,13 +2301,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 = 447; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 430; + this.state = 448; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); - this.state = 431; + this.state = 449; (localctx as BinaryOpContext)._right = this.expression(8); } break; @@ -2270,13 +2316,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 = 450; if (!(this.precpred(this._ctx, 6))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 6)"); } - this.state = 433; + this.state = 451; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); - this.state = 434; + this.state = 452; (localctx as BinaryOpContext)._right = this.expression(7); } break; @@ -2285,13 +2331,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 = 453; if (!(this.precpred(this._ctx, 5))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 5)"); } - this.state = 436; + this.state = 454; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); - this.state = 437; + this.state = 455; (localctx as BinaryOpContext)._right = this.expression(6); } break; @@ -2299,15 +2345,15 @@ 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 = 456; if (!(this.precpred(this._ctx, 21))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 21)"); } - this.state = 439; + this.state = 457; this.match(CashScriptParser.T__32); - this.state = 440; + this.state = 458; (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); - this.state = 441; + this.state = 459; this.match(CashScriptParser.T__33); } break; @@ -2315,11 +2361,11 @@ export default class CashScriptParser extends Parser { { localctx = new UnaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 442; + this.state = 460; if (!(this.precpred(this._ctx, 18))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 18)"); } - this.state = 443; + this.state = 461; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===46 || _la===47)) { @@ -2336,18 +2382,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 = 462; if (!(this.precpred(this._ctx, 17))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 17)"); } - this.state = 445; + this.state = 463; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__47); - this.state = 446; + this.state = 464; this.match(CashScriptParser.T__13); - this.state = 447; + this.state = 465; (localctx as BinaryOpContext)._right = this.expression(0); - this.state = 448; - this.match(CashScriptParser.T__14); + this.state = 466; + this.match(CashScriptParser.T__15); } break; case 14: @@ -2355,30 +2401,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 = 468; if (!(this.precpred(this._ctx, 16))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 16)"); } - this.state = 451; + this.state = 469; this.match(CashScriptParser.T__48); - this.state = 452; + this.state = 470; this.match(CashScriptParser.T__13); - this.state = 453; + this.state = 471; (localctx as SliceContext)._start = this.expression(0); - this.state = 454; - this.match(CashScriptParser.T__18); - this.state = 455; - (localctx as SliceContext)._end = this.expression(0); - this.state = 456; + this.state = 472; this.match(CashScriptParser.T__14); + this.state = 473; + (localctx as SliceContext)._end = this.expression(0); + this.state = 474; + this.match(CashScriptParser.T__15); } break; } } } - this.state = 462; + this.state = 480; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 37, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); } } } @@ -2403,7 +2449,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 463; + this.state = 481; this.match(CashScriptParser.T__63); } } @@ -2426,41 +2472,41 @@ export default class CashScriptParser extends Parser { let localctx: LiteralContext = new LiteralContext(this, this._ctx, this.state); this.enterRule(localctx, 78, CashScriptParser.RULE_literal); try { - this.state = 470; + this.state = 488; this._errHandler.sync(this); switch (this._input.LA(1)) { case 66: this.enterOuterAlt(localctx, 1); { - this.state = 465; + this.state = 483; this.match(CashScriptParser.BooleanLiteral); } break; case 68: this.enterOuterAlt(localctx, 2); { - this.state = 466; + this.state = 484; this.numberLiteral(); } break; case 75: this.enterOuterAlt(localctx, 3); { - this.state = 467; + this.state = 485; this.match(CashScriptParser.StringLiteral); } break; case 76: this.enterOuterAlt(localctx, 4); { - this.state = 468; + this.state = 486; this.match(CashScriptParser.DateLiteral); } break; case 77: this.enterOuterAlt(localctx, 5); { - this.state = 469; + this.state = 487; this.match(CashScriptParser.HexLiteral); } break; @@ -2489,14 +2535,14 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 472; + this.state = 490; this.match(CashScriptParser.NumberLiteral); - this.state = 474; + this.state = 492; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 39, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 42, this._ctx) ) { case 1: { - this.state = 473; + this.state = 491; this.match(CashScriptParser.NumberUnit); } break; @@ -2525,7 +2571,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 476; + this.state = 494; _la = this._input.LA(1); if(!(((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0))) { this._errHandler.recoverInline(this); @@ -2558,7 +2604,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 478; + this.state = 496; _la = this._input.LA(1); if(!(((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 259) !== 0))) { this._errHandler.recoverInline(this); @@ -2625,7 +2671,7 @@ 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,84,499,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, @@ -2635,155 +2681,161 @@ export default class CashScriptParser extends Parser { 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, + 1,8,5,8,141,8,8,10,8,12,8,144,9,8,1,8,1,8,3,8,148,8,8,1,8,1,8,1,9,1,9,1, + 9,1,9,1,9,5,9,157,8,9,10,9,12,9,160,9,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10, + 1,11,1,11,5,11,171,8,11,10,11,12,11,174,9,11,1,11,1,11,1,12,1,12,1,12,1, + 12,5,12,182,8,12,10,12,12,12,185,9,12,1,12,3,12,188,8,12,3,12,190,8,12, + 1,12,1,12,1,13,1,13,1,13,1,14,1,14,5,14,199,8,14,10,14,12,14,202,9,14,1, + 14,1,14,3,14,206,8,14,1,15,1,15,1,15,1,15,3,15,212,8,15,1,16,1,16,1,16, + 1,16,1,16,1,16,1,16,1,16,3,16,222,8,16,1,17,1,17,1,18,1,18,1,18,1,18,5, + 18,230,8,18,10,18,12,18,233,9,18,1,19,1,19,3,19,237,8,19,1,20,1,20,5,20, + 241,8,20,10,20,12,20,244,9,20,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1,21,1, + 21,1,21,4,21,256,8,21,11,21,12,21,257,1,21,1,21,1,21,1,22,1,22,1,22,1,22, + 1,22,3,22,268,8,22,1,23,1,23,1,23,1,23,1,23,1,23,1,23,3,23,277,8,23,1,23, + 1,23,1,24,1,24,1,24,1,24,1,24,3,24,286,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,300,8,26,1,27,1,27,1,27,3,27,305, + 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,333, + 8,31,1,32,1,32,1,33,1,33,3,33,339,8,33,1,34,1,34,1,34,1,34,5,34,345,8,34, + 10,34,12,34,348,9,34,1,34,3,34,351,8,34,3,34,353,8,34,1,34,1,34,1,35,1, + 35,1,35,1,36,1,36,1,36,1,36,5,36,364,8,36,10,36,12,36,367,9,36,1,36,3,36, + 370,8,36,3,36,372,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,385,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, + 411,8,37,10,37,12,37,414,9,37,1,37,3,37,417,8,37,3,37,419,8,37,1,37,1,37, + 1,37,1,37,3,37,425,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,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]; + 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,477,8,37, + 10,37,12,37,480,9,37,1,38,1,38,1,39,1,39,1,39,1,39,1,39,3,39,489,8,39,1, + 40,1,40,3,40,493,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,529,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,151,1,0,0,0,20, + 163,1,0,0,0,22,168,1,0,0,0,24,177,1,0,0,0,26,193,1,0,0,0,28,205,1,0,0,0, + 30,211,1,0,0,0,32,221,1,0,0,0,34,223,1,0,0,0,36,225,1,0,0,0,38,236,1,0, + 0,0,40,238,1,0,0,0,42,249,1,0,0,0,44,267,1,0,0,0,46,269,1,0,0,0,48,280, + 1,0,0,0,50,289,1,0,0,0,52,292,1,0,0,0,54,304,1,0,0,0,56,306,1,0,0,0,58, + 314,1,0,0,0,60,320,1,0,0,0,62,332,1,0,0,0,64,334,1,0,0,0,66,338,1,0,0,0, + 68,340,1,0,0,0,70,356,1,0,0,0,72,359,1,0,0,0,74,424,1,0,0,0,76,481,1,0, + 0,0,78,488,1,0,0,0,80,490,1,0,0,0,82,494,1,0,0,0,84,496,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,147,3,24,12,0,135,136,5,13,0,0,136,137,5, + 14,0,0,137,142,3,82,41,0,138,139,5,15,0,0,139,141,3,82,41,0,140,138,1,0, + 0,0,141,144,1,0,0,0,142,140,1,0,0,0,142,143,1,0,0,0,143,145,1,0,0,0,144, + 142,1,0,0,0,145,146,5,16,0,0,146,148,1,0,0,0,147,135,1,0,0,0,147,148,1, + 0,0,0,148,149,1,0,0,0,149,150,3,22,11,0,150,17,1,0,0,0,151,152,5,17,0,0, + 152,153,5,81,0,0,153,154,3,24,12,0,154,158,5,18,0,0,155,157,3,20,10,0,156, + 155,1,0,0,0,157,160,1,0,0,0,158,156,1,0,0,0,158,159,1,0,0,0,159,161,1,0, + 0,0,160,158,1,0,0,0,161,162,5,19,0,0,162,19,1,0,0,0,163,164,5,12,0,0,164, + 165,5,81,0,0,165,166,3,24,12,0,166,167,3,22,11,0,167,21,1,0,0,0,168,172, + 5,18,0,0,169,171,3,30,15,0,170,169,1,0,0,0,171,174,1,0,0,0,172,170,1,0, + 0,0,172,173,1,0,0,0,173,175,1,0,0,0,174,172,1,0,0,0,175,176,5,19,0,0,176, + 23,1,0,0,0,177,189,5,14,0,0,178,183,3,26,13,0,179,180,5,15,0,0,180,182, + 3,26,13,0,181,179,1,0,0,0,182,185,1,0,0,0,183,181,1,0,0,0,183,184,1,0,0, + 0,184,187,1,0,0,0,185,183,1,0,0,0,186,188,5,15,0,0,187,186,1,0,0,0,187, + 188,1,0,0,0,188,190,1,0,0,0,189,178,1,0,0,0,189,190,1,0,0,0,190,191,1,0, + 0,0,191,192,5,16,0,0,192,25,1,0,0,0,193,194,3,82,41,0,194,195,5,81,0,0, + 195,27,1,0,0,0,196,200,5,18,0,0,197,199,3,30,15,0,198,197,1,0,0,0,199,202, + 1,0,0,0,200,198,1,0,0,0,200,201,1,0,0,0,201,203,1,0,0,0,202,200,1,0,0,0, + 203,206,5,19,0,0,204,206,3,30,15,0,205,196,1,0,0,0,205,204,1,0,0,0,206, + 29,1,0,0,0,207,212,3,38,19,0,208,209,3,32,16,0,209,210,5,2,0,0,210,212, + 1,0,0,0,211,207,1,0,0,0,211,208,1,0,0,0,212,31,1,0,0,0,213,222,3,40,20, + 0,214,222,3,42,21,0,215,222,3,44,22,0,216,222,3,46,23,0,217,222,3,48,24, + 0,218,222,3,34,17,0,219,222,3,50,25,0,220,222,3,36,18,0,221,213,1,0,0,0, + 221,214,1,0,0,0,221,215,1,0,0,0,221,216,1,0,0,0,221,217,1,0,0,0,221,218, + 1,0,0,0,221,219,1,0,0,0,221,220,1,0,0,0,222,33,1,0,0,0,223,224,3,70,35, + 0,224,35,1,0,0,0,225,226,5,20,0,0,226,231,3,74,37,0,227,228,5,15,0,0,228, + 230,3,74,37,0,229,227,1,0,0,0,230,233,1,0,0,0,231,229,1,0,0,0,231,232,1, + 0,0,0,232,37,1,0,0,0,233,231,1,0,0,0,234,237,3,52,26,0,235,237,3,54,27, + 0,236,234,1,0,0,0,236,235,1,0,0,0,237,39,1,0,0,0,238,242,3,82,41,0,239, + 241,3,76,38,0,240,239,1,0,0,0,241,244,1,0,0,0,242,240,1,0,0,0,242,243,1, + 0,0,0,243,245,1,0,0,0,244,242,1,0,0,0,245,246,5,81,0,0,246,247,5,10,0,0, + 247,248,3,74,37,0,248,41,1,0,0,0,249,250,3,82,41,0,250,255,5,81,0,0,251, + 252,5,15,0,0,252,253,3,82,41,0,253,254,5,81,0,0,254,256,1,0,0,0,255,251, + 1,0,0,0,256,257,1,0,0,0,257,255,1,0,0,0,257,258,1,0,0,0,258,259,1,0,0,0, + 259,260,5,10,0,0,260,261,3,74,37,0,261,43,1,0,0,0,262,263,5,81,0,0,263, + 264,7,1,0,0,264,268,3,74,37,0,265,266,5,81,0,0,266,268,7,2,0,0,267,262, + 1,0,0,0,267,265,1,0,0,0,268,45,1,0,0,0,269,270,5,25,0,0,270,271,5,14,0, + 0,271,272,5,78,0,0,272,273,5,6,0,0,273,276,3,74,37,0,274,275,5,15,0,0,275, + 277,3,64,32,0,276,274,1,0,0,0,276,277,1,0,0,0,277,278,1,0,0,0,278,279,5, + 16,0,0,279,47,1,0,0,0,280,281,5,25,0,0,281,282,5,14,0,0,282,285,3,74,37, + 0,283,284,5,15,0,0,284,286,3,64,32,0,285,283,1,0,0,0,285,286,1,0,0,0,286, + 287,1,0,0,0,287,288,5,16,0,0,288,49,1,0,0,0,289,290,5,26,0,0,290,291,3, + 68,34,0,291,51,1,0,0,0,292,293,5,27,0,0,293,294,5,14,0,0,294,295,3,74,37, + 0,295,296,5,16,0,0,296,299,3,28,14,0,297,298,5,28,0,0,298,300,3,28,14,0, + 299,297,1,0,0,0,299,300,1,0,0,0,300,53,1,0,0,0,301,305,3,56,28,0,302,305, + 3,58,29,0,303,305,3,60,30,0,304,301,1,0,0,0,304,302,1,0,0,0,304,303,1,0, + 0,0,305,55,1,0,0,0,306,307,5,29,0,0,307,308,3,28,14,0,308,309,5,30,0,0, + 309,310,5,14,0,0,310,311,3,74,37,0,311,312,5,16,0,0,312,313,5,2,0,0,313, + 57,1,0,0,0,314,315,5,30,0,0,315,316,5,14,0,0,316,317,3,74,37,0,317,318, + 5,16,0,0,318,319,3,28,14,0,319,59,1,0,0,0,320,321,5,31,0,0,321,322,5,14, + 0,0,322,323,3,62,31,0,323,324,5,2,0,0,324,325,3,74,37,0,325,326,5,2,0,0, + 326,327,3,44,22,0,327,328,5,16,0,0,328,329,3,28,14,0,329,61,1,0,0,0,330, + 333,3,40,20,0,331,333,3,44,22,0,332,330,1,0,0,0,332,331,1,0,0,0,333,63, + 1,0,0,0,334,335,5,75,0,0,335,65,1,0,0,0,336,339,5,81,0,0,337,339,3,78,39, + 0,338,336,1,0,0,0,338,337,1,0,0,0,339,67,1,0,0,0,340,352,5,14,0,0,341,346, + 3,66,33,0,342,343,5,15,0,0,343,345,3,66,33,0,344,342,1,0,0,0,345,348,1, + 0,0,0,346,344,1,0,0,0,346,347,1,0,0,0,347,350,1,0,0,0,348,346,1,0,0,0,349, + 351,5,15,0,0,350,349,1,0,0,0,350,351,1,0,0,0,351,353,1,0,0,0,352,341,1, + 0,0,0,352,353,1,0,0,0,353,354,1,0,0,0,354,355,5,16,0,0,355,69,1,0,0,0,356, + 357,5,81,0,0,357,358,3,72,36,0,358,71,1,0,0,0,359,371,5,14,0,0,360,365, + 3,74,37,0,361,362,5,15,0,0,362,364,3,74,37,0,363,361,1,0,0,0,364,367,1, + 0,0,0,365,363,1,0,0,0,365,366,1,0,0,0,366,369,1,0,0,0,367,365,1,0,0,0,368, + 370,5,15,0,0,369,368,1,0,0,0,369,370,1,0,0,0,370,372,1,0,0,0,371,360,1, + 0,0,0,371,372,1,0,0,0,372,373,1,0,0,0,373,374,5,16,0,0,374,73,1,0,0,0,375, + 376,6,37,-1,0,376,377,5,14,0,0,377,378,3,74,37,0,378,379,5,16,0,0,379,425, + 1,0,0,0,380,381,3,84,42,0,381,382,5,14,0,0,382,384,3,74,37,0,383,385,5, + 15,0,0,384,383,1,0,0,0,384,385,1,0,0,0,385,386,1,0,0,0,386,387,5,16,0,0, + 387,425,1,0,0,0,388,425,3,70,35,0,389,390,5,32,0,0,390,391,5,81,0,0,391, + 425,3,72,36,0,392,393,5,35,0,0,393,394,5,33,0,0,394,395,3,74,37,0,395,396, + 5,34,0,0,396,397,7,3,0,0,397,425,1,0,0,0,398,399,5,41,0,0,399,400,5,33, + 0,0,400,401,3,74,37,0,401,402,5,34,0,0,402,403,7,4,0,0,403,425,1,0,0,0, + 404,405,7,5,0,0,405,425,3,74,37,15,406,418,5,33,0,0,407,412,3,74,37,0,408, + 409,5,15,0,0,409,411,3,74,37,0,410,408,1,0,0,0,411,414,1,0,0,0,412,410, + 1,0,0,0,412,413,1,0,0,0,413,416,1,0,0,0,414,412,1,0,0,0,415,417,5,15,0, + 0,416,415,1,0,0,0,416,417,1,0,0,0,417,419,1,0,0,0,418,407,1,0,0,0,418,419, + 1,0,0,0,419,420,1,0,0,0,420,425,5,34,0,0,421,425,5,80,0,0,422,425,5,81, + 0,0,423,425,3,78,39,0,424,375,1,0,0,0,424,380,1,0,0,0,424,388,1,0,0,0,424, + 389,1,0,0,0,424,392,1,0,0,0,424,398,1,0,0,0,424,404,1,0,0,0,424,406,1,0, + 0,0,424,421,1,0,0,0,424,422,1,0,0,0,424,423,1,0,0,0,425,478,1,0,0,0,426, + 427,10,14,0,0,427,428,7,6,0,0,428,477,3,74,37,15,429,430,10,13,0,0,430, + 431,7,7,0,0,431,477,3,74,37,14,432,433,10,12,0,0,433,434,7,8,0,0,434,477, + 3,74,37,13,435,436,10,11,0,0,436,437,7,9,0,0,437,477,3,74,37,12,438,439, + 10,10,0,0,439,440,7,10,0,0,440,477,3,74,37,11,441,442,10,9,0,0,442,443, + 5,60,0,0,443,477,3,74,37,10,444,445,10,8,0,0,445,446,5,4,0,0,446,477,3, + 74,37,9,447,448,10,7,0,0,448,449,5,61,0,0,449,477,3,74,37,8,450,451,10, + 6,0,0,451,452,5,62,0,0,452,477,3,74,37,7,453,454,10,5,0,0,454,455,5,63, + 0,0,455,477,3,74,37,6,456,457,10,21,0,0,457,458,5,33,0,0,458,459,5,68,0, + 0,459,477,5,34,0,0,460,461,10,18,0,0,461,477,7,11,0,0,462,463,10,17,0,0, + 463,464,5,48,0,0,464,465,5,14,0,0,465,466,3,74,37,0,466,467,5,16,0,0,467, + 477,1,0,0,0,468,469,10,16,0,0,469,470,5,49,0,0,470,471,5,14,0,0,471,472, + 3,74,37,0,472,473,5,15,0,0,473,474,3,74,37,0,474,475,5,16,0,0,475,477,1, + 0,0,0,476,426,1,0,0,0,476,429,1,0,0,0,476,432,1,0,0,0,476,435,1,0,0,0,476, + 438,1,0,0,0,476,441,1,0,0,0,476,444,1,0,0,0,476,447,1,0,0,0,476,450,1,0, + 0,0,476,453,1,0,0,0,476,456,1,0,0,0,476,460,1,0,0,0,476,462,1,0,0,0,476, + 468,1,0,0,0,477,480,1,0,0,0,478,476,1,0,0,0,478,479,1,0,0,0,479,75,1,0, + 0,0,480,478,1,0,0,0,481,482,5,64,0,0,482,77,1,0,0,0,483,489,5,66,0,0,484, + 489,3,80,40,0,485,489,5,75,0,0,486,489,5,76,0,0,487,489,5,77,0,0,488,483, + 1,0,0,0,488,484,1,0,0,0,488,485,1,0,0,0,488,486,1,0,0,0,488,487,1,0,0,0, + 489,79,1,0,0,0,490,492,5,68,0,0,491,493,5,67,0,0,492,491,1,0,0,0,492,493, + 1,0,0,0,493,81,1,0,0,0,494,495,7,12,0,0,495,83,1,0,0,0,496,497,7,13,0,0, + 497,85,1,0,0,0,43,89,95,101,115,118,130,142,147,158,172,183,187,189,200, + 205,211,221,231,236,242,257,267,276,285,299,304,332,338,346,350,352,365, + 369,371,384,412,416,418,424,476,478,488,492]; private static __ATN: ATN; public static get _ATN(): ATN { @@ -3013,8 +3065,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; @@ -3284,8 +3339,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; @@ -3789,7 +3847,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 6b47aa00a..9070d84fa 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 src/grammar/CashScript.g4 by ANTLR 4.13.2 import {ParseTreeVisitor} from 'antlr4'; diff --git a/packages/cashc/src/print/OutputSourceCodeTraversal.ts b/packages/cashc/src/print/OutputSourceCodeTraversal.ts index 7f703f8a9..715fb32b2 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,8 @@ 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); + const targets = node.targets.map((target) => `${target.type} ${target.name}`).join(', '); + this.addOutput(`${targets} = `, true); this.visit(node.tuple); return node; @@ -166,7 +168,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 e5d9115f8..50ef9dcfc 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 41b49cd45..fbbc662c7 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -17,6 +17,7 @@ import { ConsoleStatementNode, ConsoleParameterNode, ForNode, + TupleAssignmentTarget, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; import { SymbolTable, Symbol, SymbolType } from '../ast/SymbolTable.js'; @@ -166,7 +167,7 @@ export default class SymbolTableTraversal extends AstTraversal { } visitTupleAssignment(node: TupleAssignmentNode): Node { - [node.left, node.right].forEach((variable) => { + node.targets.forEach((variable) => { const definition = createTupleVariableDefinition(node, variable); const { name } = variable; @@ -231,7 +232,7 @@ export default class SymbolTableTraversal extends AstTraversal { function createTupleVariableDefinition( node: TupleAssignmentNode, - variable: TupleAssignmentNode['left'], + variable: TupleAssignmentTarget, ): VariableDefinitionNode { const definition = new VariableDefinitionNode(variable.type, [], variable.name, node.tuple); definition.location = node.location; diff --git a/packages/cashc/src/semantic/TypeCheckTraversal.ts b/packages/cashc/src/semantic/TypeCheckTraversal.ts index 4c5d120c1..37155ab7e 100644 --- a/packages/cashc/src/semantic/TypeCheckTraversal.ts +++ b/packages/cashc/src/semantic/TypeCheckTraversal.ts @@ -49,7 +49,6 @@ import { AssignTypeError, ArrayElementError, IndexOutOfBoundsError, - TupleAssignmentError, BitshiftBitcountNegativeError, UnusedFunctionReturnError, ReturnTypeError, @@ -57,10 +56,10 @@ import { import { BinaryOperator, NullaryOperator, UnaryOperator } from '../ast/Operator.js'; import { GlobalFunction } from '../ast/Globals.js'; import { Symbol } from '../ast/SymbolTable.js'; -import { resultingTypeForBinaryOp } from '../utils.js'; +import { functionReturnType, resultingTypeForBinaryOp } from '../utils.js'; export default class TypeCheckTraversal extends AstTraversal { - private currentFunctionReturnType: Type = PrimitiveType.VOID; + private currentFunctionReturnTypes: Type[] = []; visitVariableDefinition(node: VariableDefinitionNode): Node { node.expression = this.visit(node.expression); @@ -70,17 +69,15 @@ export default class TypeCheckTraversal extends AstTraversal { visitTupleAssignment(node: TupleAssignmentNode): Node { node.tuple = this.visit(node.tuple); - if (!(node.tuple instanceof BinaryOpNode) || node.tuple.operator !== BinaryOperator.SPLIT) { - throw new TupleAssignmentError(node.tuple); - } - 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); + const targetsType = new TupleType(node.targets.map((target) => target.type)); + if (!implicitlyCastable(node.tuple.type, targetsType)) { + const targetNames = node.targets.map((target) => target.name).join(', '); + const syntheticAssignment = new VariableDefinitionNode(targetsType, [], targetNames, node.tuple); syntheticAssignment.location = node.location; throw new AssignTypeError(syntheticAssignment); } + return node; } @@ -195,17 +192,26 @@ 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); + + // Every returned expression must be a single value: forwarding a tuple (e.g. `return pair()` + // from another multi-return function) would otherwise slip through the wrapped comparison below. + node.expressions.forEach((expression) => expectSingleValue(expression, expression.type)); + + const actualType = functionReturnType(node.expressions.map((expression) => expression.type!)); + const expectedType = functionReturnType(this.currentFunctionReturnTypes); + + if (!implicitlyCastable(actualType, expectedType)) { + throw new ReturnTypeError(node, actualType, expectedType); } + return node; } @@ -257,11 +263,18 @@ export default class TypeCheckTraversal extends AstTraversal { expectTuple(node, node.tuple.type); - if (node.index !== 0 && node.index !== 1) { + // Tuple indexing is only supported on .split() results. A multi-return function call leaves all + // of its values on the stack, so it must be destructured instead (codegen has no partial binding). + if (!(node.tuple instanceof BinaryOpNode) || node.tuple.operator !== BinaryOperator.SPLIT) { + expectSingleValue(node.tuple, node.tuple.type); + } + + const { elementTypes } = node.tuple.type as TupleType; + if (node.index < 0 || node.index >= elementTypes.length) { throw new IndexOutOfBoundsError(node); } - node.type = node.index === 0 ? (node.tuple.type as TupleType).leftType : (node.tuple.type as TupleType).rightType; + node.type = elementTypes[node.index]; return node; } @@ -314,6 +327,7 @@ export default class TypeCheckTraversal extends AstTraversal { return node; case BinaryOperator.EQ: case BinaryOperator.NE: + expectSingleValue(node.left, node.left.type); expectCompatibleBytesBounds(node, node.left.type, node.right.type); node.type = PrimitiveType.BOOL; return node; @@ -483,7 +497,7 @@ function expectCompatibleBytesBounds(node: BinaryOpNode, left?: Type, right?: Ty function expectTuple(node: ExpectedNode, actual?: Type): void { if (!(actual instanceof TupleType)) { // We use a placeholder tuple to indicate that we're expecting *any* tuple at all - const placeholderTuple = new TupleType(new BytesType(), new BytesType()); + const placeholderTuple = new TupleType([new BytesType(), new BytesType()]); throw new UnsupportedTypeError(node, actual, placeholderTuple); } } @@ -510,7 +524,7 @@ function inferTupleType(node: BinaryOpNode): Type { // string.split() -> string, string if (node.left.type === PrimitiveType.STRING) { - return new TupleType(PrimitiveType.STRING, PrimitiveType.STRING); + return new TupleType([PrimitiveType.STRING, PrimitiveType.STRING]); } // If the expression is not a bytes type, then it must be a different compatible type (e.g. sig/pubkey) @@ -519,14 +533,14 @@ function inferTupleType(node: BinaryOpNode): Type { // bytes.split(variable) -> bytes, bytes if (!(node.right instanceof IntLiteralNode)) { - return new TupleType(new BytesType(), new BytesType()); + return new TupleType([new BytesType(), new BytesType()]); } const splitIndex = Number(node.right.value); // bytes.split(NumberLiteral) -> bytes(NumberLiteral), bytes if (expressionType.bound === undefined) { - return new TupleType(new BytesType(splitIndex), new BytesType()); + return new TupleType([new BytesType(splitIndex), new BytesType()]); } if (splitIndex > expressionType.bound) { @@ -534,10 +548,10 @@ function inferTupleType(node: BinaryOpNode): Type { } // bytesX.split(NumberLiteral) -> bytes(NumberLiteral), bytes(X - NumberLiteral) - return new TupleType( + return new TupleType([ new BytesType(splitIndex), new BytesType(expressionType.bound! - splitIndex), - ); + ]); } function inferSliceType(node: SliceNode): Type { @@ -655,3 +669,9 @@ function matchSizeLiteral(expr: BinaryOpNode): { sizeNode: UnaryOpNode, literalN const isSizeOp = (node: ExpressionNode): node is UnaryOpNode => ( node instanceof UnaryOpNode && node.operator === UnaryOperator.SIZE ); + +function expectSingleValue(node: Node, type?: Type): void { + if (type instanceof TupleType) { + throw new TypeError(node, type, undefined, `Found tuple '${type}' where a single value was expected`); + } +} diff --git a/packages/cashc/src/utils.ts b/packages/cashc/src/utils.ts index c24a140db..6c46e1c85 100644 --- a/packages/cashc/src/utils.ts +++ b/packages/cashc/src/utils.ts @@ -1,6 +1,12 @@ -import { BytesType, implicitlyCastable, PrimitiveType, Type } from '@cashscript/utils'; +import { BytesType, implicitlyCastable, PrimitiveType, TupleType, Type } from '@cashscript/utils'; import { BinaryOperator } from './ast/Operator.js'; +export function functionReturnType(returnTypes?: Type[]): Type { + if (returnTypes === undefined || returnTypes.length === 0) return PrimitiveType.VOID; + if (returnTypes.length === 1) return returnTypes[0]; + return new TupleType(returnTypes); +} + export function resultingTypeForBinaryOp( operator: BinaryOperator, left: Type, diff --git a/packages/cashc/test/ast/fixtures.ts b/packages/cashc/test/ast/fixtures.ts index 55f856a56..da3e9d90a 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/AssignTypeError/destructure_count_mismatch.cash b/packages/cashc/test/compiler/AssignTypeError/destructure_count_mismatch.cash new file mode 100644 index 000000000..6f56ddb33 --- /dev/null +++ b/packages/cashc/test/compiler/AssignTypeError/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/TupleAssignmentError/unpack_not_tuple.cash b/packages/cashc/test/compiler/AssignTypeError/unpack_not_tuple.cash similarity index 100% rename from packages/cashc/test/compiler/TupleAssignmentError/unpack_not_tuple.cash rename to packages/cashc/test/compiler/AssignTypeError/unpack_not_tuple.cash diff --git a/packages/cashc/test/compiler/ReturnTypeError/too_many_return_values.cash b/packages/cashc/test/compiler/ReturnTypeError/too_many_return_values.cash new file mode 100644 index 000000000..d4df23cf9 --- /dev/null +++ b/packages/cashc/test/compiler/ReturnTypeError/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/TypeError/multi_return_tuple_comparison.cash b/packages/cashc/test/compiler/TypeError/multi_return_tuple_comparison.cash new file mode 100644 index 000000000..dad470b12 --- /dev/null +++ b/packages/cashc/test/compiler/TypeError/multi_return_tuple_comparison.cash @@ -0,0 +1,11 @@ +function pair(int a) returns (int, int) { + return a, a + 1; +} + +contract Test() { + function spend(int x) { + // Both sides have equal tuple types, so this would pass a pure type-equality check, + // but no operator works on tuples + require(pair(x) == pair(x)); + } +} diff --git a/packages/cashc/test/compiler/TypeError/multi_return_tuple_forwarding.cash b/packages/cashc/test/compiler/TypeError/multi_return_tuple_forwarding.cash new file mode 100644 index 000000000..f9230953a --- /dev/null +++ b/packages/cashc/test/compiler/TypeError/multi_return_tuple_forwarding.cash @@ -0,0 +1,15 @@ +function pair(int a) returns (int, int) { + return a, a + 1; +} + +function forward(int a) returns (int, int) { + // The tuple types match, but a returned expression must be a single value + return pair(a); +} + +contract Test() { + function spend(int x) { + int p, int q = forward(x); + require(p == q); + } +} diff --git a/packages/cashc/test/compiler/TypeError/multi_return_tuple_index.cash b/packages/cashc/test/compiler/TypeError/multi_return_tuple_index.cash new file mode 100644 index 000000000..bdacc05d1 --- /dev/null +++ b/packages/cashc/test/compiler/TypeError/multi_return_tuple_index.cash @@ -0,0 +1,11 @@ +function pair(int a) returns (int, int) { + return a, a + 1; +} + +contract Test() { + function spend(int x) { + // Tuple indexing is only supported on .split() results; a multi-return call + // must be destructured + require(pair(x)[0] == 1); + } +} diff --git a/packages/cashc/test/compiler/UnequalTypeError/multi_return_used_as_single_value.cash b/packages/cashc/test/compiler/UnequalTypeError/multi_return_used_as_single_value.cash new file mode 100644 index 000000000..27e7c92e6 --- /dev/null +++ b/packages/cashc/test/compiler/UnequalTypeError/multi_return_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/UnsupportedTypeError/multi_return_nested_in_split_rhs.cash b/packages/cashc/test/compiler/UnsupportedTypeError/multi_return_nested_in_split_rhs.cash new file mode 100644 index 000000000..dd4d46103 --- /dev/null +++ b/packages/cashc/test/compiler/UnsupportedTypeError/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/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts index a22d77437..9ae7289d6 100644 --- a/packages/cashc/test/generation/fixtures.ts +++ b/packages/cashc/test/generation/fixtures.ts @@ -1615,4 +1615,50 @@ export const fixtures: Fixture[] = [ fingerprint: '316a3305152ec0695bf80303736c79dd1f9cc2f1dbccf57d9965094401363307', }, }, + { + // A multi-return function — locks in the calling convention: return values are left on the stack + // in declared order (last value on top) and bound by an N-ary tuple destructuring at the call site. + fn: 'global_function_multi_return.cash', + artifact: { + contractName: 'GlobalFunctionMultiReturn', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // OP_DEFINE divmod (id 0): return a / b, a % b — leaves [quotient, remainder], remainder on top + '6e967b7b97 OP_0 OP_DEFINE ' + // int q, int r = divmod(x, 3); require(q == 4); require(r == 1) + + 'OP_3 OP_0 OP_INVOKE OP_SWAP OP_4 OP_NUMEQUALVERIFY OP_1 OP_NUMEQUAL', + debug: { + bytecode: '056e967b7b97008953008a7c549d519c', + logs: [], + requires: [ + { ip: 8, line: 8 }, + { ip: 11, line: 9 }, + ], + sourceMap: '1::3:1;;::::1;7:33:7:34:0;:23::35:1;;8:16:8:17:0;:21::22;:8::24:1;9:21:9:22:0;:8::24:1', + functions: [ + { + id: 0, + name: 'divmod', + inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }], + bytecode: '6e967b7b97', + sourceMap: '2:11:2:16;::::1;:18::19:0;:22::23;:18:::1', + logs: [], + requires: [], + }, + ], + }, + source: fs.readFileSync(new URL('../valid-contract-files/global_function_multi_return.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: 'f747468c9408ec52949a22dc2f271a944ee5793eabaa913c9c2b1b4c3fbd0a56', + }, + }, ]; 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 000000000..f243ae4b4 --- /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 000000000..2298ab641 --- /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 f797016e9..1b8eb5217 100644 --- a/packages/cashc/test/imports.test.ts +++ b/packages/cashc/test/imports.test.ts @@ -26,6 +26,15 @@ describe('Imports from the filesystem (compileFile)', () => { 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')); + expect(artifact.contractName).toEqual('MultiReturnMain'); + expect(artifact.bytecode).toContain('OP_INVOKE'); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + it('throws when an imported file cannot be found', () => { expect(() => compileFile(fixture('missing_import_main.cash'))).toThrow(ImportResolutionError); }); diff --git a/packages/cashc/test/valid-contract-files/global_function_altstack_cleanup.cash b/packages/cashc/test/valid-contract-files/global_function_altstack_cleanup.cash new file mode 100644 index 000000000..4f539ad7b --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_altstack_cleanup.cash @@ -0,0 +1,20 @@ +function orderedPair(int a, int b, int c) returns (int, int) { + int lo = 0; + int hi = 0; + if (c > 0) { + lo = a; + hi = b; + } else { + lo = b; + hi = a; + } + return lo, hi; +} + +contract GlobalFunctionAltStackCleanup() { + function spend(int x) { + int lo, int hi = orderedPair(1, 2, x); + require(lo == 1, "lo should be 1"); + require(hi == 2, "hi should be 2"); + } +} 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 000000000..384ab9603 --- /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 000000000..15e1ffcff --- /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/cashscript/test/debugging.test.ts b/packages/cashscript/test/debugging.test.ts index 408109291..7d882ab47 100644 --- a/packages/cashscript/test/debugging.test.ts +++ b/packages/cashscript/test/debugging.test.ts @@ -17,6 +17,7 @@ import { artifactTestFunctionDebugging, artifactTestFunctionIntermediateResults, artifactTestImportedFunctionDebugging, + artifactTestMultiReturn, } from './fixture/debugging/debugging_contracts.js'; import { sha256 } from '@cashscript/utils'; @@ -862,6 +863,25 @@ describe('Debugging tests - user-defined function frames', () => { expect(transaction).toFailRequireWith('Failing statement: require(value > 0, "value must be positive")'); }); + it('binds multi-return values to destructuring targets in declared order', () => { + const multiReturnContract = new Contract(artifactTestMultiReturn, [], { provider }); + const multiReturnUtxo = provider.addUtxo(multiReturnContract.address, randomUtxo()); + + // 13 / 3 = 4 remainder 1: both requires only pass if q binds the first return value and r the last + const transaction = new TransactionBuilder({ provider }) + .addInput(multiReturnUtxo, multiReturnContract.unlock.spend(13n)) + .addOutput({ to: multiReturnContract.address, amount: 10000n }); + + expect(transaction).not.toFailRequire(); + + // 14 / 3 = 4 remainder 2: the remainder require fails and attributes to its own line + const failingTransaction = new TransactionBuilder({ provider }) + .addInput(multiReturnUtxo, multiReturnContract.unlock.spend(14n)) + .addOutput({ to: multiReturnContract.address, amount: 10000n }); + + expect(failingTransaction).toFailRequireWith('Test.cash:10 Require statement failed at input 0 in contract Test.cash at line 10 with the following message: remainder should be 1.'); + }); + it('logs intermediate results that get optimised out inside a function', () => { const intermediateContract = new Contract(artifactTestFunctionIntermediateResults, [alicePub], { provider }); const intermediateUtxo = provider.addUtxo(intermediateContract.address, randomUtxo()); diff --git a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts index a54f7604d..58a1f7df7 100644 --- a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts +++ b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts @@ -29,6 +29,23 @@ contract Test(pubkey owner) { } `; +// Multi-value return destructuring: the requires only pass when the first declared return value +// binds to the first target (quotient) and the last to the last (remainder), pinning the runtime +// value ordering of the calling convention. +const CONTRACT_TEST_MULTI_RETURN = ` +function divmod(int a, int b) returns (int, int) { + return a / b, a % b; +} + +contract Test() { + function spend(int x) { + int q, int r = divmod(x, 3); + require(q == 4, "quotient should be 4"); + require(r == 1, "remainder should be 1"); + } +} +`; + const CONTRACT_TEST_REQUIRES = ` contract Test() { function test_logs() { @@ -468,6 +485,7 @@ export const artifactTestRequireInsideLoop = compileString(CONTRACT_TEST_REQUIRE export const artifactTestLogInsideLoop = compileString(CONTRACT_TEST_LOG_INSIDE_LOOP); export const artifactTestFunctionDebugging = compileString(CONTRACT_TEST_FUNCTION_DEBUGGING); export const artifactTestFunctionIntermediateResults = compileString(CONTRACT_TEST_FUNCTION_INTERMEDIATE_RESULTS); +export const artifactTestMultiReturn = compileString(CONTRACT_TEST_MULTI_RETURN); // 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)); diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index 63c519377..a36821c79 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -28,12 +28,11 @@ export class BytesType { export class TupleType { constructor( - public leftType: Type, - public rightType: Type, + public elementTypes: Type[], ) { } toString(): string { - return `(${this.leftType}, ${this.rightType})`; + return `(${this.elementTypes.join(', ')})`; } } @@ -120,9 +119,8 @@ export function implicitlyCastable(actual?: Type, expected?: Type): boolean { if (actual === PrimitiveType.VOID || expected === PrimitiveType.VOID) return false; if (actual instanceof TupleType && expected instanceof TupleType) { - const leftIsCompatible = implicitlyCastable(actual.leftType, expected.leftType); - const rightIsCompatible = implicitlyCastable(actual.rightType, expected.rightType); - return leftIsCompatible && rightIsCompatible; + return actual.elementTypes.length === expected.elementTypes.length + && actual.elementTypes.every((elementType, i) => implicitlyCastable(elementType, expected.elementTypes[i])); } // Can't cast between Tuple and non-Tuple diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index aa3f80391..79cfa3d2b 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -117,6 +117,22 @@ contract Example() { } ``` +A function can also return **multiple values** by declaring `returns (T1, T2, ...)` and returning a comma-separated list. A call to such a function must be destructured into exactly one variable per return value: + +```solidity +function divmod(int a, int b) returns (int, int) { + return a / b, a % b; +} + +contract Example() { + function spend(int x) { + int quotient, int remainder = divmod(x, 3); + require(quotient == 4); + require(remainder == 1); + } +} +``` + ### Importing functions from other files Top-level functions can be split across files and pulled in with an `import` directive, which makes the imported file's functions available as if they were declared locally. All `import` directives must appear at the **top of the file** after any `pragma` directives and before any function or contract definitions. @@ -152,7 +168,7 @@ Imported files can declare their own [`pragma` directives](#pragma), and every p ### Limitations This first version of user-defined functions is intentionally limited in scope: -- Functions return **at most one value** (no multiple/tuple returns), and a value-returning function must end with a single `return` statement (no early or conditional returns — compute into a variable and return it at the end). +- A value-returning function must end with a single `return` statement (no early or conditional returns — compute into a variable and return it at the end). - No advanced optimisations are performed yet on user-defined functions. :::note diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 6b01601cc..beb928199 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -8,6 +8,7 @@ title: Release Notes #### cashc compiler - :sparkles: Add support for user-defined reusable functions. +- :sparkles: Add support for multiple return values in user-defined functions, destructured at the call site. - :sparkles: Add support for `import` directives to share user-defined functions across files. - :hammer_and_wrench: Update `compileString` to take an optional `files` object for filesystem-free import resolution. - :racehorse: Add new `OP_SWAP OP_MUL` optimisation. From 5c681ffd89de008ed8f9795bbe161febb47f80e8 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 23 Jul 2026 11:55:06 +0200 Subject: [PATCH 11/37] Global constants + inlining optimisations (#426) --- .cspell.json | 4 +- AGENTS.md | 2 +- packages/cashc/src/Errors.ts | 43 +- packages/cashc/src/ast/AST.ts | 32 +- packages/cashc/src/ast/AstBuilder.ts | 18 +- packages/cashc/src/ast/AstTraversal.ts | 8 + packages/cashc/src/ast/AstVisitor.ts | 2 + packages/cashc/src/ast/SymbolTable.ts | 23 +- packages/cashc/src/compiler.ts | 49 +- packages/cashc/src/dependency-resolution.ts | 44 +- .../src/generation/GenerateTargetTraversal.ts | 131 +- packages/cashc/src/generation/inlining.ts | 74 + packages/cashc/src/grammar/CashScript.g4 | 5 + packages/cashc/src/grammar/CashScript.interp | 5 +- packages/cashc/src/grammar/CashScript.tokens | 96 +- .../cashc/src/grammar/CashScriptLexer.interp | 4 +- .../cashc/src/grammar/CashScriptLexer.tokens | 96 +- packages/cashc/src/grammar/CashScriptLexer.ts | 447 +++--- .../cashc/src/grammar/CashScriptParser.ts | 1303 +++++++++-------- .../cashc/src/grammar/CashScriptVisitor.ts | 9 +- packages/cashc/src/internal.ts | 8 + .../src/print/OutputSourceCodeTraversal.ts | 10 + .../semantic/DeadCodeEliminationTraversal.ts | 18 +- .../semantic/EnsureFinalRequireTraversal.ts | 7 +- .../semantic/LowerGlobalConstantsTraversal.ts | 113 ++ .../src/semantic/SymbolTableTraversal.ts | 53 +- .../cashc/src/semantic/TypeCheckTraversal.ts | 10 +- packages/cashc/test/ast/fixtures.ts | 55 +- .../global_constant_wrong_type.cash | 7 + .../modify_global_constant.cash | 8 + .../void_global_function_without_require.cash | 11 + .../global_constant_non_literal.cash | 7 + .../duplicate_global_constant.cash | 8 + .../global_constant_with_builtin_name.cash | 7 + .../global_constant_with_function_name.cash | 11 + .../parameter_shadows_global_constant.cash | 7 + .../variable_shadows_global_constant.cash | 8 + .../assign_to_builtin_name.cash | 6 + .../assign_to_function_name.cash | 10 + .../cashc/test/dead-code-elimination.test.ts | 164 --- packages/cashc/test/generation/fixtures.ts | 200 ++- .../cashc/test/generation/generation.test.ts | 2 +- .../cashc/test/global-definitions.test.ts | 508 +++++++ packages/cashc/test/imports.test.ts | 34 +- .../global_constant_inlined.cash | 7 + .../global_constant_literals.cash | 17 + .../global_constant_shared.cash | 8 + .../global_function_inlined.cash | 11 + packages/cashscript/src/Errors.ts | 13 +- packages/cashscript/src/debug-frame.ts | 82 +- packages/cashscript/src/debugging.ts | 5 +- packages/cashscript/test/debugging.test.ts | 88 +- .../fixture/debugging/debugging_contracts.ts | 32 +- .../fixture/debugging/function_helpers.cash | 1 + packages/utils/src/artifact.ts | 18 +- packages/utils/src/bitauth-script.ts | 9 +- packages/utils/src/script.ts | 59 +- packages/utils/src/source-map.ts | 20 + packages/utils/test/bitauth-script.test.ts | 6 +- .../test/fixtures/bitauth-script.fixture.ts | 124 +- website/docs/compiler/artifacts.md | 9 +- website/docs/compiler/compiler.md | 2 +- website/docs/compiler/grammar.md | 5 + website/docs/language/contracts.md | 58 +- website/docs/releases/release-notes.md | 2 + 65 files changed, 2873 insertions(+), 1370 deletions(-) create mode 100644 packages/cashc/src/generation/inlining.ts create mode 100644 packages/cashc/src/internal.ts create mode 100644 packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts create mode 100644 packages/cashc/test/compiler/AssignTypeError/global_constant_wrong_type.cash create mode 100644 packages/cashc/test/compiler/ConstantModificationError/modify_global_constant.cash create mode 100644 packages/cashc/test/compiler/FinalRequireStatementError/void_global_function_without_require.cash create mode 100644 packages/cashc/test/compiler/ParseError/global_constant_non_literal.cash create mode 100644 packages/cashc/test/compiler/RedefinitionError/duplicate_global_constant.cash create mode 100644 packages/cashc/test/compiler/RedefinitionError/global_constant_with_builtin_name.cash create mode 100644 packages/cashc/test/compiler/RedefinitionError/global_constant_with_function_name.cash create mode 100644 packages/cashc/test/compiler/RedefinitionError/parameter_shadows_global_constant.cash create mode 100644 packages/cashc/test/compiler/RedefinitionError/variable_shadows_global_constant.cash create mode 100644 packages/cashc/test/compiler/UndefinedReferenceError/assign_to_builtin_name.cash create mode 100644 packages/cashc/test/compiler/UndefinedReferenceError/assign_to_function_name.cash delete mode 100644 packages/cashc/test/dead-code-elimination.test.ts create mode 100644 packages/cashc/test/global-definitions.test.ts create mode 100644 packages/cashc/test/valid-contract-files/global_constant_inlined.cash create mode 100644 packages/cashc/test/valid-contract-files/global_constant_literals.cash create mode 100644 packages/cashc/test/valid-contract-files/global_constant_shared.cash create mode 100644 packages/cashc/test/valid-contract-files/global_function_inlined.cash diff --git a/.cspell.json b/.cspell.json index 9165d42ac..a4226af31 100644 --- a/.cspell.json +++ b/.cspell.json @@ -1,5 +1,5 @@ { - "version": "0.1", + "version": "0.2", "language": "en-GB", "words": [ "aave", @@ -11,6 +11,7 @@ "authchain", "anyhedge", "anyonecanpay", + "backpointer", "badlength", "bchjs", "bchreg", @@ -31,6 +32,7 @@ "boolor", "bytecode", "bytesize", + "callees", "cashaddress", "cashc", "cashproof", diff --git a/AGENTS.md b/AGENTS.md index 9d0c302a9..61233412c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,6 +1,6 @@ # CLAUDE.md -NEVER stage changes, just leave them in the working directory. +NEVER stage or unstage changes, just leave them in the working directory. This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index 072cb95af..04bf08080 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -3,8 +3,8 @@ import { IdentifierNode, ImportNode, FunctionDefinitionNode, + ConstantDefinitionNode, VariableDefinitionNode, - ParameterNode, Node, FunctionCallNode, BinaryOpNode, @@ -12,7 +12,6 @@ import { TimeOpNode, CastNode, AssignNode, - BranchNode, ArrayNode, TupleIndexOpNode, RequireNode, @@ -73,13 +72,12 @@ export class InvalidSymbolTypeError extends CashScriptError { } } -export class RedefinitionError extends CashScriptError { } - -export class FunctionRedefinitionError extends RedefinitionError { +export class RedefinitionError extends CashScriptError { constructor( - public node: FunctionDefinitionNode, + public node: Node, + public identifier: string, ) { - super(node, `Redefinition of function ${node.name}`); + super(node, `Redefinition of identifier ${identifier}`); } } @@ -99,14 +97,6 @@ export class ImportResolutionError extends CashScriptError { } } -export class VariableRedefinitionError extends RedefinitionError { - constructor( - public node: VariableDefinitionNode | ParameterNode, - ) { - super(node, `Redefinition of variable ${node.name}`); - } -} - export class UnusedVariableError extends CashScriptError { constructor( public symbol: Symbol, @@ -264,27 +254,24 @@ export class CastTypeError extends TypeError { export class AssignTypeError extends TypeError { constructor( - node: AssignNode | VariableDefinitionNode, + node: AssignNode | VariableDefinitionNode | ConstantDefinitionNode, ) { const expected = node instanceof AssignNode ? node.identifier.type : node.type; - super(node, node.expression.type, expected, `Type '${node.expression.type}' can not be assigned to variable of type '${expected}'`); - } -} - -export class ConstantConditionError extends CashScriptError { - constructor( - node: BranchNode | RequireNode, - res: boolean, - ) { - super(node, `Condition always evaluates to ${res}`); + const expression = node instanceof ConstantDefinitionNode ? node.value : node.expression; + const target = node instanceof ConstantDefinitionNode ? `constant '${node.name}'` : 'variable'; + super(node, expression.type, expected, `Type '${expression.type}' can not be assigned to ${target} of type '${expected}'`); } } export class ConstantModificationError extends CashScriptError { + constructor(node: VariableDefinitionNode | ConstantDefinitionNode); + constructor(node: Node, name: string); constructor( - node: VariableDefinitionNode, + node: Node, + name?: string, ) { - super(node, `Tried to modify immutable variable '${node.name}'`); + const constantName = name ?? (node as VariableDefinitionNode | ConstantDefinitionNode).name; + super(node, `Tried to modify immutable variable '${constantName}'`); } } diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index 4c898d0a0..4b222d15b 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -27,12 +27,13 @@ export enum FunctionKind { } export class SourceFileNode extends Node { - // The source file's scope: the table of global functions (each symbol carries its VM function-table id). + // The source file's scope: the table of global definitions (shared definitions carry a VM function-table id). symbolTable?: SymbolTable; constructor( public contract?: ContractNode, public functions: FunctionDefinitionNode[] = [], + public constants: ConstantDefinitionNode[] = [], public imports: ImportNode[] = [], public pragmas: string[] = [], ) { @@ -44,6 +45,24 @@ export class SourceFileNode extends Node { } } +export class ConstantDefinitionNode extends Node implements Named, Typed { + // Source provenance for debugging. Set on imported constants, left undefined for constants in the contract's own file. + sourceCode?: string; + sourceFile?: string; + + constructor( + public type: Type, + public name: string, + public value: LiteralNode, + ) { + super(); + } + + accept(visitor: AstVisitor): T { + return visitor.visitConstantDefinition(this); + } +} + export class ImportNode extends Node { constructor( public path: string, @@ -76,6 +95,9 @@ export class FunctionDefinitionNode extends Node implements Named { symbolTable?: SymbolTable; opRolls: Map = new Map(); + // Set when this is the synthetic zero-argument function used to lower a global constant. + constant?: ConstantDefinitionNode; + // Source provenance for debugging. Set on imported functions, left undefined for functions in the contract's own file. sourceCode?: string; sourceFile?: string; @@ -98,6 +120,7 @@ export class FunctionDefinitionNode extends Node implements Named { export class ParameterNode extends Node implements Named, Typed { constructor( public type: Type, + public modifiers: string[], public name: string, ) { super(); @@ -108,6 +131,8 @@ export class ParameterNode extends Node implements Named, Typed { } } +export type DefinitionNode = VariableDefinitionNode | ConstantDefinitionNode | FunctionDefinitionNode | ParameterNode; + export abstract class StatementNode extends Node { } export abstract class ControlStatementNode extends StatementNode { } export abstract class NonControlStatementNode extends StatementNode { } @@ -115,7 +140,7 @@ export abstract class NonControlStatementNode extends StatementNode { } export class VariableDefinitionNode extends NonControlStatementNode implements Named, Typed { constructor( public type: Type, - public modifier: string[], + public modifiers: string[], public name: string, public expression: ExpressionNode, ) { @@ -435,6 +460,9 @@ export class IdentifierNode extends ExpressionNode implements Named { export abstract class LiteralNode extends ExpressionNode { public value: T; + // Set when this is the synthetic literal node used to represent a global constant + constant?: ConstantDefinitionNode; + toString(): string { return `${this.value}`; } diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index 077ece6dd..07a7e99dc 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.visit(def.constantDefinition()) as ConstantDefinitionNode); } 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, constants, imports, pragmas); sourceFileNode.location = Location.fromCtx(ctx); return sourceFileNode; } + visitConstantDefinition(ctx: ConstantDefinitionContext): ConstantDefinitionNode { + const type = parseType(ctx.typeName().getText()); + const name = ctx.Identifier().getText(); + const value = this.createLiteral(ctx.literal()); + const constantDefinition = new ConstantDefinitionNode(type, name, value); + constantDefinition.location = Location.fromCtx(ctx); + return constantDefinition; + } + visitImportDirective(ctx: ImportDirectiveContext): ImportNode { const raw = ctx.StringLiteral().getText(); const importNode = new ImportNode(raw.substring(1, raw.length - 1)); @@ -196,7 +210,7 @@ export default class AstBuilder visitParameter(ctx: ParameterContext): ParameterNode { const type = parseType(ctx.typeName().getText()); const name = ctx.Identifier().getText(); - const parameter = new ParameterNode(type, name); + const parameter = new ParameterNode(type, [], name); parameter.location = Location.fromCtx(ctx); return parameter; } diff --git a/packages/cashc/src/ast/AstTraversal.ts b/packages/cashc/src/ast/AstTraversal.ts index 65a4c3b74..b671528e9 100644 --- a/packages/cashc/src/ast/AstTraversal.ts +++ b/packages/cashc/src/ast/AstTraversal.ts @@ -6,6 +6,7 @@ import { ParameterNode, VariableDefinitionNode, FunctionDefinitionNode, + ConstantDefinitionNode, AssignNode, IdentifierNode, BranchNode, @@ -29,6 +30,7 @@ import { NullaryOpNode, ConsoleStatementNode, ConsoleParameterNode, + LiteralNode, FunctionCallStatementNode, SliceNode, DoWhileNode, @@ -39,6 +41,7 @@ import AstVisitor from './AstVisitor.js'; export default class AstTraversal extends AstVisitor { visitSourceFile(node: SourceFileNode): Node { + node.constants = this.visitList(node.constants) as ConstantDefinitionNode[]; node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; node.contract = this.visitOptional(node.contract) as ContractNode | undefined; return node; @@ -60,6 +63,11 @@ export default class AstTraversal extends AstVisitor { return node; } + visitConstantDefinition(node: ConstantDefinitionNode): Node { + node.value = this.visit(node.value) as LiteralNode; + return node; + } + visitParameter(node: ParameterNode): Node { return node; } diff --git a/packages/cashc/src/ast/AstVisitor.ts b/packages/cashc/src/ast/AstVisitor.ts index 3b72d57f4..2682bfa5d 100644 --- a/packages/cashc/src/ast/AstVisitor.ts +++ b/packages/cashc/src/ast/AstVisitor.ts @@ -6,6 +6,7 @@ import { ParameterNode, VariableDefinitionNode, FunctionDefinitionNode, + ConstantDefinitionNode, AssignNode, IdentifierNode, BranchNode, @@ -39,6 +40,7 @@ export default abstract class AstVisitor { abstract visitImport(node: ImportNode): T; abstract visitContract(node: ContractNode): T; abstract visitFunctionDefinition(node: FunctionDefinitionNode): T; + abstract visitConstantDefinition(node: ConstantDefinitionNode): T; abstract visitParameter(node: ParameterNode): T; abstract visitVariableDefinition(node: VariableDefinitionNode): T; abstract visitTupleAssignment(node: TupleAssignmentNode): T; diff --git a/packages/cashc/src/ast/SymbolTable.ts b/packages/cashc/src/ast/SymbolTable.ts index f06dce04f..38baee7f5 100644 --- a/packages/cashc/src/ast/SymbolTable.ts +++ b/packages/cashc/src/ast/SymbolTable.ts @@ -1,21 +1,23 @@ -import { Type, Script, Op, encodeInt } from '@cashscript/utils'; +import { DebugFrame, Type, Script, Op, encodeInt } from '@cashscript/utils'; import { VariableDefinitionNode, ParameterNode, FunctionDefinitionNode, + ConstantDefinitionNode, IdentifierNode, - Node, + DefinitionNode, } from './AST.js'; import { functionReturnType } from '../utils.js'; export class Symbol { references: IdentifierNode[] = []; + inlinedFrame?: DebugFrame; private constructor( public name: string, public type: Type, public symbolType: SymbolType, - public definition?: Node, + public definition?: DefinitionNode, public parameters?: Type[], public bytecode?: Script, public functionId?: number, @@ -25,6 +27,10 @@ export class Symbol { return new Symbol(node.name, node.type, SymbolType.VARIABLE, node); } + static constant(node: ConstantDefinitionNode): Symbol { + return new Symbol(node.name, node.type, SymbolType.VARIABLE, node); + } + static global(name: string, type: Type): Symbol { return new Symbol(name, type, SymbolType.VARIABLE); } @@ -33,11 +39,9 @@ export class Symbol { return new Symbol(name, returnType, SymbolType.FUNCTION, undefined, parameters, bytecode); } - static userFunction(node: FunctionDefinitionNode, functionId: number): Symbol { + static userFunction(node: FunctionDefinitionNode): Symbol { const parameterTypes = node.parameters.map((parameter) => parameter.type); - const symbol = new Symbol(node.name, functionReturnType(node.returnTypes), SymbolType.FUNCTION, node, parameterTypes); - symbol.setFunctionId(functionId); - return symbol; + return new Symbol(node.name, functionReturnType(node.returnTypes), SymbolType.FUNCTION, node, parameterTypes); } setFunctionId(functionId: number): void { @@ -45,6 +49,11 @@ export class Symbol { this.bytecode = [encodeInt(BigInt(functionId)), Op.OP_INVOKE]; } + setInlinedBytecode(bytecode: Script, frame: DebugFrame): void { + this.bytecode = bytecode; + this.inlinedFrame = frame; + } + static class(name: string, type: Type, parameters: Type[]): Symbol { return new Symbol(name, type, SymbolType.CLASS, undefined, parameters); } diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index a46a4fa06..3a6b538ce 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -5,6 +5,7 @@ import { computeBytecodeFingerprintWithConstructorArgs, generateSourceMap, generateSourceTags, + generateInlineRanges, optimiseBytecode, optimiseBytecodeOld, scriptToAsm, @@ -33,6 +34,7 @@ import EnsureFinalRequireTraversal from './semantic/EnsureFinalRequireTraversal. import EnsureFunctionsSafeTraversal from './semantic/EnsureFunctionsSafeTraversal.js'; import InjectLocktimeGuardTraversal from './semantic/InjectLocktimeGuardTraversal.js'; import DeadCodeEliminationTraversal from './semantic/DeadCodeEliminationTraversal.js'; +import { LowerGlobalConstantsTraversal } from './semantic/LowerGlobalConstantsTraversal.js'; export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = { enforceFunctionParameterTypes: true, @@ -55,11 +57,8 @@ export interface CompileStringOptions extends CompileOptions { * @returns The compiled CashScript artifact, including ABI, bytecode and debug information. * @throws If the source code contains a syntax, semantic, or type error, or an import cannot be resolved. */ -export function compileString(code: string, compilerOptions: CompileStringOptions = {}): Artifact { - const { files, ...remainingOptions } = compilerOptions; - const resolver = createMemoryResolver(files ?? {}); - return compileCode(code, resolver, remainingOptions); -} +export const compileString: (code: string, compilerOptions?: CompileStringOptions) => Artifact = + compileStringInternal; /** * Read a `.cash` source file from disk and compile it to an `Artifact`. @@ -71,7 +70,27 @@ export function compileString(code: string, compilerOptions: CompileStringOption * @returns The compiled CashScript artifact. * @throws If the file cannot be read, or if the source contains a compilation error. */ -export function compileFile(codeFile: PathLike, compilerOptions: CompileOptions = {}): Artifact { +export const compileFile: (codeFile: PathLike, compilerOptions?: CompileOptions) => Artifact = + compileFileInternal; + + +export interface InternalCompilerOptions extends CompilerOptions { + disableInlining?: boolean; +} + +export function compileStringInternal( + code: string, + compilerOptions: CompileStringOptions & InternalCompilerOptions = {}, +): Artifact { + const { files, ...remainingOptions } = compilerOptions; + const resolver = createMemoryResolver(files ?? {}); + return compileCode(code, resolver, remainingOptions); +} + +export function compileFileInternal( + codeFile: PathLike, + compilerOptions: CompileOptions & InternalCompilerOptions = {}, +): Artifact { const filePath = codeFile instanceof URL ? fileURLToPath(codeFile) : codeFile.toString(); const code = fs.readFileSync(filePath, { encoding: 'utf-8' }); const resolver = createDiskResolver(path.dirname(filePath)); @@ -81,9 +100,9 @@ export function compileFile(codeFile: PathLike, compilerOptions: CompileOptions function compileCode( code: string, resolver: ImportResolver, - compilerOptions: CompileOptions, + compilerOptions: CompileOptions & InternalCompilerOptions, ): Artifact { - const { errorListener, ...artifactCompilerOptions } = compilerOptions; + const { errorListener, disableInlining, ...artifactCompilerOptions } = compilerOptions; const mergedCompilerOptions = { ...DEFAULT_COMPILER_OPTIONS, ...artifactCompilerOptions }; // Lexing + parsing @@ -104,11 +123,15 @@ function compileCode( ast = ast.accept(new InjectLocktimeGuardTraversal()) as Ast; } + // Turn global constants into synthetic zero-argument functions, so they can share reachability analysis, + // inlining, and VM function-ID assignment with user-defined functions + ast = ast.accept(new LowerGlobalConstantsTraversal()) as Ast; + // Dead-code elimination: drop global functions that are never invoked before code generation ast = ast.accept(new DeadCodeEliminationTraversal()) as Ast; // Code generation - const traversal = new GenerateTargetTraversal(mergedCompilerOptions); + const traversal = new GenerateTargetTraversal({ ...mergedCompilerOptions, disableInlining }); ast = ast.accept(traversal) as Ast; // Bytecode optimisation @@ -119,6 +142,7 @@ function compileCode( traversal.consoleLogs, traversal.requires, traversal.sourceTags, + traversal.inlineRanges, constructorParamLength, ); @@ -128,15 +152,14 @@ function compileCode( throw new Error('New bytecode optimisation is not backwards compatible, please report this issue to the CashScript team'); } - // Attach debug information - const sourceTags = generateSourceTags(optimisationResult.sourceTags); const debug = { bytecode: binToHex(scriptToBytecode(optimisationResult.script)), sourceMap: generateSourceMap(optimisationResult.locationData), logs: optimisationResult.logs, requires: optimisationResult.requires, - ...(sourceTags ? { sourceTags } : {}), - ...(traversal.frames.length > 0 ? { functions: traversal.frames } : {}), + sourceTags: generateSourceTags(optimisationResult.sourceTags) || undefined, + functions: traversal.frames.length > 0 ? traversal.frames : undefined, + inlineRanges: generateInlineRanges(optimisationResult.inlineRanges) || undefined, }; const fingerprint = computeBytecodeFingerprintWithConstructorArgs(optimisationResult.script, constructorParamLength); diff --git a/packages/cashc/src/dependency-resolution.ts b/packages/cashc/src/dependency-resolution.ts index 5c8b96e2f..363938982 100644 --- a/packages/cashc/src/dependency-resolution.ts +++ b/packages/cashc/src/dependency-resolution.ts @@ -1,6 +1,11 @@ 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 +67,31 @@ export function resolveDependencies( ); } - const importedFunctions = collectImports(ast.imports, resolver, errorListener); - ast.functions = [...importedFunctions, ...ast.functions]; + const importedDefinitions = collectImports(ast.imports, resolver, errorListener); + ast.functions = [...importedDefinitions.functions, ...ast.functions]; + ast.constants = [...importedDefinitions.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 definition 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 []; @@ -102,9 +113,20 @@ function collectImports( func.sourceCode = importedSource; func.sourceFile = resolver.sourceName(canonicalPath); }); + importedAst.constants.forEach((constant) => { + constant.sourceCode = importedSource; + constant.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 778ad80f8..f283c0caa 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -11,8 +11,11 @@ import { scriptToAsm, scriptToBytecode, optimiseBytecode, + OptimiseBytecodeResult, generateSourceMap, generateSourceTags, + generateInlineRanges, + parseSourceTags, FullLocationData, DebugFrame, LogEntry, @@ -22,7 +25,6 @@ import { StackItem, BytesType, TupleType, - CompilerOptions, SourceTagEntry, SourceTagKind, } from '@cashscript/utils'; @@ -71,6 +73,15 @@ import { compileUnaryOp, } from './utils.js'; import { isNumericType } from '../utils.js'; +import { collectFunctionCalls, isRecursive, shouldInline } from './inlining.js'; +import type { InternalCompilerOptions } from '../compiler.js'; + +interface InlineRange { + startIp: number; + endIp: number; + frame: DebugFrame; + line: number; +} export default class GenerateTargetTraversal extends AstTraversal { private locationData: FullLocationData = []; // detailed location data needed for sourcemap creation @@ -86,8 +97,9 @@ export default class GenerateTargetTraversal extends AstTraversal { private scopeDepth = 0; private currentFunction: FunctionDefinitionNode; private constructorParameterCount: number; + inlineRanges: InlineRange[] = []; - constructor(private compilerOptions: CompilerOptions) { + constructor(private compilerOptions: InternalCompilerOptions) { super(); } @@ -144,6 +156,8 @@ export default class GenerateTargetTraversal extends AstTraversal { // The contract is guaranteed to exist here (compileString throws MissingContractError otherwise). node.contract = this.visit(node.contract!) as ContractNode; + this.mergeInlinedDebugInfo(); + // Minimally encode output by going Script -> ASM -> Script this.output = asmToScript(scriptToAsm(this.output)); @@ -152,19 +166,83 @@ export default class GenerateTargetTraversal extends AstTraversal { return node; } + private mergeInlinedDebugInfo(): void { + this.inlineRanges.forEach(({ startIp, frame, line }) => { + this.requires.push(...frame.requires.map((entry) => ({ + ...entry, + ip: entry.ip + startIp, + line, + }))); + + this.consoleLogs.push(...frame.logs.map((entry) => ({ + ...entry, + ip: entry.ip + startIp, + data: entry.data.map((item) => (typeof item === 'string' ? item : { ...item, ip: item.ip + startIp })), + line, + }))); + + // Source tags use opcode indices rather than ips, which excludes the constructor arguments + const startIndex = startIp - this.constructorParameterCount; + this.sourceTags.push(...parseSourceTags(frame.sourceTags ?? '').map((entry) => ({ + ...entry, + startIndex: entry.startIndex + startIndex, + endIndex: entry.endIndex + startIndex, + }))); + }); + + // Restore overall program order, since the merged entries were appended after this program's own + this.requires.sort((a, b) => a.ip - b.ip); + this.consoleLogs.sort((a, b) => a.ip - b.ip); + this.sourceTags.sort((a, b) => a.startIndex - b.startIndex); + } + private defineGlobalFunctions(node: SourceFileNode): void { + // Assign function IDs to recursive functions first + const recursiveFunctions = node.functions.filter(isRecursive); + recursiveFunctions.forEach((func, functionId) => { + node.symbolTable!.getFromThis(func.name)!.setFunctionId(functionId); + }); + + const reachableCalls = [node.contract!, ...node.functions].flatMap((n) => collectFunctionCalls(n)); + const definedFunctions: Array<{ func: FunctionDefinitionNode, compiledResult: OptimiseBytecodeResult }> = []; + let nextFunctionId = recursiveFunctions.length; + node.functions.forEach((func) => { - const { functionId } = node.symbolTable!.getFromThis(func.name)!; - const bodyBytecode = this.compileGlobalFunctionBody(func, functionId!); + const symbol = node.symbolTable!.getFromThis(func.name)!; + const compiledResult = this.compileGlobalFunctionBody(func); + + // If the function should be inlined, we ONLY update the symbol + if (shouldInline(symbol, compiledResult, reachableCalls, nextFunctionId, this.compilerOptions)) { + symbol.setInlinedBytecode(compiledResult.script, this.buildDebugFrame(func, compiledResult)); + return; + } + + // If the function ID is not yet assigned, we assign it (skipped for recursive functions which were assigned above) + if (symbol.functionId === undefined) { + symbol.setFunctionId(nextFunctionId); + nextFunctionId += 1; + } + // Pre-assigned recursive functions and non-inlined functions should be defined + definedFunctions[symbol.functionId!] = { func, compiledResult }; + }); + + // Emit definitions in ID order so debug.functions[n] corresponds to the n-th define site (id n). + definedFunctions.forEach(({ func, compiledResult }, functionId) => { + this.frames.push(this.buildDebugFrame(func, compiledResult, functionId)); const locationData = { location: func.location, positionHint: PositionHint.START }; - this.emit(bodyBytecode, locationData); // - this.emit(encodeInt(BigInt(functionId!)), locationData); // + this.emit(scriptToBytecode(compiledResult.script), locationData); // + this.emit(encodeInt(BigInt(functionId)), locationData); // this.emit(Op.OP_DEFINE, { ...locationData, positionHint: PositionHint.END }); }); + + // Inlined callables are documented as id-less frames after the defined ones + node.functions + .flatMap((func) => node.symbolTable!.getFromThis(func.name)!.inlinedFrame ?? []) + .forEach((frame) => this.frames.push(frame)); } - private compileGlobalFunctionBody(node: FunctionDefinitionNode, functionId: number): Uint8Array { + private compileGlobalFunctionBody(node: FunctionDefinitionNode): OptimiseBytecodeResult { const bodyTraversal = new GenerateTargetTraversal(this.compilerOptions); bodyTraversal.currentFunction = node; bodyTraversal.constructorParameterCount = 0; @@ -177,33 +255,40 @@ export default class GenerateTargetTraversal extends AstTraversal { bodyTraversal.visit(node.body); bodyTraversal.cleanGlobalFunctionStack(node); + bodyTraversal.mergeInlinedDebugInfo(); - const optimised = optimiseBytecode( + const optimisedResult = optimiseBytecode( bodyTraversal.output, bodyTraversal.locationData, bodyTraversal.consoleLogs, bodyTraversal.requires, bodyTraversal.sourceTags, + bodyTraversal.inlineRanges, 0, ); - const bodyBytecode = scriptToBytecode(optimised.script); - const sourceTags = generateSourceTags(optimised.sourceTags); + return optimisedResult; + } - this.frames.push({ + private buildDebugFrame( + node: FunctionDefinitionNode, + optimised: OptimiseBytecodeResult, + functionId?: number, + ): DebugFrame { + return { id: functionId, name: node.name, + kind: node.constant ? ('constant' as const) : undefined, inputs: node.parameters.map((parameter) => ({ name: parameter.name, type: parameter.type.toString() })), - bytecode: binToHex(bodyBytecode), + bytecode: binToHex(scriptToBytecode(optimised.script)), sourceMap: generateSourceMap(optimised.locationData), - ...(sourceTags ? { sourceTags } : {}), - ...(node.sourceCode !== undefined ? { source: node.sourceCode } : {}), - ...(node.sourceFile !== undefined ? { sourceFile: node.sourceFile } : {}), + sourceTags: generateSourceTags(optimised.sourceTags) || undefined, + source: node.sourceCode, + sourceFile: node.sourceFile, logs: optimised.logs, requires: optimised.requires, - }); - - return bodyBytecode; + inlineRanges: generateInlineRanges(optimised.inlineRanges) || undefined, + }; } cleanGlobalFunctionStack(node: FunctionDefinitionNode): void { @@ -665,7 +750,16 @@ export default class GenerateTargetTraversal extends AstTraversal { const symbol = node.identifier.symbol!; node.parameters = this.visitList(node.parameters); + + const startIp = this.output.length + this.constructorParameterCount; + const endIp = startIp + symbol.bytecode!.length - 1; + this.emit(symbol.bytecode!, { location: node.location, positionHint: PositionHint.END }); + + if (symbol.inlinedFrame) { + this.inlineRanges.push({ startIp, endIp, frame: symbol.inlinedFrame, line: node.location.start.line }); + } + this.popFromStack(node.parameters.length); // The call leaves one value per declared return type (none for a void function); a multi-return @@ -897,3 +991,4 @@ export default class GenerateTargetTraversal extends AstTraversal { return node; } } + diff --git a/packages/cashc/src/generation/inlining.ts b/packages/cashc/src/generation/inlining.ts new file mode 100644 index 000000000..3ecad1f50 --- /dev/null +++ b/packages/cashc/src/generation/inlining.ts @@ -0,0 +1,74 @@ +import { + encodeInt, + OptimiseBytecodeResult, + Script, + scriptToBytecode, +} from '@cashscript/utils'; +import { FunctionCallNode, FunctionDefinitionNode, Node } from '../ast/AST.js'; +import AstTraversal from '../ast/AstTraversal.js'; +import { Symbol } from '../ast/SymbolTable.js'; +import type { InternalCompilerOptions } from '../compiler.js'; + +export const shouldInline = ( + symbol: Symbol, + optimisedResult: OptimiseBytecodeResult, + reachableCalls: FunctionCallNode[], + nextFunctionId: number, + compilerOptions: InternalCompilerOptions, +): boolean => { + if (compilerOptions.disableInlining) return false; + if (symbol.functionId !== undefined) return false; + + const callCount = reachableCalls.filter((call) => call.identifier.symbol === symbol).length; + return isWorthInlining(nextFunctionId, optimisedResult.script, callCount); +}; + +function isWorthInlining(candidateFunctionId: number, bodyScript: Script, callCount: number): boolean { + const bodyBytes = scriptToBytecode(bodyScript).length; + const idBytes = scriptToBytecode([encodeInt(BigInt(candidateFunctionId))]).length; + + const bytesWhenDefined = bodyBytes + idBytes + 1 + callCount * (idBytes + 1); + const bytesWhenInlined = callCount * bodyBytes; + + return bytesWhenInlined <= bytesWhenDefined; +} + +class FunctionCallCollector extends AstTraversal { + functionCalls: FunctionCallNode[] = []; + + visitFunctionCall(node: FunctionCallNode): Node { + this.functionCalls.push(node); + node.parameters = this.visitList(node.parameters); + return node; + } +} + +export function collectFunctionCalls(node: Node): FunctionCallNode[] { + const collector = new FunctionCallCollector(); + collector.visit(node); + return collector.functionCalls; +} + +export function isRecursive(func: FunctionDefinitionNode): boolean { + return transitiveCalledFunctions(func).includes(func); +} + +function transitiveCalledFunctions(func: FunctionDefinitionNode): FunctionDefinitionNode[] { + const callees: FunctionDefinitionNode[] = []; + + const visit = (current: FunctionDefinitionNode): void => calledFunctions(current).forEach((callee) => { + if (callees.includes(callee)) return; + callees.push(callee); + visit(callee); + }); + + visit(func); + return callees; +} + +function calledFunctions(func: FunctionDefinitionNode): FunctionDefinitionNode[] { + return collectFunctionCalls(func.body) + .map((call) => call.identifier.symbol?.definition) + .filter((definition): definition is FunctionDefinitionNode => definition instanceof FunctionDefinitionNode) + .filter((definition, index, definitions) => definitions.indexOf(definition) === index); +} diff --git a/packages/cashc/src/grammar/CashScript.g4 b/packages/cashc/src/grammar/CashScript.g4 index c980df8fd..d3733ca9f 100644 --- a/packages/cashc/src/grammar/CashScript.g4 +++ b/packages/cashc/src/grammar/CashScript.g4 @@ -30,6 +30,7 @@ importDirective topLevelDefinition : globalFunctionDefinition + | constantDefinition | contractDefinition ; @@ -37,6 +38,10 @@ globalFunctionDefinition : 'function' Identifier parameterList ('returns' '(' typeName (',' typeName)* ')')? functionBody ; +constantDefinition + : typeName 'constant' Identifier '=' literal ';' + ; + contractDefinition : 'contract' Identifier parameterList '{' contractFunctionDefinition* '}' ; diff --git a/packages/cashc/src/grammar/CashScript.interp b/packages/cashc/src/grammar/CashScript.interp index 5a9ef9b58..ddd920389 100644 --- a/packages/cashc/src/grammar/CashScript.interp +++ b/packages/cashc/src/grammar/CashScript.interp @@ -16,6 +16,7 @@ null '(' ',' ')' +'constant' 'contract' '{' '}' @@ -63,7 +64,6 @@ null '|' '&&' '||' -'constant' null null null @@ -182,6 +182,7 @@ versionOperator importDirective topLevelDefinition globalFunctionDefinition +constantDefinition contractDefinition contractFunctionDefinition functionBody @@ -219,4 +220,4 @@ typeCast atn: -[4, 1, 84, 499, 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, 5, 8, 141, 8, 8, 10, 8, 12, 8, 144, 9, 8, 1, 8, 1, 8, 3, 8, 148, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 5, 9, 157, 8, 9, 10, 9, 12, 9, 160, 9, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11, 5, 11, 171, 8, 11, 10, 11, 12, 11, 174, 9, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 5, 12, 182, 8, 12, 10, 12, 12, 12, 185, 9, 12, 1, 12, 3, 12, 188, 8, 12, 3, 12, 190, 8, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 199, 8, 14, 10, 14, 12, 14, 202, 9, 14, 1, 14, 1, 14, 3, 14, 206, 8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 212, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 222, 8, 16, 1, 17, 1, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 230, 8, 18, 10, 18, 12, 18, 233, 9, 18, 1, 19, 1, 19, 3, 19, 237, 8, 19, 1, 20, 1, 20, 5, 20, 241, 8, 20, 10, 20, 12, 20, 244, 9, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 4, 21, 256, 8, 21, 11, 21, 12, 21, 257, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 3, 22, 268, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 277, 8, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 286, 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, 300, 8, 26, 1, 27, 1, 27, 1, 27, 3, 27, 305, 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, 333, 8, 31, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 339, 8, 33, 1, 34, 1, 34, 1, 34, 1, 34, 5, 34, 345, 8, 34, 10, 34, 12, 34, 348, 9, 34, 1, 34, 3, 34, 351, 8, 34, 3, 34, 353, 8, 34, 1, 34, 1, 34, 1, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 364, 8, 36, 10, 36, 12, 36, 367, 9, 36, 1, 36, 3, 36, 370, 8, 36, 3, 36, 372, 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, 385, 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, 411, 8, 37, 10, 37, 12, 37, 414, 9, 37, 1, 37, 3, 37, 417, 8, 37, 3, 37, 419, 8, 37, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 425, 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, 477, 8, 37, 10, 37, 12, 37, 480, 9, 37, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 489, 8, 39, 1, 40, 1, 40, 3, 40, 493, 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, 529, 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, 151, 1, 0, 0, 0, 20, 163, 1, 0, 0, 0, 22, 168, 1, 0, 0, 0, 24, 177, 1, 0, 0, 0, 26, 193, 1, 0, 0, 0, 28, 205, 1, 0, 0, 0, 30, 211, 1, 0, 0, 0, 32, 221, 1, 0, 0, 0, 34, 223, 1, 0, 0, 0, 36, 225, 1, 0, 0, 0, 38, 236, 1, 0, 0, 0, 40, 238, 1, 0, 0, 0, 42, 249, 1, 0, 0, 0, 44, 267, 1, 0, 0, 0, 46, 269, 1, 0, 0, 0, 48, 280, 1, 0, 0, 0, 50, 289, 1, 0, 0, 0, 52, 292, 1, 0, 0, 0, 54, 304, 1, 0, 0, 0, 56, 306, 1, 0, 0, 0, 58, 314, 1, 0, 0, 0, 60, 320, 1, 0, 0, 0, 62, 332, 1, 0, 0, 0, 64, 334, 1, 0, 0, 0, 66, 338, 1, 0, 0, 0, 68, 340, 1, 0, 0, 0, 70, 356, 1, 0, 0, 0, 72, 359, 1, 0, 0, 0, 74, 424, 1, 0, 0, 0, 76, 481, 1, 0, 0, 0, 78, 488, 1, 0, 0, 0, 80, 490, 1, 0, 0, 0, 82, 494, 1, 0, 0, 0, 84, 496, 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, 147, 3, 24, 12, 0, 135, 136, 5, 13, 0, 0, 136, 137, 5, 14, 0, 0, 137, 142, 3, 82, 41, 0, 138, 139, 5, 15, 0, 0, 139, 141, 3, 82, 41, 0, 140, 138, 1, 0, 0, 0, 141, 144, 1, 0, 0, 0, 142, 140, 1, 0, 0, 0, 142, 143, 1, 0, 0, 0, 143, 145, 1, 0, 0, 0, 144, 142, 1, 0, 0, 0, 145, 146, 5, 16, 0, 0, 146, 148, 1, 0, 0, 0, 147, 135, 1, 0, 0, 0, 147, 148, 1, 0, 0, 0, 148, 149, 1, 0, 0, 0, 149, 150, 3, 22, 11, 0, 150, 17, 1, 0, 0, 0, 151, 152, 5, 17, 0, 0, 152, 153, 5, 81, 0, 0, 153, 154, 3, 24, 12, 0, 154, 158, 5, 18, 0, 0, 155, 157, 3, 20, 10, 0, 156, 155, 1, 0, 0, 0, 157, 160, 1, 0, 0, 0, 158, 156, 1, 0, 0, 0, 158, 159, 1, 0, 0, 0, 159, 161, 1, 0, 0, 0, 160, 158, 1, 0, 0, 0, 161, 162, 5, 19, 0, 0, 162, 19, 1, 0, 0, 0, 163, 164, 5, 12, 0, 0, 164, 165, 5, 81, 0, 0, 165, 166, 3, 24, 12, 0, 166, 167, 3, 22, 11, 0, 167, 21, 1, 0, 0, 0, 168, 172, 5, 18, 0, 0, 169, 171, 3, 30, 15, 0, 170, 169, 1, 0, 0, 0, 171, 174, 1, 0, 0, 0, 172, 170, 1, 0, 0, 0, 172, 173, 1, 0, 0, 0, 173, 175, 1, 0, 0, 0, 174, 172, 1, 0, 0, 0, 175, 176, 5, 19, 0, 0, 176, 23, 1, 0, 0, 0, 177, 189, 5, 14, 0, 0, 178, 183, 3, 26, 13, 0, 179, 180, 5, 15, 0, 0, 180, 182, 3, 26, 13, 0, 181, 179, 1, 0, 0, 0, 182, 185, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 183, 184, 1, 0, 0, 0, 184, 187, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 186, 188, 5, 15, 0, 0, 187, 186, 1, 0, 0, 0, 187, 188, 1, 0, 0, 0, 188, 190, 1, 0, 0, 0, 189, 178, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 191, 1, 0, 0, 0, 191, 192, 5, 16, 0, 0, 192, 25, 1, 0, 0, 0, 193, 194, 3, 82, 41, 0, 194, 195, 5, 81, 0, 0, 195, 27, 1, 0, 0, 0, 196, 200, 5, 18, 0, 0, 197, 199, 3, 30, 15, 0, 198, 197, 1, 0, 0, 0, 199, 202, 1, 0, 0, 0, 200, 198, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, 203, 1, 0, 0, 0, 202, 200, 1, 0, 0, 0, 203, 206, 5, 19, 0, 0, 204, 206, 3, 30, 15, 0, 205, 196, 1, 0, 0, 0, 205, 204, 1, 0, 0, 0, 206, 29, 1, 0, 0, 0, 207, 212, 3, 38, 19, 0, 208, 209, 3, 32, 16, 0, 209, 210, 5, 2, 0, 0, 210, 212, 1, 0, 0, 0, 211, 207, 1, 0, 0, 0, 211, 208, 1, 0, 0, 0, 212, 31, 1, 0, 0, 0, 213, 222, 3, 40, 20, 0, 214, 222, 3, 42, 21, 0, 215, 222, 3, 44, 22, 0, 216, 222, 3, 46, 23, 0, 217, 222, 3, 48, 24, 0, 218, 222, 3, 34, 17, 0, 219, 222, 3, 50, 25, 0, 220, 222, 3, 36, 18, 0, 221, 213, 1, 0, 0, 0, 221, 214, 1, 0, 0, 0, 221, 215, 1, 0, 0, 0, 221, 216, 1, 0, 0, 0, 221, 217, 1, 0, 0, 0, 221, 218, 1, 0, 0, 0, 221, 219, 1, 0, 0, 0, 221, 220, 1, 0, 0, 0, 222, 33, 1, 0, 0, 0, 223, 224, 3, 70, 35, 0, 224, 35, 1, 0, 0, 0, 225, 226, 5, 20, 0, 0, 226, 231, 3, 74, 37, 0, 227, 228, 5, 15, 0, 0, 228, 230, 3, 74, 37, 0, 229, 227, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 37, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 234, 237, 3, 52, 26, 0, 235, 237, 3, 54, 27, 0, 236, 234, 1, 0, 0, 0, 236, 235, 1, 0, 0, 0, 237, 39, 1, 0, 0, 0, 238, 242, 3, 82, 41, 0, 239, 241, 3, 76, 38, 0, 240, 239, 1, 0, 0, 0, 241, 244, 1, 0, 0, 0, 242, 240, 1, 0, 0, 0, 242, 243, 1, 0, 0, 0, 243, 245, 1, 0, 0, 0, 244, 242, 1, 0, 0, 0, 245, 246, 5, 81, 0, 0, 246, 247, 5, 10, 0, 0, 247, 248, 3, 74, 37, 0, 248, 41, 1, 0, 0, 0, 249, 250, 3, 82, 41, 0, 250, 255, 5, 81, 0, 0, 251, 252, 5, 15, 0, 0, 252, 253, 3, 82, 41, 0, 253, 254, 5, 81, 0, 0, 254, 256, 1, 0, 0, 0, 255, 251, 1, 0, 0, 0, 256, 257, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 260, 5, 10, 0, 0, 260, 261, 3, 74, 37, 0, 261, 43, 1, 0, 0, 0, 262, 263, 5, 81, 0, 0, 263, 264, 7, 1, 0, 0, 264, 268, 3, 74, 37, 0, 265, 266, 5, 81, 0, 0, 266, 268, 7, 2, 0, 0, 267, 262, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 268, 45, 1, 0, 0, 0, 269, 270, 5, 25, 0, 0, 270, 271, 5, 14, 0, 0, 271, 272, 5, 78, 0, 0, 272, 273, 5, 6, 0, 0, 273, 276, 3, 74, 37, 0, 274, 275, 5, 15, 0, 0, 275, 277, 3, 64, 32, 0, 276, 274, 1, 0, 0, 0, 276, 277, 1, 0, 0, 0, 277, 278, 1, 0, 0, 0, 278, 279, 5, 16, 0, 0, 279, 47, 1, 0, 0, 0, 280, 281, 5, 25, 0, 0, 281, 282, 5, 14, 0, 0, 282, 285, 3, 74, 37, 0, 283, 284, 5, 15, 0, 0, 284, 286, 3, 64, 32, 0, 285, 283, 1, 0, 0, 0, 285, 286, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 288, 5, 16, 0, 0, 288, 49, 1, 0, 0, 0, 289, 290, 5, 26, 0, 0, 290, 291, 3, 68, 34, 0, 291, 51, 1, 0, 0, 0, 292, 293, 5, 27, 0, 0, 293, 294, 5, 14, 0, 0, 294, 295, 3, 74, 37, 0, 295, 296, 5, 16, 0, 0, 296, 299, 3, 28, 14, 0, 297, 298, 5, 28, 0, 0, 298, 300, 3, 28, 14, 0, 299, 297, 1, 0, 0, 0, 299, 300, 1, 0, 0, 0, 300, 53, 1, 0, 0, 0, 301, 305, 3, 56, 28, 0, 302, 305, 3, 58, 29, 0, 303, 305, 3, 60, 30, 0, 304, 301, 1, 0, 0, 0, 304, 302, 1, 0, 0, 0, 304, 303, 1, 0, 0, 0, 305, 55, 1, 0, 0, 0, 306, 307, 5, 29, 0, 0, 307, 308, 3, 28, 14, 0, 308, 309, 5, 30, 0, 0, 309, 310, 5, 14, 0, 0, 310, 311, 3, 74, 37, 0, 311, 312, 5, 16, 0, 0, 312, 313, 5, 2, 0, 0, 313, 57, 1, 0, 0, 0, 314, 315, 5, 30, 0, 0, 315, 316, 5, 14, 0, 0, 316, 317, 3, 74, 37, 0, 317, 318, 5, 16, 0, 0, 318, 319, 3, 28, 14, 0, 319, 59, 1, 0, 0, 0, 320, 321, 5, 31, 0, 0, 321, 322, 5, 14, 0, 0, 322, 323, 3, 62, 31, 0, 323, 324, 5, 2, 0, 0, 324, 325, 3, 74, 37, 0, 325, 326, 5, 2, 0, 0, 326, 327, 3, 44, 22, 0, 327, 328, 5, 16, 0, 0, 328, 329, 3, 28, 14, 0, 329, 61, 1, 0, 0, 0, 330, 333, 3, 40, 20, 0, 331, 333, 3, 44, 22, 0, 332, 330, 1, 0, 0, 0, 332, 331, 1, 0, 0, 0, 333, 63, 1, 0, 0, 0, 334, 335, 5, 75, 0, 0, 335, 65, 1, 0, 0, 0, 336, 339, 5, 81, 0, 0, 337, 339, 3, 78, 39, 0, 338, 336, 1, 0, 0, 0, 338, 337, 1, 0, 0, 0, 339, 67, 1, 0, 0, 0, 340, 352, 5, 14, 0, 0, 341, 346, 3, 66, 33, 0, 342, 343, 5, 15, 0, 0, 343, 345, 3, 66, 33, 0, 344, 342, 1, 0, 0, 0, 345, 348, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 347, 350, 1, 0, 0, 0, 348, 346, 1, 0, 0, 0, 349, 351, 5, 15, 0, 0, 350, 349, 1, 0, 0, 0, 350, 351, 1, 0, 0, 0, 351, 353, 1, 0, 0, 0, 352, 341, 1, 0, 0, 0, 352, 353, 1, 0, 0, 0, 353, 354, 1, 0, 0, 0, 354, 355, 5, 16, 0, 0, 355, 69, 1, 0, 0, 0, 356, 357, 5, 81, 0, 0, 357, 358, 3, 72, 36, 0, 358, 71, 1, 0, 0, 0, 359, 371, 5, 14, 0, 0, 360, 365, 3, 74, 37, 0, 361, 362, 5, 15, 0, 0, 362, 364, 3, 74, 37, 0, 363, 361, 1, 0, 0, 0, 364, 367, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 366, 1, 0, 0, 0, 366, 369, 1, 0, 0, 0, 367, 365, 1, 0, 0, 0, 368, 370, 5, 15, 0, 0, 369, 368, 1, 0, 0, 0, 369, 370, 1, 0, 0, 0, 370, 372, 1, 0, 0, 0, 371, 360, 1, 0, 0, 0, 371, 372, 1, 0, 0, 0, 372, 373, 1, 0, 0, 0, 373, 374, 5, 16, 0, 0, 374, 73, 1, 0, 0, 0, 375, 376, 6, 37, -1, 0, 376, 377, 5, 14, 0, 0, 377, 378, 3, 74, 37, 0, 378, 379, 5, 16, 0, 0, 379, 425, 1, 0, 0, 0, 380, 381, 3, 84, 42, 0, 381, 382, 5, 14, 0, 0, 382, 384, 3, 74, 37, 0, 383, 385, 5, 15, 0, 0, 384, 383, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 387, 5, 16, 0, 0, 387, 425, 1, 0, 0, 0, 388, 425, 3, 70, 35, 0, 389, 390, 5, 32, 0, 0, 390, 391, 5, 81, 0, 0, 391, 425, 3, 72, 36, 0, 392, 393, 5, 35, 0, 0, 393, 394, 5, 33, 0, 0, 394, 395, 3, 74, 37, 0, 395, 396, 5, 34, 0, 0, 396, 397, 7, 3, 0, 0, 397, 425, 1, 0, 0, 0, 398, 399, 5, 41, 0, 0, 399, 400, 5, 33, 0, 0, 400, 401, 3, 74, 37, 0, 401, 402, 5, 34, 0, 0, 402, 403, 7, 4, 0, 0, 403, 425, 1, 0, 0, 0, 404, 405, 7, 5, 0, 0, 405, 425, 3, 74, 37, 15, 406, 418, 5, 33, 0, 0, 407, 412, 3, 74, 37, 0, 408, 409, 5, 15, 0, 0, 409, 411, 3, 74, 37, 0, 410, 408, 1, 0, 0, 0, 411, 414, 1, 0, 0, 0, 412, 410, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 416, 1, 0, 0, 0, 414, 412, 1, 0, 0, 0, 415, 417, 5, 15, 0, 0, 416, 415, 1, 0, 0, 0, 416, 417, 1, 0, 0, 0, 417, 419, 1, 0, 0, 0, 418, 407, 1, 0, 0, 0, 418, 419, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 420, 425, 5, 34, 0, 0, 421, 425, 5, 80, 0, 0, 422, 425, 5, 81, 0, 0, 423, 425, 3, 78, 39, 0, 424, 375, 1, 0, 0, 0, 424, 380, 1, 0, 0, 0, 424, 388, 1, 0, 0, 0, 424, 389, 1, 0, 0, 0, 424, 392, 1, 0, 0, 0, 424, 398, 1, 0, 0, 0, 424, 404, 1, 0, 0, 0, 424, 406, 1, 0, 0, 0, 424, 421, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 424, 423, 1, 0, 0, 0, 425, 478, 1, 0, 0, 0, 426, 427, 10, 14, 0, 0, 427, 428, 7, 6, 0, 0, 428, 477, 3, 74, 37, 15, 429, 430, 10, 13, 0, 0, 430, 431, 7, 7, 0, 0, 431, 477, 3, 74, 37, 14, 432, 433, 10, 12, 0, 0, 433, 434, 7, 8, 0, 0, 434, 477, 3, 74, 37, 13, 435, 436, 10, 11, 0, 0, 436, 437, 7, 9, 0, 0, 437, 477, 3, 74, 37, 12, 438, 439, 10, 10, 0, 0, 439, 440, 7, 10, 0, 0, 440, 477, 3, 74, 37, 11, 441, 442, 10, 9, 0, 0, 442, 443, 5, 60, 0, 0, 443, 477, 3, 74, 37, 10, 444, 445, 10, 8, 0, 0, 445, 446, 5, 4, 0, 0, 446, 477, 3, 74, 37, 9, 447, 448, 10, 7, 0, 0, 448, 449, 5, 61, 0, 0, 449, 477, 3, 74, 37, 8, 450, 451, 10, 6, 0, 0, 451, 452, 5, 62, 0, 0, 452, 477, 3, 74, 37, 7, 453, 454, 10, 5, 0, 0, 454, 455, 5, 63, 0, 0, 455, 477, 3, 74, 37, 6, 456, 457, 10, 21, 0, 0, 457, 458, 5, 33, 0, 0, 458, 459, 5, 68, 0, 0, 459, 477, 5, 34, 0, 0, 460, 461, 10, 18, 0, 0, 461, 477, 7, 11, 0, 0, 462, 463, 10, 17, 0, 0, 463, 464, 5, 48, 0, 0, 464, 465, 5, 14, 0, 0, 465, 466, 3, 74, 37, 0, 466, 467, 5, 16, 0, 0, 467, 477, 1, 0, 0, 0, 468, 469, 10, 16, 0, 0, 469, 470, 5, 49, 0, 0, 470, 471, 5, 14, 0, 0, 471, 472, 3, 74, 37, 0, 472, 473, 5, 15, 0, 0, 473, 474, 3, 74, 37, 0, 474, 475, 5, 16, 0, 0, 475, 477, 1, 0, 0, 0, 476, 426, 1, 0, 0, 0, 476, 429, 1, 0, 0, 0, 476, 432, 1, 0, 0, 0, 476, 435, 1, 0, 0, 0, 476, 438, 1, 0, 0, 0, 476, 441, 1, 0, 0, 0, 476, 444, 1, 0, 0, 0, 476, 447, 1, 0, 0, 0, 476, 450, 1, 0, 0, 0, 476, 453, 1, 0, 0, 0, 476, 456, 1, 0, 0, 0, 476, 460, 1, 0, 0, 0, 476, 462, 1, 0, 0, 0, 476, 468, 1, 0, 0, 0, 477, 480, 1, 0, 0, 0, 478, 476, 1, 0, 0, 0, 478, 479, 1, 0, 0, 0, 479, 75, 1, 0, 0, 0, 480, 478, 1, 0, 0, 0, 481, 482, 5, 64, 0, 0, 482, 77, 1, 0, 0, 0, 483, 489, 5, 66, 0, 0, 484, 489, 3, 80, 40, 0, 485, 489, 5, 75, 0, 0, 486, 489, 5, 76, 0, 0, 487, 489, 5, 77, 0, 0, 488, 483, 1, 0, 0, 0, 488, 484, 1, 0, 0, 0, 488, 485, 1, 0, 0, 0, 488, 486, 1, 0, 0, 0, 488, 487, 1, 0, 0, 0, 489, 79, 1, 0, 0, 0, 490, 492, 5, 68, 0, 0, 491, 493, 5, 67, 0, 0, 492, 491, 1, 0, 0, 0, 492, 493, 1, 0, 0, 0, 493, 81, 1, 0, 0, 0, 494, 495, 7, 12, 0, 0, 495, 83, 1, 0, 0, 0, 496, 497, 7, 13, 0, 0, 497, 85, 1, 0, 0, 0, 43, 89, 95, 101, 115, 118, 130, 142, 147, 158, 172, 183, 187, 189, 200, 205, 211, 221, 231, 236, 242, 257, 267, 276, 285, 299, 304, 332, 338, 346, 350, 352, 365, 369, 371, 384, 412, 416, 418, 424, 476, 478, 488, 492] \ No newline at end of file +[4, 1, 84, 509, 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, 1, 0, 5, 0, 90, 8, 0, 10, 0, 12, 0, 93, 9, 0, 1, 0, 5, 0, 96, 8, 0, 10, 0, 12, 0, 99, 9, 0, 1, 0, 5, 0, 102, 8, 0, 10, 0, 12, 0, 105, 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, 118, 8, 3, 1, 4, 3, 4, 121, 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, 134, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 144, 8, 8, 10, 8, 12, 8, 147, 9, 8, 1, 8, 1, 8, 3, 8, 151, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 167, 8, 10, 10, 10, 12, 10, 170, 9, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 5, 12, 181, 8, 12, 10, 12, 12, 12, 184, 9, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 192, 8, 13, 10, 13, 12, 13, 195, 9, 13, 1, 13, 3, 13, 198, 8, 13, 3, 13, 200, 8, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 209, 8, 15, 10, 15, 12, 15, 212, 9, 15, 1, 15, 1, 15, 3, 15, 216, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 222, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 232, 8, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 240, 8, 19, 10, 19, 12, 19, 243, 9, 19, 1, 20, 1, 20, 3, 20, 247, 8, 20, 1, 21, 1, 21, 5, 21, 251, 8, 21, 10, 21, 12, 21, 254, 9, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 4, 22, 266, 8, 22, 11, 22, 12, 22, 267, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 278, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 287, 8, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 296, 8, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 310, 8, 27, 1, 28, 1, 28, 1, 28, 3, 28, 315, 8, 28, 1, 29, 1, 29, 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, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 343, 8, 32, 1, 33, 1, 33, 1, 34, 1, 34, 3, 34, 349, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 355, 8, 35, 10, 35, 12, 35, 358, 9, 35, 1, 35, 3, 35, 361, 8, 35, 3, 35, 363, 8, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 374, 8, 37, 10, 37, 12, 37, 377, 9, 37, 1, 37, 3, 37, 380, 8, 37, 3, 37, 382, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 395, 8, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 421, 8, 38, 10, 38, 12, 38, 424, 9, 38, 1, 38, 3, 38, 427, 8, 38, 3, 38, 429, 8, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 435, 8, 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, 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, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 487, 8, 38, 10, 38, 12, 38, 490, 9, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 499, 8, 40, 1, 41, 1, 41, 3, 41, 503, 8, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 0, 1, 76, 44, 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, 0, 14, 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, 1, 0, 71, 73, 2, 0, 71, 72, 79, 79, 539, 0, 91, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 4, 113, 1, 0, 0, 0, 6, 115, 1, 0, 0, 0, 8, 120, 1, 0, 0, 0, 10, 124, 1, 0, 0, 0, 12, 126, 1, 0, 0, 0, 14, 133, 1, 0, 0, 0, 16, 135, 1, 0, 0, 0, 18, 154, 1, 0, 0, 0, 20, 161, 1, 0, 0, 0, 22, 173, 1, 0, 0, 0, 24, 178, 1, 0, 0, 0, 26, 187, 1, 0, 0, 0, 28, 203, 1, 0, 0, 0, 30, 215, 1, 0, 0, 0, 32, 221, 1, 0, 0, 0, 34, 231, 1, 0, 0, 0, 36, 233, 1, 0, 0, 0, 38, 235, 1, 0, 0, 0, 40, 246, 1, 0, 0, 0, 42, 248, 1, 0, 0, 0, 44, 259, 1, 0, 0, 0, 46, 277, 1, 0, 0, 0, 48, 279, 1, 0, 0, 0, 50, 290, 1, 0, 0, 0, 52, 299, 1, 0, 0, 0, 54, 302, 1, 0, 0, 0, 56, 314, 1, 0, 0, 0, 58, 316, 1, 0, 0, 0, 60, 324, 1, 0, 0, 0, 62, 330, 1, 0, 0, 0, 64, 342, 1, 0, 0, 0, 66, 344, 1, 0, 0, 0, 68, 348, 1, 0, 0, 0, 70, 350, 1, 0, 0, 0, 72, 366, 1, 0, 0, 0, 74, 369, 1, 0, 0, 0, 76, 434, 1, 0, 0, 0, 78, 491, 1, 0, 0, 0, 80, 498, 1, 0, 0, 0, 82, 500, 1, 0, 0, 0, 84, 504, 1, 0, 0, 0, 86, 506, 1, 0, 0, 0, 88, 90, 3, 2, 1, 0, 89, 88, 1, 0, 0, 0, 90, 93, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 97, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 94, 96, 3, 12, 6, 0, 95, 94, 1, 0, 0, 0, 96, 99, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 103, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 100, 102, 3, 14, 7, 0, 101, 100, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 107, 5, 0, 0, 1, 107, 1, 1, 0, 0, 0, 108, 109, 5, 1, 0, 0, 109, 110, 3, 4, 2, 0, 110, 111, 3, 6, 3, 0, 111, 112, 5, 2, 0, 0, 112, 3, 1, 0, 0, 0, 113, 114, 5, 3, 0, 0, 114, 5, 1, 0, 0, 0, 115, 117, 3, 8, 4, 0, 116, 118, 3, 8, 4, 0, 117, 116, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 7, 1, 0, 0, 0, 119, 121, 3, 10, 5, 0, 120, 119, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 123, 5, 65, 0, 0, 123, 9, 1, 0, 0, 0, 124, 125, 7, 0, 0, 0, 125, 11, 1, 0, 0, 0, 126, 127, 5, 11, 0, 0, 127, 128, 5, 75, 0, 0, 128, 129, 5, 2, 0, 0, 129, 13, 1, 0, 0, 0, 130, 134, 3, 16, 8, 0, 131, 134, 3, 18, 9, 0, 132, 134, 3, 20, 10, 0, 133, 130, 1, 0, 0, 0, 133, 131, 1, 0, 0, 0, 133, 132, 1, 0, 0, 0, 134, 15, 1, 0, 0, 0, 135, 136, 5, 12, 0, 0, 136, 137, 5, 81, 0, 0, 137, 150, 3, 26, 13, 0, 138, 139, 5, 13, 0, 0, 139, 140, 5, 14, 0, 0, 140, 145, 3, 84, 42, 0, 141, 142, 5, 15, 0, 0, 142, 144, 3, 84, 42, 0, 143, 141, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 148, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 149, 5, 16, 0, 0, 149, 151, 1, 0, 0, 0, 150, 138, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 153, 3, 24, 12, 0, 153, 17, 1, 0, 0, 0, 154, 155, 3, 84, 42, 0, 155, 156, 5, 17, 0, 0, 156, 157, 5, 81, 0, 0, 157, 158, 5, 10, 0, 0, 158, 159, 3, 80, 40, 0, 159, 160, 5, 2, 0, 0, 160, 19, 1, 0, 0, 0, 161, 162, 5, 18, 0, 0, 162, 163, 5, 81, 0, 0, 163, 164, 3, 26, 13, 0, 164, 168, 5, 19, 0, 0, 165, 167, 3, 22, 11, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 172, 5, 20, 0, 0, 172, 21, 1, 0, 0, 0, 173, 174, 5, 12, 0, 0, 174, 175, 5, 81, 0, 0, 175, 176, 3, 26, 13, 0, 176, 177, 3, 24, 12, 0, 177, 23, 1, 0, 0, 0, 178, 182, 5, 19, 0, 0, 179, 181, 3, 32, 16, 0, 180, 179, 1, 0, 0, 0, 181, 184, 1, 0, 0, 0, 182, 180, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 185, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 186, 5, 20, 0, 0, 186, 25, 1, 0, 0, 0, 187, 199, 5, 14, 0, 0, 188, 193, 3, 28, 14, 0, 189, 190, 5, 15, 0, 0, 190, 192, 3, 28, 14, 0, 191, 189, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 198, 5, 15, 0, 0, 197, 196, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 200, 1, 0, 0, 0, 199, 188, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, 202, 5, 16, 0, 0, 202, 27, 1, 0, 0, 0, 203, 204, 3, 84, 42, 0, 204, 205, 5, 81, 0, 0, 205, 29, 1, 0, 0, 0, 206, 210, 5, 19, 0, 0, 207, 209, 3, 32, 16, 0, 208, 207, 1, 0, 0, 0, 209, 212, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 213, 1, 0, 0, 0, 212, 210, 1, 0, 0, 0, 213, 216, 5, 20, 0, 0, 214, 216, 3, 32, 16, 0, 215, 206, 1, 0, 0, 0, 215, 214, 1, 0, 0, 0, 216, 31, 1, 0, 0, 0, 217, 222, 3, 40, 20, 0, 218, 219, 3, 34, 17, 0, 219, 220, 5, 2, 0, 0, 220, 222, 1, 0, 0, 0, 221, 217, 1, 0, 0, 0, 221, 218, 1, 0, 0, 0, 222, 33, 1, 0, 0, 0, 223, 232, 3, 42, 21, 0, 224, 232, 3, 44, 22, 0, 225, 232, 3, 46, 23, 0, 226, 232, 3, 48, 24, 0, 227, 232, 3, 50, 25, 0, 228, 232, 3, 36, 18, 0, 229, 232, 3, 52, 26, 0, 230, 232, 3, 38, 19, 0, 231, 223, 1, 0, 0, 0, 231, 224, 1, 0, 0, 0, 231, 225, 1, 0, 0, 0, 231, 226, 1, 0, 0, 0, 231, 227, 1, 0, 0, 0, 231, 228, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 230, 1, 0, 0, 0, 232, 35, 1, 0, 0, 0, 233, 234, 3, 72, 36, 0, 234, 37, 1, 0, 0, 0, 235, 236, 5, 21, 0, 0, 236, 241, 3, 76, 38, 0, 237, 238, 5, 15, 0, 0, 238, 240, 3, 76, 38, 0, 239, 237, 1, 0, 0, 0, 240, 243, 1, 0, 0, 0, 241, 239, 1, 0, 0, 0, 241, 242, 1, 0, 0, 0, 242, 39, 1, 0, 0, 0, 243, 241, 1, 0, 0, 0, 244, 247, 3, 54, 27, 0, 245, 247, 3, 56, 28, 0, 246, 244, 1, 0, 0, 0, 246, 245, 1, 0, 0, 0, 247, 41, 1, 0, 0, 0, 248, 252, 3, 84, 42, 0, 249, 251, 3, 78, 39, 0, 250, 249, 1, 0, 0, 0, 251, 254, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 255, 1, 0, 0, 0, 254, 252, 1, 0, 0, 0, 255, 256, 5, 81, 0, 0, 256, 257, 5, 10, 0, 0, 257, 258, 3, 76, 38, 0, 258, 43, 1, 0, 0, 0, 259, 260, 3, 84, 42, 0, 260, 265, 5, 81, 0, 0, 261, 262, 5, 15, 0, 0, 262, 263, 3, 84, 42, 0, 263, 264, 5, 81, 0, 0, 264, 266, 1, 0, 0, 0, 265, 261, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 267, 268, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 270, 5, 10, 0, 0, 270, 271, 3, 76, 38, 0, 271, 45, 1, 0, 0, 0, 272, 273, 5, 81, 0, 0, 273, 274, 7, 1, 0, 0, 274, 278, 3, 76, 38, 0, 275, 276, 5, 81, 0, 0, 276, 278, 7, 2, 0, 0, 277, 272, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 278, 47, 1, 0, 0, 0, 279, 280, 5, 26, 0, 0, 280, 281, 5, 14, 0, 0, 281, 282, 5, 78, 0, 0, 282, 283, 5, 6, 0, 0, 283, 286, 3, 76, 38, 0, 284, 285, 5, 15, 0, 0, 285, 287, 3, 66, 33, 0, 286, 284, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 289, 5, 16, 0, 0, 289, 49, 1, 0, 0, 0, 290, 291, 5, 26, 0, 0, 291, 292, 5, 14, 0, 0, 292, 295, 3, 76, 38, 0, 293, 294, 5, 15, 0, 0, 294, 296, 3, 66, 33, 0, 295, 293, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 298, 5, 16, 0, 0, 298, 51, 1, 0, 0, 0, 299, 300, 5, 27, 0, 0, 300, 301, 3, 70, 35, 0, 301, 53, 1, 0, 0, 0, 302, 303, 5, 28, 0, 0, 303, 304, 5, 14, 0, 0, 304, 305, 3, 76, 38, 0, 305, 306, 5, 16, 0, 0, 306, 309, 3, 30, 15, 0, 307, 308, 5, 29, 0, 0, 308, 310, 3, 30, 15, 0, 309, 307, 1, 0, 0, 0, 309, 310, 1, 0, 0, 0, 310, 55, 1, 0, 0, 0, 311, 315, 3, 58, 29, 0, 312, 315, 3, 60, 30, 0, 313, 315, 3, 62, 31, 0, 314, 311, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 314, 313, 1, 0, 0, 0, 315, 57, 1, 0, 0, 0, 316, 317, 5, 30, 0, 0, 317, 318, 3, 30, 15, 0, 318, 319, 5, 31, 0, 0, 319, 320, 5, 14, 0, 0, 320, 321, 3, 76, 38, 0, 321, 322, 5, 16, 0, 0, 322, 323, 5, 2, 0, 0, 323, 59, 1, 0, 0, 0, 324, 325, 5, 31, 0, 0, 325, 326, 5, 14, 0, 0, 326, 327, 3, 76, 38, 0, 327, 328, 5, 16, 0, 0, 328, 329, 3, 30, 15, 0, 329, 61, 1, 0, 0, 0, 330, 331, 5, 32, 0, 0, 331, 332, 5, 14, 0, 0, 332, 333, 3, 64, 32, 0, 333, 334, 5, 2, 0, 0, 334, 335, 3, 76, 38, 0, 335, 336, 5, 2, 0, 0, 336, 337, 3, 46, 23, 0, 337, 338, 5, 16, 0, 0, 338, 339, 3, 30, 15, 0, 339, 63, 1, 0, 0, 0, 340, 343, 3, 42, 21, 0, 341, 343, 3, 46, 23, 0, 342, 340, 1, 0, 0, 0, 342, 341, 1, 0, 0, 0, 343, 65, 1, 0, 0, 0, 344, 345, 5, 75, 0, 0, 345, 67, 1, 0, 0, 0, 346, 349, 5, 81, 0, 0, 347, 349, 3, 80, 40, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0, 0, 349, 69, 1, 0, 0, 0, 350, 362, 5, 14, 0, 0, 351, 356, 3, 68, 34, 0, 352, 353, 5, 15, 0, 0, 353, 355, 3, 68, 34, 0, 354, 352, 1, 0, 0, 0, 355, 358, 1, 0, 0, 0, 356, 354, 1, 0, 0, 0, 356, 357, 1, 0, 0, 0, 357, 360, 1, 0, 0, 0, 358, 356, 1, 0, 0, 0, 359, 361, 5, 15, 0, 0, 360, 359, 1, 0, 0, 0, 360, 361, 1, 0, 0, 0, 361, 363, 1, 0, 0, 0, 362, 351, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 364, 1, 0, 0, 0, 364, 365, 5, 16, 0, 0, 365, 71, 1, 0, 0, 0, 366, 367, 5, 81, 0, 0, 367, 368, 3, 74, 37, 0, 368, 73, 1, 0, 0, 0, 369, 381, 5, 14, 0, 0, 370, 375, 3, 76, 38, 0, 371, 372, 5, 15, 0, 0, 372, 374, 3, 76, 38, 0, 373, 371, 1, 0, 0, 0, 374, 377, 1, 0, 0, 0, 375, 373, 1, 0, 0, 0, 375, 376, 1, 0, 0, 0, 376, 379, 1, 0, 0, 0, 377, 375, 1, 0, 0, 0, 378, 380, 5, 15, 0, 0, 379, 378, 1, 0, 0, 0, 379, 380, 1, 0, 0, 0, 380, 382, 1, 0, 0, 0, 381, 370, 1, 0, 0, 0, 381, 382, 1, 0, 0, 0, 382, 383, 1, 0, 0, 0, 383, 384, 5, 16, 0, 0, 384, 75, 1, 0, 0, 0, 385, 386, 6, 38, -1, 0, 386, 387, 5, 14, 0, 0, 387, 388, 3, 76, 38, 0, 388, 389, 5, 16, 0, 0, 389, 435, 1, 0, 0, 0, 390, 391, 3, 86, 43, 0, 391, 392, 5, 14, 0, 0, 392, 394, 3, 76, 38, 0, 393, 395, 5, 15, 0, 0, 394, 393, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 396, 1, 0, 0, 0, 396, 397, 5, 16, 0, 0, 397, 435, 1, 0, 0, 0, 398, 435, 3, 72, 36, 0, 399, 400, 5, 33, 0, 0, 400, 401, 5, 81, 0, 0, 401, 435, 3, 74, 37, 0, 402, 403, 5, 36, 0, 0, 403, 404, 5, 34, 0, 0, 404, 405, 3, 76, 38, 0, 405, 406, 5, 35, 0, 0, 406, 407, 7, 3, 0, 0, 407, 435, 1, 0, 0, 0, 408, 409, 5, 42, 0, 0, 409, 410, 5, 34, 0, 0, 410, 411, 3, 76, 38, 0, 411, 412, 5, 35, 0, 0, 412, 413, 7, 4, 0, 0, 413, 435, 1, 0, 0, 0, 414, 415, 7, 5, 0, 0, 415, 435, 3, 76, 38, 15, 416, 428, 5, 34, 0, 0, 417, 422, 3, 76, 38, 0, 418, 419, 5, 15, 0, 0, 419, 421, 3, 76, 38, 0, 420, 418, 1, 0, 0, 0, 421, 424, 1, 0, 0, 0, 422, 420, 1, 0, 0, 0, 422, 423, 1, 0, 0, 0, 423, 426, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 425, 427, 5, 15, 0, 0, 426, 425, 1, 0, 0, 0, 426, 427, 1, 0, 0, 0, 427, 429, 1, 0, 0, 0, 428, 417, 1, 0, 0, 0, 428, 429, 1, 0, 0, 0, 429, 430, 1, 0, 0, 0, 430, 435, 5, 35, 0, 0, 431, 435, 5, 80, 0, 0, 432, 435, 5, 81, 0, 0, 433, 435, 3, 80, 40, 0, 434, 385, 1, 0, 0, 0, 434, 390, 1, 0, 0, 0, 434, 398, 1, 0, 0, 0, 434, 399, 1, 0, 0, 0, 434, 402, 1, 0, 0, 0, 434, 408, 1, 0, 0, 0, 434, 414, 1, 0, 0, 0, 434, 416, 1, 0, 0, 0, 434, 431, 1, 0, 0, 0, 434, 432, 1, 0, 0, 0, 434, 433, 1, 0, 0, 0, 435, 488, 1, 0, 0, 0, 436, 437, 10, 14, 0, 0, 437, 438, 7, 6, 0, 0, 438, 487, 3, 76, 38, 15, 439, 440, 10, 13, 0, 0, 440, 441, 7, 7, 0, 0, 441, 487, 3, 76, 38, 14, 442, 443, 10, 12, 0, 0, 443, 444, 7, 8, 0, 0, 444, 487, 3, 76, 38, 13, 445, 446, 10, 11, 0, 0, 446, 447, 7, 9, 0, 0, 447, 487, 3, 76, 38, 12, 448, 449, 10, 10, 0, 0, 449, 450, 7, 10, 0, 0, 450, 487, 3, 76, 38, 11, 451, 452, 10, 9, 0, 0, 452, 453, 5, 61, 0, 0, 453, 487, 3, 76, 38, 10, 454, 455, 10, 8, 0, 0, 455, 456, 5, 4, 0, 0, 456, 487, 3, 76, 38, 9, 457, 458, 10, 7, 0, 0, 458, 459, 5, 62, 0, 0, 459, 487, 3, 76, 38, 8, 460, 461, 10, 6, 0, 0, 461, 462, 5, 63, 0, 0, 462, 487, 3, 76, 38, 7, 463, 464, 10, 5, 0, 0, 464, 465, 5, 64, 0, 0, 465, 487, 3, 76, 38, 6, 466, 467, 10, 21, 0, 0, 467, 468, 5, 34, 0, 0, 468, 469, 5, 68, 0, 0, 469, 487, 5, 35, 0, 0, 470, 471, 10, 18, 0, 0, 471, 487, 7, 11, 0, 0, 472, 473, 10, 17, 0, 0, 473, 474, 5, 49, 0, 0, 474, 475, 5, 14, 0, 0, 475, 476, 3, 76, 38, 0, 476, 477, 5, 16, 0, 0, 477, 487, 1, 0, 0, 0, 478, 479, 10, 16, 0, 0, 479, 480, 5, 50, 0, 0, 480, 481, 5, 14, 0, 0, 481, 482, 3, 76, 38, 0, 482, 483, 5, 15, 0, 0, 483, 484, 3, 76, 38, 0, 484, 485, 5, 16, 0, 0, 485, 487, 1, 0, 0, 0, 486, 436, 1, 0, 0, 0, 486, 439, 1, 0, 0, 0, 486, 442, 1, 0, 0, 0, 486, 445, 1, 0, 0, 0, 486, 448, 1, 0, 0, 0, 486, 451, 1, 0, 0, 0, 486, 454, 1, 0, 0, 0, 486, 457, 1, 0, 0, 0, 486, 460, 1, 0, 0, 0, 486, 463, 1, 0, 0, 0, 486, 466, 1, 0, 0, 0, 486, 470, 1, 0, 0, 0, 486, 472, 1, 0, 0, 0, 486, 478, 1, 0, 0, 0, 487, 490, 1, 0, 0, 0, 488, 486, 1, 0, 0, 0, 488, 489, 1, 0, 0, 0, 489, 77, 1, 0, 0, 0, 490, 488, 1, 0, 0, 0, 491, 492, 5, 17, 0, 0, 492, 79, 1, 0, 0, 0, 493, 499, 5, 66, 0, 0, 494, 499, 3, 82, 41, 0, 495, 499, 5, 75, 0, 0, 496, 499, 5, 76, 0, 0, 497, 499, 5, 77, 0, 0, 498, 493, 1, 0, 0, 0, 498, 494, 1, 0, 0, 0, 498, 495, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 498, 497, 1, 0, 0, 0, 499, 81, 1, 0, 0, 0, 500, 502, 5, 68, 0, 0, 501, 503, 5, 67, 0, 0, 502, 501, 1, 0, 0, 0, 502, 503, 1, 0, 0, 0, 503, 83, 1, 0, 0, 0, 504, 505, 7, 12, 0, 0, 505, 85, 1, 0, 0, 0, 506, 507, 7, 13, 0, 0, 507, 87, 1, 0, 0, 0, 43, 91, 97, 103, 117, 120, 133, 145, 150, 168, 182, 193, 197, 199, 210, 215, 221, 231, 241, 246, 252, 267, 277, 286, 295, 309, 314, 342, 348, 356, 360, 362, 375, 379, 381, 394, 422, 426, 428, 434, 486, 488, 498, 502] \ No newline at end of file diff --git a/packages/cashc/src/grammar/CashScript.tokens b/packages/cashc/src/grammar/CashScript.tokens index 14524e521..074f0fc19 100644 --- a/packages/cashc/src/grammar/CashScript.tokens +++ b/packages/cashc/src/grammar/CashScript.tokens @@ -98,52 +98,52 @@ LINE_COMMENT=84 '('=14 ','=15 ')'=16 -'contract'=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 +'constant'=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 'bytes'=72 diff --git a/packages/cashc/src/grammar/CashScriptLexer.interp b/packages/cashc/src/grammar/CashScriptLexer.interp index 24b54e13f..8cd270bcc 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.interp +++ b/packages/cashc/src/grammar/CashScriptLexer.interp @@ -16,6 +16,7 @@ null '(' ',' ')' +'constant' 'contract' '{' '}' @@ -63,7 +64,6 @@ null '|' '&&' '||' -'constant' null null null @@ -266,4 +266,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, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 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, 235, 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, 44, 0, 0, 232, 30, 1, 0, 0, 0, 233, 234, 5, 41, 0, 0, 234, 32, 1, 0, 0, 0, 235, 236, 5, 99, 0, 0, 236, 237, 5, 111, 0, 0, 237, 238, 5, 110, 0, 0, 238, 239, 5, 116, 0, 0, 239, 240, 5, 114, 0, 0, 240, 241, 5, 97, 0, 0, 241, 242, 5, 99, 0, 0, 242, 243, 5, 116, 0, 0, 243, 34, 1, 0, 0, 0, 244, 245, 5, 123, 0, 0, 245, 36, 1, 0, 0, 0, 246, 247, 5, 125, 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, 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, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 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, 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, 235, 1, 0, 0, 0, 35, 244, 1, 0, 0, 0, 37, 253, 1, 0, 0, 0, 39, 255, 1, 0, 0, 0, 41, 257, 1, 0, 0, 0, 43, 264, 1, 0, 0, 0, 45, 267, 1, 0, 0, 0, 47, 270, 1, 0, 0, 0, 49, 273, 1, 0, 0, 0, 51, 276, 1, 0, 0, 0, 53, 284, 1, 0, 0, 0, 55, 296, 1, 0, 0, 0, 57, 299, 1, 0, 0, 0, 59, 304, 1, 0, 0, 0, 61, 307, 1, 0, 0, 0, 63, 313, 1, 0, 0, 0, 65, 317, 1, 0, 0, 0, 67, 321, 1, 0, 0, 0, 69, 323, 1, 0, 0, 0, 71, 325, 1, 0, 0, 0, 73, 336, 1, 0, 0, 0, 75, 343, 1, 0, 0, 0, 77, 360, 1, 0, 0, 0, 79, 375, 1, 0, 0, 0, 81, 390, 1, 0, 0, 0, 83, 403, 1, 0, 0, 0, 85, 413, 1, 0, 0, 0, 87, 438, 1, 0, 0, 0, 89, 453, 1, 0, 0, 0, 91, 472, 1, 0, 0, 0, 93, 488, 1, 0, 0, 0, 95, 499, 1, 0, 0, 0, 97, 507, 1, 0, 0, 0, 99, 514, 1, 0, 0, 0, 101, 521, 1, 0, 0, 0, 103, 523, 1, 0, 0, 0, 105, 525, 1, 0, 0, 0, 107, 527, 1, 0, 0, 0, 109, 529, 1, 0, 0, 0, 111, 531, 1, 0, 0, 0, 113, 533, 1, 0, 0, 0, 115, 536, 1, 0, 0, 0, 117, 539, 1, 0, 0, 0, 119, 542, 1, 0, 0, 0, 121, 545, 1, 0, 0, 0, 123, 547, 1, 0, 0, 0, 125, 549, 1, 0, 0, 0, 127, 552, 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, 44, 0, 0, 232, 30, 1, 0, 0, 0, 233, 234, 5, 41, 0, 0, 234, 32, 1, 0, 0, 0, 235, 236, 5, 99, 0, 0, 236, 237, 5, 111, 0, 0, 237, 238, 5, 110, 0, 0, 238, 239, 5, 115, 0, 0, 239, 240, 5, 116, 0, 0, 240, 241, 5, 97, 0, 0, 241, 242, 5, 110, 0, 0, 242, 243, 5, 116, 0, 0, 243, 34, 1, 0, 0, 0, 244, 245, 5, 99, 0, 0, 245, 246, 5, 111, 0, 0, 246, 247, 5, 110, 0, 0, 247, 248, 5, 116, 0, 0, 248, 249, 5, 114, 0, 0, 249, 250, 5, 97, 0, 0, 250, 251, 5, 99, 0, 0, 251, 252, 5, 116, 0, 0, 252, 36, 1, 0, 0, 0, 253, 254, 5, 123, 0, 0, 254, 38, 1, 0, 0, 0, 255, 256, 5, 125, 0, 0, 256, 40, 1, 0, 0, 0, 257, 258, 5, 114, 0, 0, 258, 259, 5, 101, 0, 0, 259, 260, 5, 116, 0, 0, 260, 261, 5, 117, 0, 0, 261, 262, 5, 114, 0, 0, 262, 263, 5, 110, 0, 0, 263, 42, 1, 0, 0, 0, 264, 265, 5, 43, 0, 0, 265, 266, 5, 61, 0, 0, 266, 44, 1, 0, 0, 0, 267, 268, 5, 45, 0, 0, 268, 269, 5, 61, 0, 0, 269, 46, 1, 0, 0, 0, 270, 271, 5, 43, 0, 0, 271, 272, 5, 43, 0, 0, 272, 48, 1, 0, 0, 0, 273, 274, 5, 45, 0, 0, 274, 275, 5, 45, 0, 0, 275, 50, 1, 0, 0, 0, 276, 277, 5, 114, 0, 0, 277, 278, 5, 101, 0, 0, 278, 279, 5, 113, 0, 0, 279, 280, 5, 117, 0, 0, 280, 281, 5, 105, 0, 0, 281, 282, 5, 114, 0, 0, 282, 283, 5, 101, 0, 0, 283, 52, 1, 0, 0, 0, 284, 285, 5, 99, 0, 0, 285, 286, 5, 111, 0, 0, 286, 287, 5, 110, 0, 0, 287, 288, 5, 115, 0, 0, 288, 289, 5, 111, 0, 0, 289, 290, 5, 108, 0, 0, 290, 291, 5, 101, 0, 0, 291, 292, 5, 46, 0, 0, 292, 293, 5, 108, 0, 0, 293, 294, 5, 111, 0, 0, 294, 295, 5, 103, 0, 0, 295, 54, 1, 0, 0, 0, 296, 297, 5, 105, 0, 0, 297, 298, 5, 102, 0, 0, 298, 56, 1, 0, 0, 0, 299, 300, 5, 101, 0, 0, 300, 301, 5, 108, 0, 0, 301, 302, 5, 115, 0, 0, 302, 303, 5, 101, 0, 0, 303, 58, 1, 0, 0, 0, 304, 305, 5, 100, 0, 0, 305, 306, 5, 111, 0, 0, 306, 60, 1, 0, 0, 0, 307, 308, 5, 119, 0, 0, 308, 309, 5, 104, 0, 0, 309, 310, 5, 105, 0, 0, 310, 311, 5, 108, 0, 0, 311, 312, 5, 101, 0, 0, 312, 62, 1, 0, 0, 0, 313, 314, 5, 102, 0, 0, 314, 315, 5, 111, 0, 0, 315, 316, 5, 114, 0, 0, 316, 64, 1, 0, 0, 0, 317, 318, 5, 110, 0, 0, 318, 319, 5, 101, 0, 0, 319, 320, 5, 119, 0, 0, 320, 66, 1, 0, 0, 0, 321, 322, 5, 91, 0, 0, 322, 68, 1, 0, 0, 0, 323, 324, 5, 93, 0, 0, 324, 70, 1, 0, 0, 0, 325, 326, 5, 116, 0, 0, 326, 327, 5, 120, 0, 0, 327, 328, 5, 46, 0, 0, 328, 329, 5, 111, 0, 0, 329, 330, 5, 117, 0, 0, 330, 331, 5, 116, 0, 0, 331, 332, 5, 112, 0, 0, 332, 333, 5, 117, 0, 0, 333, 334, 5, 116, 0, 0, 334, 335, 5, 115, 0, 0, 335, 72, 1, 0, 0, 0, 336, 337, 5, 46, 0, 0, 337, 338, 5, 118, 0, 0, 338, 339, 5, 97, 0, 0, 339, 340, 5, 108, 0, 0, 340, 341, 5, 117, 0, 0, 341, 342, 5, 101, 0, 0, 342, 74, 1, 0, 0, 0, 343, 344, 5, 46, 0, 0, 344, 345, 5, 108, 0, 0, 345, 346, 5, 111, 0, 0, 346, 347, 5, 99, 0, 0, 347, 348, 5, 107, 0, 0, 348, 349, 5, 105, 0, 0, 349, 350, 5, 110, 0, 0, 350, 351, 5, 103, 0, 0, 351, 352, 5, 66, 0, 0, 352, 353, 5, 121, 0, 0, 353, 354, 5, 116, 0, 0, 354, 355, 5, 101, 0, 0, 355, 356, 5, 99, 0, 0, 356, 357, 5, 111, 0, 0, 357, 358, 5, 100, 0, 0, 358, 359, 5, 101, 0, 0, 359, 76, 1, 0, 0, 0, 360, 361, 5, 46, 0, 0, 361, 362, 5, 116, 0, 0, 362, 363, 5, 111, 0, 0, 363, 364, 5, 107, 0, 0, 364, 365, 5, 101, 0, 0, 365, 366, 5, 110, 0, 0, 366, 367, 5, 67, 0, 0, 367, 368, 5, 97, 0, 0, 368, 369, 5, 116, 0, 0, 369, 370, 5, 101, 0, 0, 370, 371, 5, 103, 0, 0, 371, 372, 5, 111, 0, 0, 372, 373, 5, 114, 0, 0, 373, 374, 5, 121, 0, 0, 374, 78, 1, 0, 0, 0, 375, 376, 5, 46, 0, 0, 376, 377, 5, 110, 0, 0, 377, 378, 5, 102, 0, 0, 378, 379, 5, 116, 0, 0, 379, 380, 5, 67, 0, 0, 380, 381, 5, 111, 0, 0, 381, 382, 5, 109, 0, 0, 382, 383, 5, 109, 0, 0, 383, 384, 5, 105, 0, 0, 384, 385, 5, 116, 0, 0, 385, 386, 5, 109, 0, 0, 386, 387, 5, 101, 0, 0, 387, 388, 5, 110, 0, 0, 388, 389, 5, 116, 0, 0, 389, 80, 1, 0, 0, 0, 390, 391, 5, 46, 0, 0, 391, 392, 5, 116, 0, 0, 392, 393, 5, 111, 0, 0, 393, 394, 5, 107, 0, 0, 394, 395, 5, 101, 0, 0, 395, 396, 5, 110, 0, 0, 396, 397, 5, 65, 0, 0, 397, 398, 5, 109, 0, 0, 398, 399, 5, 111, 0, 0, 399, 400, 5, 117, 0, 0, 400, 401, 5, 110, 0, 0, 401, 402, 5, 116, 0, 0, 402, 82, 1, 0, 0, 0, 403, 404, 5, 116, 0, 0, 404, 405, 5, 120, 0, 0, 405, 406, 5, 46, 0, 0, 406, 407, 5, 105, 0, 0, 407, 408, 5, 110, 0, 0, 408, 409, 5, 112, 0, 0, 409, 410, 5, 117, 0, 0, 410, 411, 5, 116, 0, 0, 411, 412, 5, 115, 0, 0, 412, 84, 1, 0, 0, 0, 413, 414, 5, 46, 0, 0, 414, 415, 5, 111, 0, 0, 415, 416, 5, 117, 0, 0, 416, 417, 5, 116, 0, 0, 417, 418, 5, 112, 0, 0, 418, 419, 5, 111, 0, 0, 419, 420, 5, 105, 0, 0, 420, 421, 5, 110, 0, 0, 421, 422, 5, 116, 0, 0, 422, 423, 5, 84, 0, 0, 423, 424, 5, 114, 0, 0, 424, 425, 5, 97, 0, 0, 425, 426, 5, 110, 0, 0, 426, 427, 5, 115, 0, 0, 427, 428, 5, 97, 0, 0, 428, 429, 5, 99, 0, 0, 429, 430, 5, 116, 0, 0, 430, 431, 5, 105, 0, 0, 431, 432, 5, 111, 0, 0, 432, 433, 5, 110, 0, 0, 433, 434, 5, 72, 0, 0, 434, 435, 5, 97, 0, 0, 435, 436, 5, 115, 0, 0, 436, 437, 5, 104, 0, 0, 437, 86, 1, 0, 0, 0, 438, 439, 5, 46, 0, 0, 439, 440, 5, 111, 0, 0, 440, 441, 5, 117, 0, 0, 441, 442, 5, 116, 0, 0, 442, 443, 5, 112, 0, 0, 443, 444, 5, 111, 0, 0, 444, 445, 5, 105, 0, 0, 445, 446, 5, 110, 0, 0, 446, 447, 5, 116, 0, 0, 447, 448, 5, 73, 0, 0, 448, 449, 5, 110, 0, 0, 449, 450, 5, 100, 0, 0, 450, 451, 5, 101, 0, 0, 451, 452, 5, 120, 0, 0, 452, 88, 1, 0, 0, 0, 453, 454, 5, 46, 0, 0, 454, 455, 5, 117, 0, 0, 455, 456, 5, 110, 0, 0, 456, 457, 5, 108, 0, 0, 457, 458, 5, 111, 0, 0, 458, 459, 5, 99, 0, 0, 459, 460, 5, 107, 0, 0, 460, 461, 5, 105, 0, 0, 461, 462, 5, 110, 0, 0, 462, 463, 5, 103, 0, 0, 463, 464, 5, 66, 0, 0, 464, 465, 5, 121, 0, 0, 465, 466, 5, 116, 0, 0, 466, 467, 5, 101, 0, 0, 467, 468, 5, 99, 0, 0, 468, 469, 5, 111, 0, 0, 469, 470, 5, 100, 0, 0, 470, 471, 5, 101, 0, 0, 471, 90, 1, 0, 0, 0, 472, 473, 5, 46, 0, 0, 473, 474, 5, 115, 0, 0, 474, 475, 5, 101, 0, 0, 475, 476, 5, 113, 0, 0, 476, 477, 5, 117, 0, 0, 477, 478, 5, 101, 0, 0, 478, 479, 5, 110, 0, 0, 479, 480, 5, 99, 0, 0, 480, 481, 5, 101, 0, 0, 481, 482, 5, 78, 0, 0, 482, 483, 5, 117, 0, 0, 483, 484, 5, 109, 0, 0, 484, 485, 5, 98, 0, 0, 485, 486, 5, 101, 0, 0, 486, 487, 5, 114, 0, 0, 487, 92, 1, 0, 0, 0, 488, 489, 5, 46, 0, 0, 489, 490, 5, 114, 0, 0, 490, 491, 5, 101, 0, 0, 491, 492, 5, 118, 0, 0, 492, 493, 5, 101, 0, 0, 493, 494, 5, 114, 0, 0, 494, 495, 5, 115, 0, 0, 495, 496, 5, 101, 0, 0, 496, 497, 5, 40, 0, 0, 497, 498, 5, 41, 0, 0, 498, 94, 1, 0, 0, 0, 499, 500, 5, 46, 0, 0, 500, 501, 5, 108, 0, 0, 501, 502, 5, 101, 0, 0, 502, 503, 5, 110, 0, 0, 503, 504, 5, 103, 0, 0, 504, 505, 5, 116, 0, 0, 505, 506, 5, 104, 0, 0, 506, 96, 1, 0, 0, 0, 507, 508, 5, 46, 0, 0, 508, 509, 5, 115, 0, 0, 509, 510, 5, 112, 0, 0, 510, 511, 5, 108, 0, 0, 511, 512, 5, 105, 0, 0, 512, 513, 5, 116, 0, 0, 513, 98, 1, 0, 0, 0, 514, 515, 5, 46, 0, 0, 515, 516, 5, 115, 0, 0, 516, 517, 5, 108, 0, 0, 517, 518, 5, 105, 0, 0, 518, 519, 5, 99, 0, 0, 519, 520, 5, 101, 0, 0, 520, 100, 1, 0, 0, 0, 521, 522, 5, 33, 0, 0, 522, 102, 1, 0, 0, 0, 523, 524, 5, 45, 0, 0, 524, 104, 1, 0, 0, 0, 525, 526, 5, 42, 0, 0, 526, 106, 1, 0, 0, 0, 527, 528, 5, 47, 0, 0, 528, 108, 1, 0, 0, 0, 529, 530, 5, 37, 0, 0, 530, 110, 1, 0, 0, 0, 531, 532, 5, 43, 0, 0, 532, 112, 1, 0, 0, 0, 533, 534, 5, 62, 0, 0, 534, 535, 5, 62, 0, 0, 535, 114, 1, 0, 0, 0, 536, 537, 5, 60, 0, 0, 537, 538, 5, 60, 0, 0, 538, 116, 1, 0, 0, 0, 539, 540, 5, 61, 0, 0, 540, 541, 5, 61, 0, 0, 541, 118, 1, 0, 0, 0, 542, 543, 5, 33, 0, 0, 543, 544, 5, 61, 0, 0, 544, 120, 1, 0, 0, 0, 545, 546, 5, 38, 0, 0, 546, 122, 1, 0, 0, 0, 547, 548, 5, 124, 0, 0, 548, 124, 1, 0, 0, 0, 549, 550, 5, 38, 0, 0, 550, 551, 5, 38, 0, 0, 551, 126, 1, 0, 0, 0, 552, 553, 5, 124, 0, 0, 553, 554, 5, 124, 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 diff --git a/packages/cashc/src/grammar/CashScriptLexer.tokens b/packages/cashc/src/grammar/CashScriptLexer.tokens index 14524e521..074f0fc19 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.tokens +++ b/packages/cashc/src/grammar/CashScriptLexer.tokens @@ -98,52 +98,52 @@ LINE_COMMENT=84 '('=14 ','=15 ')'=16 -'contract'=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 +'constant'=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 'bytes'=72 diff --git a/packages/cashc/src/grammar/CashScriptLexer.ts b/packages/cashc/src/grammar/CashScriptLexer.ts index 52ab29538..d384f897a 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.2 +// Generated from src/grammar/CashScript.g4 by ANTLR 4.13.1 // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { ATN, @@ -108,7 +108,8 @@ export default class CashScriptLexer extends Lexer { "'function'", "'returns'", "'('", "','", - "')'", "'contract'", + "')'", "'constant'", + "'contract'", "'{'", "'}'", "'return'", "'+='", "'-='", @@ -141,7 +142,6 @@ export default class CashScriptLexer extends Lexer { "'=='", "'!='", "'&'", "'|'", "'&&'", "'||'", - "'constant'", null, null, null, null, null, null, @@ -248,28 +248,28 @@ export default class CashScriptLexer extends Lexer { 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,16,1,16,1,16,1,16,1,16,1,16,1,16,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, + 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,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, @@ -330,17 +330,17 @@ export default class CashScriptLexer extends Lexer { 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,235, - 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, + 1,0,0,0,35,244,1,0,0,0,37,253,1,0,0,0,39,255,1,0,0,0,41,257,1,0,0,0,43, + 264,1,0,0,0,45,267,1,0,0,0,47,270,1,0,0,0,49,273,1,0,0,0,51,276,1,0,0,0, + 53,284,1,0,0,0,55,296,1,0,0,0,57,299,1,0,0,0,59,304,1,0,0,0,61,307,1,0, + 0,0,63,313,1,0,0,0,65,317,1,0,0,0,67,321,1,0,0,0,69,323,1,0,0,0,71,325, + 1,0,0,0,73,336,1,0,0,0,75,343,1,0,0,0,77,360,1,0,0,0,79,375,1,0,0,0,81, + 390,1,0,0,0,83,403,1,0,0,0,85,413,1,0,0,0,87,438,1,0,0,0,89,453,1,0,0,0, + 91,472,1,0,0,0,93,488,1,0,0,0,95,499,1,0,0,0,97,507,1,0,0,0,99,514,1,0, + 0,0,101,521,1,0,0,0,103,523,1,0,0,0,105,525,1,0,0,0,107,527,1,0,0,0,109, + 529,1,0,0,0,111,531,1,0,0,0,113,533,1,0,0,0,115,536,1,0,0,0,117,539,1,0, + 0,0,119,542,1,0,0,0,121,545,1,0,0,0,123,547,1,0,0,0,125,549,1,0,0,0,127, + 552,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, @@ -361,194 +361,193 @@ export default class CashScriptLexer extends Lexer { 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,44,0,0,232,30,1,0,0,0,233,234,5,41,0,0,234, 32,1,0,0,0,235,236,5,99,0,0,236,237,5,111,0,0,237,238,5,110,0,0,238,239, - 5,116,0,0,239,240,5,114,0,0,240,241,5,97,0,0,241,242,5,99,0,0,242,243,5, - 116,0,0,243,34,1,0,0,0,244,245,5,123,0,0,245,36,1,0,0,0,246,247,5,125,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]; + 5,115,0,0,239,240,5,116,0,0,240,241,5,97,0,0,241,242,5,110,0,0,242,243, + 5,116,0,0,243,34,1,0,0,0,244,245,5,99,0,0,245,246,5,111,0,0,246,247,5,110, + 0,0,247,248,5,116,0,0,248,249,5,114,0,0,249,250,5,97,0,0,250,251,5,99,0, + 0,251,252,5,116,0,0,252,36,1,0,0,0,253,254,5,123,0,0,254,38,1,0,0,0,255, + 256,5,125,0,0,256,40,1,0,0,0,257,258,5,114,0,0,258,259,5,101,0,0,259,260, + 5,116,0,0,260,261,5,117,0,0,261,262,5,114,0,0,262,263,5,110,0,0,263,42, + 1,0,0,0,264,265,5,43,0,0,265,266,5,61,0,0,266,44,1,0,0,0,267,268,5,45,0, + 0,268,269,5,61,0,0,269,46,1,0,0,0,270,271,5,43,0,0,271,272,5,43,0,0,272, + 48,1,0,0,0,273,274,5,45,0,0,274,275,5,45,0,0,275,50,1,0,0,0,276,277,5,114, + 0,0,277,278,5,101,0,0,278,279,5,113,0,0,279,280,5,117,0,0,280,281,5,105, + 0,0,281,282,5,114,0,0,282,283,5,101,0,0,283,52,1,0,0,0,284,285,5,99,0,0, + 285,286,5,111,0,0,286,287,5,110,0,0,287,288,5,115,0,0,288,289,5,111,0,0, + 289,290,5,108,0,0,290,291,5,101,0,0,291,292,5,46,0,0,292,293,5,108,0,0, + 293,294,5,111,0,0,294,295,5,103,0,0,295,54,1,0,0,0,296,297,5,105,0,0,297, + 298,5,102,0,0,298,56,1,0,0,0,299,300,5,101,0,0,300,301,5,108,0,0,301,302, + 5,115,0,0,302,303,5,101,0,0,303,58,1,0,0,0,304,305,5,100,0,0,305,306,5, + 111,0,0,306,60,1,0,0,0,307,308,5,119,0,0,308,309,5,104,0,0,309,310,5,105, + 0,0,310,311,5,108,0,0,311,312,5,101,0,0,312,62,1,0,0,0,313,314,5,102,0, + 0,314,315,5,111,0,0,315,316,5,114,0,0,316,64,1,0,0,0,317,318,5,110,0,0, + 318,319,5,101,0,0,319,320,5,119,0,0,320,66,1,0,0,0,321,322,5,91,0,0,322, + 68,1,0,0,0,323,324,5,93,0,0,324,70,1,0,0,0,325,326,5,116,0,0,326,327,5, + 120,0,0,327,328,5,46,0,0,328,329,5,111,0,0,329,330,5,117,0,0,330,331,5, + 116,0,0,331,332,5,112,0,0,332,333,5,117,0,0,333,334,5,116,0,0,334,335,5, + 115,0,0,335,72,1,0,0,0,336,337,5,46,0,0,337,338,5,118,0,0,338,339,5,97, + 0,0,339,340,5,108,0,0,340,341,5,117,0,0,341,342,5,101,0,0,342,74,1,0,0, + 0,343,344,5,46,0,0,344,345,5,108,0,0,345,346,5,111,0,0,346,347,5,99,0,0, + 347,348,5,107,0,0,348,349,5,105,0,0,349,350,5,110,0,0,350,351,5,103,0,0, + 351,352,5,66,0,0,352,353,5,121,0,0,353,354,5,116,0,0,354,355,5,101,0,0, + 355,356,5,99,0,0,356,357,5,111,0,0,357,358,5,100,0,0,358,359,5,101,0,0, + 359,76,1,0,0,0,360,361,5,46,0,0,361,362,5,116,0,0,362,363,5,111,0,0,363, + 364,5,107,0,0,364,365,5,101,0,0,365,366,5,110,0,0,366,367,5,67,0,0,367, + 368,5,97,0,0,368,369,5,116,0,0,369,370,5,101,0,0,370,371,5,103,0,0,371, + 372,5,111,0,0,372,373,5,114,0,0,373,374,5,121,0,0,374,78,1,0,0,0,375,376, + 5,46,0,0,376,377,5,110,0,0,377,378,5,102,0,0,378,379,5,116,0,0,379,380, + 5,67,0,0,380,381,5,111,0,0,381,382,5,109,0,0,382,383,5,109,0,0,383,384, + 5,105,0,0,384,385,5,116,0,0,385,386,5,109,0,0,386,387,5,101,0,0,387,388, + 5,110,0,0,388,389,5,116,0,0,389,80,1,0,0,0,390,391,5,46,0,0,391,392,5,116, + 0,0,392,393,5,111,0,0,393,394,5,107,0,0,394,395,5,101,0,0,395,396,5,110, + 0,0,396,397,5,65,0,0,397,398,5,109,0,0,398,399,5,111,0,0,399,400,5,117, + 0,0,400,401,5,110,0,0,401,402,5,116,0,0,402,82,1,0,0,0,403,404,5,116,0, + 0,404,405,5,120,0,0,405,406,5,46,0,0,406,407,5,105,0,0,407,408,5,110,0, + 0,408,409,5,112,0,0,409,410,5,117,0,0,410,411,5,116,0,0,411,412,5,115,0, + 0,412,84,1,0,0,0,413,414,5,46,0,0,414,415,5,111,0,0,415,416,5,117,0,0,416, + 417,5,116,0,0,417,418,5,112,0,0,418,419,5,111,0,0,419,420,5,105,0,0,420, + 421,5,110,0,0,421,422,5,116,0,0,422,423,5,84,0,0,423,424,5,114,0,0,424, + 425,5,97,0,0,425,426,5,110,0,0,426,427,5,115,0,0,427,428,5,97,0,0,428,429, + 5,99,0,0,429,430,5,116,0,0,430,431,5,105,0,0,431,432,5,111,0,0,432,433, + 5,110,0,0,433,434,5,72,0,0,434,435,5,97,0,0,435,436,5,115,0,0,436,437,5, + 104,0,0,437,86,1,0,0,0,438,439,5,46,0,0,439,440,5,111,0,0,440,441,5,117, + 0,0,441,442,5,116,0,0,442,443,5,112,0,0,443,444,5,111,0,0,444,445,5,105, + 0,0,445,446,5,110,0,0,446,447,5,116,0,0,447,448,5,73,0,0,448,449,5,110, + 0,0,449,450,5,100,0,0,450,451,5,101,0,0,451,452,5,120,0,0,452,88,1,0,0, + 0,453,454,5,46,0,0,454,455,5,117,0,0,455,456,5,110,0,0,456,457,5,108,0, + 0,457,458,5,111,0,0,458,459,5,99,0,0,459,460,5,107,0,0,460,461,5,105,0, + 0,461,462,5,110,0,0,462,463,5,103,0,0,463,464,5,66,0,0,464,465,5,121,0, + 0,465,466,5,116,0,0,466,467,5,101,0,0,467,468,5,99,0,0,468,469,5,111,0, + 0,469,470,5,100,0,0,470,471,5,101,0,0,471,90,1,0,0,0,472,473,5,46,0,0,473, + 474,5,115,0,0,474,475,5,101,0,0,475,476,5,113,0,0,476,477,5,117,0,0,477, + 478,5,101,0,0,478,479,5,110,0,0,479,480,5,99,0,0,480,481,5,101,0,0,481, + 482,5,78,0,0,482,483,5,117,0,0,483,484,5,109,0,0,484,485,5,98,0,0,485,486, + 5,101,0,0,486,487,5,114,0,0,487,92,1,0,0,0,488,489,5,46,0,0,489,490,5,114, + 0,0,490,491,5,101,0,0,491,492,5,118,0,0,492,493,5,101,0,0,493,494,5,114, + 0,0,494,495,5,115,0,0,495,496,5,101,0,0,496,497,5,40,0,0,497,498,5,41,0, + 0,498,94,1,0,0,0,499,500,5,46,0,0,500,501,5,108,0,0,501,502,5,101,0,0,502, + 503,5,110,0,0,503,504,5,103,0,0,504,505,5,116,0,0,505,506,5,104,0,0,506, + 96,1,0,0,0,507,508,5,46,0,0,508,509,5,115,0,0,509,510,5,112,0,0,510,511, + 5,108,0,0,511,512,5,105,0,0,512,513,5,116,0,0,513,98,1,0,0,0,514,515,5, + 46,0,0,515,516,5,115,0,0,516,517,5,108,0,0,517,518,5,105,0,0,518,519,5, + 99,0,0,519,520,5,101,0,0,520,100,1,0,0,0,521,522,5,33,0,0,522,102,1,0,0, + 0,523,524,5,45,0,0,524,104,1,0,0,0,525,526,5,42,0,0,526,106,1,0,0,0,527, + 528,5,47,0,0,528,108,1,0,0,0,529,530,5,37,0,0,530,110,1,0,0,0,531,532,5, + 43,0,0,532,112,1,0,0,0,533,534,5,62,0,0,534,535,5,62,0,0,535,114,1,0,0, + 0,536,537,5,60,0,0,537,538,5,60,0,0,538,116,1,0,0,0,539,540,5,61,0,0,540, + 541,5,61,0,0,541,118,1,0,0,0,542,543,5,33,0,0,543,544,5,61,0,0,544,120, + 1,0,0,0,545,546,5,38,0,0,546,122,1,0,0,0,547,548,5,124,0,0,548,124,1,0, + 0,0,549,550,5,38,0,0,550,551,5,38,0,0,551,126,1,0,0,0,552,553,5,124,0,0, + 553,554,5,124,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]; 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 ae797cf80..f78d40316 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.2 +// Generated from src/grammar/CashScript.g4 by ANTLR 4.13.1 // noinspection ES6UnusedImports,JSUnusedGlobalSymbols,JSUnusedLocalSymbols import { @@ -102,7 +102,7 @@ export default class CashScriptParser extends Parser { public static readonly WHITESPACE = 82; public static readonly COMMENT = 83; public static readonly LINE_COMMENT = 84; - public static override readonly EOF = Token.EOF; + public static readonly EOF = Token.EOF; public static readonly RULE_sourceFile = 0; public static readonly RULE_pragmaDirective = 1; public static readonly RULE_pragmaName = 2; @@ -112,40 +112,41 @@ export default class CashScriptParser extends Parser { 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 = 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_assignStatement = 23; + public static readonly RULE_timeOpStatement = 24; + public static readonly RULE_requireStatement = 25; + public static readonly RULE_consoleStatement = 26; + public static readonly RULE_ifStatement = 27; + public static readonly RULE_loopStatement = 28; + public static readonly RULE_doWhileStatement = 29; + public static readonly RULE_whileStatement = 30; + public static readonly RULE_forStatement = 31; + public static readonly RULE_forInit = 32; + public static readonly RULE_requireMessage = 33; + public static readonly RULE_consoleParameter = 34; + public static readonly RULE_consoleParameterList = 35; + public static readonly RULE_functionCall = 36; + public static readonly RULE_expressionList = 37; + public static readonly RULE_expression = 38; + public static readonly RULE_modifier = 39; + public static readonly RULE_literal = 40; + public static readonly RULE_numberLiteral = 41; + public static readonly RULE_typeName = 42; + public static readonly RULE_typeCast = 43; public static readonly literalNames: (string | null)[] = [ null, "'pragma'", "';'", "'cashscript'", "'^'", "'~'", @@ -155,7 +156,8 @@ export default class CashScriptParser extends Parser { "'function'", "'returns'", "'('", "','", - "')'", "'contract'", + "')'", "'constant'", + "'contract'", "'{'", "'}'", "'return'", "'+='", "'-='", @@ -188,7 +190,6 @@ export default class CashScriptParser extends Parser { "'=='", "'!='", "'&'", "'|'", "'&&'", "'||'", - "'constant'", null, null, null, null, null, null, @@ -247,14 +248,14 @@ export default class CashScriptParser extends Parser { 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", + "constantDefinition", "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", ]; public get grammarFileName(): string { return "CashScript.g4"; } public get literalNames(): (string | null)[] { return CashScriptParser.literalNames; } @@ -278,49 +279,49 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 89; + this.state = 91; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===1) { { { - this.state = 86; + this.state = 88; this.pragmaDirective(); } } - this.state = 91; + this.state = 93; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 95; + this.state = 97; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===11) { { { - this.state = 92; + this.state = 94; this.importDirective(); } } - this.state = 97; + this.state = 99; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 101; + this.state = 103; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===12 || _la===17) { + while (_la===12 || _la===18 || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0)) { { { - this.state = 98; + this.state = 100; this.topLevelDefinition(); } } - this.state = 103; + this.state = 105; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 104; + this.state = 106; this.match(CashScriptParser.EOF); } } @@ -345,13 +346,13 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 106; + this.state = 108; this.match(CashScriptParser.T__0); - this.state = 107; + this.state = 109; this.pragmaName(); - this.state = 108; + this.state = 110; this.pragmaValue(); - this.state = 109; + this.state = 111; this.match(CashScriptParser.T__1); } } @@ -376,7 +377,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 111; + this.state = 113; this.match(CashScriptParser.T__2); } } @@ -402,14 +403,14 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 113; - this.versionConstraint(); this.state = 115; + this.versionConstraint(); + this.state = 117; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0) || _la===65) { { - this.state = 114; + this.state = 116; this.versionConstraint(); } } @@ -438,17 +439,17 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 118; + this.state = 120; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0)) { { - this.state = 117; + this.state = 119; this.versionOperator(); } } - this.state = 120; + this.state = 122; this.match(CashScriptParser.VersionLiteral); } } @@ -474,7 +475,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 122; + this.state = 124; _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0))) { this._errHandler.recoverInline(this); @@ -506,11 +507,11 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 124; + this.state = 126; this.match(CashScriptParser.T__10); - this.state = 125; + this.state = 127; this.match(CashScriptParser.StringLiteral); - this.state = 126; + this.state = 128; this.match(CashScriptParser.T__1); } } @@ -533,20 +534,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 = 133; this._errHandler.sync(this); switch (this._input.LA(1)) { case 12: this.enterOuterAlt(localctx, 1); { - this.state = 128; + this.state = 130; this.globalFunctionDefinition(); } break; - case 17: + case 71: + case 72: + case 73: this.enterOuterAlt(localctx, 2); { - this.state = 129; + this.state = 131; + this.constantDefinition(); + } + break; + case 18: + this.enterOuterAlt(localctx, 3); + { + this.state = 132; this.contractDefinition(); } break; @@ -576,45 +586,45 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 132; + this.state = 135; this.match(CashScriptParser.T__11); - this.state = 133; + this.state = 136; this.match(CashScriptParser.Identifier); - this.state = 134; + this.state = 137; this.parameterList(); - this.state = 147; + this.state = 150; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===13) { { - this.state = 135; + this.state = 138; this.match(CashScriptParser.T__12); - this.state = 136; + this.state = 139; this.match(CashScriptParser.T__13); - this.state = 137; + this.state = 140; this.typeName(); - this.state = 142; + this.state = 145; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===15) { { { - this.state = 138; + this.state = 141; this.match(CashScriptParser.T__14); - this.state = 139; + this.state = 142; this.typeName(); } } - this.state = 144; + this.state = 147; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 145; + this.state = 148; this.match(CashScriptParser.T__15); } } - this.state = 149; + this.state = 152; this.functionBody(); } } @@ -633,37 +643,72 @@ 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, 18, CashScriptParser.RULE_constantDefinition); + try { + this.enterOuterAlt(localctx, 1); + { + this.state = 154; + this.typeName(); + this.state = 155; + this.match(CashScriptParser.T__16); + this.state = 156; + this.match(CashScriptParser.Identifier); + this.state = 157; + this.match(CashScriptParser.T__9); + this.state = 158; + this.literal(); + this.state = 159; + 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 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 = 151; - this.match(CashScriptParser.T__16); - this.state = 152; + this.state = 161; + this.match(CashScriptParser.T__17); + this.state = 162; this.match(CashScriptParser.Identifier); - this.state = 153; + this.state = 163; this.parameterList(); - this.state = 154; - this.match(CashScriptParser.T__17); - this.state = 158; + this.state = 164; + this.match(CashScriptParser.T__18); + this.state = 168; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===12) { { { - this.state = 155; + this.state = 165; this.contractFunctionDefinition(); } } - this.state = 160; + this.state = 170; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 161; - this.match(CashScriptParser.T__18); + this.state = 171; + this.match(CashScriptParser.T__19); } } catch (re) { @@ -683,17 +728,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 = 163; + this.state = 173; this.match(CashScriptParser.T__11); - this.state = 164; + this.state = 174; this.match(CashScriptParser.Identifier); - this.state = 165; + this.state = 175; this.parameterList(); - this.state = 166; + this.state = 176; this.functionBody(); } } @@ -714,29 +759,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 = 168; - this.match(CashScriptParser.T__17); - this.state = 172; + this.state = 178; + this.match(CashScriptParser.T__18); + this.state = 182; 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 - 21)) & ~0x1F) === 0 && ((1 << (_la - 21)) & 3809) !== 0) || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 1031) !== 0)) { { { - this.state = 169; + this.state = 179; this.statement(); } } - this.state = 174; + this.state = 184; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 175; - this.match(CashScriptParser.T__18); + this.state = 185; + this.match(CashScriptParser.T__19); } } catch (re) { @@ -756,45 +801,45 @@ 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 = 177; + this.state = 187; this.match(CashScriptParser.T__13); - this.state = 189; + this.state = 199; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0)) { { - this.state = 178; + this.state = 188; this.parameter(); - this.state = 183; + this.state = 193; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 10, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 179; + this.state = 189; this.match(CashScriptParser.T__14); - this.state = 180; + this.state = 190; this.parameter(); } } } - this.state = 185; + this.state = 195; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 10, this._ctx); } - this.state = 187; + this.state = 197; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 186; + this.state = 196; this.match(CashScriptParser.T__14); } } @@ -802,7 +847,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 191; + this.state = 201; this.match(CashScriptParser.T__15); } } @@ -823,13 +868,13 @@ 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); try { this.enterOuterAlt(localctx, 1); { - this.state = 193; + this.state = 203; this.typeName(); - this.state = 194; + this.state = 204; this.match(CashScriptParser.Identifier); } } @@ -850,49 +895,49 @@ 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 = 205; + this.state = 215; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 18: + case 19: this.enterOuterAlt(localctx, 1); { - this.state = 196; - this.match(CashScriptParser.T__17); - this.state = 200; + this.state = 206; + this.match(CashScriptParser.T__18); + this.state = 210; 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 - 21)) & ~0x1F) === 0 && ((1 << (_la - 21)) & 3809) !== 0) || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 1031) !== 0)) { { { - this.state = 197; + this.state = 207; this.statement(); } } - this.state = 202; + this.state = 212; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 203; - this.match(CashScriptParser.T__18); + this.state = 213; + this.match(CashScriptParser.T__19); } break; - case 20: - case 25: + case 21: case 26: case 27: - case 29: + case 28: case 30: case 31: + case 32: case 71: case 72: case 73: case 81: this.enterOuterAlt(localctx, 2); { - this.state = 204; + this.state = 214; this.statement(); } break; @@ -917,33 +962,33 @@ 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 = 211; + this.state = 221; 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 = 207; + this.state = 217; this.controlStatement(); } break; - case 20: - case 25: + case 21: case 26: + case 27: case 71: case 72: case 73: case 81: this.enterOuterAlt(localctx, 2); { - this.state = 208; + this.state = 218; this.nonControlStatement(); - this.state = 209; + this.state = 219; this.match(CashScriptParser.T__1); } break; @@ -968,64 +1013,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 = 221; + this.state = 231; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 16, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 213; + this.state = 223; this.variableDefinition(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 214; + this.state = 224; this.tupleAssignment(); } break; case 3: this.enterOuterAlt(localctx, 3); { - this.state = 215; + this.state = 225; this.assignStatement(); } break; case 4: this.enterOuterAlt(localctx, 4); { - this.state = 216; + this.state = 226; this.timeOpStatement(); } break; case 5: this.enterOuterAlt(localctx, 5); { - this.state = 217; + this.state = 227; this.requireStatement(); } break; case 6: this.enterOuterAlt(localctx, 6); { - this.state = 218; + this.state = 228; this.functionCallStatement(); } break; case 7: this.enterOuterAlt(localctx, 7); { - this.state = 219; + this.state = 229; this.consoleStatement(); } break; case 8: this.enterOuterAlt(localctx, 8); { - this.state = 220; + this.state = 230; this.returnStatement(); } break; @@ -1048,11 +1093,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 = 223; + this.state = 233; this.functionCall(); } } @@ -1073,28 +1118,28 @@ 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 = 225; - this.match(CashScriptParser.T__19); - this.state = 226; + this.state = 235; + this.match(CashScriptParser.T__20); + this.state = 236; this.expression(0); - this.state = 231; + this.state = 241; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===15) { { { - this.state = 227; + this.state = 237; this.match(CashScriptParser.T__14); - this.state = 228; + this.state = 238; this.expression(0); } } - this.state = 233; + this.state = 243; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1117,24 +1162,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 = 236; + this.state = 246; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 27: + case 28: this.enterOuterAlt(localctx, 1); { - this.state = 234; + this.state = 244; this.ifStatement(); } break; - case 29: case 30: case 31: + case 32: this.enterOuterAlt(localctx, 2); { - this.state = 235; + this.state = 245; this.loopStatement(); } break; @@ -1159,32 +1204,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 = 238; + this.state = 248; this.typeName(); - this.state = 242; + this.state = 252; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===64) { + while (_la===17) { { { - this.state = 239; + this.state = 249; this.modifier(); } } - this.state = 244; + this.state = 254; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 245; + this.state = 255; this.match(CashScriptParser.Identifier); - this.state = 246; + this.state = 256; this.match(CashScriptParser.T__9); - this.state = 247; + this.state = 257; this.expression(0); } } @@ -1205,36 +1250,36 @@ 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 = 249; + this.state = 259; this.typeName(); - this.state = 250; + this.state = 260; this.match(CashScriptParser.Identifier); - this.state = 255; + this.state = 265; this._errHandler.sync(this); _la = this._input.LA(1); do { { { - this.state = 251; + this.state = 261; this.match(CashScriptParser.T__14); - this.state = 252; + this.state = 262; this.typeName(); - this.state = 253; + this.state = 263; this.match(CashScriptParser.Identifier); } } - this.state = 257; + this.state = 267; this._errHandler.sync(this); _la = this._input.LA(1); } while (_la===15); - this.state = 259; + this.state = 269; this.match(CashScriptParser.T__9); - this.state = 260; + this.state = 270; this.expression(0); } } @@ -1255,40 +1300,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, 46, CashScriptParser.RULE_assignStatement); let _la: number; try { - this.state = 267; + this.state = 277; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 21, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 262; + this.state = 272; this.match(CashScriptParser.Identifier); - this.state = 263; + this.state = 273; 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 = 264; + this.state = 274; this.expression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 265; + this.state = 275; this.match(CashScriptParser.Identifier); - this.state = 266; + this.state = 276; 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 { @@ -1316,34 +1361,34 @@ 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, 48, CashScriptParser.RULE_timeOpStatement); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 269; - this.match(CashScriptParser.T__24); - this.state = 270; + this.state = 279; + this.match(CashScriptParser.T__25); + this.state = 280; this.match(CashScriptParser.T__13); - this.state = 271; + this.state = 281; this.match(CashScriptParser.TxVar); - this.state = 272; + this.state = 282; this.match(CashScriptParser.T__5); - this.state = 273; + this.state = 283; this.expression(0); - this.state = 276; + this.state = 286; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 274; + this.state = 284; this.match(CashScriptParser.T__14); - this.state = 275; + this.state = 285; this.requireMessage(); } } - this.state = 278; + this.state = 288; this.match(CashScriptParser.T__15); } } @@ -1364,30 +1409,30 @@ 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, 50, CashScriptParser.RULE_requireStatement); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 280; - this.match(CashScriptParser.T__24); - this.state = 281; + this.state = 290; + this.match(CashScriptParser.T__25); + this.state = 291; this.match(CashScriptParser.T__13); - this.state = 282; + this.state = 292; this.expression(0); - this.state = 285; + this.state = 295; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 283; + this.state = 293; this.match(CashScriptParser.T__14); - this.state = 284; + this.state = 294; this.requireMessage(); } } - this.state = 287; + this.state = 297; this.match(CashScriptParser.T__15); } } @@ -1408,13 +1453,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, 52, CashScriptParser.RULE_consoleStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 289; - this.match(CashScriptParser.T__25); - this.state = 290; + this.state = 299; + this.match(CashScriptParser.T__26); + this.state = 300; this.consoleParameterList(); } } @@ -1435,28 +1480,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, 54, CashScriptParser.RULE_ifStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 292; - this.match(CashScriptParser.T__26); - this.state = 293; + this.state = 302; + this.match(CashScriptParser.T__27); + this.state = 303; this.match(CashScriptParser.T__13); - this.state = 294; + this.state = 304; this.expression(0); - this.state = 295; + this.state = 305; this.match(CashScriptParser.T__15); - this.state = 296; + this.state = 306; localctx._ifBlock = this.block(); - this.state = 299; + this.state = 309; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 24, this._ctx) ) { case 1: { - this.state = 297; - this.match(CashScriptParser.T__27); - this.state = 298; + this.state = 307; + this.match(CashScriptParser.T__28); + this.state = 308; localctx._elseBlock = this.block(); } break; @@ -1480,29 +1525,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, 56, CashScriptParser.RULE_loopStatement); try { - this.state = 304; + this.state = 314; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 29: + case 30: this.enterOuterAlt(localctx, 1); { - this.state = 301; + this.state = 311; this.doWhileStatement(); } break; - case 30: + case 31: this.enterOuterAlt(localctx, 2); { - this.state = 302; + this.state = 312; this.whileStatement(); } break; - case 31: + case 32: this.enterOuterAlt(localctx, 3); { - this.state = 303; + this.state = 313; this.forStatement(); } break; @@ -1527,23 +1572,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, 58, CashScriptParser.RULE_doWhileStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 306; - this.match(CashScriptParser.T__28); - this.state = 307; - this.block(); - this.state = 308; + this.state = 316; this.match(CashScriptParser.T__29); - this.state = 309; + this.state = 317; + this.block(); + this.state = 318; + this.match(CashScriptParser.T__30); + this.state = 319; this.match(CashScriptParser.T__13); - this.state = 310; + this.state = 320; this.expression(0); - this.state = 311; + this.state = 321; this.match(CashScriptParser.T__15); - this.state = 312; + this.state = 322; this.match(CashScriptParser.T__1); } } @@ -1564,19 +1609,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, 60, CashScriptParser.RULE_whileStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 314; - this.match(CashScriptParser.T__29); - this.state = 315; + this.state = 324; + this.match(CashScriptParser.T__30); + this.state = 325; this.match(CashScriptParser.T__13); - this.state = 316; + this.state = 326; this.expression(0); - this.state = 317; + this.state = 327; this.match(CashScriptParser.T__15); - this.state = 318; + this.state = 328; this.block(); } } @@ -1597,27 +1642,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, 62, CashScriptParser.RULE_forStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 320; - this.match(CashScriptParser.T__30); - this.state = 321; + this.state = 330; + this.match(CashScriptParser.T__31); + this.state = 331; this.match(CashScriptParser.T__13); - this.state = 322; + this.state = 332; this.forInit(); - this.state = 323; + this.state = 333; this.match(CashScriptParser.T__1); - this.state = 324; + this.state = 334; this.expression(0); - this.state = 325; + this.state = 335; this.match(CashScriptParser.T__1); - this.state = 326; + this.state = 336; this.assignStatement(); - this.state = 327; + this.state = 337; this.match(CashScriptParser.T__15); - this.state = 328; + this.state = 338; this.block(); } } @@ -1638,9 +1683,9 @@ 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, 64, CashScriptParser.RULE_forInit); try { - this.state = 332; + this.state = 342; this._errHandler.sync(this); switch (this._input.LA(1)) { case 71: @@ -1648,14 +1693,14 @@ export default class CashScriptParser extends Parser { case 73: this.enterOuterAlt(localctx, 1); { - this.state = 330; + this.state = 340; this.variableDefinition(); } break; case 81: this.enterOuterAlt(localctx, 2); { - this.state = 331; + this.state = 341; this.assignStatement(); } break; @@ -1680,11 +1725,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, 66, CashScriptParser.RULE_requireMessage); try { this.enterOuterAlt(localctx, 1); { - this.state = 334; + this.state = 344; this.match(CashScriptParser.StringLiteral); } } @@ -1705,15 +1750,15 @@ 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, 68, CashScriptParser.RULE_consoleParameter); try { - this.state = 338; + this.state = 348; this._errHandler.sync(this); switch (this._input.LA(1)) { case 81: this.enterOuterAlt(localctx, 1); { - this.state = 336; + this.state = 346; this.match(CashScriptParser.Identifier); } break; @@ -1724,7 +1769,7 @@ export default class CashScriptParser extends Parser { case 77: this.enterOuterAlt(localctx, 2); { - this.state = 337; + this.state = 347; this.literal(); } break; @@ -1749,45 +1794,45 @@ 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, 70, CashScriptParser.RULE_consoleParameterList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 340; + this.state = 350; this.match(CashScriptParser.T__13); - this.state = 352; + this.state = 362; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 36357) !== 0)) { { - this.state = 341; + this.state = 351; this.consoleParameter(); - this.state = 346; + this.state = 356; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 342; + this.state = 352; this.match(CashScriptParser.T__14); - this.state = 343; + this.state = 353; this.consoleParameter(); } } } - this.state = 348; + this.state = 358; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); } - this.state = 350; + this.state = 360; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 349; + this.state = 359; this.match(CashScriptParser.T__14); } } @@ -1795,7 +1840,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 354; + this.state = 364; this.match(CashScriptParser.T__15); } } @@ -1816,13 +1861,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, 72, CashScriptParser.RULE_functionCall); try { this.enterOuterAlt(localctx, 1); { - this.state = 356; + this.state = 366; this.match(CashScriptParser.Identifier); - this.state = 357; + this.state = 367; this.expressionList(); } } @@ -1843,45 +1888,45 @@ 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, 74, CashScriptParser.RULE_expressionList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 359; + this.state = 369; this.match(CashScriptParser.T__13); - this.state = 371; + this.state = 381; 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===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 61029) !== 0)) { { - this.state = 360; + this.state = 370; this.expression(0); - this.state = 365; + this.state = 375; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 31, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 361; + this.state = 371; this.match(CashScriptParser.T__14); - this.state = 362; + this.state = 372; this.expression(0); } } } - this.state = 367; + this.state = 377; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 31, this._ctx); } - this.state = 369; + this.state = 379; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 368; + this.state = 378; this.match(CashScriptParser.T__14); } } @@ -1889,7 +1934,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 373; + this.state = 383; this.match(CashScriptParser.T__15); } } @@ -1920,14 +1965,14 @@ 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 = 76; + this.enterRecursionRule(localctx, 76, CashScriptParser.RULE_expression, _p); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 424; + this.state = 434; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 38, this._ctx) ) { case 1: @@ -1936,11 +1981,11 @@ export default class CashScriptParser extends Parser { this._ctx = localctx; _prevctx = localctx; - this.state = 376; + this.state = 386; this.match(CashScriptParser.T__13); - this.state = 377; + this.state = 387; this.expression(0); - this.state = 378; + this.state = 388; this.match(CashScriptParser.T__15); } break; @@ -1949,23 +1994,23 @@ export default class CashScriptParser extends Parser { localctx = new CastContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 380; + this.state = 390; this.typeCast(); - this.state = 381; + this.state = 391; this.match(CashScriptParser.T__13); - this.state = 382; + this.state = 392; (localctx as CastContext)._castable = this.expression(0); - this.state = 384; + this.state = 394; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 383; + this.state = 393; this.match(CashScriptParser.T__14); } } - this.state = 386; + this.state = 396; this.match(CashScriptParser.T__15); } break; @@ -1974,7 +2019,7 @@ export default class CashScriptParser extends Parser { localctx = new FunctionCallExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 388; + this.state = 398; this.functionCall(); } break; @@ -1983,11 +2028,11 @@ export default class CashScriptParser extends Parser { localctx = new InstantiationContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 389; - this.match(CashScriptParser.T__31); - this.state = 390; + this.state = 399; + this.match(CashScriptParser.T__32); + this.state = 400; this.match(CashScriptParser.Identifier); - this.state = 391; + this.state = 401; this.expressionList(); } break; @@ -1996,18 +2041,18 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 392; - (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__34); - this.state = 393; - this.match(CashScriptParser.T__32); - this.state = 394; - this.expression(0); - this.state = 395; + this.state = 402; + (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__35); + this.state = 403; this.match(CashScriptParser.T__33); - this.state = 396; + this.state = 404; + this.expression(0); + this.state = 405; + this.match(CashScriptParser.T__34); + this.state = 406; (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 { @@ -2021,18 +2066,18 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 398; - (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__40); - this.state = 399; - this.match(CashScriptParser.T__32); - this.state = 400; - this.expression(0); - this.state = 401; + this.state = 408; + (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__41); + this.state = 409; this.match(CashScriptParser.T__33); - this.state = 402; + this.state = 410; + this.expression(0); + this.state = 411; + this.match(CashScriptParser.T__34); + this.state = 412; (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 { @@ -2046,17 +2091,17 @@ export default class CashScriptParser extends Parser { localctx = new UnaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 404; + this.state = 414; (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 = 405; + this.state = 415; this.expression(15); } break; @@ -2065,39 +2110,39 @@ export default class CashScriptParser extends Parser { localctx = new ArrayContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 406; - this.match(CashScriptParser.T__32); - this.state = 418; + this.state = 416; + this.match(CashScriptParser.T__33); + this.state = 428; 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===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 61029) !== 0)) { { - this.state = 407; + this.state = 417; this.expression(0); - this.state = 412; + this.state = 422; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 408; + this.state = 418; this.match(CashScriptParser.T__14); - this.state = 409; + this.state = 419; this.expression(0); } } } - this.state = 414; + this.state = 424; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); } - this.state = 416; + this.state = 426; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 415; + this.state = 425; this.match(CashScriptParser.T__14); } } @@ -2105,8 +2150,8 @@ export default class CashScriptParser extends Parser { } } - this.state = 420; - this.match(CashScriptParser.T__33); + this.state = 430; + this.match(CashScriptParser.T__34); } break; case 9: @@ -2114,7 +2159,7 @@ export default class CashScriptParser extends Parser { localctx = new NullaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 421; + this.state = 431; this.match(CashScriptParser.NullaryOp); } break; @@ -2123,7 +2168,7 @@ export default class CashScriptParser extends Parser { localctx = new IdentifierContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 422; + this.state = 432; this.match(CashScriptParser.Identifier); } break; @@ -2132,13 +2177,13 @@ export default class CashScriptParser extends Parser { localctx = new LiteralExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 423; + this.state = 433; this.literal(); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 478; + this.state = 488; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { @@ -2148,7 +2193,7 @@ export default class CashScriptParser extends Parser { } _prevctx = localctx; { - this.state = 476; + this.state = 486; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 39, this._ctx) ) { case 1: @@ -2156,21 +2201,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 = 426; + this.state = 436; if (!(this.precpred(this._ctx, 14))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 14)"); } - this.state = 427; + this.state = 437; (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 = 428; + this.state = 438; (localctx as BinaryOpContext)._right = this.expression(15); } break; @@ -2179,21 +2224,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 = 429; + this.state = 439; if (!(this.precpred(this._ctx, 13))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 13)"); } - this.state = 430; + this.state = 440; (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 = 431; + this.state = 441; (localctx as BinaryOpContext)._right = this.expression(14); } break; @@ -2202,21 +2247,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 = 432; + this.state = 442; if (!(this.precpred(this._ctx, 12))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 12)"); } - this.state = 433; + this.state = 443; (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 = 434; + this.state = 444; (localctx as BinaryOpContext)._right = this.expression(13); } break; @@ -2225,11 +2270,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 = 435; + this.state = 445; if (!(this.precpred(this._ctx, 11))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 11)"); } - this.state = 436; + this.state = 446; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 960) !== 0))) { @@ -2239,7 +2284,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 437; + this.state = 447; (localctx as BinaryOpContext)._right = this.expression(12); } break; @@ -2248,21 +2293,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 = 438; + this.state = 448; if (!(this.precpred(this._ctx, 10))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 10)"); } - this.state = 439; + this.state = 449; (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 = 440; + this.state = 450; (localctx as BinaryOpContext)._right = this.expression(11); } break; @@ -2271,13 +2316,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 = 441; + this.state = 451; if (!(this.precpred(this._ctx, 9))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 9)"); } - this.state = 442; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__59); - this.state = 443; + this.state = 452; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); + this.state = 453; (localctx as BinaryOpContext)._right = this.expression(10); } break; @@ -2286,13 +2331,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 = 444; + this.state = 454; if (!(this.precpred(this._ctx, 8))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 8)"); } - this.state = 445; + this.state = 455; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__3); - this.state = 446; + this.state = 456; (localctx as BinaryOpContext)._right = this.expression(9); } break; @@ -2301,13 +2346,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 = 447; + this.state = 457; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 448; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); - this.state = 449; + this.state = 458; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); + this.state = 459; (localctx as BinaryOpContext)._right = this.expression(8); } break; @@ -2316,13 +2361,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 = 450; + this.state = 460; if (!(this.precpred(this._ctx, 6))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 6)"); } - this.state = 451; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); - this.state = 452; + this.state = 461; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); + this.state = 462; (localctx as BinaryOpContext)._right = this.expression(7); } break; @@ -2331,13 +2376,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 = 453; + this.state = 463; if (!(this.precpred(this._ctx, 5))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 5)"); } - this.state = 454; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); - this.state = 455; + this.state = 464; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__63); + this.state = 465; (localctx as BinaryOpContext)._right = this.expression(6); } break; @@ -2345,30 +2390,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 = 456; + this.state = 466; if (!(this.precpred(this._ctx, 21))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 21)"); } - this.state = 457; - this.match(CashScriptParser.T__32); - this.state = 458; - (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); - this.state = 459; + this.state = 467; this.match(CashScriptParser.T__33); + this.state = 468; + (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); + this.state = 469; + 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 = 460; + this.state = 470; if (!(this.precpred(this._ctx, 18))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 18)"); } - this.state = 461; + this.state = 471; (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 { @@ -2382,17 +2427,17 @@ 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 = 462; + this.state = 472; if (!(this.precpred(this._ctx, 17))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 17)"); } - this.state = 463; - (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__47); - this.state = 464; + this.state = 473; + (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__48); + this.state = 474; this.match(CashScriptParser.T__13); - this.state = 465; + this.state = 475; (localctx as BinaryOpContext)._right = this.expression(0); - this.state = 466; + this.state = 476; this.match(CashScriptParser.T__15); } break; @@ -2401,28 +2446,28 @@ 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 = 468; + this.state = 478; if (!(this.precpred(this._ctx, 16))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 16)"); } - this.state = 469; - this.match(CashScriptParser.T__48); - this.state = 470; + this.state = 479; + this.match(CashScriptParser.T__49); + this.state = 480; this.match(CashScriptParser.T__13); - this.state = 471; + this.state = 481; (localctx as SliceContext)._start = this.expression(0); - this.state = 472; + this.state = 482; this.match(CashScriptParser.T__14); - this.state = 473; + this.state = 483; (localctx as SliceContext)._end = this.expression(0); - this.state = 474; + this.state = 484; this.match(CashScriptParser.T__15); } break; } } } - this.state = 480; + this.state = 490; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); } @@ -2445,12 +2490,12 @@ 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, 78, CashScriptParser.RULE_modifier); try { this.enterOuterAlt(localctx, 1); { - this.state = 481; - this.match(CashScriptParser.T__63); + this.state = 491; + this.match(CashScriptParser.T__16); } } catch (re) { @@ -2470,43 +2515,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, 80, CashScriptParser.RULE_literal); try { - this.state = 488; + this.state = 498; this._errHandler.sync(this); switch (this._input.LA(1)) { case 66: this.enterOuterAlt(localctx, 1); { - this.state = 483; + this.state = 493; this.match(CashScriptParser.BooleanLiteral); } break; case 68: this.enterOuterAlt(localctx, 2); { - this.state = 484; + this.state = 494; this.numberLiteral(); } break; case 75: this.enterOuterAlt(localctx, 3); { - this.state = 485; + this.state = 495; this.match(CashScriptParser.StringLiteral); } break; case 76: this.enterOuterAlt(localctx, 4); { - this.state = 486; + this.state = 496; this.match(CashScriptParser.DateLiteral); } break; case 77: this.enterOuterAlt(localctx, 5); { - this.state = 487; + this.state = 497; this.match(CashScriptParser.HexLiteral); } break; @@ -2531,18 +2576,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, 82, CashScriptParser.RULE_numberLiteral); try { this.enterOuterAlt(localctx, 1); { - this.state = 490; + this.state = 500; this.match(CashScriptParser.NumberLiteral); - this.state = 492; + this.state = 502; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 42, this._ctx) ) { case 1: { - this.state = 491; + this.state = 501; this.match(CashScriptParser.NumberUnit); } break; @@ -2566,12 +2611,12 @@ 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, 84, CashScriptParser.RULE_typeName); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 494; + this.state = 504; _la = this._input.LA(1); if(!(((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0))) { this._errHandler.recoverInline(this); @@ -2599,12 +2644,12 @@ 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, 86, CashScriptParser.RULE_typeCast); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 496; + this.state = 506; _la = this._input.LA(1); if(!(((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 259) !== 0))) { this._errHandler.recoverInline(this); @@ -2632,7 +2677,7 @@ export default class CashScriptParser extends Parser { public sempred(localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 37: + case 38: return this.expression_sempred(localctx as ExpressionContext, predIndex); } return true; @@ -2671,171 +2716,174 @@ export default class CashScriptParser extends Parser { return true; } - public static readonly _serializedATN: number[] = [4,1,84,499,2,0,7,0,2, + public static readonly _serializedATN: number[] = [4,1,84,509,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,5,8,141,8,8,10,8,12,8,144,9,8,1,8,1,8,3,8,148,8,8,1,8,1,8,1,9,1,9,1, - 9,1,9,1,9,5,9,157,8,9,10,9,12,9,160,9,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10, - 1,11,1,11,5,11,171,8,11,10,11,12,11,174,9,11,1,11,1,11,1,12,1,12,1,12,1, - 12,5,12,182,8,12,10,12,12,12,185,9,12,1,12,3,12,188,8,12,3,12,190,8,12, - 1,12,1,12,1,13,1,13,1,13,1,14,1,14,5,14,199,8,14,10,14,12,14,202,9,14,1, - 14,1,14,3,14,206,8,14,1,15,1,15,1,15,1,15,3,15,212,8,15,1,16,1,16,1,16, - 1,16,1,16,1,16,1,16,1,16,3,16,222,8,16,1,17,1,17,1,18,1,18,1,18,1,18,5, - 18,230,8,18,10,18,12,18,233,9,18,1,19,1,19,3,19,237,8,19,1,20,1,20,5,20, - 241,8,20,10,20,12,20,244,9,20,1,20,1,20,1,20,1,20,1,21,1,21,1,21,1,21,1, - 21,1,21,4,21,256,8,21,11,21,12,21,257,1,21,1,21,1,21,1,22,1,22,1,22,1,22, - 1,22,3,22,268,8,22,1,23,1,23,1,23,1,23,1,23,1,23,1,23,3,23,277,8,23,1,23, - 1,23,1,24,1,24,1,24,1,24,1,24,3,24,286,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,300,8,26,1,27,1,27,1,27,3,27,305, - 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,333, - 8,31,1,32,1,32,1,33,1,33,3,33,339,8,33,1,34,1,34,1,34,1,34,5,34,345,8,34, - 10,34,12,34,348,9,34,1,34,3,34,351,8,34,3,34,353,8,34,1,34,1,34,1,35,1, - 35,1,35,1,36,1,36,1,36,1,36,5,36,364,8,36,10,36,12,36,367,9,36,1,36,3,36, - 370,8,36,3,36,372,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,385,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, - 411,8,37,10,37,12,37,414,9,37,1,37,3,37,417,8,37,3,37,419,8,37,1,37,1,37, - 1,37,1,37,3,37,425,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,477,8,37, - 10,37,12,37,480,9,37,1,38,1,38,1,39,1,39,1,39,1,39,1,39,3,39,489,8,39,1, - 40,1,40,3,40,493,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,529,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,151,1,0,0,0,20, - 163,1,0,0,0,22,168,1,0,0,0,24,177,1,0,0,0,26,193,1,0,0,0,28,205,1,0,0,0, - 30,211,1,0,0,0,32,221,1,0,0,0,34,223,1,0,0,0,36,225,1,0,0,0,38,236,1,0, - 0,0,40,238,1,0,0,0,42,249,1,0,0,0,44,267,1,0,0,0,46,269,1,0,0,0,48,280, - 1,0,0,0,50,289,1,0,0,0,52,292,1,0,0,0,54,304,1,0,0,0,56,306,1,0,0,0,58, - 314,1,0,0,0,60,320,1,0,0,0,62,332,1,0,0,0,64,334,1,0,0,0,66,338,1,0,0,0, - 68,340,1,0,0,0,70,356,1,0,0,0,72,359,1,0,0,0,74,424,1,0,0,0,76,481,1,0, - 0,0,78,488,1,0,0,0,80,490,1,0,0,0,82,494,1,0,0,0,84,496,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,147,3,24,12,0,135,136,5,13,0,0,136,137,5, - 14,0,0,137,142,3,82,41,0,138,139,5,15,0,0,139,141,3,82,41,0,140,138,1,0, - 0,0,141,144,1,0,0,0,142,140,1,0,0,0,142,143,1,0,0,0,143,145,1,0,0,0,144, - 142,1,0,0,0,145,146,5,16,0,0,146,148,1,0,0,0,147,135,1,0,0,0,147,148,1, - 0,0,0,148,149,1,0,0,0,149,150,3,22,11,0,150,17,1,0,0,0,151,152,5,17,0,0, - 152,153,5,81,0,0,153,154,3,24,12,0,154,158,5,18,0,0,155,157,3,20,10,0,156, - 155,1,0,0,0,157,160,1,0,0,0,158,156,1,0,0,0,158,159,1,0,0,0,159,161,1,0, - 0,0,160,158,1,0,0,0,161,162,5,19,0,0,162,19,1,0,0,0,163,164,5,12,0,0,164, - 165,5,81,0,0,165,166,3,24,12,0,166,167,3,22,11,0,167,21,1,0,0,0,168,172, - 5,18,0,0,169,171,3,30,15,0,170,169,1,0,0,0,171,174,1,0,0,0,172,170,1,0, - 0,0,172,173,1,0,0,0,173,175,1,0,0,0,174,172,1,0,0,0,175,176,5,19,0,0,176, - 23,1,0,0,0,177,189,5,14,0,0,178,183,3,26,13,0,179,180,5,15,0,0,180,182, - 3,26,13,0,181,179,1,0,0,0,182,185,1,0,0,0,183,181,1,0,0,0,183,184,1,0,0, - 0,184,187,1,0,0,0,185,183,1,0,0,0,186,188,5,15,0,0,187,186,1,0,0,0,187, - 188,1,0,0,0,188,190,1,0,0,0,189,178,1,0,0,0,189,190,1,0,0,0,190,191,1,0, - 0,0,191,192,5,16,0,0,192,25,1,0,0,0,193,194,3,82,41,0,194,195,5,81,0,0, - 195,27,1,0,0,0,196,200,5,18,0,0,197,199,3,30,15,0,198,197,1,0,0,0,199,202, - 1,0,0,0,200,198,1,0,0,0,200,201,1,0,0,0,201,203,1,0,0,0,202,200,1,0,0,0, - 203,206,5,19,0,0,204,206,3,30,15,0,205,196,1,0,0,0,205,204,1,0,0,0,206, - 29,1,0,0,0,207,212,3,38,19,0,208,209,3,32,16,0,209,210,5,2,0,0,210,212, - 1,0,0,0,211,207,1,0,0,0,211,208,1,0,0,0,212,31,1,0,0,0,213,222,3,40,20, - 0,214,222,3,42,21,0,215,222,3,44,22,0,216,222,3,46,23,0,217,222,3,48,24, - 0,218,222,3,34,17,0,219,222,3,50,25,0,220,222,3,36,18,0,221,213,1,0,0,0, - 221,214,1,0,0,0,221,215,1,0,0,0,221,216,1,0,0,0,221,217,1,0,0,0,221,218, - 1,0,0,0,221,219,1,0,0,0,221,220,1,0,0,0,222,33,1,0,0,0,223,224,3,70,35, - 0,224,35,1,0,0,0,225,226,5,20,0,0,226,231,3,74,37,0,227,228,5,15,0,0,228, - 230,3,74,37,0,229,227,1,0,0,0,230,233,1,0,0,0,231,229,1,0,0,0,231,232,1, - 0,0,0,232,37,1,0,0,0,233,231,1,0,0,0,234,237,3,52,26,0,235,237,3,54,27, - 0,236,234,1,0,0,0,236,235,1,0,0,0,237,39,1,0,0,0,238,242,3,82,41,0,239, - 241,3,76,38,0,240,239,1,0,0,0,241,244,1,0,0,0,242,240,1,0,0,0,242,243,1, - 0,0,0,243,245,1,0,0,0,244,242,1,0,0,0,245,246,5,81,0,0,246,247,5,10,0,0, - 247,248,3,74,37,0,248,41,1,0,0,0,249,250,3,82,41,0,250,255,5,81,0,0,251, - 252,5,15,0,0,252,253,3,82,41,0,253,254,5,81,0,0,254,256,1,0,0,0,255,251, - 1,0,0,0,256,257,1,0,0,0,257,255,1,0,0,0,257,258,1,0,0,0,258,259,1,0,0,0, - 259,260,5,10,0,0,260,261,3,74,37,0,261,43,1,0,0,0,262,263,5,81,0,0,263, - 264,7,1,0,0,264,268,3,74,37,0,265,266,5,81,0,0,266,268,7,2,0,0,267,262, - 1,0,0,0,267,265,1,0,0,0,268,45,1,0,0,0,269,270,5,25,0,0,270,271,5,14,0, - 0,271,272,5,78,0,0,272,273,5,6,0,0,273,276,3,74,37,0,274,275,5,15,0,0,275, - 277,3,64,32,0,276,274,1,0,0,0,276,277,1,0,0,0,277,278,1,0,0,0,278,279,5, - 16,0,0,279,47,1,0,0,0,280,281,5,25,0,0,281,282,5,14,0,0,282,285,3,74,37, - 0,283,284,5,15,0,0,284,286,3,64,32,0,285,283,1,0,0,0,285,286,1,0,0,0,286, - 287,1,0,0,0,287,288,5,16,0,0,288,49,1,0,0,0,289,290,5,26,0,0,290,291,3, - 68,34,0,291,51,1,0,0,0,292,293,5,27,0,0,293,294,5,14,0,0,294,295,3,74,37, - 0,295,296,5,16,0,0,296,299,3,28,14,0,297,298,5,28,0,0,298,300,3,28,14,0, - 299,297,1,0,0,0,299,300,1,0,0,0,300,53,1,0,0,0,301,305,3,56,28,0,302,305, - 3,58,29,0,303,305,3,60,30,0,304,301,1,0,0,0,304,302,1,0,0,0,304,303,1,0, - 0,0,305,55,1,0,0,0,306,307,5,29,0,0,307,308,3,28,14,0,308,309,5,30,0,0, - 309,310,5,14,0,0,310,311,3,74,37,0,311,312,5,16,0,0,312,313,5,2,0,0,313, - 57,1,0,0,0,314,315,5,30,0,0,315,316,5,14,0,0,316,317,3,74,37,0,317,318, - 5,16,0,0,318,319,3,28,14,0,319,59,1,0,0,0,320,321,5,31,0,0,321,322,5,14, - 0,0,322,323,3,62,31,0,323,324,5,2,0,0,324,325,3,74,37,0,325,326,5,2,0,0, - 326,327,3,44,22,0,327,328,5,16,0,0,328,329,3,28,14,0,329,61,1,0,0,0,330, - 333,3,40,20,0,331,333,3,44,22,0,332,330,1,0,0,0,332,331,1,0,0,0,333,63, - 1,0,0,0,334,335,5,75,0,0,335,65,1,0,0,0,336,339,5,81,0,0,337,339,3,78,39, - 0,338,336,1,0,0,0,338,337,1,0,0,0,339,67,1,0,0,0,340,352,5,14,0,0,341,346, - 3,66,33,0,342,343,5,15,0,0,343,345,3,66,33,0,344,342,1,0,0,0,345,348,1, - 0,0,0,346,344,1,0,0,0,346,347,1,0,0,0,347,350,1,0,0,0,348,346,1,0,0,0,349, - 351,5,15,0,0,350,349,1,0,0,0,350,351,1,0,0,0,351,353,1,0,0,0,352,341,1, - 0,0,0,352,353,1,0,0,0,353,354,1,0,0,0,354,355,5,16,0,0,355,69,1,0,0,0,356, - 357,5,81,0,0,357,358,3,72,36,0,358,71,1,0,0,0,359,371,5,14,0,0,360,365, - 3,74,37,0,361,362,5,15,0,0,362,364,3,74,37,0,363,361,1,0,0,0,364,367,1, - 0,0,0,365,363,1,0,0,0,365,366,1,0,0,0,366,369,1,0,0,0,367,365,1,0,0,0,368, - 370,5,15,0,0,369,368,1,0,0,0,369,370,1,0,0,0,370,372,1,0,0,0,371,360,1, - 0,0,0,371,372,1,0,0,0,372,373,1,0,0,0,373,374,5,16,0,0,374,73,1,0,0,0,375, - 376,6,37,-1,0,376,377,5,14,0,0,377,378,3,74,37,0,378,379,5,16,0,0,379,425, - 1,0,0,0,380,381,3,84,42,0,381,382,5,14,0,0,382,384,3,74,37,0,383,385,5, - 15,0,0,384,383,1,0,0,0,384,385,1,0,0,0,385,386,1,0,0,0,386,387,5,16,0,0, - 387,425,1,0,0,0,388,425,3,70,35,0,389,390,5,32,0,0,390,391,5,81,0,0,391, - 425,3,72,36,0,392,393,5,35,0,0,393,394,5,33,0,0,394,395,3,74,37,0,395,396, - 5,34,0,0,396,397,7,3,0,0,397,425,1,0,0,0,398,399,5,41,0,0,399,400,5,33, - 0,0,400,401,3,74,37,0,401,402,5,34,0,0,402,403,7,4,0,0,403,425,1,0,0,0, - 404,405,7,5,0,0,405,425,3,74,37,15,406,418,5,33,0,0,407,412,3,74,37,0,408, - 409,5,15,0,0,409,411,3,74,37,0,410,408,1,0,0,0,411,414,1,0,0,0,412,410, - 1,0,0,0,412,413,1,0,0,0,413,416,1,0,0,0,414,412,1,0,0,0,415,417,5,15,0, - 0,416,415,1,0,0,0,416,417,1,0,0,0,417,419,1,0,0,0,418,407,1,0,0,0,418,419, - 1,0,0,0,419,420,1,0,0,0,420,425,5,34,0,0,421,425,5,80,0,0,422,425,5,81, - 0,0,423,425,3,78,39,0,424,375,1,0,0,0,424,380,1,0,0,0,424,388,1,0,0,0,424, - 389,1,0,0,0,424,392,1,0,0,0,424,398,1,0,0,0,424,404,1,0,0,0,424,406,1,0, - 0,0,424,421,1,0,0,0,424,422,1,0,0,0,424,423,1,0,0,0,425,478,1,0,0,0,426, - 427,10,14,0,0,427,428,7,6,0,0,428,477,3,74,37,15,429,430,10,13,0,0,430, - 431,7,7,0,0,431,477,3,74,37,14,432,433,10,12,0,0,433,434,7,8,0,0,434,477, - 3,74,37,13,435,436,10,11,0,0,436,437,7,9,0,0,437,477,3,74,37,12,438,439, - 10,10,0,0,439,440,7,10,0,0,440,477,3,74,37,11,441,442,10,9,0,0,442,443, - 5,60,0,0,443,477,3,74,37,10,444,445,10,8,0,0,445,446,5,4,0,0,446,477,3, - 74,37,9,447,448,10,7,0,0,448,449,5,61,0,0,449,477,3,74,37,8,450,451,10, - 6,0,0,451,452,5,62,0,0,452,477,3,74,37,7,453,454,10,5,0,0,454,455,5,63, - 0,0,455,477,3,74,37,6,456,457,10,21,0,0,457,458,5,33,0,0,458,459,5,68,0, - 0,459,477,5,34,0,0,460,461,10,18,0,0,461,477,7,11,0,0,462,463,10,17,0,0, - 463,464,5,48,0,0,464,465,5,14,0,0,465,466,3,74,37,0,466,467,5,16,0,0,467, - 477,1,0,0,0,468,469,10,16,0,0,469,470,5,49,0,0,470,471,5,14,0,0,471,472, - 3,74,37,0,472,473,5,15,0,0,473,474,3,74,37,0,474,475,5,16,0,0,475,477,1, - 0,0,0,476,426,1,0,0,0,476,429,1,0,0,0,476,432,1,0,0,0,476,435,1,0,0,0,476, - 438,1,0,0,0,476,441,1,0,0,0,476,444,1,0,0,0,476,447,1,0,0,0,476,450,1,0, - 0,0,476,453,1,0,0,0,476,456,1,0,0,0,476,460,1,0,0,0,476,462,1,0,0,0,476, - 468,1,0,0,0,477,480,1,0,0,0,478,476,1,0,0,0,478,479,1,0,0,0,479,75,1,0, - 0,0,480,478,1,0,0,0,481,482,5,64,0,0,482,77,1,0,0,0,483,489,5,66,0,0,484, - 489,3,80,40,0,485,489,5,75,0,0,486,489,5,76,0,0,487,489,5,77,0,0,488,483, - 1,0,0,0,488,484,1,0,0,0,488,485,1,0,0,0,488,486,1,0,0,0,488,487,1,0,0,0, - 489,79,1,0,0,0,490,492,5,68,0,0,491,493,5,67,0,0,492,491,1,0,0,0,492,493, - 1,0,0,0,493,81,1,0,0,0,494,495,7,12,0,0,495,83,1,0,0,0,496,497,7,13,0,0, - 497,85,1,0,0,0,43,89,95,101,115,118,130,142,147,158,172,183,187,189,200, - 205,211,221,231,236,242,257,267,276,285,299,304,332,338,346,350,352,365, - 369,371,384,412,416,418,424,476,478,488,492]; + 39,7,39,2,40,7,40,2,41,7,41,2,42,7,42,2,43,7,43,1,0,5,0,90,8,0,10,0,12, + 0,93,9,0,1,0,5,0,96,8,0,10,0,12,0,99,9,0,1,0,5,0,102,8,0,10,0,12,0,105, + 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,118,8,3,1,4,3,4,121, + 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,134,8,7,1,8,1,8,1,8, + 1,8,1,8,1,8,1,8,1,8,5,8,144,8,8,10,8,12,8,147,9,8,1,8,1,8,3,8,151,8,8,1, + 8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,5,10,167,8,10, + 10,10,12,10,170,9,10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,12,1,12,5,12, + 181,8,12,10,12,12,12,184,9,12,1,12,1,12,1,13,1,13,1,13,1,13,5,13,192,8, + 13,10,13,12,13,195,9,13,1,13,3,13,198,8,13,3,13,200,8,13,1,13,1,13,1,14, + 1,14,1,14,1,15,1,15,5,15,209,8,15,10,15,12,15,212,9,15,1,15,1,15,3,15,216, + 8,15,1,16,1,16,1,16,1,16,3,16,222,8,16,1,17,1,17,1,17,1,17,1,17,1,17,1, + 17,1,17,3,17,232,8,17,1,18,1,18,1,19,1,19,1,19,1,19,5,19,240,8,19,10,19, + 12,19,243,9,19,1,20,1,20,3,20,247,8,20,1,21,1,21,5,21,251,8,21,10,21,12, + 21,254,9,21,1,21,1,21,1,21,1,21,1,22,1,22,1,22,1,22,1,22,1,22,4,22,266, + 8,22,11,22,12,22,267,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,23,3,23,278,8, + 23,1,24,1,24,1,24,1,24,1,24,1,24,1,24,3,24,287,8,24,1,24,1,24,1,25,1,25, + 1,25,1,25,1,25,3,25,296,8,25,1,25,1,25,1,26,1,26,1,26,1,27,1,27,1,27,1, + 27,1,27,1,27,1,27,3,27,310,8,27,1,28,1,28,1,28,3,28,315,8,28,1,29,1,29, + 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,31,1,31,1, + 31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,32,1,32,3,32,343,8,32,1,33,1,33, + 1,34,1,34,3,34,349,8,34,1,35,1,35,1,35,1,35,5,35,355,8,35,10,35,12,35,358, + 9,35,1,35,3,35,361,8,35,3,35,363,8,35,1,35,1,35,1,36,1,36,1,36,1,37,1,37, + 1,37,1,37,5,37,374,8,37,10,37,12,37,377,9,37,1,37,3,37,380,8,37,3,37,382, + 8,37,1,37,1,37,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,3,38,395,8, + 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,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,5,38,421,8,38,10,38,12, + 38,424,9,38,1,38,3,38,427,8,38,3,38,429,8,38,1,38,1,38,1,38,1,38,3,38,435, + 8,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,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,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,38,1,38,1,38,1,38,1,38,1,38,5,38,487,8,38,10,38,12,38,490,9,38, + 1,39,1,39,1,40,1,40,1,40,1,40,1,40,3,40,499,8,40,1,41,1,41,3,41,503,8,41, + 1,42,1,42,1,43,1,43,1,43,0,1,76,44,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,0,14,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,1,0,71,73,2,0,71,72,79,79,539,0,91,1,0,0,0,2,108,1,0, + 0,0,4,113,1,0,0,0,6,115,1,0,0,0,8,120,1,0,0,0,10,124,1,0,0,0,12,126,1,0, + 0,0,14,133,1,0,0,0,16,135,1,0,0,0,18,154,1,0,0,0,20,161,1,0,0,0,22,173, + 1,0,0,0,24,178,1,0,0,0,26,187,1,0,0,0,28,203,1,0,0,0,30,215,1,0,0,0,32, + 221,1,0,0,0,34,231,1,0,0,0,36,233,1,0,0,0,38,235,1,0,0,0,40,246,1,0,0,0, + 42,248,1,0,0,0,44,259,1,0,0,0,46,277,1,0,0,0,48,279,1,0,0,0,50,290,1,0, + 0,0,52,299,1,0,0,0,54,302,1,0,0,0,56,314,1,0,0,0,58,316,1,0,0,0,60,324, + 1,0,0,0,62,330,1,0,0,0,64,342,1,0,0,0,66,344,1,0,0,0,68,348,1,0,0,0,70, + 350,1,0,0,0,72,366,1,0,0,0,74,369,1,0,0,0,76,434,1,0,0,0,78,491,1,0,0,0, + 80,498,1,0,0,0,82,500,1,0,0,0,84,504,1,0,0,0,86,506,1,0,0,0,88,90,3,2,1, + 0,89,88,1,0,0,0,90,93,1,0,0,0,91,89,1,0,0,0,91,92,1,0,0,0,92,97,1,0,0,0, + 93,91,1,0,0,0,94,96,3,12,6,0,95,94,1,0,0,0,96,99,1,0,0,0,97,95,1,0,0,0, + 97,98,1,0,0,0,98,103,1,0,0,0,99,97,1,0,0,0,100,102,3,14,7,0,101,100,1,0, + 0,0,102,105,1,0,0,0,103,101,1,0,0,0,103,104,1,0,0,0,104,106,1,0,0,0,105, + 103,1,0,0,0,106,107,5,0,0,1,107,1,1,0,0,0,108,109,5,1,0,0,109,110,3,4,2, + 0,110,111,3,6,3,0,111,112,5,2,0,0,112,3,1,0,0,0,113,114,5,3,0,0,114,5,1, + 0,0,0,115,117,3,8,4,0,116,118,3,8,4,0,117,116,1,0,0,0,117,118,1,0,0,0,118, + 7,1,0,0,0,119,121,3,10,5,0,120,119,1,0,0,0,120,121,1,0,0,0,121,122,1,0, + 0,0,122,123,5,65,0,0,123,9,1,0,0,0,124,125,7,0,0,0,125,11,1,0,0,0,126,127, + 5,11,0,0,127,128,5,75,0,0,128,129,5,2,0,0,129,13,1,0,0,0,130,134,3,16,8, + 0,131,134,3,18,9,0,132,134,3,20,10,0,133,130,1,0,0,0,133,131,1,0,0,0,133, + 132,1,0,0,0,134,15,1,0,0,0,135,136,5,12,0,0,136,137,5,81,0,0,137,150,3, + 26,13,0,138,139,5,13,0,0,139,140,5,14,0,0,140,145,3,84,42,0,141,142,5,15, + 0,0,142,144,3,84,42,0,143,141,1,0,0,0,144,147,1,0,0,0,145,143,1,0,0,0,145, + 146,1,0,0,0,146,148,1,0,0,0,147,145,1,0,0,0,148,149,5,16,0,0,149,151,1, + 0,0,0,150,138,1,0,0,0,150,151,1,0,0,0,151,152,1,0,0,0,152,153,3,24,12,0, + 153,17,1,0,0,0,154,155,3,84,42,0,155,156,5,17,0,0,156,157,5,81,0,0,157, + 158,5,10,0,0,158,159,3,80,40,0,159,160,5,2,0,0,160,19,1,0,0,0,161,162,5, + 18,0,0,162,163,5,81,0,0,163,164,3,26,13,0,164,168,5,19,0,0,165,167,3,22, + 11,0,166,165,1,0,0,0,167,170,1,0,0,0,168,166,1,0,0,0,168,169,1,0,0,0,169, + 171,1,0,0,0,170,168,1,0,0,0,171,172,5,20,0,0,172,21,1,0,0,0,173,174,5,12, + 0,0,174,175,5,81,0,0,175,176,3,26,13,0,176,177,3,24,12,0,177,23,1,0,0,0, + 178,182,5,19,0,0,179,181,3,32,16,0,180,179,1,0,0,0,181,184,1,0,0,0,182, + 180,1,0,0,0,182,183,1,0,0,0,183,185,1,0,0,0,184,182,1,0,0,0,185,186,5,20, + 0,0,186,25,1,0,0,0,187,199,5,14,0,0,188,193,3,28,14,0,189,190,5,15,0,0, + 190,192,3,28,14,0,191,189,1,0,0,0,192,195,1,0,0,0,193,191,1,0,0,0,193,194, + 1,0,0,0,194,197,1,0,0,0,195,193,1,0,0,0,196,198,5,15,0,0,197,196,1,0,0, + 0,197,198,1,0,0,0,198,200,1,0,0,0,199,188,1,0,0,0,199,200,1,0,0,0,200,201, + 1,0,0,0,201,202,5,16,0,0,202,27,1,0,0,0,203,204,3,84,42,0,204,205,5,81, + 0,0,205,29,1,0,0,0,206,210,5,19,0,0,207,209,3,32,16,0,208,207,1,0,0,0,209, + 212,1,0,0,0,210,208,1,0,0,0,210,211,1,0,0,0,211,213,1,0,0,0,212,210,1,0, + 0,0,213,216,5,20,0,0,214,216,3,32,16,0,215,206,1,0,0,0,215,214,1,0,0,0, + 216,31,1,0,0,0,217,222,3,40,20,0,218,219,3,34,17,0,219,220,5,2,0,0,220, + 222,1,0,0,0,221,217,1,0,0,0,221,218,1,0,0,0,222,33,1,0,0,0,223,232,3,42, + 21,0,224,232,3,44,22,0,225,232,3,46,23,0,226,232,3,48,24,0,227,232,3,50, + 25,0,228,232,3,36,18,0,229,232,3,52,26,0,230,232,3,38,19,0,231,223,1,0, + 0,0,231,224,1,0,0,0,231,225,1,0,0,0,231,226,1,0,0,0,231,227,1,0,0,0,231, + 228,1,0,0,0,231,229,1,0,0,0,231,230,1,0,0,0,232,35,1,0,0,0,233,234,3,72, + 36,0,234,37,1,0,0,0,235,236,5,21,0,0,236,241,3,76,38,0,237,238,5,15,0,0, + 238,240,3,76,38,0,239,237,1,0,0,0,240,243,1,0,0,0,241,239,1,0,0,0,241,242, + 1,0,0,0,242,39,1,0,0,0,243,241,1,0,0,0,244,247,3,54,27,0,245,247,3,56,28, + 0,246,244,1,0,0,0,246,245,1,0,0,0,247,41,1,0,0,0,248,252,3,84,42,0,249, + 251,3,78,39,0,250,249,1,0,0,0,251,254,1,0,0,0,252,250,1,0,0,0,252,253,1, + 0,0,0,253,255,1,0,0,0,254,252,1,0,0,0,255,256,5,81,0,0,256,257,5,10,0,0, + 257,258,3,76,38,0,258,43,1,0,0,0,259,260,3,84,42,0,260,265,5,81,0,0,261, + 262,5,15,0,0,262,263,3,84,42,0,263,264,5,81,0,0,264,266,1,0,0,0,265,261, + 1,0,0,0,266,267,1,0,0,0,267,265,1,0,0,0,267,268,1,0,0,0,268,269,1,0,0,0, + 269,270,5,10,0,0,270,271,3,76,38,0,271,45,1,0,0,0,272,273,5,81,0,0,273, + 274,7,1,0,0,274,278,3,76,38,0,275,276,5,81,0,0,276,278,7,2,0,0,277,272, + 1,0,0,0,277,275,1,0,0,0,278,47,1,0,0,0,279,280,5,26,0,0,280,281,5,14,0, + 0,281,282,5,78,0,0,282,283,5,6,0,0,283,286,3,76,38,0,284,285,5,15,0,0,285, + 287,3,66,33,0,286,284,1,0,0,0,286,287,1,0,0,0,287,288,1,0,0,0,288,289,5, + 16,0,0,289,49,1,0,0,0,290,291,5,26,0,0,291,292,5,14,0,0,292,295,3,76,38, + 0,293,294,5,15,0,0,294,296,3,66,33,0,295,293,1,0,0,0,295,296,1,0,0,0,296, + 297,1,0,0,0,297,298,5,16,0,0,298,51,1,0,0,0,299,300,5,27,0,0,300,301,3, + 70,35,0,301,53,1,0,0,0,302,303,5,28,0,0,303,304,5,14,0,0,304,305,3,76,38, + 0,305,306,5,16,0,0,306,309,3,30,15,0,307,308,5,29,0,0,308,310,3,30,15,0, + 309,307,1,0,0,0,309,310,1,0,0,0,310,55,1,0,0,0,311,315,3,58,29,0,312,315, + 3,60,30,0,313,315,3,62,31,0,314,311,1,0,0,0,314,312,1,0,0,0,314,313,1,0, + 0,0,315,57,1,0,0,0,316,317,5,30,0,0,317,318,3,30,15,0,318,319,5,31,0,0, + 319,320,5,14,0,0,320,321,3,76,38,0,321,322,5,16,0,0,322,323,5,2,0,0,323, + 59,1,0,0,0,324,325,5,31,0,0,325,326,5,14,0,0,326,327,3,76,38,0,327,328, + 5,16,0,0,328,329,3,30,15,0,329,61,1,0,0,0,330,331,5,32,0,0,331,332,5,14, + 0,0,332,333,3,64,32,0,333,334,5,2,0,0,334,335,3,76,38,0,335,336,5,2,0,0, + 336,337,3,46,23,0,337,338,5,16,0,0,338,339,3,30,15,0,339,63,1,0,0,0,340, + 343,3,42,21,0,341,343,3,46,23,0,342,340,1,0,0,0,342,341,1,0,0,0,343,65, + 1,0,0,0,344,345,5,75,0,0,345,67,1,0,0,0,346,349,5,81,0,0,347,349,3,80,40, + 0,348,346,1,0,0,0,348,347,1,0,0,0,349,69,1,0,0,0,350,362,5,14,0,0,351,356, + 3,68,34,0,352,353,5,15,0,0,353,355,3,68,34,0,354,352,1,0,0,0,355,358,1, + 0,0,0,356,354,1,0,0,0,356,357,1,0,0,0,357,360,1,0,0,0,358,356,1,0,0,0,359, + 361,5,15,0,0,360,359,1,0,0,0,360,361,1,0,0,0,361,363,1,0,0,0,362,351,1, + 0,0,0,362,363,1,0,0,0,363,364,1,0,0,0,364,365,5,16,0,0,365,71,1,0,0,0,366, + 367,5,81,0,0,367,368,3,74,37,0,368,73,1,0,0,0,369,381,5,14,0,0,370,375, + 3,76,38,0,371,372,5,15,0,0,372,374,3,76,38,0,373,371,1,0,0,0,374,377,1, + 0,0,0,375,373,1,0,0,0,375,376,1,0,0,0,376,379,1,0,0,0,377,375,1,0,0,0,378, + 380,5,15,0,0,379,378,1,0,0,0,379,380,1,0,0,0,380,382,1,0,0,0,381,370,1, + 0,0,0,381,382,1,0,0,0,382,383,1,0,0,0,383,384,5,16,0,0,384,75,1,0,0,0,385, + 386,6,38,-1,0,386,387,5,14,0,0,387,388,3,76,38,0,388,389,5,16,0,0,389,435, + 1,0,0,0,390,391,3,86,43,0,391,392,5,14,0,0,392,394,3,76,38,0,393,395,5, + 15,0,0,394,393,1,0,0,0,394,395,1,0,0,0,395,396,1,0,0,0,396,397,5,16,0,0, + 397,435,1,0,0,0,398,435,3,72,36,0,399,400,5,33,0,0,400,401,5,81,0,0,401, + 435,3,74,37,0,402,403,5,36,0,0,403,404,5,34,0,0,404,405,3,76,38,0,405,406, + 5,35,0,0,406,407,7,3,0,0,407,435,1,0,0,0,408,409,5,42,0,0,409,410,5,34, + 0,0,410,411,3,76,38,0,411,412,5,35,0,0,412,413,7,4,0,0,413,435,1,0,0,0, + 414,415,7,5,0,0,415,435,3,76,38,15,416,428,5,34,0,0,417,422,3,76,38,0,418, + 419,5,15,0,0,419,421,3,76,38,0,420,418,1,0,0,0,421,424,1,0,0,0,422,420, + 1,0,0,0,422,423,1,0,0,0,423,426,1,0,0,0,424,422,1,0,0,0,425,427,5,15,0, + 0,426,425,1,0,0,0,426,427,1,0,0,0,427,429,1,0,0,0,428,417,1,0,0,0,428,429, + 1,0,0,0,429,430,1,0,0,0,430,435,5,35,0,0,431,435,5,80,0,0,432,435,5,81, + 0,0,433,435,3,80,40,0,434,385,1,0,0,0,434,390,1,0,0,0,434,398,1,0,0,0,434, + 399,1,0,0,0,434,402,1,0,0,0,434,408,1,0,0,0,434,414,1,0,0,0,434,416,1,0, + 0,0,434,431,1,0,0,0,434,432,1,0,0,0,434,433,1,0,0,0,435,488,1,0,0,0,436, + 437,10,14,0,0,437,438,7,6,0,0,438,487,3,76,38,15,439,440,10,13,0,0,440, + 441,7,7,0,0,441,487,3,76,38,14,442,443,10,12,0,0,443,444,7,8,0,0,444,487, + 3,76,38,13,445,446,10,11,0,0,446,447,7,9,0,0,447,487,3,76,38,12,448,449, + 10,10,0,0,449,450,7,10,0,0,450,487,3,76,38,11,451,452,10,9,0,0,452,453, + 5,61,0,0,453,487,3,76,38,10,454,455,10,8,0,0,455,456,5,4,0,0,456,487,3, + 76,38,9,457,458,10,7,0,0,458,459,5,62,0,0,459,487,3,76,38,8,460,461,10, + 6,0,0,461,462,5,63,0,0,462,487,3,76,38,7,463,464,10,5,0,0,464,465,5,64, + 0,0,465,487,3,76,38,6,466,467,10,21,0,0,467,468,5,34,0,0,468,469,5,68,0, + 0,469,487,5,35,0,0,470,471,10,18,0,0,471,487,7,11,0,0,472,473,10,17,0,0, + 473,474,5,49,0,0,474,475,5,14,0,0,475,476,3,76,38,0,476,477,5,16,0,0,477, + 487,1,0,0,0,478,479,10,16,0,0,479,480,5,50,0,0,480,481,5,14,0,0,481,482, + 3,76,38,0,482,483,5,15,0,0,483,484,3,76,38,0,484,485,5,16,0,0,485,487,1, + 0,0,0,486,436,1,0,0,0,486,439,1,0,0,0,486,442,1,0,0,0,486,445,1,0,0,0,486, + 448,1,0,0,0,486,451,1,0,0,0,486,454,1,0,0,0,486,457,1,0,0,0,486,460,1,0, + 0,0,486,463,1,0,0,0,486,466,1,0,0,0,486,470,1,0,0,0,486,472,1,0,0,0,486, + 478,1,0,0,0,487,490,1,0,0,0,488,486,1,0,0,0,488,489,1,0,0,0,489,77,1,0, + 0,0,490,488,1,0,0,0,491,492,5,17,0,0,492,79,1,0,0,0,493,499,5,66,0,0,494, + 499,3,82,41,0,495,499,5,75,0,0,496,499,5,76,0,0,497,499,5,77,0,0,498,493, + 1,0,0,0,498,494,1,0,0,0,498,495,1,0,0,0,498,496,1,0,0,0,498,497,1,0,0,0, + 499,81,1,0,0,0,500,502,5,68,0,0,501,503,5,67,0,0,502,501,1,0,0,0,502,503, + 1,0,0,0,503,83,1,0,0,0,504,505,7,12,0,0,505,85,1,0,0,0,506,507,7,13,0,0, + 507,87,1,0,0,0,43,91,97,103,117,120,133,145,150,168,182,193,197,199,210, + 215,221,231,241,246,252,267,277,286,295,309,314,342,348,356,360,362,375, + 379,381,394,422,426,428,434,486,488,498,502]; private static __ATN: ATN; public static get _ATN(): ATN { @@ -3034,6 +3082,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; } @@ -3085,6 +3136,34 @@ export class GlobalFunctionDefinitionContext 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 literal(): LiteralContext { + return this.getTypedRuleContext(LiteralContext, 0) as LiteralContext; + } + 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 ContractDefinitionContext extends ParserRuleContext { constructor(parser?: CashScriptParser, parent?: ParserRuleContext, invokingState?: number) { super(parent, invokingState); @@ -3847,7 +3926,7 @@ export class ExpressionContext extends ParserRuleContext { public get ruleIndex(): number { return CashScriptParser.RULE_expression; } - public override copyFrom(ctx: ExpressionContext): void { + public copyFrom(ctx: ExpressionContext): void { super.copyFrom(ctx); } } diff --git a/packages/cashc/src/grammar/CashScriptVisitor.ts b/packages/cashc/src/grammar/CashScriptVisitor.ts index 9070d84fa..187bf8c79 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.2 +// Generated from src/grammar/CashScript.g4 by ANTLR 4.13.1 import {ParseTreeVisitor} from 'antlr4'; @@ -12,6 +12,7 @@ import { VersionOperatorContext } from "./CashScriptParser.js"; import { ImportDirectiveContext } from "./CashScriptParser.js"; import { TopLevelDefinitionContext } from "./CashScriptParser.js"; import { GlobalFunctionDefinitionContext } from "./CashScriptParser.js"; +import { ConstantDefinitionContext } from "./CashScriptParser.js"; import { ContractDefinitionContext } from "./CashScriptParser.js"; import { ContractFunctionDefinitionContext } from "./CashScriptParser.js"; import { FunctionBodyContext } from "./CashScriptParser.js"; @@ -122,6 +123,12 @@ export default class CashScriptVisitor extends ParseTreeVisitor * @return the visitor result */ visitGlobalFunctionDefinition?: (ctx: GlobalFunctionDefinitionContext) => 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.contractDefinition`. * @param ctx the parse tree diff --git a/packages/cashc/src/internal.ts b/packages/cashc/src/internal.ts new file mode 100644 index 000000000..4d5d7a98b --- /dev/null +++ b/packages/cashc/src/internal.ts @@ -0,0 +1,8 @@ +/* + * Internal entry point for this repo's own test suites. The compile functions exported here also + * accept internal-only compiler options (e.g. `disableInlining`), which are deliberately absent + * from the package's public API. This module is not re-exported from the package index and + * carries no stability guarantees. + */ +export { compileFileInternal as compileFile, compileStringInternal as compileString } from './compiler.js'; +export type { InternalCompilerOptions } from './compiler.js'; diff --git a/packages/cashc/src/print/OutputSourceCodeTraversal.ts b/packages/cashc/src/print/OutputSourceCodeTraversal.ts index 715fb32b2..b94406128 100644 --- a/packages/cashc/src/print/OutputSourceCodeTraversal.ts +++ b/packages/cashc/src/print/OutputSourceCodeTraversal.ts @@ -8,6 +8,7 @@ import { ParameterNode, VariableDefinitionNode, FunctionDefinitionNode, + ConstantDefinitionNode, AssignNode, IdentifierNode, BranchNode, @@ -37,6 +38,7 @@ import { ForNode, NonControlStatementNode, ExpressionNode, + LiteralNode, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; @@ -68,6 +70,7 @@ export default class OutputSourceCodeTraversal extends AstTraversal { visitSourceFile(node: SourceFileNode): Node { node.imports = this.visitList(node.imports) as ImportNode[]; + node.constants = this.visitList(node.constants) as ConstantDefinitionNode[]; node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; if (node.contract) node.contract = this.visit(node.contract) as ContractNode; return node; @@ -107,6 +110,13 @@ export default class OutputSourceCodeTraversal extends AstTraversal { return node; } + visitConstantDefinition(node: ConstantDefinitionNode): Node { + this.addOutput(`${node.type} constant ${node.name} = `, true); + node.value = this.visit(node.value) as LiteralNode; + this.addOutput(';\n'); + return node; + } + visitCommaList(list: Node[]): Node[] { return list.map((e, i) => { const visited = this.visit(e); diff --git a/packages/cashc/src/semantic/DeadCodeEliminationTraversal.ts b/packages/cashc/src/semantic/DeadCodeEliminationTraversal.ts index 657414902..cacaff94d 100644 --- a/packages/cashc/src/semantic/DeadCodeEliminationTraversal.ts +++ b/packages/cashc/src/semantic/DeadCodeEliminationTraversal.ts @@ -7,19 +7,14 @@ import { import AstTraversal from '../ast/AstTraversal.js'; export default class DeadCodeEliminationTraversal extends AstTraversal { - private reachableFunctions = new Set(); + private visitedFunctions: FunctionDefinitionNode[] = []; + private reachableFunctions: FunctionDefinitionNode[] = []; visitSourceFile(node: SourceFileNode): Node { super.visitOptional(node.contract); - // Set the node.functions to the reachable functions and re-index functionIds, the order is based on insertion - // into the set, which is most stable for the functionId as it is based on contract structure rather than - // name or order of declaration. - node.functions = [...this.reachableFunctions]; - node.functions.forEach((func, index) => { - node.symbolTable!.getFromThis(func.name)!.setFunctionId(index); - }); - + // The reachable functions are stored callee-first, which code generation relies on + node.functions = this.reachableFunctions; return node; } @@ -30,9 +25,10 @@ export default class DeadCodeEliminationTraversal extends AstTraversal { if (!functionDefinition || !(functionDefinition instanceof FunctionDefinitionNode)) return node; // Only descend into a function the first time it is reached to prevent infinite recursion. - if (!this.reachableFunctions.has(functionDefinition)) { - this.reachableFunctions.add(functionDefinition); + if (!this.visitedFunctions.includes(functionDefinition)) { + this.visitedFunctions.push(functionDefinition); this.visit(functionDefinition.body); + this.reachableFunctions.push(functionDefinition); } return node; diff --git a/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts b/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts index 50ef9dcfc..bc474c3dc 100644 --- a/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts +++ b/packages/cashc/src/semantic/EnsureFinalRequireTraversal.ts @@ -2,7 +2,6 @@ import { ContractNode, ParameterNode, FunctionDefinitionNode, - FunctionKind, RequireNode, ReturnNode, TimeOpNode, @@ -44,10 +43,10 @@ export default class EnsureFinalRequireTraversal extends AstTraversal { throw new EmptyFunctionError(node); } - if (node.kind === FunctionKind.CONTRACT) { - ensureFinalStatementIsRequire(node.body); - } else if (node.returnTypes !== undefined) { + if (node.returnTypes !== undefined) { ensureSingleTailReturn(node.body); + } else { + ensureFinalStatementIsRequire(node.body); } return node; diff --git a/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts b/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts new file mode 100644 index 000000000..56845d1bc --- /dev/null +++ b/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts @@ -0,0 +1,113 @@ +import { + BlockNode, + BoolLiteralNode, + ConsoleStatementNode, + ConstantDefinitionNode, + ContractNode, + FunctionCallNode, + FunctionDefinitionNode, + FunctionKind, + HexLiteralNode, + IdentifierNode, + IntLiteralNode, + LiteralNode, + Node, + ReturnNode, + SourceFileNode, + StringLiteralNode, +} from '../ast/AST.js'; +import { Symbol, SymbolTable } from '../ast/SymbolTable.js'; +import AstTraversal from '../ast/AstTraversal.js'; + +// Lowers constants to synthetic zero-argument global functions, so they can share reachability analysis and +// VM function-ID assignment with user-defined functions. +export class LowerGlobalConstantsTraversal extends AstTraversal { + private symbolTable: SymbolTable; + + visitSourceFile(node: SourceFileNode): Node { + this.symbolTable = node.symbolTable!; + + // Every constant becomes a function definition (replacing the constant's symbol in the table) + const constantFunctions = node.constants.map((constant) => { + const definition = createConstantFunction(constant); + this.symbolTable.set(Symbol.userFunction(definition)); + return definition; + }); + + node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; + node.contract = this.visitOptional(node.contract) as ContractNode | undefined; + node.functions.push(...constantFunctions); + return node; + } + + // constant usage within console.log statements are exempt from the rewrite because we + // want to log the constant value at compile-time, not the function call at runtime + visitConsoleStatement(node: ConsoleStatementNode): Node { + return node; + } + + visitBoolLiteral(node: BoolLiteralNode): Node { + return this.lowerLiteral(node); + } + + visitIntLiteral(node: IntLiteralNode): Node { + return this.lowerLiteral(node); + } + + visitStringLiteral(node: StringLiteralNode): Node { + return this.lowerLiteral(node); + } + + visitHexLiteral(node: HexLiteralNode): Node { + return this.lowerLiteral(node); + } + + private lowerLiteral(node: LiteralNode): Node { + if (!node.constant) return node; + + const symbol = this.symbolTable.getFromThis(node.constant.name)!; + const identifier = new IdentifierNode(node.constant.name); + identifier.location = node.location; + identifier.type = node.type; + identifier.symbol = symbol; + symbol.references.push(identifier); + + const call = new FunctionCallNode(identifier, []); + call.location = node.location; + call.type = node.type; + return call; + } +} + +// Create a synthetic FunctionDefinitionNode that represents a lowered constant +function createConstantFunction(constant: ConstantDefinitionNode): FunctionDefinitionNode { + const literal = cloneLiteral(constant.value); + literal.type = constant.type; + const returnStatement = new ReturnNode([literal]); + returnStatement.location = constant.location; + const body = new BlockNode([returnStatement]); + body.location = constant.location; + + const definition = new FunctionDefinitionNode(FunctionKind.GLOBAL, constant.name, [], body, [constant.type]); + definition.constant = constant; + definition.location = constant.location; + definition.sourceCode = constant.sourceCode; + definition.sourceFile = constant.sourceFile; + return definition; +} + +// Create a synthetic LiteralNode that represents a reference to a lowered constant function, +// so later passes can treat it as a literal +export function createConstantLiteral(constant: ConstantDefinitionNode, reference: IdentifierNode): LiteralNode { + const literal = cloneLiteral(constant.value); + literal.location = reference.location; + literal.type = constant.type; + literal.constant = constant; + return literal; +} + +function cloneLiteral(node: LiteralNode): LiteralNode { + const clone: LiteralNode = Object.assign(Object.create(Object.getPrototypeOf(node)), node); + if (clone instanceof HexLiteralNode) clone.value = clone.value.slice(); + return clone; +} diff --git a/packages/cashc/src/semantic/SymbolTableTraversal.ts b/packages/cashc/src/semantic/SymbolTableTraversal.ts index fbbc662c7..29480b665 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -5,6 +5,7 @@ import { ParameterNode, VariableDefinitionNode, FunctionDefinitionNode, + ConstantDefinitionNode, FunctionKind, IdentifierNode, StatementNode, @@ -21,9 +22,9 @@ import { } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; import { SymbolTable, Symbol, SymbolType } from '../ast/SymbolTable.js'; +import { createConstantLiteral } from './LowerGlobalConstantsTraversal.js'; import { - FunctionRedefinitionError, - VariableRedefinitionError, + RedefinitionError, UndefinedReferenceError, UnusedVariableError, InvalidSymbolTypeError, @@ -40,12 +41,14 @@ export default class SymbolTableTraversal extends AstTraversal { visitSourceFile(node: SourceFileNode): Node { const globalFunctionTable = new SymbolTable(this.symbolTables[0]); - node.functions.forEach((functionNode, functionId) => { - if (globalFunctionTable.get(functionNode.name)) { - throw new FunctionRedefinitionError(functionNode); - } - const symbol = Symbol.userFunction(functionNode, functionId); - globalFunctionTable.set(symbol); + node.functions.forEach((functionNode) => { + if (globalFunctionTable.get(functionNode.name)) throw new RedefinitionError(functionNode, functionNode.name); + globalFunctionTable.set(Symbol.userFunction(functionNode)); + }); + + node.constants.forEach((constantNode) => { + if (globalFunctionTable.get(constantNode.name)) throw new RedefinitionError(constantNode, constantNode.name); + globalFunctionTable.set(Symbol.constant(constantNode)); }); node.symbolTable = globalFunctionTable; @@ -76,7 +79,7 @@ export default class SymbolTableTraversal extends AstTraversal { visitParameter(node: ParameterNode): Node { if (this.symbolTables[0].get(node.name)) { - throw new VariableRedefinitionError(node); + throw new RedefinitionError(node, node.name); } this.symbolTables[0].set(Symbol.variable(node)); @@ -88,7 +91,7 @@ export default class SymbolTableTraversal extends AstTraversal { if (node.kind === FunctionKind.CONTRACT) { if (this.contractFunctionNames.get(node.name)) { - throw new FunctionRedefinitionError(node); + throw new RedefinitionError(node, node.name); } this.contractFunctionNames.set(node.name, true); } @@ -143,7 +146,7 @@ export default class SymbolTableTraversal extends AstTraversal { visitVariableDefinition(node: VariableDefinitionNode): Node { if (this.symbolTables[0].get(node.name)) { - throw new VariableRedefinitionError(node); + throw new RedefinitionError(node, node.name); } node.expression = this.visit(node.expression); @@ -154,13 +157,19 @@ export default class SymbolTableTraversal extends AstTraversal { } visitAssign(node: AssignNode): Node { - const v = this.symbolTables[0].get(node.identifier.name)?.definition as VariableDefinitionNode; - // const used_modifiers = [] # PREVENT USER FROM USING SAME MODIFIER AGAIN - v?.modifier?.forEach((modifier) => { - if (modifier === Modifier.CONSTANT) { - throw new ConstantModificationError(v); - } - }); + const definition = this.symbolTables[0].get(node.identifier.name)?.definition; + + if (definition === undefined || definition instanceof FunctionDefinitionNode) { + throw new UndefinedReferenceError(node.identifier); + } + + if (definition instanceof ConstantDefinitionNode) { + throw new ConstantModificationError(node, node.identifier.name); + } + + if (definition.modifiers?.includes(Modifier.CONSTANT)) { + throw new ConstantModificationError(node, node.identifier.name); + } super.visitAssign(node); return node; @@ -172,7 +181,7 @@ export default class SymbolTableTraversal extends AstTraversal { const { name } = variable; if (this.symbolTables[0].get(name)) { - throw new VariableRedefinitionError(definition); + throw new RedefinitionError(definition, name); } this.symbolTables[0].set( Symbol.variable(definition), @@ -218,6 +227,12 @@ export default class SymbolTableTraversal extends AstTraversal { throw new InvalidSymbolTypeError(node, this.expectedSymbolType); } + // Global constant references are replaced by their literal value, so all later passes + // (type checking, literal-driven analysis, codegen) see a plain literal at the use site. + if (symbol.definition instanceof ConstantDefinitionNode) { + return createConstantLiteral(symbol.definition, node); + } + node.symbol = symbol; node.symbol.references.push(node); diff --git a/packages/cashc/src/semantic/TypeCheckTraversal.ts b/packages/cashc/src/semantic/TypeCheckTraversal.ts index 37155ab7e..f0b89b2af 100644 --- a/packages/cashc/src/semantic/TypeCheckTraversal.ts +++ b/packages/cashc/src/semantic/TypeCheckTraversal.ts @@ -16,6 +16,8 @@ import { FunctionCallNode, FunctionCallStatementNode, FunctionDefinitionNode, + ConstantDefinitionNode, + LiteralNode, ParameterNode, UnaryOpNode, BinaryOpNode, @@ -61,6 +63,12 @@ import { functionReturnType, resultingTypeForBinaryOp } from '../utils.js'; export default class TypeCheckTraversal extends AstTraversal { private currentFunctionReturnTypes: Type[] = []; + visitConstantDefinition(node: ConstantDefinitionNode): Node { + node.value = this.visit(node.value) as LiteralNode; + expectAssignable(node, node.value.type, node.type); + return node; + } + visitVariableDefinition(node: VariableDefinitionNode): Node { node.expression = this.visit(node.expression); expectAssignable(node, node.expression.type, node.type); @@ -502,7 +510,7 @@ function expectTuple(node: ExpectedNode, actual?: Type): void { } } -type AssigningNode = AssignNode | VariableDefinitionNode; +type AssigningNode = AssignNode | VariableDefinitionNode | ConstantDefinitionNode; function expectAssignable(node: AssigningNode, actual?: Type, expected?: Type): void { if (!implicitlyCastable(actual, expected)) { throw new AssignTypeError(node); diff --git a/packages/cashc/test/ast/fixtures.ts b/packages/cashc/test/ast/fixtures.ts index da3e9d90a..9cfd509a0 100644 --- a/packages/cashc/test/ast/fixtures.ts +++ b/packages/cashc/test/ast/fixtures.ts @@ -44,13 +44,13 @@ export const fixtures: Fixture[] = [ ast: new SourceFileNode( new ContractNode( 'P2PKH', - [new ParameterNode(new BytesType(20), 'pkh')], + [new ParameterNode(new BytesType(20), [], 'pkh')], [new FunctionDefinitionNode( FunctionKind.CONTRACT, 'spend', [ - new ParameterNode(PrimitiveType.PUBKEY, 'pk'), - new ParameterNode(PrimitiveType.SIG, 's'), + new ParameterNode(PrimitiveType.PUBKEY, [], 'pk'), + new ParameterNode(PrimitiveType.SIG, [], 's'), ], new BlockNode([ new RequireNode( @@ -76,11 +76,11 @@ export const fixtures: Fixture[] = [ ast: new SourceFileNode( new ContractNode( 'Reassignment', - [new ParameterNode(PrimitiveType.INT, 'x'), new ParameterNode(PrimitiveType.STRING, 'y')], + [new ParameterNode(PrimitiveType.INT, [], 'x'), new ParameterNode(PrimitiveType.STRING, [], 'y')], [new FunctionDefinitionNode( FunctionKind.CONTRACT, 'hello', - [new ParameterNode(PrimitiveType.PUBKEY, 'pk'), new ParameterNode(PrimitiveType.SIG, 's')], + [new ParameterNode(PrimitiveType.PUBKEY, [], 'pk'), new ParameterNode(PrimitiveType.SIG, [], 's')], new BlockNode([ new VariableDefinitionNode( PrimitiveType.INT, @@ -150,12 +150,12 @@ export const fixtures: Fixture[] = [ ast: new SourceFileNode( new ContractNode( 'MultiFunctionIfStatements', - [new ParameterNode(PrimitiveType.INT, 'x'), new ParameterNode(PrimitiveType.INT, 'y')], + [new ParameterNode(PrimitiveType.INT, [], 'x'), new ParameterNode(PrimitiveType.INT, [], 'y')], [ new FunctionDefinitionNode( FunctionKind.CONTRACT, 'transfer', - [new ParameterNode(PrimitiveType.INT, 'a'), new ParameterNode(PrimitiveType.INT, 'b')], + [new ParameterNode(PrimitiveType.INT, [], 'a'), new ParameterNode(PrimitiveType.INT, [], 'b')], new BlockNode([ new VariableDefinitionNode( PrimitiveType.INT, @@ -239,7 +239,7 @@ export const fixtures: Fixture[] = [ new FunctionDefinitionNode( FunctionKind.CONTRACT, 'timeout', - [new ParameterNode(PrimitiveType.INT, 'b')], + [new ParameterNode(PrimitiveType.INT, [], 'b')], new BlockNode([ new VariableDefinitionNode( PrimitiveType.INT, @@ -312,16 +312,16 @@ export const fixtures: Fixture[] = [ new ContractNode( 'MultiSig', [ - new ParameterNode(PrimitiveType.PUBKEY, 'pk1'), - new ParameterNode(PrimitiveType.PUBKEY, 'pk2'), - new ParameterNode(PrimitiveType.PUBKEY, 'pk3'), + new ParameterNode(PrimitiveType.PUBKEY, [], 'pk1'), + new ParameterNode(PrimitiveType.PUBKEY, [], 'pk2'), + new ParameterNode(PrimitiveType.PUBKEY, [], 'pk3'), ], [new FunctionDefinitionNode( FunctionKind.CONTRACT, 'spend', [ - new ParameterNode(PrimitiveType.SIG, 's1'), - new ParameterNode(PrimitiveType.SIG, 's2'), + new ParameterNode(PrimitiveType.SIG, [], 's1'), + new ParameterNode(PrimitiveType.SIG, [], 's2'), ], new BlockNode([ new RequireNode( @@ -351,18 +351,18 @@ export const fixtures: Fixture[] = [ new ContractNode( 'HodlVault', [ - new ParameterNode(PrimitiveType.PUBKEY, 'ownerPk'), - new ParameterNode(PrimitiveType.PUBKEY, 'oraclePk'), - new ParameterNode(PrimitiveType.INT, 'minBlock'), - new ParameterNode(PrimitiveType.INT, 'priceTarget'), + new ParameterNode(PrimitiveType.PUBKEY, [], 'ownerPk'), + new ParameterNode(PrimitiveType.PUBKEY, [], 'oraclePk'), + new ParameterNode(PrimitiveType.INT, [], 'minBlock'), + new ParameterNode(PrimitiveType.INT, [], 'priceTarget'), ], [new FunctionDefinitionNode( FunctionKind.CONTRACT, 'spend', [ - new ParameterNode(PrimitiveType.SIG, 'ownerSig'), - new ParameterNode(PrimitiveType.DATASIG, 'oracleSig'), - new ParameterNode(new BytesType(8), 'oracleMessage'), + new ParameterNode(PrimitiveType.SIG, [], 'ownerSig'), + new ParameterNode(PrimitiveType.DATASIG, [], 'oracleSig'), + new ParameterNode(new BytesType(8), [], 'oracleMessage'), ], new BlockNode([ new TupleAssignmentNode( @@ -654,10 +654,10 @@ export const fixtures: Fixture[] = [ new ContractNode( 'Mecenas', [ - new ParameterNode(new BytesType(20), 'recipient'), - new ParameterNode(new BytesType(20), 'funder'), - new ParameterNode(PrimitiveType.INT, 'pledge'), - new ParameterNode(PrimitiveType.INT, 'period'), + new ParameterNode(new BytesType(20), [], 'recipient'), + new ParameterNode(new BytesType(20), [], 'funder'), + new ParameterNode(PrimitiveType.INT, [], 'pledge'), + new ParameterNode(PrimitiveType.INT, [], 'period'), ], [ new FunctionDefinitionNode( @@ -786,8 +786,8 @@ export const fixtures: Fixture[] = [ FunctionKind.CONTRACT, 'reclaim', [ - new ParameterNode(PrimitiveType.PUBKEY, 'pk'), - new ParameterNode(PrimitiveType.SIG, 's'), + new ParameterNode(PrimitiveType.PUBKEY, [], 'pk'), + new ParameterNode(PrimitiveType.SIG, [], 's'), ], new BlockNode([ new RequireNode( @@ -918,6 +918,7 @@ export const fixtures: Fixture[] = [ ), [], [], + [], ['>=0.8.0'], ), }, @@ -931,7 +932,7 @@ export const fixtures: Fixture[] = [ new FunctionDefinitionNode( FunctionKind.CONTRACT, 'spend', - [new ParameterNode(PrimitiveType.INT, 'value')], + [new ParameterNode(PrimitiveType.INT, [], 'value')], new BlockNode([ new RequireNode( new BinaryOpNode( diff --git a/packages/cashc/test/compiler/AssignTypeError/global_constant_wrong_type.cash b/packages/cashc/test/compiler/AssignTypeError/global_constant_wrong_type.cash new file mode 100644 index 000000000..7017faae8 --- /dev/null +++ b/packages/cashc/test/compiler/AssignTypeError/global_constant_wrong_type.cash @@ -0,0 +1,7 @@ +bool constant VALUE = 1; + +contract GlobalConstantWrongType() { + function spend() { + require(true); + } +} diff --git a/packages/cashc/test/compiler/ConstantModificationError/modify_global_constant.cash b/packages/cashc/test/compiler/ConstantModificationError/modify_global_constant.cash new file mode 100644 index 000000000..4f6bcf0d1 --- /dev/null +++ b/packages/cashc/test/compiler/ConstantModificationError/modify_global_constant.cash @@ -0,0 +1,8 @@ +int constant VALUE = 1; + +contract ModifyGlobalConstant() { + function spend() { + VALUE = 2; + require(true); + } +} diff --git a/packages/cashc/test/compiler/FinalRequireStatementError/void_global_function_without_require.cash b/packages/cashc/test/compiler/FinalRequireStatementError/void_global_function_without_require.cash new file mode 100644 index 000000000..c226aab83 --- /dev/null +++ b/packages/cashc/test/compiler/FinalRequireStatementError/void_global_function_without_require.cash @@ -0,0 +1,11 @@ +function increment(int x) { + x = x + 1; + console.log("incremented", x); +} + +contract VoidGlobalFunctionWithoutRequire() { + function spend(int n) { + increment(n); + require(n < 100); + } +} diff --git a/packages/cashc/test/compiler/ParseError/global_constant_non_literal.cash b/packages/cashc/test/compiler/ParseError/global_constant_non_literal.cash new file mode 100644 index 000000000..c9ee4ec45 --- /dev/null +++ b/packages/cashc/test/compiler/ParseError/global_constant_non_literal.cash @@ -0,0 +1,7 @@ +int constant VALUE = 4 + 9; + +contract GlobalConstantNonLiteral() { + function spend() { + require(VALUE == 13); + } +} diff --git a/packages/cashc/test/compiler/RedefinitionError/duplicate_global_constant.cash b/packages/cashc/test/compiler/RedefinitionError/duplicate_global_constant.cash new file mode 100644 index 000000000..697a30610 --- /dev/null +++ b/packages/cashc/test/compiler/RedefinitionError/duplicate_global_constant.cash @@ -0,0 +1,8 @@ +int constant VALUE = 1; +int constant VALUE = 2; + +contract DuplicateGlobalConstant() { + function spend() { + require(VALUE == 1); + } +} diff --git a/packages/cashc/test/compiler/RedefinitionError/global_constant_with_builtin_name.cash b/packages/cashc/test/compiler/RedefinitionError/global_constant_with_builtin_name.cash new file mode 100644 index 000000000..d7ba8d88d --- /dev/null +++ b/packages/cashc/test/compiler/RedefinitionError/global_constant_with_builtin_name.cash @@ -0,0 +1,7 @@ +int constant abs = 1; + +contract GlobalConstantWithBuiltinName() { + function spend() { + require(abs == 1); + } +} diff --git a/packages/cashc/test/compiler/RedefinitionError/global_constant_with_function_name.cash b/packages/cashc/test/compiler/RedefinitionError/global_constant_with_function_name.cash new file mode 100644 index 000000000..204d18c4a --- /dev/null +++ b/packages/cashc/test/compiler/RedefinitionError/global_constant_with_function_name.cash @@ -0,0 +1,11 @@ +int constant helper = 1; + +function helper() returns (int) { + return 1; +} + +contract GlobalConstantWithFunctionName() { + function spend() { + require(helper() == 1); + } +} diff --git a/packages/cashc/test/compiler/RedefinitionError/parameter_shadows_global_constant.cash b/packages/cashc/test/compiler/RedefinitionError/parameter_shadows_global_constant.cash new file mode 100644 index 000000000..d2a8dc395 --- /dev/null +++ b/packages/cashc/test/compiler/RedefinitionError/parameter_shadows_global_constant.cash @@ -0,0 +1,7 @@ +int constant VALUE = 1; + +contract ParameterShadowsGlobalConstant(int VALUE) { + function spend() { + require(VALUE == 1); + } +} diff --git a/packages/cashc/test/compiler/RedefinitionError/variable_shadows_global_constant.cash b/packages/cashc/test/compiler/RedefinitionError/variable_shadows_global_constant.cash new file mode 100644 index 000000000..602590527 --- /dev/null +++ b/packages/cashc/test/compiler/RedefinitionError/variable_shadows_global_constant.cash @@ -0,0 +1,8 @@ +int constant VALUE = 1; + +contract VariableShadowsGlobalConstant() { + function spend() { + int VALUE = 2; + require(VALUE == 2); + } +} diff --git a/packages/cashc/test/compiler/UndefinedReferenceError/assign_to_builtin_name.cash b/packages/cashc/test/compiler/UndefinedReferenceError/assign_to_builtin_name.cash new file mode 100644 index 000000000..435003317 --- /dev/null +++ b/packages/cashc/test/compiler/UndefinedReferenceError/assign_to_builtin_name.cash @@ -0,0 +1,6 @@ +contract AssignToBuiltinName() { + function spend(int x) { + abs = x; + require(abs > 0); + } +} diff --git a/packages/cashc/test/compiler/UndefinedReferenceError/assign_to_function_name.cash b/packages/cashc/test/compiler/UndefinedReferenceError/assign_to_function_name.cash new file mode 100644 index 000000000..7c89c6f5a --- /dev/null +++ b/packages/cashc/test/compiler/UndefinedReferenceError/assign_to_function_name.cash @@ -0,0 +1,10 @@ +function double(int a) returns (int) { + return a * 2; +} + +contract AssignToFunctionName() { + function spend(int x) { + double = 5; + require(double(x) == 10); + } +} diff --git a/packages/cashc/test/dead-code-elimination.test.ts b/packages/cashc/test/dead-code-elimination.test.ts deleted file mode 100644 index 1665bdc05..000000000 --- a/packages/cashc/test/dead-code-elimination.test.ts +++ /dev/null @@ -1,164 +0,0 @@ -import { compileString } from '../src/index.js'; - -const countOpDefines = (bytecode: string): number => [...bytecode.matchAll(/OP_DEFINE/g)].length; - -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; } - - contract Test() { - function spend(int x) { - require(used(x) == 6); - } - }`; - - const artifact = compileString(code); - expect(countOpDefines(artifact.bytecode)).toEqual(1); - expect(artifact.bytecode).toContain('OP_INVOKE'); - }); - - it('eliminates functions that are only reachable through other dead functions', () => { - const code = ` - function used(int a) returns (int) { return a + 1; } - function deadCaller(int a) returns (int) { return deadLeaf(a); } - function deadLeaf(int a) returns (int) { return a * 2; } - - contract Test() { - function spend(int x) { - require(used(x) == 6); - } - }`; - - // Only `used` is reachable; both `deadCaller` and the function it calls (`deadLeaf`) are dropped. - const artifact = compileString(code); - expect(countOpDefines(artifact.bytecode)).toEqual(1); - }); - - it('keeps a function that is only reachable transitively', () => { - const code = ` - function outer(int a) returns (int) { return inner(a) + 1; } - function inner(int a) returns (int) { return a * 2; } - - contract Test() { - function spend(int x) { - require(outer(x) == 7); - } - }`; - - // `outer` is called directly and `inner` only through `outer` — both must be defined. - const artifact = compileString(code); - expect(countOpDefines(artifact.bytecode)).toEqual(2); - }); - - it('keeps a recursive function without looping forever', () => { - const code = ` - function f(int n) returns (int) { return f(n); } - - contract Test() { - function spend(int x) { - require(f(x) == 0); - } - }`; - - const artifact = compileString(code); - expect(countOpDefines(artifact.bytecode)).toEqual(1); - }); - - it('keeps mutually recursive functions that are reachable', () => { - const code = ` - function a(int n) returns (int) { return b(n); } - function b(int n) returns (int) { return a(n); } - - contract Test() { - function spend(int x) { - require(a(x) == 0); - } - }`; - - const artifact = compileString(code); - expect(countOpDefines(artifact.bytecode)).toEqual(2); - }); - - it('eliminates a mutually recursive cycle that is never reached', () => { - const code = ` - function used(int n) returns (int) { return n + 1; } - function deadA(int n) returns (int) { return deadB(n); } - function deadB(int n) returns (int) { return deadA(n); } - - contract Test() { - function spend(int x) { - require(used(x) == 1); - } - }`; - - // deadA <-> deadB form a cycle but neither is reachable, so both are dropped. - const artifact = compileString(code); - expect(countOpDefines(artifact.bytecode)).toEqual(1); - }); - - it('eliminates an unused imported function', () => { - // math.cash exports both `addOne` and `double`; only `double` is used here, so `addOne` is dropped. - const code = 'import "./math.cash";\ncontract Test() { function spend(int x) { require(double(x) == 8); } }'; - const mathSource = ` - function addOne(int a) returns (int) { return a + 1; } - function double(int a) returns (int) { return a * 2; } - `; - - const artifact = compileString(code, { files: { './math.cash': mathSource } }); - expect(countOpDefines(artifact.bytecode)).toEqual(1); - }); -}); - -describe('Stable function id assignment', () => { - it('reordering function declarations does not change the bytecode', () => { - const ordered = ` - function a(int n) returns (int) { return n + 1; } - function b(int n) returns (int) { return n * 2; } - - contract Test() { - function spend(int x) { - require(b(x) + a(x) == 10); - } - }`; - - const reordered = ` - function b(int n) returns (int) { return n * 2; } - function a(int n) returns (int) { return n + 1; } - - contract Test() { - function spend(int x) { - require(b(x) + a(x) == 10); - } - }`; - - // functionIds follow call order (b, then a) rather than declaration order, so swapping the two - // declarations produces byte-identical output. - expect(compileString(reordered).bytecode).toEqual(compileString(ordered).bytecode); - }); - - it('renaming a function does not change the bytecode', () => { - const original = ` - function apple(int n) returns (int) { return n + 1; } - function mango(int n) returns (int) { return n * 2; } - - contract Test() { - function spend(int x) { - require(mango(x) + apple(x) == 10); - } - }`; - - const renamed = ` - function zebra(int n) returns (int) { return n + 1; } - function mango(int n) returns (int) { return n * 2; } - - contract Test() { - function spend(int x) { - require(mango(x) + zebra(x) == 10); - } - }`; - - expect(compileString(renamed).bytecode).toEqual(compileString(original).bytecode); - }); -}); diff --git a/packages/cashc/test/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts index 9ae7289d6..3283c5059 100644 --- a/packages/cashc/test/generation/fixtures.ts +++ b/packages/cashc/test/generation/fixtures.ts @@ -1,4 +1,5 @@ -import { Artifact, CompilerOptions } from '@cashscript/utils'; +import { Artifact } from '@cashscript/utils'; +import { InternalCompilerOptions } from '../../src/internal.js'; import fs from 'fs'; import { URL } from 'url'; import { version } from '../../src/index.js'; @@ -6,7 +7,7 @@ import { version } from '../../src/index.js'; interface Fixture { fn: string, artifact: Artifact, - compilerOptions?: CompilerOptions, + compilerOptions?: InternalCompilerOptions, } export const fixtures: Fixture[] = [ @@ -1411,6 +1412,7 @@ export const fixtures: Fixture[] = [ { // A single global function — the basic OP_DEFINE / OP_INVOKE calling convention. fn: 'global_function_simple.cash', + compilerOptions: { disableInlining: true }, artifact: { contractName: 'GlobalFunctionSimple', constructorInputs: [], @@ -1456,6 +1458,7 @@ 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: [], @@ -1500,6 +1503,7 @@ export const fixtures: Fixture[] = [ { // 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: [], @@ -1545,55 +1549,57 @@ 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: [], abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], bytecode: - // Functions are defined in call order (DFS from the contract), so m1 is id 0, leaf id 1, m2 id 2. - // OP_DEFINE m1 (id 0): return leaf(a) * 2 - '518a5295 OP_0 OP_DEFINE ' - // OP_DEFINE leaf (id 1): return a + 1 - + '8b OP_1 OP_DEFINE ' + // Functions are defined in callee-first order (leaf before its callers), so leaf is id 0, + // m1 id 1, m2 id 2. + // OP_DEFINE leaf (id 0): return a + 1 + '8b OP_0 OP_DEFINE ' + // OP_DEFINE m1 (id 1): return leaf(a) * 2 + + '008a5295 OP_1 OP_DEFINE ' // OP_DEFINE m2 (id 2): return leaf(a) + 3 - + '518a5393 OP_2 OP_DEFINE ' + + '008a5393 OP_2 OP_DEFINE ' // require(m1(x) + m2(x) == 18) - + 'OP_DUP OP_0 OP_INVOKE OP_SWAP OP_2 OP_INVOKE OP_ADD 12 OP_NUMEQUAL', + + 'OP_DUP OP_1 OP_INVOKE OP_SWAP OP_2 OP_INVOKE OP_ADD 12 OP_NUMEQUAL', debug: { - bytecode: '04518a52950089018b518904518a5393528976008a7c528a9301129c', + bytecode: '018b008904008a5295518904008a5393528976518a7c528a9301129c', logs: [], requires: [ { ip: 18, line: 6 }, ], - sourceMap: '2::4:1;;::::1;1::3::0;;::::1;2::4::0;;::::1;6:19:6:20:0;:16::21:1;;:27::28:0;:24::29:1;;:16;:33::35:0;:8::37:1', + sourceMap: '1::3:1;;::::1;2::4::0;;::::1;::::0;;::::1;6:19:6:20:0;:16::21:1;;:27::28:0;:24::29:1;;:16;:33::35:0;:8::37:1', functions: [ { id: 0, - name: 'm1', + name: 'leaf', inputs: [{ name: 'a', type: 'int' }], - bytecode: '518a5295', - sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', + bytecode: '8b', + sourceMap: '2:11:2:16:1', logs: [], requires: [], - source: fs.readFileSync(new URL('../import-fixtures/mid1.cash', import.meta.url), { encoding: 'utf-8' }), - sourceFile: 'mid1.cash', + source: fs.readFileSync(new URL('../import-fixtures/leaf.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'leaf.cash', }, { id: 1, - name: 'leaf', + name: 'm1', inputs: [{ name: 'a', type: 'int' }], - bytecode: '8b', - sourceMap: '2:11:2:16:1', + bytecode: '008a5295', + sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', logs: [], requires: [], - source: fs.readFileSync(new URL('../import-fixtures/leaf.cash', import.meta.url), { encoding: 'utf-8' }), - sourceFile: 'leaf.cash', + source: fs.readFileSync(new URL('../import-fixtures/mid1.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'mid1.cash', }, { id: 2, name: 'm2', inputs: [{ name: 'a', type: 'int' }], - bytecode: '518a5393', + bytecode: '008a5393', sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', logs: [], requires: [], @@ -1615,10 +1621,160 @@ export const fixtures: Fixture[] = [ fingerprint: '316a3305152ec0695bf80303736c79dd1f9cc2f1dbccf57d9965094401363307', }, }, + { + // A small global constant used repeatedly — inlined as a plain literal at each use site (no + // OP_DEFINE), with source locations mapping to the use sites rather than the declaration. + fn: 'global_constant_inlined.cash', + artifact: { + contractName: 'GlobalConstantInlined', + constructorInputs: [{ name: 'value', type: 'int' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // require(value + ONE + ONE == 3) + 'OP_1ADD OP_1ADD OP_3 OP_NUMEQUAL', + debug: { + bytecode: '8b8b539c', + logs: [], + requires: [ + { ip: 5, line: 5 }, + ], + sourceMap: '5:16:5:27:1;:::33;:37::38:0;:8::40:1', + // Both literal pushes were fused into the OP_1ADDs during optimisation; the ranges track them + inlineRanges: '1:1:ONE;2:2:ONE', + functions: [ + { + // The inlined constant is documented as an id-less frame; both of its literal pushes + // were emitted at the use sites and fused into the OP_1ADDs during optimisation + name: 'ONE', + kind: 'constant', + inputs: [], + bytecode: '51', + sourceMap: '1:19:1:20', + logs: [], + requires: [], + }, + ], + }, + source: fs.readFileSync(new URL('../valid-contract-files/global_constant_inlined.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: '0d639aa764e1dc4045e25efe7dc27bd247b3cd45dd6c3a878a83bc3015e38a59', + }, + }, + { + // A global constant used repeatedly — lowered to a zero-argument VM function definition with a + // kind: 'constant' debug frame; each use compiles to an OP_INVOKE. + fn: 'global_constant_shared.cash', + artifact: { + contractName: 'GlobalConstantShared', + constructorInputs: [{ name: 'first', type: 'bytes32' }, { name: 'second', type: 'bytes32' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // OP_DEFINE HASH (id 0): the 32-byte literal + '203333333333333333333333333333333333333333333333333333333333333333 OP_0 OP_DEFINE ' + // require(first == HASH); require(second == HASH) + + 'OP_0 OP_INVOKE OP_EQUALVERIFY OP_0 OP_INVOKE OP_EQUAL', + debug: { + bytecode: '212033333333333333333333333333333333333333333333333333333333333333330089008a88008a87', + logs: [], + requires: [ + { ip: 7, line: 5 }, + { ip: 11, line: 6 }, + ], + sourceMap: '1::1:91;;::::1;5:25:5:29;;:8::31;6:26:6:30;;:8::32', + functions: [ + { + id: 0, + name: 'HASH', + kind: 'constant', + inputs: [], + bytecode: '203333333333333333333333333333333333333333333333333333333333333333', + sourceMap: '1:24:1:90', + logs: [], + requires: [], + }, + ], + }, + source: fs.readFileSync(new URL('../valid-contract-files/global_constant_shared.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: '6a5509a2ece64c7e47b4e1185da2f8b92fc0e1f75cc818be86b783c7bf134c5e', + }, + }, + { + // A single-use global function — inlined at the call site, splicing its console.log and require + // metadata into the contract's debug info (same-file bodies keep their own source lines). + fn: 'global_function_inlined.cash', + artifact: { + contractName: 'GlobalFunctionInlined', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'n', type: 'int' }] }], + bytecode: + // require(checked(n) == n), with checked(x) spliced in: + // console.log ... require(x > 0, "positive") ... return x + 'OP_DUP OP_DUP OP_0 OP_GREATERTHAN OP_VERIFY OP_NUMEQUAL', + debug: { + bytecode: '767600a0699c', + logs: [ + { ip: 1, line: 9, data: ['checking', { stackIndex: 0, type: 'int', ip: 1 }] }, + ], + requires: [ + { ip: 4, line: 9, message: 'positive' }, + { ip: 6, line: 9 }, + ], + // The emitted body ops (ips 1-4) and the merged require/log entries above all map to the + // call site; the function's own lines live on its frame below, tied together by the range + sourceMap: '9:24:9:25;:16::26:1;;;;:8::33', + inlineRanges: '1:4:checked', + functions: [ + { + // The inlined function is documented as an id-less frame carrying its compiled body + // and frame-local debug info (ips from 0) + name: 'checked', + inputs: [{ name: 'x', type: 'int' }], + bytecode: '7600a069', + sourceMap: '3:12:3:13;:16::17;:12:::1;:4::31', + logs: [ + { ip: 0, line: 2, data: ['checking', { stackIndex: 0, type: 'int', ip: 0 }] }, + ], + requires: [ + { ip: 3, line: 3, message: 'positive' }, + ], + }, + ], + }, + source: fs.readFileSync(new URL('../valid-contract-files/global_function_inlined.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: 'a19e54aee90995fe784da8e5501a95020d91aa1ccf17ac1f3c7a3e7be0813a73', + }, + }, { // A multi-return function — locks in the calling convention: return values are left on the stack // in declared order (last value on top) and bound by an N-ary tuple destructuring at the call site. fn: 'global_function_multi_return.cash', + compilerOptions: { disableInlining: true }, artifact: { contractName: 'GlobalFunctionMultiReturn', constructorInputs: [], diff --git a/packages/cashc/test/generation/generation.test.ts b/packages/cashc/test/generation/generation.test.ts index 4e4168817..4d5c71226 100644 --- a/packages/cashc/test/generation/generation.test.ts +++ b/packages/cashc/test/generation/generation.test.ts @@ -4,7 +4,7 @@ */ import { URL } from 'url'; -import { compileFile } from '../../src/index.js'; +import { compileFile } from '../../src/internal.js'; import { fixtures } from './fixtures.js'; describe('Code generation & target code optimisation', () => { diff --git a/packages/cashc/test/global-definitions.test.ts b/packages/cashc/test/global-definitions.test.ts new file mode 100644 index 000000000..bbb735deb --- /dev/null +++ b/packages/cashc/test/global-definitions.test.ts @@ -0,0 +1,508 @@ +/* global-definitions.test.ts + * + * - This file tests the compilation behaviour of user-defined global functions and constants: + * dead-code elimination of unreachable definitions, the byte-size-driven decisions to inline + * definitions at their call sites or to share them as OP_DEFINE / OP_INVOKE definitions, the + * lowering of constants to zero-argument functions, and stable VM function-ID assignment. + * - Compile errors are tested with the fixture files in ./compiler, and the exact compiled output + * is locked in by the fixtures in generation/fixtures.ts. + */ + +import { compileString } from '../src/internal.js'; + +const countOp = (bytecode: string, opcode: string): number => [...bytecode.matchAll(new RegExp(opcode, 'g'))].length; + +const longHex = (byte: string): string => `0x${byte.repeat(32)}`; + +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; } + + contract Test() { + function spend(int x) { + require(used(x) == 6); + } + }`; + + const artifact = compileString(code, { disableInlining: true }); + expect(countOp(artifact.bytecode, 'OP_DEFINE')).toEqual(1); + expect(artifact.bytecode).toContain('OP_INVOKE'); + }); + + it('eliminates functions that are only reachable through other dead functions', () => { + const code = ` + function used(int a) returns (int) { return a + 1; } + function deadCaller(int a) returns (int) { return deadLeaf(a); } + function deadLeaf(int a) returns (int) { return a * 2; } + + contract Test() { + function spend(int x) { + require(used(x) == 6); + } + }`; + + // Only `used` is reachable; both `deadCaller` and the function it calls (`deadLeaf`) are dropped. + const artifact = compileString(code, { disableInlining: true }); + expect(countOp(artifact.bytecode, 'OP_DEFINE')).toEqual(1); + }); + + it('keeps a function that is only reachable transitively', () => { + const code = ` + function outer(int a) returns (int) { return inner(a) + 1; } + function inner(int a) returns (int) { return a * 2; } + + contract Test() { + function spend(int x) { + require(outer(x) == 7); + } + }`; + + // `outer` is called directly and `inner` only through `outer` — both must be defined. + const artifact = compileString(code, { disableInlining: true }); + expect(countOp(artifact.bytecode, 'OP_DEFINE')).toEqual(2); + }); + + it('keeps a recursive function without looping forever', () => { + const code = ` + function f(int n) returns (int) { return f(n); } + + contract Test() { + function spend(int x) { + require(f(x) == 0); + } + }`; + + const artifact = compileString(code, { disableInlining: true }); + expect(countOp(artifact.bytecode, 'OP_DEFINE')).toEqual(1); + }); + + it('keeps mutually recursive functions that are reachable', () => { + const code = ` + function a(int n) returns (int) { return b(n); } + function b(int n) returns (int) { return a(n); } + + contract Test() { + function spend(int x) { + require(a(x) == 0); + } + }`; + + const artifact = compileString(code, { disableInlining: true }); + expect(countOp(artifact.bytecode, 'OP_DEFINE')).toEqual(2); + }); + + it('eliminates a mutually recursive cycle that is never reached', () => { + const code = ` + function used(int n) returns (int) { return n + 1; } + function deadA(int n) returns (int) { return deadB(n); } + function deadB(int n) returns (int) { return deadA(n); } + + contract Test() { + function spend(int x) { + require(used(x) == 1); + } + }`; + + // deadA <-> deadB form a cycle but neither is reachable, so both are dropped. + const artifact = compileString(code, { disableInlining: true }); + expect(countOp(artifact.bytecode, 'OP_DEFINE')).toEqual(1); + }); + + it('eliminates an unused imported function', () => { + // math.cash exports both `addOne` and `double`; only `double` is used here, so `addOne` is dropped. + const code = 'import "./math.cash";\ncontract Test() { function spend(int x) { require(double(x) == 8); } }'; + const mathSource = ` + function addOne(int a) returns (int) { return a + 1; } + function double(int a) returns (int) { return a * 2; } + `; + + const artifact = compileString(code, { files: { './math.cash': mathSource }, disableInlining: true }); + expect(countOp(artifact.bytecode, 'OP_DEFINE')).toEqual(1); + }); + + it('does not define an unused constant', () => { + const contract = ` + contract Unused() { + function spend() { + require(true); + } + }`; + + const withConstant = compileString(`bytes32 constant UNUSED = ${longHex('11')};\n${contract}`); + expect(withConstant.bytecode).toEqual(compileString(contract).bytecode); + }); + + it('does not define a constant referenced only by console.log', () => { + const contract = (message: string): string => ` + contract ConsoleOnly() { + function spend() { + console.log(${message}); + require(true); + } + }`; + + const withConstant = compileString(`string constant MESSAGE = "debug only";\n${contract('MESSAGE')}`); + expect(withConstant.bytecode).toEqual(compileString(contract('"debug only"')).bytecode); + }); +}); + +describe('Inlining and shared definitions', () => { + it('inlines a single-use function', () => { + 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(bytecode).not.toContain('OP_DEFINE'); + expect(bytecode).not.toContain('OP_INVOKE'); + }); + + it('inlines a small multi-use function when that is no larger', () => { + const code = ` + function identity(int x) returns (int) { return x; } + contract C() { function spend(int n) { require(identity(n) + identity(n) == 12); } }`; + + expect(compileString(code).bytecode).not.toContain('OP_DEFINE'); + }); + + it('shares a large multi-use function with OP_DEFINE and 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(bytecode).toContain('OP_DEFINE'); + expect(bytecode).toContain('OP_INVOKE'); + }); + + it('ignores call sites inside eliminated functions when deciding to inline', () => { + const code = ` + function big(int x) returns (int) { return (x * 7 + 3) * (x + 11) - 5; } + function unused(int x) returns (int) { return big(x) + big(x + 1) + big(x + 2); } + contract C() { function spend(int n) { require(big(n) > 0); } }`; + + // big is multi-use on paper, but all extra call sites live in the eliminated function + // unused — only the single reachable call counts, so big is inlined + const { bytecode } = compileString(code); + expect(bytecode).not.toContain('OP_DEFINE'); + expect(bytecode).not.toContain('OP_INVOKE'); + }); + + it('inlines nested single-use functions in callee-first order', () => { + const code = ` + function outer(int x) returns (int) { return inner(x) + 1; } + function inner(int x) returns (int) { return x * 2; } + contract C() { function spend(int n) { require(outer(n) == 7); } }`; + + const { bytecode } = compileString(code); + expect(bytecode).not.toContain('OP_DEFINE'); + expect(bytecode).not.toContain('OP_INVOKE'); + }); + + it('keeps every member of a mutually recursive component defined', () => { + const code = ` + function even(int n) returns (bool) { return odd(n); } + function odd(int n) returns (bool) { return even(n); } + contract C() { function spend(int n) { require(even(n)); } }`; + + const { bytecode } = compileString(code); + expect(countOp(bytecode, 'OP_DEFINE')).toBe(2); + expect(bytecode).toContain('OP_INVOKE'); + }); + + it('inlines a large constant when it is used once', () => { + const contract = (value: string): string => ` + contract OneUse(bytes32 candidate) { + function spend() { + require(candidate == ${value}); + } + }`; + + const artifact = compileString(`bytes32 constant HASH = ${longHex('22')};\n${contract('HASH')}`); + expect(artifact.bytecode).toEqual(compileString(contract(longHex('22'))).bytecode); + expect(artifact.bytecode).not.toContain('OP_DEFINE'); + }); + + it('lists inlined functions as id-less frames after the defined ones', () => { + const code = ` + function wrapper(int x) returns (int) { return shared(x) + shared(x + 1); } + function shared(int x) returns (int) { return (x * 7 + 3) * (x + 11) - 5; } + contract C() { + function spend(int n) { require(wrapper(n) > 0); } + }`; + + // wrapper is single-use and inlined: it keeps a debug frame documenting its compiled body, + // but no id or define site + const artifact = compileString(code); + expect(artifact.debug?.functions?.map(({ name, id }) => ({ name, id }))).toEqual([ + { name: 'shared', id: 0 }, + { name: 'wrapper', id: undefined }, + ]); + expect(countOp(artifact.bytecode, 'OP_0 OP_INVOKE')).toBe(2); + }); + + it('attributes merged debug info to the call site and keeps own lines on the frame', () => { + const code = ` + function checkSmall(int x) { + require(x < 100, "too big"); + } + contract C() { + function spend(int n) { + checkSmall(n); + require(n > 0); + } + }`; + + // Merged entries uniformly take the call-site line (like the source map); the function's + // own line is retained on its frame for future source attribution + const artifact = compileString(code); + expect(artifact.bytecode).not.toContain('OP_DEFINE'); + expect(artifact.debug?.requires).toContainEqual(expect.objectContaining({ + line: 7, + message: 'too big', + })); + expect(artifact.debug?.functions?.[0].requires).toContainEqual(expect.objectContaining({ + line: 3, + message: 'too big', + })); + }); + + it('attributes debug info of an inlined imported function to the call site', () => { + const importedSource = 'function assertPositive(int value) {\n require(value > 0, "must be positive");\n}'; + const source = ` + import "./helpers.cash"; + contract C() { + function spend(int n) { + assertPositive(n); + require(n < 100); + } + }`; + + // Lines from another file cannot appear in the contract's source map, so the merged require + // is attributed to the call-site line; the function's frame retains its source provenance + const artifact = compileString(source, { files: { './helpers.cash': importedSource } }); + expect(artifact.bytecode).not.toContain('OP_DEFINE'); + expect(artifact.debug?.requires).toContainEqual(expect.objectContaining({ + line: 5, + message: 'must be positive', + })); + expect(artifact.debug?.functions).toContainEqual(expect.objectContaining({ + name: 'assertPositive', + sourceFile: 'helpers.cash', + source: importedSource, + requires: [expect.objectContaining({ line: 2, message: 'must be positive' })], + })); + expect(artifact.debug?.functions?.[0].id).toBeUndefined(); + expect(artifact.debug?.inlineRanges).toMatch(/^\d+:\d+:assertPositive$/); + }); + + it('attributes debug info spliced into a defined body to the call site within that body', () => { + const importedSource = 'function assertSmall(int value) {\n require(value < 1000, "value too large");\n}'; + const source = ` + import "./helpers.cash"; + contract C() { + function spend(int n) { require(big(n) + big(n + 1) > 0); } + } + function big(int x) returns (int) { + assertSmall(x); + require(x > 0, "must be positive"); + return (x * 7 + 3) * (x + 11) - 5; + }`; + + // assertSmall is inlined into the shared function big, so its require joins big's + // frame-local requires, attributed to the call-site line inside big + const artifact = compileString(source, { files: { './helpers.cash': importedSource } }); + expect(artifact.debug?.functions?.map(({ name, id }) => ({ name, id }))).toEqual([ + { name: 'big', id: 0 }, + { name: 'assertSmall', id: undefined }, + ]); + expect(artifact.debug?.functions?.[0].requires).toContainEqual(expect.objectContaining({ + line: 7, + message: 'value too large', + })); + expect(artifact.debug?.functions?.[0].inlineRanges).toMatch(/^\d+:\d+:assertSmall$/); + }); + + it('can disable inlining for callers that need the shared-definition form', () => { + 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(bytecode).toContain('OP_DEFINE'); + expect(bytecode).toContain('OP_INVOKE'); + }); +}); + +describe('Global constants', () => { + it('compiles a constant identically to an equivalent zero-argument function', () => { + const contract = (reference: string): string => ` + contract Repeated(bytes32 first, bytes32 second) { + function spend() { + require(first == ${reference} && second == ${reference}); + } + }`; + + const constant = compileString(`bytes32 constant HASH = ${longHex('33')};\n${contract('HASH')}`); + const fn = compileString(`function HASH() returns (bytes32) { return ${longHex('33')}; }\n${contract('HASH()')}`); + + expect(countOp(constant.bytecode, 'OP_DEFINE')).toBe(1); + expect(countOp(constant.bytecode, 'OP_INVOKE')).toBe(2); + expect(constant.bytecode).toEqual(fn.bytecode); + }); + + it('retains debug source provenance for imported constants', () => { + const importedSource = `bytes32 constant IMPORTED_HASH = ${longHex('44')};`; + const source = ` + import "./constants.cash"; + contract Imported(bytes32 first, bytes32 second) { + function spend() { + require(first == IMPORTED_HASH && second == IMPORTED_HASH); + } + }`; + + const artifact = compileString(source, { files: { './constants.cash': importedSource } }); + expect(countOp(artifact.bytecode, 'OP_DEFINE')).toBe(1); + expect(artifact.debug?.functions?.[0]).toMatchObject({ + name: 'IMPORTED_HASH', + kind: 'constant', + source: importedSource, + sourceFile: 'constants.cash', + }); + }); +}); + +describe('Stable function ID assignment', () => { + it('reordering function declarations does not change the bytecode', () => { + const ordered = ` + function a(int n) returns (int) { return n + 1; } + function b(int n) returns (int) { return n * 2; } + + contract Test() { + function spend(int x) { + require(b(x) + a(x) == 10); + } + }`; + + const reordered = ` + function b(int n) returns (int) { return n * 2; } + function a(int n) returns (int) { return n + 1; } + + contract Test() { + function spend(int x) { + require(b(x) + a(x) == 10); + } + }`; + + // functionIds follow call order (b, then a) rather than declaration order, so swapping the two + // declarations produces byte-identical output. + expect(compileString(reordered, { disableInlining: true }).bytecode) + .toEqual(compileString(ordered, { disableInlining: true }).bytecode); + }); + + it('renaming a function does not change the bytecode', () => { + const original = ` + function apple(int n) returns (int) { return n + 1; } + function mango(int n) returns (int) { return n * 2; } + + contract Test() { + function spend(int x) { + require(mango(x) + apple(x) == 10); + } + }`; + + const renamed = ` + function zebra(int n) returns (int) { return n + 1; } + function mango(int n) returns (int) { return n * 2; } + + contract Test() { + function spend(int x) { + require(mango(x) + zebra(x) == 10); + } + }`; + + expect(compileString(renamed, { disableInlining: true }).bytecode) + .toEqual(compileString(original, { disableInlining: true }).bytecode); + }); + + it('assigns IDs by first use across functions and constants', () => { + const source = (first: string, second: string, fn: string, order: number[]): string => { + const definitions = [ + `bytes32 constant ${first} = ${longHex('aa')};`, + `function ${fn}() returns (bytes32) { return ${longHex('cc')}; }`, + `bytes32 constant ${second} = ${longHex('bb')};`, + ]; + + return ` + ${order.map((index) => definitions[index]).join('\n')} + contract Stable(bytes32 a, bytes32 b, bytes32 c) { + function spend() { + require(a == ${first} && b == ${fn}() && c == ${second}); + } + }`; + }; + + const original = compileString(source('FIRST', 'SECOND', 'value', [0, 1, 2]), { disableInlining: true }); + const renamedAndReordered = compileString(source('ALPHA', 'OMEGA', 'renamed', [2, 0, 1]), { disableInlining: true }); + + expect(renamedAndReordered.bytecode).toEqual(original.bytecode); + expect(original.debug?.functions?.map(({ name, id }) => ({ name, id }))).toEqual([ + { name: 'FIRST', id: 0 }, + { name: 'value', id: 1 }, + { name: 'SECOND', id: 2 }, + ]); + }); + + it('keeps bytecode identical under renaming and reordering while inlining is active', () => { + const source = (first: string, second: string, fn: string, order: number[]): string => { + const definitions = [ + `bytes32 constant ${first} = ${longHex('aa')};`, + `function ${fn}() returns (bytes32) { return ${longHex('cc')}; }`, + `bytes32 constant ${second} = ${longHex('bb')};`, + ]; + + return ` + ${order.map((index) => definitions[index]).join('\n')} + contract Stable(bytes32 a, bytes32 b, bytes32 c, bytes32 d, bytes32 e, bytes32 f) { + function spend() { + require(a == ${first} && b == ${first}); + require(c == ${fn}() && d == ${fn}()); + require(e == ${second} && f == ${second}); + } + }`; + }; + + const original = compileString(source('FIRST', 'SECOND', 'value', [0, 1, 2])); + const renamedAndReordered = compileString(source('ALPHA', 'OMEGA', 'renamed', [2, 0, 1])); + + expect(renamedAndReordered.bytecode).toEqual(original.bytecode); + expect(original.debug?.functions?.map(({ name, id }) => ({ name, id }))).toEqual([ + { name: 'FIRST', id: 0 }, + { name: 'value', id: 1 }, + { name: 'SECOND', id: 2 }, + ]); + }); + + it('assigns dense IDs when an inlined definition sits between shared ones', () => { + const source = ` + bytes32 constant FIRST = ${longHex('aa')}; + function identity(bytes32 value) returns (bytes32) { return value; } + bytes32 constant SECOND = ${longHex('bb')}; + contract Contiguous(bytes32 a, bytes32 b, bytes32 c, bytes32 d, bytes32 e) { + function spend() { + require(a == FIRST && b == FIRST); + require(identity(c) == c); + require(d == SECOND && e == SECOND); + } + }`; + + const artifact = compileString(source); + expect(artifact.debug?.functions?.map(({ name, id }) => ({ name, id }))).toEqual([ + { name: 'FIRST', id: 0 }, + { name: 'SECOND', id: 1 }, + { name: 'identity', id: undefined }, + ]); + }); +}); diff --git a/packages/cashc/test/imports.test.ts b/packages/cashc/test/imports.test.ts index 1b8eb5217..d0c1c1674 100644 --- a/packages/cashc/test/imports.test.ts +++ b/packages/cashc/test/imports.test.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import { fileURLToPath } from 'url'; -import { compileFile, compileString } from '../src/index.js'; -import { ImportResolutionError, FunctionRedefinitionError, VersionError } from '../src/Errors.js'; +import { compileFile, compileString } from '../src/internal.js'; +import { ImportResolutionError, RedefinitionError, VersionError } from '../src/Errors.js'; const fixture = (name: string): string => fileURLToPath(new URL(`./import-fixtures/${name}`, import.meta.url)); @@ -11,7 +11,7 @@ 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')); + 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,7 +21,7 @@ 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); }); @@ -29,7 +29,7 @@ describe('Imports from the filesystem (compileFile)', () => { 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')); + 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); @@ -41,19 +41,19 @@ describe('Imports from the filesystem (compileFile)', () => { it('throws when an imported function collides with a local function of the same name', () => { // duplicate_import_main defines `shared` and imports a file that also defines `shared`. - expect(() => compileFile(fixture('duplicate_import_main.cash'))).toThrow(FunctionRedefinitionError); + expect(() => compileFile(fixture('duplicate_import_main.cash'))).toThrow(RedefinitionError); }); 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')); + const artifact = compileFile(fixture('nested_main.cash'), { disableInlining: true }); expect(artifact.debug?.functions?.map((func) => func.sourceFile)).toEqual(['nested/helper.cash']); }); @@ -72,14 +72,14 @@ 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 } }); + 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); }); @@ -91,7 +91,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']); }); @@ -104,7 +104,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); }); @@ -117,7 +117,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); }); @@ -125,7 +125,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); }); @@ -139,7 +139,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); }); @@ -169,7 +169,7 @@ 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')); + const fromDisk = compileFile(fixture('complex/main.cash'), { disableInlining: true }); const files = { 'lib/a.cash': readFixture('complex/lib/a.cash'), @@ -177,7 +177,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/valid-contract-files/global_constant_inlined.cash b/packages/cashc/test/valid-contract-files/global_constant_inlined.cash new file mode 100644 index 000000000..f582bea84 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_constant_inlined.cash @@ -0,0 +1,7 @@ +int constant ONE = 1; + +contract GlobalConstantInlined(int value) { + function spend() { + require(value + ONE + ONE == 3); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_constant_literals.cash b/packages/cashc/test/valid-contract-files/global_constant_literals.cash new file mode 100644 index 000000000..a27a7eb6d --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_constant_literals.cash @@ -0,0 +1,17 @@ +bool constant ENABLED = true; +int constant NEGATIVE = -7; +int constant INTERVAL = 2 hours; +int constant DEADLINE = date("2021-02-17T01:30:00"); +string constant GREETING = 'hello'; +bytes4 constant MAGIC = 0x01020304; + +contract GlobalConstantLiterals() { + function spend(bool enabled, int negative, int interval, int deadline, string greeting, bytes4 magic) { + require(enabled == ENABLED); + require(negative == NEGATIVE); + require(interval == INTERVAL); + require(deadline == DEADLINE); + require(greeting == GREETING); + require(magic == MAGIC); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_constant_shared.cash b/packages/cashc/test/valid-contract-files/global_constant_shared.cash new file mode 100644 index 000000000..c64c198fe --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_constant_shared.cash @@ -0,0 +1,8 @@ +bytes32 constant HASH = 0x3333333333333333333333333333333333333333333333333333333333333333; + +contract GlobalConstantShared(bytes32 first, bytes32 second) { + function spend() { + require(first == HASH); + require(second == HASH); + } +} diff --git a/packages/cashc/test/valid-contract-files/global_function_inlined.cash b/packages/cashc/test/valid-contract-files/global_function_inlined.cash new file mode 100644 index 000000000..73457c459 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_function_inlined.cash @@ -0,0 +1,11 @@ +function checked(int x) returns (int) { + console.log("checking", x); + require(x > 0, "positive"); + return x; +} + +contract GlobalFunctionInlined() { + function spend(int n) { + require(checked(n) == n); + } +} diff --git a/packages/cashscript/src/Errors.ts b/packages/cashscript/src/Errors.ts index 85740c714..cd27b4a2e 100644 --- a/packages/cashscript/src/Errors.ts +++ b/packages/cashscript/src/Errors.ts @@ -1,5 +1,5 @@ import { Artifact, RequireStatement, sourceMapToLocationData, Type } from '@cashscript/utils'; -import { ResolvedFrame, rootFrame } from './debug-frame.js'; +import { ResolvedFrame, resolveInlineAttribution, rootFrame } from './debug-frame.js'; export class TypeError extends Error { constructor(actual: string, expected: Type) { @@ -161,10 +161,15 @@ export class FailedRequireError extends FailedTransactionError { frame?: ResolvedFrame, ) { const resolvedFrame = frame ?? rootFrame(artifact); - const { statement, lineNumber } = getLocationDataForFrame(resolvedFrame, failingInstructionPointer); - const context = formatFrameContext(resolvedFrame, artifact.contractName, lineNumber); - const baseMessage = `${resolvedFrame.sourceName}:${lineNumber} Require statement failed at input ${inputIndex} ${context}`; + const inline = resolveInlineAttribution(artifact, resolvedFrame, requireStatement, 'requires'); + const attributedFrame = inline?.frame ?? resolvedFrame; + const attributedIp = inline?.entry.ip ?? failingInstructionPointer; + + const { statement, lineNumber } = getLocationDataForFrame(attributedFrame, attributedIp); + const context = formatFrameContext(attributedFrame, artifact.contractName, lineNumber); + + const baseMessage = `${attributedFrame.sourceName}:${lineNumber} Require statement failed at input ${inputIndex} ${context}`; const baseMessageWithRequireMessage = `${baseMessage} with the following message: ${requireStatement.message}`; const headline = `${requireStatement.message ? baseMessageWithRequireMessage : baseMessage}.`; diff --git a/packages/cashscript/src/debug-frame.ts b/packages/cashscript/src/debug-frame.ts index 5ec61c830..fd72b9c6a 100644 --- a/packages/cashscript/src/debug-frame.ts +++ b/packages/cashscript/src/debug-frame.ts @@ -1,5 +1,5 @@ import { AuthenticationProgramStateCommon, binToHex, encodeAuthenticationInstructions } from '@bitauth/libauth'; -import { Artifact, LogEntry, RequireStatement } from '@cashscript/utils'; +import { Artifact, DebugEntry, DebugFrame, LogEntry, RequireStatement, parseInlineRanges } from '@cashscript/utils'; export interface ResolvedFrame { sourceMap: string; @@ -8,6 +8,7 @@ export interface ResolvedFrame { ipOffset: number; requires: readonly RequireStatement[]; logs: readonly LogEntry[]; + inlineRanges?: string; functionName?: string; } @@ -18,6 +19,7 @@ export const rootFrame = (artifact: Artifact): ResolvedFrame => ({ ipOffset: artifact.constructorInputs.length, requires: artifact.debug?.requires ?? [], logs: artifact.debug?.logs ?? [], + inlineRanges: artifact.debug?.inlineRanges, }); export const getActiveBytecode = (step: AuthenticationProgramStateCommon): string => @@ -27,19 +29,81 @@ export const resolveFrame = ( artifact: Artifact, step: AuthenticationProgramStateCommon, ): ResolvedFrame => { - const frames = artifact.debug?.functions ?? []; + // Only defined frames (id present) execute as standalone VM functions; an inlined callable's + // frame documents a body that only ever runs spliced into another program + const frames = (artifact.debug?.functions ?? []).filter((candidate) => candidate.id !== undefined); const activeBytecode = frames.length > 0 ? getActiveBytecode(step) : undefined; const frame = frames.find((candidate) => candidate.bytecode === activeBytecode); if (!frame) return rootFrame(artifact); + return resolveDebugFrame(artifact, frame); +}; + +const resolveDebugFrame = (artifact: Artifact, frame: DebugFrame): ResolvedFrame => ({ + sourceMap: frame.sourceMap, + source: frame.source ?? artifact.source, + sourceName: frame.sourceFile ?? `${artifact.contractName}.cash`, + ipOffset: 0, // function bodies have no constructor-arg prefix; their ips start at 0 + requires: frame.requires, + logs: frame.logs, + inlineRanges: frame.inlineRanges, + functionName: frame.sourceFile ? frame.name : undefined, +}); + +export interface InlineAttribution { + frame: ResolvedFrame; // the inlined callable, resolved like any other frame + entry: DebugEntry; // the callable's own entry (frame-local ip and line) +} + +export const resolveInlineAttribution = ( + artifact: Artifact, + containerFrame: ResolvedFrame, + entry: DebugEntry, + kind: 'requires' | 'logs', +): InlineAttribution | undefined => { + const range = parseInlineRanges(containerFrame.inlineRanges ?? '') + .find((candidate) => entry.ip >= candidate.startIp && entry.ip <= candidate.endIp); + if (!range) return undefined; + + const inlinedFrame = artifact.debug?.functions?.find((candidate) => candidate.name === range.frameName); + if (!inlinedFrame) return undefined; + + const frameEntry = findMatchingFrameEntry(containerFrame[kind], inlinedFrame[kind], range, entry); + if (!frameEntry) return undefined; + + const frame = resolveDebugFrame(artifact, inlinedFrame); + + // The callable may itself contain deeper inlined callables: attribute to the innermost one + return resolveInlineAttribution(artifact, frame, frameEntry, kind) ?? { frame, entry: frameEntry }; +}; + +// A log merged from an inlined callable is attributed to the callable's own source +export const attributeLogEntry = ( + artifact: Artifact, + frame: ResolvedFrame, + logEntry: LogEntry, +): { logEntry: LogEntry, sourceName: string } => { + const inline = resolveInlineAttribution(artifact, frame, logEntry, 'logs'); + if (!inline) return { logEntry, sourceName: frame.sourceName }; + return { - sourceMap: frame.sourceMap, - source: frame.source ?? artifact.source, - sourceName: frame.sourceFile ?? `${artifact.contractName}.cash`, - ipOffset: 0, // function bodies have no constructor-arg prefix; their ips start at 0 - requires: frame.requires, - logs: frame.logs, - ...(frame.sourceFile !== undefined ? { functionName: frame.name } : {}), + logEntry: { ...logEntry, line: inline.entry.line }, + sourceName: inline.frame.sourceName, }; }; + +const findMatchingFrameEntry = ( + containerEntries: readonly DebugEntry[], + frameEntries: readonly DebugEntry[], + range: { startIp: number, endIp: number }, + entry: DebugEntry, +): DebugEntry | undefined => { + const entriesInRange = containerEntries.filter((candidate) => ( + candidate.ip >= range.startIp && candidate.ip <= range.endIp + )); + + const position = entriesInRange.indexOf(entry); + if (position === -1) return undefined; + return frameEntries[position]; +}; diff --git a/packages/cashscript/src/debugging.ts b/packages/cashscript/src/debugging.ts index cbbeb4bc6..ac5f85649 100644 --- a/packages/cashscript/src/debugging.ts +++ b/packages/cashscript/src/debugging.ts @@ -2,7 +2,7 @@ import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationPro import { Artifact, LogData, LogEntry, Op, PrimitiveType, StackItem, asmToBytecode, bytecodeToAsm, decodeBool, decodeInt, decodeString } from '@cashscript/utils'; import { findLastIndex, toRegExp } from './utils.js'; import { FailedRequireError, FailedTransactionError, FailedTransactionEvaluationError } from './Errors.js'; -import { getActiveBytecode, resolveFrame } from './debug-frame.js'; +import { attributeLogEntry, getActiveBytecode, resolveFrame } from './debug-frame.js'; import { getBitauthUri } from './libauth-template/LibauthTemplate.js'; import { VmTarget } from './interfaces.js'; @@ -105,7 +105,8 @@ const debugSingleScenario = ( return logEntries.map((logEntry) => { const decodedLogData = logEntry.data .map((dataEntry) => decodeLogDataEntry(dataEntry, reversedPriorDebugSteps, vm, frameBytecode)); - return { logEntry, decodedLogData, sourceName: frame.sourceName }; + + return { ...attributeLogEntry(artifact, frame, logEntry), decodedLogData }; }); }); diff --git a/packages/cashscript/test/debugging.test.ts b/packages/cashscript/test/debugging.test.ts index 7d882ab47..dd9f5b0a0 100644 --- a/packages/cashscript/test/debugging.test.ts +++ b/packages/cashscript/test/debugging.test.ts @@ -15,9 +15,12 @@ import { artifactTestRequireInsideLoop, artifactTestLogInsideLoop, artifactTestFunctionDebugging, + artifactTestFunctionDebuggingDefined, artifactTestFunctionIntermediateResults, artifactTestImportedFunctionDebugging, + artifactTestImportedFunctionDebuggingDefined, artifactTestMultiReturn, + artifactTestMultilineFunctionRequire, } from './fixture/debugging/debugging_contracts.js'; import { sha256 } from '@cashscript/utils'; @@ -828,7 +831,13 @@ describe('Debugging tests - user-defined function frames', () => { const importedContract = new Contract(artifactTestImportedFunctionDebugging, [], { provider }); const importedUtxo = provider.addUtxo(importedContract.address, randomUtxo()); - it('attributes a console.log inside a function to the function source line', () => { + 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 an inlined function to the function source line', () => { const transaction = new TransactionBuilder({ provider }) .addInput(contractUtxo, contract.unlock.spend(5n)) .addOutput({ to: contract.address, amount: 10000n }); @@ -836,11 +845,13 @@ describe('Debugging tests - user-defined function frames', () => { expect(transaction).toLog(new RegExp('^\\[Input #0] Test.cash:3 checking 5$')); }); - it('attributes a require failing inside a function to the function source line', () => { + it('attributes a require failing inside an inlined function to the function source line', () => { const transaction = new TransactionBuilder({ provider }) .addInput(contractUtxo, contract.unlock.spend(0n)) .addOutput({ to: contract.address, amount: 10000n }); + // The artifact's inline ranges tie the merged require back to the function's own frame, so + // inlining is transparent: the failure reads like the defined variant below 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")'); }); @@ -854,12 +865,54 @@ 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 multiline require failing inside an inlined function with its full statement', () => { + const multilineContract = new Contract(artifactTestMultilineFunctionRequire, [], { provider }); + const multilineUtxo = provider.addUtxo(multilineContract.address, randomUtxo()); + + const transaction = new TransactionBuilder({ provider }) + .addInput(multilineUtxo, multilineContract.unlock.spend(0n)) + .addOutput({ to: multilineContract.address, amount: 10000n }); + + expect(transaction).toFailRequireWith('Test.cash:3 Require statement failed at input 0 in contract Test.cash at line 3 with the following message: value must be positive.'); + expect(transaction).toFailRequireWith(`Failing statement: require( + value > 0, + "value must be positive" + )`); + }); + + it('attributes a require failing inside an inlined imported function to the imported function', () => { const transaction = new TransactionBuilder({ provider }) .addInput(importedUtxo, importedContract.unlock.spend(0n)) .addOutput({ to: importedContract.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.'); + // Inlining is transparent for debugging: the failure reads exactly like the defined + // (OP_DEFINE'd) form of the same function — see the defined variants below + expect(transaction).toFailRequireWith('function_helpers.cash:3 Require statement failed at input 0 in contract Test, function assertPositive (function_helpers.cash, line 3) 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 an inlined imported function to the imported file', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(importedUtxo, importedContract.unlock.spend(5n)) + .addOutput({ to: importedContract.address, amount: 10000n }); + + expect(transaction).toLog(new RegExp('^\\[Input #0] function_helpers.cash:2 checking 5$')); + }); + + it('attributes a console.log inside an imported function frame to the imported file', () => { + const transaction = new TransactionBuilder({ provider }) + .addInput(importedDefinedUtxo, importedDefinedContract.unlock.spend(5n)) + .addOutput({ to: importedDefinedContract.address, amount: 10000n }); + + expect(transaction).toLog(new RegExp('^\\[Input #0] function_helpers.cash:2 checking 5$')); + }); + + it('attributes a require failing inside an imported function frame 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:3 Require statement failed at input 0 in contract Test, function assertPositive (function_helpers.cash, line 3) with the following message: value must be positive.'); expect(transaction).toFailRequireWith('Failing statement: require(value > 0, "value must be positive")'); }); @@ -896,11 +949,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) {'); @@ -910,14 +963,27 @@ 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('>>> imported from function_helpers.cash'); expect(lockScript).toContain('/* function assertPositive(int value) {'); expect(lockScript).toContain('> OP_0 OP_DEFINE'); }); + + it('renders an inlined function body without a definition or invocation', () => { + 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; + + 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 58a1f7df7..e556bd827 100644 --- a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts +++ b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts @@ -1,4 +1,4 @@ -import { compileFile, compileString } from 'cashc'; +import { compileFile, compileString } from 'cashc/dist/internal.js'; const CONTRACT_TEST_FUNCTION_DEBUGGING = ` function checkValue(int value) { @@ -29,6 +29,24 @@ contract Test(pubkey owner) { } `; +// The require statement inside the (inlined) function spans multiple lines, so its statement can +// only be extracted through the function frame's source map rather than a single source line. +const CONTRACT_TEST_MULTILINE_FUNCTION_REQUIRE = ` +function checkRange(int value) { + require( + value > 0, + "value must be positive" + ); +} + +contract Test() { + function spend(int x) { + checkRange(x); + require(x < 100); + } +} +`; + // Multi-value return destructuring: the requires only pass when the first declared return value // binds to the first target (quotient) and the last to the last (remainder), pinning the runtime // value ordering of the calling convention. @@ -486,6 +504,18 @@ export const artifactTestLogInsideLoop = compileString(CONTRACT_TEST_LOG_INSIDE_ export const artifactTestFunctionDebugging = compileString(CONTRACT_TEST_FUNCTION_DEBUGGING); export const artifactTestFunctionIntermediateResults = compileString(CONTRACT_TEST_FUNCTION_INTERMEDIATE_RESULTS); export const artifactTestMultiReturn = compileString(CONTRACT_TEST_MULTI_RETURN); +export const artifactTestMultilineFunctionRequire = compileString(CONTRACT_TEST_MULTILINE_FUNCTION_REQUIRE); // 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 are debugged +// through their own frames (attributing to their own source instead of the call site). +export const artifactTestFunctionDebuggingDefined = compileString( + CONTRACT_TEST_FUNCTION_DEBUGGING, + { disableInlining: true }, +); +export const artifactTestImportedFunctionDebuggingDefined = compileFile( + new URL('./function_importer.cash', import.meta.url), + { disableInlining: true }, +); diff --git a/packages/cashscript/test/fixture/debugging/function_helpers.cash b/packages/cashscript/test/fixture/debugging/function_helpers.cash index f031f25c0..4805c1819 100644 --- a/packages/cashscript/test/fixture/debugging/function_helpers.cash +++ b/packages/cashscript/test/fixture/debugging/function_helpers.cash @@ -1,3 +1,4 @@ function assertPositive(int value) { + console.log("checking", value); require(value > 0, "value must be positive"); } diff --git a/packages/utils/src/artifact.ts b/packages/utils/src/artifact.ts index 040c3b474..ba2c34d41 100644 --- a/packages/utils/src/artifact.ts +++ b/packages/utils/src/artifact.ts @@ -19,12 +19,14 @@ export interface DebugInformation { logs: readonly LogEntry[]; // log entries generated from `console.log` statements requires: readonly RequireStatement[]; // messages for failing `require` statements sourceTags?: string; // semantic tags for opcodes (e.g. loop update/condition ranges) - functions?: readonly DebugFrame[]; // Debug metadata for each user-defined function + functions?: readonly DebugFrame[]; // Debug metadata for each global definition (defined frames first, then inlined ones) + inlineRanges?: string; // runs where inlined callables' bodies were emitted (see `generateInlineRanges`) } export interface DebugFrame { - id: number; // the function's id, as used with OP_DEFINE and OP_INVOKE in the bytecode - name: string; // the function's name + id?: number; // the function's id, as used with OP_DEFINE and OP_INVOKE in the bytecode; absent for inlined callables + name: string; // the function/constant's name + kind?: 'constant'; // present when the VM function is the lowered form of a global constant; absent for regular functions inputs: readonly AbiInput[]; // the function's parameters (name and type), mirroring the ABI; for reference bytecode: string; // hex of the function body bytecode (exactly what OP_DEFINE stores and the VM runs) sourceMap: string; // frame-local source map (ips starting from 0) @@ -33,6 +35,13 @@ export interface DebugFrame { sourceFile?: string; // originating file name for imported functions; absent means the contract's file logs: readonly LogEntry[]; // frame-local log entries requires: readonly RequireStatement[]; // frame-local require statements + inlineRanges?: string; // runs where inlined callables' bodies were emitted within this body (frame-local ips) +} + +export interface InlineRange { + startIp: number; // first ip of the emitted body (inclusive) + endIp: number; // last ip of the emitted body (inclusive) + frame: DebugFrame; // the inlined callable's debug frame } export interface LogEntry { @@ -62,6 +71,9 @@ export interface RequireStatement { message?: string; // custom message for failing `require` statement } +// Any debug entry that lives at an instruction pointer and attributes to a source line +export type DebugEntry = RequireStatement | LogEntry; + export interface Artifact { contractName: string; constructorInputs: readonly AbiInput[]; diff --git a/packages/utils/src/bitauth-script.ts b/packages/utils/src/bitauth-script.ts index b2aee008e..1a137b7a8 100644 --- a/packages/utils/src/bitauth-script.ts +++ b/packages/utils/src/bitauth-script.ts @@ -63,7 +63,9 @@ function segmentScript(params: WalkParams): Segment[] { const { script, sourceLines } = params; const locationData = sourceMapToLocationData(params.sourceMap); const tags = parseSourceTags(params.sourceTags ?? ''); - const frames = params.functions ?? []; + // Only defined (OP_DEFINE'd) frames have a define site in the script; inlined callables are + // listed after them in the functions list purely as documentation and render nothing here + const frames = (params.functions ?? []).filter((frame) => frame.id !== undefined); const segments: Segment[] = []; let index = 0; @@ -203,7 +205,7 @@ function renderFunctionDefinition( const sourceLines = isImported ? frame.source!.split('\n') : context.sourceLines; const headerRows = isImported - ? [{ asm: '', comment: `>>> function ${frame.name} (imported from ${frame.sourceFile})` }] + ? [{ asm: '', comment: `>>> imported from ${frame.sourceFile}` }] : []; return { @@ -212,9 +214,10 @@ function renderFunctionDefinition( }; } +// Only called for defined frames (id present), which segmentScript filters on function buildFunctionSection(frame: DebugFrame, location: LocationI, sourceLines: string[]): Row[] { const bodyScript = bytecodeToScript(hexToBin(frame.bytecode)); - const defineAsm = scriptToBitAuthAsm([encodeInt(BigInt(frame.id)), Op.OP_DEFINE]); + const defineAsm = scriptToBitAuthAsm([encodeInt(BigInt(frame.id!)), Op.OP_DEFINE]); const { start, end } = location; if (end.line === start.line) { diff --git a/packages/utils/src/script.ts b/packages/utils/src/script.ts index c5892e5ce..4d114a5ee 100644 --- a/packages/utils/src/script.ts +++ b/packages/utils/src/script.ts @@ -12,7 +12,7 @@ import OptimisationsEquivFile from './cashproof-optimisations.js'; import { optimisationReplacements } from './optimisations.js'; import { range } from './data.js'; import { FullLocationData, PositionHint, SingleLocationData, SourceTagEntry, SourceTagKind } from './types.js'; -import { LogEntry, RequireStatement } from './artifact.js'; +import { InlineRange, LogEntry, RequireStatement } from './artifact.js'; export const Op = OpcodesBch; export type Op = number; @@ -154,12 +154,13 @@ export function generateContractBytecodeScript(baseScript: Script, encodedConstr return [...encodedConstructorArgs.slice().reverse(), ...baseScript]; } -interface OptimiseBytecodeResult { +export interface OptimiseBytecodeResult { script: Script; locationData: FullLocationData; logs: LogEntry[]; requires: RequireStatement[]; sourceTags: SourceTagEntry[]; + inlineRanges: InlineRange[]; } export function optimiseBytecode( @@ -168,6 +169,7 @@ export function optimiseBytecode( logs: LogEntry[], requires: RequireStatement[], sourceTags: SourceTagEntry[], + inlineRanges: InlineRange[], constructorParamLength: number, runs: number = 1000, ): OptimiseBytecodeResult { @@ -179,7 +181,10 @@ export function optimiseBytecode( logs: newLogs, requires: newRequires, sourceTags: newSourceTags, - } = replaceOps(script, locationData, logs, requires, sourceTags, constructorParamLength, optimisationReplacements); + inlineRanges: newInlineRanges, + } = replaceOps( + script, locationData, logs, requires, sourceTags, inlineRanges, constructorParamLength, optimisationReplacements, + ); // Break on fixed point if (scriptToAsm(oldScript) === scriptToAsm(newScript)) break; @@ -189,9 +194,12 @@ export function optimiseBytecode( logs = newLogs; requires = newRequires; sourceTags = newSourceTags; + inlineRanges = newInlineRanges; } - return { script, locationData, logs, requires, sourceTags: reconcileScopeCleanupTags(script, sourceTags) }; + return { + script, locationData, logs, requires, sourceTags: reconcileScopeCleanupTags(script, sourceTags), inlineRanges, + }; } const SCOPE_CLEANUP_OPCODES = [Op.OP_DROP, Op.OP_NIP, Op.OP_2DROP]; @@ -271,6 +279,7 @@ interface ReplaceOpsResult { logs: LogEntry[]; requires: RequireStatement[]; sourceTags: SourceTagEntry[]; + inlineRanges: InlineRange[]; } function replaceOps( @@ -279,6 +288,7 @@ function replaceOps( logs: LogEntry[], requires: RequireStatement[], sourceTags: SourceTagEntry[], + inlineRanges: InlineRange[], constructorParamLength: number, optimisations: string[][], ): ReplaceOpsResult { @@ -287,6 +297,7 @@ function replaceOps( let newLogs = [...logs]; let newRequires = [...requires]; let newSourceTags = [...sourceTags]; + let newInlineRanges = [...inlineRanges]; optimisations.forEach(([pattern, replacement]) => { let processedAsm = ''; @@ -342,25 +353,21 @@ function replaceOps( // the constructor parameters still have to get added to the front of the script when a new Contract is created. const scriptIp = scriptIndex + constructorParamLength; - newRequires = newRequires.map((require) => { - // We calculate the new ip of the require by subtracting the length diff between the matched pattern and replacement - const newCalculatedRequireIp = require.ip - lengthDiff; + // Positions after the replaced pattern shift back by the length difference; positions inside + // the replaced pattern clamp to the pattern's start. (Positions inside a pattern are impossible + // for the current set of optimisations, but the clamp future-proofs the code.) + const adjustPosition = (position: number, patternStart: number): number => ( + position >= patternStart ? Math.max(patternStart, position - lengthDiff) : position + ); - return { - ...require, - // If the require is within the pattern, we want to make sure that the new ip is at least the scriptIp - // Note that this is impossible for the current set of optimisations, but future proofs the code - ip: require.ip >= scriptIp ? Math.max(scriptIp, newCalculatedRequireIp) : require.ip, - }; - }); + newRequires = newRequires.map((require) => ({ + ...require, + ip: adjustPosition(require.ip, scriptIp), + })); newLogs = newLogs.map((log) => { - // We calculate the new ip of the log by subtracting the length diff between the matched pattern and replacement - const newCalculatedLogIp = log.ip - lengthDiff; - return { - // If the log is within the pattern, we want to make sure that the new ip is at least the scriptIp - ip: log.ip >= scriptIp ? Math.max(scriptIp, newCalculatedLogIp) : log.ip, + ip: adjustPosition(log.ip, scriptIp), line: log.line, data: log.data.map((data) => { if (typeof data === 'string') return data; @@ -387,11 +394,18 @@ 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 they adjust against 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: adjustPosition(tag.startIndex, scriptIndex), + endIndex: adjustPosition(tag.endIndex, scriptIndex), + })); + + // Inline ranges use ip coordinates (like requires), so both bounds adjust against scriptIp + newInlineRanges = newInlineRanges.map((inlineRange) => ({ + ...inlineRange, + startIp: adjustPosition(inlineRange.startIp, scriptIp), + endIp: adjustPosition(inlineRange.endIp, scriptIp), })); // We add the replacement to the processed asm @@ -419,6 +433,7 @@ function replaceOps( logs: newLogs, requires: newRequires, sourceTags: newSourceTags, + inlineRanges: newInlineRanges, }; } diff --git a/packages/utils/src/source-map.ts b/packages/utils/src/source-map.ts index 3f7e883c9..246feab0a 100644 --- a/packages/utils/src/source-map.ts +++ b/packages/utils/src/source-map.ts @@ -1,4 +1,5 @@ import { FullLocationData, PositionHint, SingleLocationData, SourceTagEntry, SourceTagKind } from './types.js'; +import { InlineRange } from './artifact.js'; /* * The source mappings for the bytecode use the following notation (similar to Solidity): @@ -141,3 +142,22 @@ export function generateSourceTags(entries: SourceTagEntry[]): string { if (entries.length === 0) return ''; return entries.map((entry) => `${entry.startIndex}:${entry.endIndex}:${entry.kind}`).join(';'); } + +/* + * Format: "startIp:endIp:name;..." — the runs where inlined callables' bodies were emitted within + * one program, referencing each callable's debug frame by its (globally unique) name + */ +export function generateInlineRanges(entries: InlineRange[]): string { + return entries + .filter((entry) => entry.endIp >= entry.startIp) // a body optimised down to nothing leaves no run + .map((entry) => `${entry.startIp}:${entry.endIp}:${entry.frame.name}`) + .join(';'); +} + +export function parseInlineRanges(inlineRanges: string): { startIp: number, endIp: number, frameName: string }[] { + if (!inlineRanges) return []; + return inlineRanges.split(';').map((segment) => { + const [startStr, endStr, frameName] = segment.split(':'); + return { startIp: Number(startStr), endIp: Number(endStr), frameName }; + }); +} diff --git a/packages/utils/test/bitauth-script.test.ts b/packages/utils/test/bitauth-script.test.ts index 06e1a7820..a4be46d02 100644 --- a/packages/utils/test/bitauth-script.test.ts +++ b/packages/utils/test/bitauth-script.test.ts @@ -3,7 +3,7 @@ import { Artifact } from '../src/artifact.js'; import { asmToScript, scriptToBytecode } from '../src/script.js'; import { formatBitAuthScript } from '../src/bitauth-script.js'; import { FunctionFixture, fixtures, functionFixtures } from './fixtures/bitauth-script.fixture.js'; -import { compileFile, compileString } from 'cashc'; +import { compileFile, compileString } from 'cashc/dist/internal.js'; describe('Libauth Script formatting', () => { fixtures.forEach((fixture) => { @@ -54,8 +54,8 @@ describe('Libauth Script formatting', () => { describe('User-defined function formatting', () => { 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), fixture.compilerOptions) + : compileString(fixture.sourceCode!, fixture.compilerOptions)); 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 97bbb9b9f..eca0f858e 100644 --- a/packages/utils/test/fixtures/bitauth-script.fixture.ts +++ b/packages/utils/test/fixtures/bitauth-script.fixture.ts @@ -1,5 +1,7 @@ /* eslint-disable max-len */ +import { InternalCompilerOptions } from 'cashc/dist/internal.js'; + export interface Fixture { name: string; sourceCode: string; @@ -407,12 +409,14 @@ export interface FunctionFixture { name: string; sourceCode?: string; // compiled with compileString when set file?: string; // compiled with compileFile, relative to this fixtures directory (used for imports) + compilerOptions?: InternalCompilerOptions; expectedBitAuthScript: string; } export const functionFixtures: FunctionFixture[] = [ { name: 'LocalFunctions (same-file functions with loop + recursion)', + compilerOptions: { disableInlining: true }, sourceCode: ` function sumTo(int n) returns (int) { int sum = 0; @@ -437,7 +441,18 @@ contract LocalFunctions() { } } `.replace(/^\n+/, '').replace(/\n+$/, ''), + // fib is recursive, so it receives its id before the callee-first compilation pass and is + // defined first; sumTo follows in id order. expectedBitAuthScript: ` +< /* function fib(int n) returns (int) { */ + OP_DUP OP_DUP /* int result = n; */ + OP_2 OP_GREATERTHANOREQUAL OP_IF /* if (n >= 2) { */ + OP_OVER OP_1SUB OP_0 OP_INVOKE OP_2 OP_PICK OP_2 OP_SUB OP_0 OP_INVOKE OP_ADD OP_NIP /* result = fib(n - 1) + fib(n - 2); */ + OP_ENDIF /* } */ + /* return result; */ + OP_NIP /* >>> scope cleanup */ +> OP_0 OP_DEFINE /* } */ + /* */ < /* function sumTo(int n) returns (int) { */ OP_0 /* int sum = 0; */ OP_0 OP_BEGIN OP_DUP OP_3 OP_PICK OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF /* for (int i = 0; i < n; i = i + 1) { */ @@ -448,21 +463,12 @@ contract LocalFunctions() { /* } */ /* return sum; */ OP_NIP /* >>> scope cleanup */ -> OP_0 OP_DEFINE /* } */ - /* */ -< /* function fib(int n) returns (int) { */ - OP_DUP OP_DUP /* int result = n; */ - OP_2 OP_GREATERTHANOREQUAL OP_IF /* if (n >= 2) { */ - OP_OVER OP_1SUB OP_1 OP_INVOKE OP_2 OP_PICK OP_2 OP_SUB OP_1 OP_INVOKE OP_ADD OP_NIP /* result = fib(n - 1) + fib(n - 2); */ - OP_ENDIF /* } */ - /* return result; */ - OP_NIP /* >>> scope cleanup */ > OP_1 OP_DEFINE /* } */ /* */ /* contract LocalFunctions() { */ /* function spend() { */ -OP_5 OP_0 OP_INVOKE OP_10 OP_NUMEQUALVERIFY /* require(sumTo(5) == 10, 'sum mismatch'); */ -OP_7 OP_1 OP_INVOKE OP_13 OP_NUMEQUAL /* require(fib(7) == 13, 'fib mismatch'); */ +OP_5 OP_1 OP_INVOKE OP_10 OP_NUMEQUALVERIFY /* require(sumTo(5) == 10, 'sum mismatch'); */ +OP_7 OP_0 OP_INVOKE OP_13 OP_NUMEQUAL /* require(fib(7) == 13, 'fib mismatch'); */ /* } */ /* } */ `.replace(/^\n+/, '').replace(/\n+$/, ''), @@ -470,13 +476,14 @@ OP_7 OP_1 OP_INVOKE OP_13 OP_NUMEQUAL { name: 'ImportedFunctions (two imported functions from one file)', file: 'function-imports/importer.cash', + compilerOptions: { disableInlining: true }, expectedBitAuthScript: ` - /* >>> function double (imported from helpers.cash) */ + /* >>> imported from helpers.cash */ < /* function double(int x) returns (int) { */ OP_2 OP_MUL /* return x * 2; */ > OP_0 OP_DEFINE /* } */ /* */ - /* >>> function addChecked (imported from helpers.cash) */ + /* >>> 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_GREATERTHANOREQUAL OP_VERIFY /* require(sum >= a, "overflow"); */ @@ -498,6 +505,7 @@ OP_SWAP OP_1 OP_INVOKE OP_15 OP_NUMEQUAL /* require(addChecked(do // The single-byte 0x81 body (lone OP_BIN2NUM) gets minimally encoded as the opcode OP_1NEGATE at the // define site, so it must be matched to its frame by push-data equality rather than element shape. name: 'MinimalBody (single-byte function body, minimally encoded define site)', + compilerOptions: { disableInlining: true }, sourceCode: ` function toInt(bytes b) returns (int) { return int(b); @@ -530,10 +538,69 @@ OP_0 OP_INVOKE OP_0 OP_GREATERTHAN OP_VERIFY /* require(toInt(b) > 0, 'n OP_3 OP_1 OP_INVOKE OP_6 OP_NUMEQUAL /* require(double(3) == 6, 'bad double'); */ /* } */ /* } */ +`.replace(/^\n+/, '').replace(/\n+$/, ''), + }, + { + // A large constant used twice is lowered to a shared definition rendered as a define push group + // on its declaration line; the small constant ONE stays inlined at its use site (as OP_1ADD). + name: 'GlobalConstants (shared and inlined constants)', + sourceCode: ` +bytes32 constant HASH = 0x3333333333333333333333333333333333333333333333333333333333333333; +int constant ONE = 1; + +contract GlobalConstants(bytes32 first, bytes32 second) { + function spend(int n) { + require(first == HASH, 'first mismatch'); + require(second == HASH, 'second mismatch'); + require(n + ONE == 2, 'n mismatch'); + } +} +`.replace(/^\n+/, '').replace(/\n+$/, ''), + expectedBitAuthScript: ` +< <0x3333333333333333333333333333333333333333333333333333333333333333> > OP_0 OP_DEFINE /* bytes32 constant HASH = 0x3333333333333333333333333333333333333333333333333333333333333333; */ + /* */ + /* int constant ONE = 1; */ + /* */ + /* contract GlobalConstants(bytes32 first, bytes32 second) { */ + /* function spend(int n) { */ +OP_0 OP_INVOKE OP_EQUALVERIFY /* require(first == HASH, 'first mismatch'); */ +OP_0 OP_INVOKE OP_EQUALVERIFY /* require(second == HASH, 'second mismatch'); */ +OP_1ADD OP_2 OP_NUMEQUAL /* require(n + ONE == 2, 'n mismatch'); */ + /* } */ + /* } */ +`.replace(/^\n+/, '').replace(/\n+$/, ''), + }, + { + // A single-use function is inlined at the call site instead of defined: no define push groups, + // and the emitted body opcodes are attributed to the call site (the function's own source + // renders as bare comment lines). + name: 'InlinedFunction (single-use function inlined at the call site)', + sourceCode: ` +function double(int x) returns (int) { + return x * 2; +} + +contract InlinedFunction() { + function spend(int n) { + require(double(n) == 10, 'mismatch'); + } +} +`.replace(/^\n+/, '').replace(/\n+$/, ''), + expectedBitAuthScript: ` + /* function double(int x) returns (int) { */ + /* return x * 2; */ + /* } */ + /* */ + /* contract InlinedFunction() { */ + /* function spend(int n) { */ +OP_2 OP_MUL OP_10 OP_NUMEQUAL /* require(double(n) == 10, 'mismatch'); */ + /* } */ + /* } */ `.replace(/^\n+/, '').replace(/\n+$/, ''), }, { name: 'AfterContract (function defined below the contract in the same file)', + compilerOptions: { disableInlining: true }, sourceCode: ` contract AfterContract() { function spend(int x) { @@ -556,6 +623,37 @@ OP_0 OP_INVOKE OP_10 OP_NUMEQUAL /* require(double(x) == 10, 'mismatch') /* } */ /* } */ /* */ +`.replace(/^\n+/, '').replace(/\n+$/, ''), + }, + { + // Global constants are zero-argument VM functions: each definition renders as a define push + // group on the constant's declaration line, and each use compiles to an OP_INVOKE. + name: 'GlobalConstants (constants as zero-argument function definitions)', + compilerOptions: { disableInlining: true }, + sourceCode: ` +bytes32 constant HASH = 0x3333333333333333333333333333333333333333333333333333333333333333; +int constant ONE = 1; + +contract GlobalConstants(bytes32 first, bytes32 second) { + function spend(int n) { + require(first == HASH, 'first mismatch'); + require(second == HASH, 'second mismatch'); + require(n + ONE == 2, 'n mismatch'); + } +} +`.replace(/^\n+/, '').replace(/\n+$/, ''), + expectedBitAuthScript: ` +< <0x3333333333333333333333333333333333333333333333333333333333333333> > OP_0 OP_DEFINE /* bytes32 constant HASH = 0x3333333333333333333333333333333333333333333333333333333333333333; */ + /* */ +< OP_1 > OP_1 OP_DEFINE /* int constant ONE = 1; */ + /* */ + /* contract GlobalConstants(bytes32 first, bytes32 second) { */ + /* function spend(int n) { */ +OP_0 OP_INVOKE OP_EQUALVERIFY /* require(first == HASH, 'first mismatch'); */ +OP_0 OP_INVOKE OP_EQUALVERIFY /* require(second == HASH, 'second mismatch'); */ +OP_1 OP_INVOKE OP_ADD OP_2 OP_NUMEQUAL /* require(n + ONE == 2, 'n mismatch'); */ + /* } */ + /* } */ `.replace(/^\n+/, '').replace(/\n+$/, ''), }, ]; diff --git a/website/docs/compiler/artifacts.md b/website/docs/compiler/artifacts.md index d56f93dbc..766dc907f 100644 --- a/website/docs/compiler/artifacts.md +++ b/website/docs/compiler/artifacts.md @@ -27,7 +27,8 @@ interface Artifact { logs: LogEntry[] // log entries generated from `console.log` statements requires: RequireStatement[] // messages for failing `require` statements sourceTags?: string // semantic tags for opcodes (e.g. loop update/condition ranges) - functions?: DebugFrame[] // debug metadata for each user-defined function + functions?: DebugFrame[] // debug metadata for each global definition (defined frames first, then inlined ones) + inlineRanges?: string // "startIp:endIp:name;..." — runs where inlined callables' bodies were emitted } updatedAt: string // Last datetime this artifact was updated (in ISO format) fingerprint?: string // SHA256 of the normalized bytecode pattern (BCH bytecode fingerprinting standard) @@ -63,8 +64,9 @@ interface RequireStatement { } interface DebugFrame { - id: number; // the function's id, as used with OP_DEFINE / OP_INVOKE in the bytecode - name: string; // the function's name + id?: number; // the function's id, as used with OP_DEFINE / OP_INVOKE in the bytecode (absent for inlined callables) + name: string; // the source definition's name + kind?: 'constant'; // present when the VM function implements a global constant; absent for regular functions inputs: AbiInput[]; // the function's parameters (name and type) bytecode: string; // hex-encoded bytecode of the function body (exactly what OP_DEFINE stores) sourceMap: string; // source map of the function body (instruction pointers starting from 0) @@ -73,6 +75,7 @@ interface DebugFrame { sourceFile?: string; // file name the function is imported from (absent for the contract's own file) logs: LogEntry[]; // log entries within the function body requires: RequireStatement[]; // messages for failing `require` statements within the function body + inlineRanges?: string; // runs where inlined callables' bodies were emitted within this body (frame-local ips) } interface CompilerOptions { diff --git a/website/docs/compiler/compiler.md b/website/docs/compiler/compiler.md index ca261d986..a8341823b 100644 --- a/website/docs/compiler/compiler.md +++ b/website/docs/compiler/compiler.md @@ -101,7 +101,7 @@ const source = await result.text(); const P2PKH = compileString(source); ``` -`compileString` never reads from the filesystem, so `import` directives that pull in [user-defined functions](/docs/language/contracts#user-defined-functions) are resolved from the `files` compiler option instead. Its keys are the import paths relative to the main source (using forward slashes), and its values are the corresponding source code strings. +`compileString` never reads from the filesystem, so `import` directives that pull in [top-level definitions](/docs/language/contracts#importing-functions-and-constants-from-other-files) are resolved from the `files` compiler option instead. Its keys are the import paths relative to the main source (using forward slashes), and its values are the corresponding source code strings. ```ts const mathSource = ` diff --git a/website/docs/compiler/grammar.md b/website/docs/compiler/grammar.md index 060931884..6d28bb806 100644 --- a/website/docs/compiler/grammar.md +++ b/website/docs/compiler/grammar.md @@ -36,6 +36,7 @@ importDirective topLevelDefinition : globalFunctionDefinition + | constantDefinition | contractDefinition ; @@ -226,6 +227,10 @@ typeCast | UnsafeCast ; +constantDefinition + : typeName 'constant' Identifier '=' literal ';' + ; + VersionLiteral : [0-9]+ '.' [0-9]+ '.' [0-9]+ ; diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index 79cfa3d2b..3baba574b 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -41,6 +41,26 @@ The typings for the constructor arguments are only semantic and used when initia Upon initialization of the contract, constructor parameters are encoded and added to the contract's bytecode in the reversed order of their declaration. This can be important when manually constructing the contract locking script for debugging or optimization purposes. ::: +## Global constants +Global constants are declared at the **top level** of a `.cash` file, outside the contract, and can be used by contract functions and user-defined functions. Their initialiser must currently be a literal; expressions and casts are not supported. + +```solidity +int constant MAX_ATTEMPTS = 3; +int constant TIMEOUT = 12; // 12 blocks +bytes32 constant EMPTY_HASH = 0x0000000000000000000000000000000000000000000000000000000000000000; + +contract Example() { + function spend(int attempts) { + require(attempts < MAX_ATTEMPTS); + require(this.age >= TIMEOUT); + } +} +``` + +The literal must be assignable to the declared type. Global constants are immutable, and their names share the global namespace with user-defined functions and built-in symbols. Parameters and local variables cannot shadow them. + +Global constants do not become constructor arguments or mutable stack variables. The compiler treats them like zero-argument value-returning functions internally: small values and one-use constants are generally inlined, while larger values used repeatedly can be shared with `OP_DEFINE`/`OP_INVOKE`. + ## Functions The main construct in a CashScript contract is the function. A contract can contain one or multiple functions that can be executed to trigger transactions that spend money from the contract. At its core, the result of a function is just a yes or no answer to the question 'Can money be sent out of this contract?'. However, by using 'covenants it's possible to specify additional conditions — like restricting *where* money can be sent. To learn more about covenants, refer to the [CashScript Covenants Guide](/docs/guides/covenants). @@ -80,7 +100,7 @@ The typings for function arguments are enforced by default for boolean values an ::: ## User-defined functions -Reusable functions are declared at the **top level** of a `.cash` file, outside the contract. They are compiled to the BCH VM's native function opcodes (`OP_DEFINE`/`OP_INVOKE`, available since the May 2026 upgrade), so a function's body is stored once and shared across every call site rather than duplicated. +Reusable functions are declared at the **top level** of a `.cash` file, outside the contract. The compiler chooses between inlining their bodies and sharing them with the BCH VM's native function opcodes (`OP_DEFINE`/`OP_INVOKE`), based on the resulting bytecode size. Single-use functions are inlined; recursive functions remain shared definitions. A function may return a **single value** using a `returns (T)` clause, and is called from contract functions or from other top-level functions: @@ -133,15 +153,35 @@ contract Example() { } ``` -### Importing functions from other files -Top-level functions can be split across files and pulled in with an `import` directive, which makes the imported file's functions available as if they were declared locally. All `import` directives must appear at the **top of the file** after any `pragma` directives and before any function or contract definitions. +## Global constants +Global constants are declared at the **top level** of a `.cash` file, outside the contract, and can be used by contract functions and user-defined functions. Their initialiser must be a literal: expressions and casts are not supported. + +```solidity +int constant MAX_ATTEMPTS = 3; +int constant TIMEOUT = 2 hours; +bytes32 constant EMPTY_HASH = 0x0000000000000000000000000000000000000000000000000000000000000000; + +contract Example() { + function spend(int attempts) { + require(attempts < MAX_ATTEMPTS); + require(tx.time >= TIMEOUT); + } +} +``` + +The literal must be assignable to the declared type. Global constants are immutable, and their names share the global namespace with user-defined functions and built-in symbols. Parameters and local variables cannot shadow them. + +### Importing functions and constants from other files +Top-level functions and constants can be split across files and pulled in with an `import` directive, which makes the imported functions and constants available as if they were declared locally. All `import` directives must appear at the **top of the file** after any `pragma` directives and before any constant, function or contract definitions. Imports are resolved relative to the importing file: from the filesystem when compiling with [`compileFile`](/docs/compiler#compilefile), or from the `files` compiler option when using [`compileString`](/docs/compiler#compilestring). ```solidity // math.cash +int constant FACTOR = 2; + function double(int a) returns (int) { - return a * 2; + return a * FACTOR; } ``` @@ -157,7 +197,7 @@ contract Main() { } ``` -Imported function names share a single global namespace, so a name may only be defined once across the whole import graph. Files reached through more than one import path (diamond imports) are resolved once. +Imported function and constant names share a single global namespace, so a name may only be defined once across the whole import graph. Files reached through more than one import path (diamond imports) are resolved once. Imported files can declare their own [`pragma` directives](#pragma), and every pragma across the whole import graph — the main file and all (transitively) imported files — must be satisfied by the compiler version. @@ -169,7 +209,7 @@ Imported files can declare their own [`pragma` directives](#pragma), and every p This first version of user-defined functions is intentionally limited in scope: - A value-returning function must end with a single `return` statement (no early or conditional returns — compute into a variable and return it at the end). -- No advanced optimisations are performed yet on user-defined functions. +- A void function must end with a `require` statement, just like contract functions (when it ends with an if-statement or loop, every branch must end with a `require`). :::note Recursive and mutually recursive functions are allowed and compile fine. At runtime the VM control stack is limited to 100 entries, shared between recursion depth and nested `if` and loop blocks, so excessively deep recursion will fail when the contract gets spent. @@ -351,18 +391,18 @@ contract P2PKH(bytes20 pkh) { ## Scope -CashScript uses nested scopes for parameters, variables and global functions. There cannot be two identical names within the same scope or within a nested scope. +CashScript uses nested scopes for global constants, parameters, variables and global functions. There cannot be two identical names within the same scope or within a nested scope. There are the following scopes in the nesting order: -- **Global scope** - contains global functions and global variables (e.g. `sha256`, `hash160`, `checkSig`, etc.) +- **Global scope** - contains global constants, global functions and built-in symbols (e.g. `sha256`, `hash160`, `checkSig`, etc.) - **Contract scope** - contains contract parameters - **Function scope** - contains function parameters and local variables - **Local scope** - contains local variables introduced by control flow blocks (e.g. `if`, `else`) #### Example ```solidity -// Global scope (contains global functions and global variables like sha256, hash160, checkSig, etc.) +// Global scope (contains global constants, functions and built-in symbols like sha256, hash160, checkSig, etc.) // Contract scope (contains contract parameters - sender, recipient, timeout) contract TransferWithTimeout( diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index beb928199..198f39b15 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -9,8 +9,10 @@ title: Release Notes #### cashc compiler - :sparkles: Add support for user-defined reusable functions. - :sparkles: Add support for multiple return values in user-defined functions, destructured at the call site. +- :sparkles: Add support for top-level global constants. - :sparkles: Add support for `import` directives to share user-defined functions across files. - :hammer_and_wrench: Update `compileString` to take an optional `files` object for filesystem-free import resolution. +- :racehorse: Inline global functions and constants when this is no larger than `OP_DEFINE`/`OP_INVOKE`. - :racehorse: Add new `OP_SWAP OP_MUL` optimisation. #### CashScript SDK From 6ec38a408ae034e909673c39b0faadfc8c2a731d Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 23 Jul 2026 11:56:02 +0200 Subject: [PATCH 12/37] Bump version to 0.14.0-next.2 --- examples/package.json | 6 +++--- examples/testing-suite/package.json | 6 +++--- packages/cashc/package.json | 4 ++-- packages/cashc/src/index.ts | 2 +- packages/cashscript/package.json | 4 ++-- packages/utils/package.json | 2 +- website/docs/releases/release-notes.md | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/package.json b/examples/package.json index d29356661..ba4f6d055 100644 --- a/examples/package.json +++ b/examples/package.json @@ -1,7 +1,7 @@ { "name": "cashscript-examples", "private": true, - "version": "0.14.0-next.1", + "version": "0.14.0-next.2", "description": "Usage examples of the CashScript SDK", "main": "p2pkh.js", "type": "module", @@ -13,8 +13,8 @@ "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", "@types/node": "^22.17.0", - "cashc": "^0.14.0-next.1", - "cashscript": "^0.14.0-next.1", + "cashc": "^0.14.0-next.2", + "cashscript": "^0.14.0-next.2", "eslint": "^8.56.0", "typescript": "^5.9.2" } diff --git a/examples/testing-suite/package.json b/examples/testing-suite/package.json index a21bfdeae..187a0c413 100644 --- a/examples/testing-suite/package.json +++ b/examples/testing-suite/package.json @@ -1,6 +1,6 @@ { "name": "testing-suite", - "version": "0.14.0-next.1", + "version": "0.14.0-next.2", "description": "Example project to develop and test CashScript contracts", "main": "index.js", "type": "module", @@ -18,8 +18,8 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "cashc": "^0.14.0-next.1", - "cashscript": "^0.14.0-next.1" + "cashc": "^0.14.0-next.2", + "cashscript": "^0.14.0-next.2" }, "devDependencies": { "tsx": "^4.20.3", diff --git a/packages/cashc/package.json b/packages/cashc/package.json index 4ba502900..aeaa5d8dd 100644 --- a/packages/cashc/package.json +++ b/packages/cashc/package.json @@ -1,6 +1,6 @@ { "name": "cashc", - "version": "0.14.0-next.1", + "version": "0.14.0-next.2", "description": "Compile Bitcoin Cash contracts to Bitcoin Cash Script or artifacts", "keywords": [ "bitcoin", @@ -48,7 +48,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.1", + "@cashscript/utils": "^0.14.0-next.2", "antlr4": "^4.13.2", "commander": "^14.0.0", "semver": "^7.7.2" diff --git a/packages/cashc/src/index.ts b/packages/cashc/src/index.ts index 6b4a48d80..039b94389 100644 --- a/packages/cashc/src/index.ts +++ b/packages/cashc/src/index.ts @@ -6,4 +6,4 @@ export { export * from './ast/Location.js'; export * from './ast/error-listeners.js'; -export const version = '0.14.0-next.1'; +export const version = '0.14.0-next.2'; diff --git a/packages/cashscript/package.json b/packages/cashscript/package.json index 6dd7e128b..07d34d87e 100644 --- a/packages/cashscript/package.json +++ b/packages/cashscript/package.json @@ -1,6 +1,6 @@ { "name": "cashscript", - "version": "0.14.0-next.1", + "version": "0.14.0-next.2", "description": "Easily write and interact with Bitcoin Cash contracts", "keywords": [ "bitcoin cash", @@ -42,7 +42,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.1", + "@cashscript/utils": "^0.14.0-next.2", "@electrum-cash/network": "^4.1.3", "fflate": "^0.8.2", "semver": "^7.7.2" diff --git a/packages/utils/package.json b/packages/utils/package.json index 4b7e079a8..de2eb6ed7 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@cashscript/utils", - "version": "0.14.0-next.1", + "version": "0.14.0-next.2", "description": "CashScript utilities and types", "keywords": [ "bitcoin cash", diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 198f39b15..dac6805b7 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -2,7 +2,7 @@ title: Release Notes --- -## v0.14.0-next.1 +## v0.14.0-next.2 ⚠️ Note that this is a pre-release version and is not yet stable. There will likely be breaking changes to the APIs and compiler output in subsequent pre-releases. From a5ce8c4f521ba7436ce97c2335c0e3b3b48a63c0 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 28 Jul 2026 12:40:45 +0200 Subject: [PATCH 13/37] Add stack trace to failing require statements inside functions (#429) --- packages/cashscript/src/Errors.ts | 49 ++--- packages/cashscript/src/debug-frame.ts | 198 ++++++++++++++++-- packages/cashscript/src/debugging.ts | 23 +- packages/cashscript/test/debugging.test.ts | 90 +++++++- .../fixture/debugging/debugging_contracts.ts | 103 +++++++++ packages/utils/src/source-map.ts | 16 +- 6 files changed, 418 insertions(+), 61 deletions(-) diff --git a/packages/cashscript/src/Errors.ts b/packages/cashscript/src/Errors.ts index cd27b4a2e..dd12a9f07 100644 --- a/packages/cashscript/src/Errors.ts +++ b/packages/cashscript/src/Errors.ts @@ -1,5 +1,11 @@ -import { Artifact, RequireStatement, sourceMapToLocationData, Type } from '@cashscript/utils'; -import { ResolvedFrame, resolveInlineAttribution, rootFrame } from './debug-frame.js'; +import { Artifact, RequireStatement, Type } from '@cashscript/utils'; +import { + CallStackEntry, + ResolvedFrame, + getLocationDataForFrame, + resolveInlineAttribution, + rootFrame, +} from './debug-frame.js'; export class TypeError extends Error { constructor(actual: string, expected: Type) { @@ -159,6 +165,7 @@ export class FailedRequireError extends FailedTransactionError { public bitauthUri: string, public libauthErrorMessage?: string, frame?: ResolvedFrame, + public callStack: CallStackEntry[] = [], ) { const resolvedFrame = frame ?? rootFrame(artifact); @@ -175,9 +182,12 @@ export class FailedRequireError extends FailedTransactionError { // Compiler-injected guards (e.g. the tx.locktime guard) have no user-written source, so the // extracted statement is empty — the require message fully describes the failure on its own. - const fullMessage = statement.trim() ? `${headline}\nFailing statement: ${statement}` : headline; + const statementMessage = statement.trim() ? `${headline}\nFailing statement: ${statement}` : headline; - super(fullMessage, bitauthUri); + // A single-entry call stack adds nothing over the headline, so it is only shown for nested calls + const callStackMessage = callStack.length >= 2 ? `\n${formatCallStack(callStack)}` : ''; + + super(statementMessage + callStackMessage, bitauthUri); } } @@ -189,28 +199,9 @@ const formatFrameContext = (frame: ResolvedFrame, contractName: string, lineNumb return `in contract ${contractName}.cash at line ${lineNumber}`; }; -const getLocationDataForFrame = ( - frame: ResolvedFrame, - instructionPointer: number, -): { lineNumber: number, statement: string } => { - const locationData = sourceMapToLocationData(frame.sourceMap); - - // We subtract the frame's ip offset (the constructor-arg prefix for the root frame, 0 for helper - // frames) because those pushes are present in the evaluation (and thus the instruction pointer) but - // not in the source code (and thus the location data). - const modifiedInstructionPointer = instructionPointer - frame.ipOffset; - - const { location } = locationData[modifiedInstructionPointer]; - - const failingLines = frame.source.split('\n').slice(location.start.line - 1, location.end.line); - - // Slice off the start and end of the statement's start and end lines to only return the failing part - // Note that we first slice off the end, to avoid shifting the end column index - failingLines[failingLines.length - 1] = failingLines[failingLines.length - 1].slice(0, location.end.column); - failingLines[0] = failingLines[0].slice(location.start.column); - - const statement = failingLines.join('\n'); - const lineNumber = location.start.line; - - return { statement, lineNumber }; -}; +const formatCallStack = (callStack: CallStackEntry[]): string => callStack + .map(({ functionName, sourceName, line, statement }) => { + const location = functionName ? `${functionName} (${sourceName}:${line})` : `${sourceName}:${line}`; + return ` at ${location} — ${statement}`; + }) + .join('\n'); diff --git a/packages/cashscript/src/debug-frame.ts b/packages/cashscript/src/debug-frame.ts index fd72b9c6a..234131c93 100644 --- a/packages/cashscript/src/debug-frame.ts +++ b/packages/cashscript/src/debug-frame.ts @@ -1,5 +1,24 @@ -import { AuthenticationProgramStateCommon, binToHex, encodeAuthenticationInstructions } from '@bitauth/libauth'; -import { Artifact, DebugEntry, DebugFrame, LogEntry, RequireStatement, parseInlineRanges } from '@cashscript/utils'; +import { + AuthenticationInstruction, + AuthenticationProgramStackFrame, + AuthenticationProgramStateCommon, + binToHex, + encodeAuthenticationInstructions, + hexToBin, +} from '@bitauth/libauth'; +import { + Artifact, + DebugEntry, + DebugFrame, + InlineRange, + LogEntry, + Op, + RequireStatement, + Script, + bytecodeToScript, + parseAndResolveInlineRanges, + sourceMapToLocationData, +} from '@cashscript/utils'; export interface ResolvedFrame { sourceMap: string; @@ -12,6 +31,13 @@ export interface ResolvedFrame { functionName?: string; } +export interface CallStackEntry { + functionName?: string; // absent for the contract's own code + sourceName: string; + line: number; + statement: string; // flattened to a single line for display +} + export const rootFrame = (artifact: Artifact): ResolvedFrame => ({ sourceMap: artifact.debug?.sourceMap ?? '', source: artifact.source, @@ -22,22 +48,22 @@ export const rootFrame = (artifact: Artifact): ResolvedFrame => ({ inlineRanges: artifact.debug?.inlineRanges, }); -export const getActiveBytecode = (step: AuthenticationProgramStateCommon): string => - binToHex(encodeAuthenticationInstructions(step.instructions)); +export const getActiveBytecode = (instructions: AuthenticationInstruction[]): string => + binToHex(encodeAuthenticationInstructions(instructions)); export const resolveFrame = ( artifact: Artifact, step: AuthenticationProgramStateCommon, -): ResolvedFrame => { - // Only defined frames (id present) execute as standalone VM functions; an inlined callable's - // frame documents a body that only ever runs spliced into another program - const frames = (artifact.debug?.functions ?? []).filter((candidate) => candidate.id !== undefined); - const activeBytecode = frames.length > 0 ? getActiveBytecode(step) : undefined; - const frame = frames.find((candidate) => candidate.bytecode === activeBytecode); +): ResolvedFrame => resolveFrameByBytecode(artifact, getActiveBytecode(step.instructions)); - if (!frame) return rootFrame(artifact); +// Only defined frames (id present) execute as standalone VM programs; an inlined callable's +// frame documents a body that only ever runs spliced into another program +const resolveFrameByBytecode = (artifact: Artifact, activeBytecode: string): ResolvedFrame => { + const frame = (artifact.debug?.functions ?? []) + .filter((candidate) => candidate.id !== undefined) + .find((candidate) => candidate.bytecode === activeBytecode); - return resolveDebugFrame(artifact, frame); + return frame ? resolveDebugFrame(artifact, frame) : rootFrame(artifact); }; const resolveDebugFrame = (artifact: Artifact, frame: DebugFrame): ResolvedFrame => ({ @@ -48,7 +74,7 @@ const resolveDebugFrame = (artifact: Artifact, frame: DebugFrame): ResolvedFrame requires: frame.requires, logs: frame.logs, inlineRanges: frame.inlineRanges, - functionName: frame.sourceFile ? frame.name : undefined, + functionName: frame.name, }); export interface InlineAttribution { @@ -62,20 +88,31 @@ export const resolveInlineAttribution = ( entry: DebugEntry, kind: 'requires' | 'logs', ): InlineAttribution | undefined => { - const range = parseInlineRanges(containerFrame.inlineRanges ?? '') - .find((candidate) => entry.ip >= candidate.startIp && entry.ip <= candidate.endIp); - if (!range) return undefined; + const attributionStack = resolveInlineAttributionStack(artifact, containerFrame, entry, kind); + return attributionStack[0]; +}; - const inlinedFrame = artifact.debug?.functions?.find((candidate) => candidate.name === range.frameName); - if (!inlinedFrame) return undefined; +// The chain of inlined callables containing the entry, from the innermost to the outermost +const resolveInlineAttributionStack = ( + artifact: Artifact, + containerFrame: ResolvedFrame, + entry: DebugEntry, + kind: 'requires' | 'logs', +): InlineAttribution[] => { + const range = parseAndResolveInlineRanges(containerFrame.inlineRanges, artifact.debug?.functions) + .find((candidate) => entry.ip >= candidate.startIp && entry.ip <= candidate.endIp); + if (!range) return []; - const frameEntry = findMatchingFrameEntry(containerFrame[kind], inlinedFrame[kind], range, entry); - if (!frameEntry) return undefined; + const frameEntry = findMatchingFrameEntry(containerFrame[kind], range.frame[kind], range, entry); + if (!frameEntry) return []; - const frame = resolveDebugFrame(artifact, inlinedFrame); + const frame = resolveDebugFrame(artifact, range.frame); - // The callable may itself contain deeper inlined callables: attribute to the innermost one - return resolveInlineAttribution(artifact, frame, frameEntry, kind) ?? { frame, entry: frameEntry }; + // The callable may itself contain deeper inlined callables + return [ + ...resolveInlineAttributionStack(artifact, frame, frameEntry, kind), + { frame, entry: frameEntry }, + ]; }; // A log merged from an inlined callable is attributed to the callable's own source @@ -107,3 +144,118 @@ const findMatchingFrameEntry = ( if (position === -1) return undefined; return frameEntries[position]; }; + +export const buildCallStack = ( + artifact: Artifact, + failingStep: AuthenticationProgramStateCommon, + failingFrame: ResolvedFrame, + requireStatement: RequireStatement, + failingInstructionPointer: number, +): CallStackEntry[] => { + // These entries represent any called inlined functions at the top of the call stack. These are handled separately, + // because the failing debug step refers to the frameEntry below, so we manually need to handle "deeper" calls + const inlineEntries = resolveInlineAttributionStack(artifact, failingFrame, requireStatement, 'requires') + .map(({ frame, entry }) => toCallStackEntry(frame, entry.ip)); + + // This entry is the actual VM-level failing function + const frameEntry = toCallStackEntry(failingFrame, failingInstructionPointer); + + // These entries are the rest of the callstack, so all the intermediate (defined & inlined) functions that call + // the VM-level failing function + const runtimeCallers = failingStep.controlStack + .filter(isAuthenticationProgramStackFrame) + .reverse() + .flatMap((controlFrame) => { + const callerBytecode = getActiveBytecode(controlFrame.instructions); + const callerFrame = resolveFrameByBytecode(artifact, callerBytecode); + // The control frame stores the ip to resume at, which is one past the OP_INVOKE call site + return expandRuntimeCaller(artifact, callerFrame, bytecodeToScript(hexToBin(callerBytecode)), controlFrame.ip - 1); + }); + + return [...inlineEntries, frameEntry, ...runtimeCallers]; +}; + +const expandRuntimeCaller = ( + artifact: Artifact, + frame: ResolvedFrame, + script: Script, + invokeIp: number, +): CallStackEntry[] => [ + ...resolveInlinedCallerHops(artifact, frame, script, invokeIp), + toCallStackEntry(frame, invokeIp), +]; + +// Every defined function already gets expanded in buildCallStack, so this function exists to make sure any inlined +// callers also get added to the call stack +const resolveInlinedCallerHops = ( + artifact: Artifact, + frame: ResolvedFrame, + script: Script, + invokeIp: number, +): CallStackEntry[] => { + const inlineRange = parseAndResolveInlineRanges(frame.inlineRanges, artifact.debug?.functions) + .find((candidate) => invokeIp >= candidate.startIp && invokeIp <= candidate.endIp); + if (!inlineRange) return []; + + const frameScript = bytecodeToScript(hexToBin(inlineRange.frame.bytecode)); + const frameLocalIp = findMatchingFrameInvokeIp(script, frameScript, inlineRange, invokeIp); + if (frameLocalIp === undefined) return []; + + // The invoke is expanded again within the callable, since deeper inlined callables may wrap it + return expandRuntimeCaller(artifact, resolveDebugFrame(artifact, inlineRange.frame), frameScript, frameLocalIp); +}; + +// The container's n-th OP_INVOKE within the range corresponds to the n-th OP_INVOKE in the inlined +// callable's own bytecode, matching by position gives the invoke's exact frame-local ip. +const findMatchingFrameInvokeIp = ( + containerScript: Script, + frameScript: Script, + range: InlineRange, + invokeIp: number, +): number | undefined => { + const position = containerScript.slice(range.startIp, invokeIp).filter((op) => op === Op.OP_INVOKE).length; + const frameInvokeIps = frameScript.flatMap((op, ip) => (op === Op.OP_INVOKE ? [ip] : [])); + return frameInvokeIps[position]; +}; + +const isAuthenticationProgramStackFrame = ( + item: AuthenticationProgramStackFrame | boolean | number, +): item is AuthenticationProgramStackFrame => typeof item === 'object'; + +const toCallStackEntry = (frame: ResolvedFrame, instructionPointer: number): CallStackEntry => { + const { lineNumber, statement } = getLocationDataForFrame(frame, instructionPointer); + const flattenedStatement = statement.split('\n').map((line) => line.trim()).join(' '); + + return { + functionName: frame.functionName, + sourceName: frame.sourceName, + line: lineNumber, + statement: flattenedStatement, + }; +}; + +export const getLocationDataForFrame = ( + frame: ResolvedFrame, + instructionPointer: number, +): { lineNumber: number, statement: string } => { + const locationData = sourceMapToLocationData(frame.sourceMap); + + // We subtract the frame's ip offset (the constructor-arg prefix for the root frame, 0 for helper + // frames) because those pushes are present in the evaluation (and thus the instruction pointer) but + // not in the source code (and thus the location data). + const modifiedInstructionPointer = instructionPointer - frame.ipOffset; + + const { location } = locationData[modifiedInstructionPointer]; + + const failingLines = frame.source.split('\n').slice(location.start.line - 1, location.end.line); + + // Slice off the start and end of the statement's start and end lines to only return the failing part + // Note that we first slice off the end, to avoid shifting the end column index + failingLines[failingLines.length - 1] = failingLines[failingLines.length - 1].slice(0, location.end.column); + failingLines[0] = failingLines[0].slice(location.start.column); + + const statement = failingLines.join('\n'); + const lineNumber = location.start.line; + + return { statement, lineNumber }; +}; diff --git a/packages/cashscript/src/debugging.ts b/packages/cashscript/src/debugging.ts index ac5f85649..3ad2a5df5 100644 --- a/packages/cashscript/src/debugging.ts +++ b/packages/cashscript/src/debugging.ts @@ -2,7 +2,7 @@ import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationPro import { Artifact, LogData, LogEntry, Op, PrimitiveType, StackItem, asmToBytecode, bytecodeToAsm, decodeBool, decodeInt, decodeString } from '@cashscript/utils'; import { findLastIndex, toRegExp } from './utils.js'; import { FailedRequireError, FailedTransactionError, FailedTransactionEvaluationError } from './Errors.js'; -import { attributeLogEntry, getActiveBytecode, resolveFrame } from './debug-frame.js'; +import { attributeLogEntry, buildCallStack, getActiveBytecode, resolveFrame } from './debug-frame.js'; import { getBitauthUri } from './libauth-template/LibauthTemplate.js'; import { VmTarget } from './interfaces.js'; @@ -100,7 +100,7 @@ const debugSingleScenario = ( if (logEntries.length === 0) return []; const reversedPriorDebugSteps = executedDebugSteps.slice(0, index + 1).reverse(); - const frameBytecode = getActiveBytecode(debugStep); + const frameBytecode = getActiveBytecode(debugStep.instructions); return logEntries.map((logEntry) => { const decodedLogData = logEntry.data @@ -148,9 +148,11 @@ const debugSingleScenario = ( const requireStatement = frame.requires.find((statement) => statement.ip === requireStatementIp); if (requireStatement) { + const callStack = buildCallStack(artifact, lastExecutedDebugStep, frame, requireStatement, failingIp); + // Note that we use failingIp here rather than requireStatementIp, see comment above throw new FailedRequireError( - artifact, failingIp, requireStatement, inputIndex, getBitauthUri(template), error, frame, + artifact, failingIp, requireStatement, inputIndex, getBitauthUri(template), error, frame, callStack, ); } @@ -188,8 +190,19 @@ const debugSingleScenario = ( const requireStatement = frame.requires.find((message) => message.ip === finalExecutedVerifyIp); if (requireStatement) { + const callStack = buildCallStack( + artifact, lastExecutedDebugStep, frame, requireStatement, sourcemapInstructionPointer, + ); + throw new FailedRequireError( - artifact, sourcemapInstructionPointer, requireStatement, inputIndex, getBitauthUri(template), undefined, frame, + artifact, + sourcemapInstructionPointer, + requireStatement, + inputIndex, + getBitauthUri(template), + undefined, + frame, + callStack, ); } @@ -260,7 +273,7 @@ const decodeLogDataEntry = ( if (typeof dataEntry === 'string') return dataEntry; const dataEntryDebugStep = reversedPriorDebugSteps.find( - (step) => step.ip === dataEntry.ip && getActiveBytecode(step) === frameBytecode, + (step) => step.ip === dataEntry.ip && getActiveBytecode(step.instructions) === frameBytecode, ); if (!dataEntryDebugStep) { diff --git a/packages/cashscript/test/debugging.test.ts b/packages/cashscript/test/debugging.test.ts index dd9f5b0a0..e023c6666 100644 --- a/packages/cashscript/test/debugging.test.ts +++ b/packages/cashscript/test/debugging.test.ts @@ -21,6 +21,11 @@ import { artifactTestImportedFunctionDebuggingDefined, artifactTestMultiReturn, artifactTestMultilineFunctionRequire, + artifactTestNestedFunctions, + artifactTestNestedFunctionsDefined, + artifactTestNestedImportedFunctions, + artifactTestMixedNestedFunctions, + artifactTestInlinedCallingDefined, } from './fixture/debugging/debugging_contracts.js'; import { sha256 } from '@cashscript/utils'; @@ -852,7 +857,7 @@ describe('Debugging tests - user-defined function frames', () => { // The artifact's inline ranges tie the merged require back to the function's own frame, so // inlining is transparent: the failure reads like the defined variant below - 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('Test.cash:4 Require statement failed at input 0 in contract Test, function checkValue (Test.cash, line 4) with the following message: value must be positive.'); expect(transaction).toFailRequireWith('Failing statement: require(value > 0, "value must be positive")'); }); @@ -865,6 +870,85 @@ describe('Debugging tests - user-defined function frames', () => { expect(transaction).toFailRequireWith('Failing statement: require(x < 100, "x must be small")'); }); + it('shows a call stack when a require fails in a nested inlined function', () => { + const nestedContract = new Contract(artifactTestNestedFunctions, [], { provider }); + const nestedUtxo = provider.addUtxo(nestedContract.address, randomUtxo()); + + const transaction = new TransactionBuilder({ provider }) + .addInput(nestedUtxo, nestedContract.unlock.spend(0n)) + .addOutput({ to: nestedContract.address, amount: 10000n }); + + expect(transaction).toFailRequireWith('Test.cash:3 Require statement failed at input 0 in contract Test, function assertPositive (Test.cash, line 3) with the following message: value must be positive.'); + expect(transaction).toFailRequireWith(` at assertPositive (Test.cash:3) — require(value > 0, "value must be positive"); + at validate (Test.cash:7) — assertPositive(amount) + at Test.cash:13 — validate(x)`); + }); + + it('shows a call stack when a require fails in a nested defined function', () => { + const nestedContract = new Contract(artifactTestNestedFunctionsDefined, [], { provider }); + const nestedUtxo = provider.addUtxo(nestedContract.address, randomUtxo()); + + const transaction = new TransactionBuilder({ provider }) + .addInput(nestedUtxo, nestedContract.unlock.spend(0n)) + .addOutput({ to: nestedContract.address, amount: 10000n }); + + // The trace is identical to the inlined variant: runtime callers come from the VM's control + // stack instead of inline ranges, but the displayed stack is the same + expect(transaction).toFailRequireWith('Test.cash:3 Require statement failed at input 0 in contract Test, function assertPositive (Test.cash, line 3) with the following message: value must be positive.'); + expect(transaction).toFailRequireWith(` at assertPositive (Test.cash:3) — require(value > 0, "value must be positive"); + at validate (Test.cash:7) — assertPositive(amount) + at Test.cash:13 — validate(x)`); + }); + + it('shows a call stack across imported functions', () => { + const nestedContract = new Contract(artifactTestNestedImportedFunctions, [], { provider }); + const nestedUtxo = provider.addUtxo(nestedContract.address, randomUtxo()); + + const transaction = new TransactionBuilder({ provider }) + .addInput(nestedUtxo, nestedContract.unlock.spend(0n)) + .addOutput({ to: nestedContract.address, amount: 10000n }); + + expect(transaction).toFailRequireWith('nested_helpers.cash:3 Require statement failed at input 0 in contract Test, function assertPositive (nested_helpers.cash, line 3) with the following message: value must be positive.'); + expect(transaction).toFailRequireWith(` at assertPositive (nested_helpers.cash:3) — require(value > 0, "value must be positive"); + at validate (nested_helpers.cash:7) — assertPositive(amount) + at Test.cash:6 — validate(x)`); + }); + + it('shows a call stack when an inlined function calls a defined function', () => { + const inlinedCallingDefinedContract = new Contract(artifactTestInlinedCallingDefined, [], { provider }); + const inlinedCallingDefinedUtxo = provider.addUtxo(inlinedCallingDefinedContract.address, randomUtxo()); + + const transaction = new TransactionBuilder({ provider }) + .addInput(inlinedCallingDefinedUtxo, inlinedCallingDefinedContract.unlock.spend(0n)) + .addOutput({ to: inlinedCallingDefinedContract.address, amount: 10000n }); + + // The invoke of bigCheck sits inside the inlined wrapper's body within the contract; the + // inline range and the invoke's position within it give wrapper its own hop + expect(transaction).toFailRequireWith('Test.cash:3 Require statement failed at input 0 in contract Test, function bigCheck (Test.cash, line 3) with the following message: v must be positive.'); + expect(transaction).toFailRequireWith(` at bigCheck (Test.cash:3) — require(v > 0, "v must be positive"); + at wrapper (Test.cash:8) — bigCheck(v) + at Test.cash:13 — wrapper(x)`); + }); + + it('shows a call stack alternating between defined and inlined functions', () => { + const mixedContract = new Contract(artifactTestMixedNestedFunctions, [], { provider }); + const mixedUtxo = provider.addUtxo(mixedContract.address, randomUtxo()); + + const transaction = new TransactionBuilder({ provider }) + .addInput(mixedUtxo, mixedContract.unlock.spend(0n)) + .addOutput({ to: mixedContract.address, amount: 10000n }); + + // The inlined innerCheck attributes through deepHelper's inline ranges; the runtime hops come + // from the VM's control stack, with the inlined middle recovered from the position of the + // deepHelper invoke within middle's inline range in outerHelper + expect(transaction).toFailRequireWith('Test.cash:3 Require statement failed at input 0 in contract Test, function innerCheck (Test.cash, line 3) with the following message: v must be positive.'); + expect(transaction).toFailRequireWith(` at innerCheck (Test.cash:3) — require(v > 0, "v must be positive"); + at deepHelper (Test.cash:7) — innerCheck(v) + at middle (Test.cash:12) — deepHelper(v) + at outerHelper (Test.cash:16) — middle(v) + at Test.cash:21 — outerHelper(x)`); + }); + it('attributes a multiline require failing inside an inlined function with its full statement', () => { const multilineContract = new Contract(artifactTestMultilineFunctionRequire, [], { provider }); const multilineUtxo = provider.addUtxo(multilineContract.address, randomUtxo()); @@ -873,11 +957,13 @@ describe('Debugging tests - user-defined function frames', () => { .addInput(multilineUtxo, multilineContract.unlock.spend(0n)) .addOutput({ to: multilineContract.address, amount: 10000n }); - expect(transaction).toFailRequireWith('Test.cash:3 Require statement failed at input 0 in contract Test.cash at line 3 with the following message: value must be positive.'); + expect(transaction).toFailRequireWith('Test.cash:3 Require statement failed at input 0 in contract Test, function checkRange (Test.cash, line 3) with the following message: value must be positive.'); expect(transaction).toFailRequireWith(`Failing statement: require( value > 0, "value must be positive" )`); + // In the call stack display, the multiline statement is flattened to a single line + expect(transaction).toFailRequireWith('at checkRange (Test.cash:3) — require( value > 0, "value must be positive" )'); }); it('attributes a require failing inside an inlined imported function to the imported function', () => { diff --git a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts index e556bd827..417f76198 100644 --- a/packages/cashscript/test/fixture/debugging/debugging_contracts.ts +++ b/packages/cashscript/test/fixture/debugging/debugging_contracts.ts @@ -29,6 +29,98 @@ contract Test(pubkey owner) { } `; +// Nested function calls, so a require failing in the innermost function produces a call stack +// through the intermediate function into the contract. The Defined variant exercises the same +// stack through the VM's control stack instead of through inline ranges. +const CONTRACT_TEST_NESTED_FUNCTIONS = ` +function assertPositive(int value) { + require(value > 0, "value must be positive"); +} + +function validate(int amount) { + assertPositive(amount); + require(amount < 1000, "amount too large"); +} + +contract Test() { + function spend(int x) { + validate(x); + require(x < 100); + } +} +`; + +// The same nested-call shape as CONTRACT_TEST_NESTED_FUNCTIONS, but with the functions imported +// from another file, so the call stack attributes its hops to the imported file. +const NESTED_HELPERS_SOURCE = ` +function assertPositive(int value) { + require(value > 0, "value must be positive"); +} + +function validate(int amount) { + assertPositive(amount); + require(amount < 1000, "amount too large"); +} +`; + +const CONTRACT_TEST_NESTED_IMPORTED_FUNCTIONS = ` +import "./nested_helpers.cash"; + +contract Test() { + function spend(int x) { + validate(x); + require(x < 100); + } +} +`; + +// The inlined wrapper invokes the defined bigCheck, where the require fails — the smallest shape +// where an inline range and the VM's control stack combine in one call stack. +const CONTRACT_TEST_INLINED_CALLING_DEFINED = ` +function bigCheck(int v) returns (int) { + require(v > 0, "v must be positive"); + return (v * 7 + 3) * (v + 11) - 5; +} + +function wrapper(int v) returns (int) { + return bigCheck(v) + bigCheck(v + 1); +} + +contract Test() { + function spend(int x) { + require(wrapper(x) > 0, "sum must be positive"); + } +} +`; + +// Alternates between shared and inlined callables: spend invokes the defined outerHelper, which +// contains the inlined middle, which invokes the defined deepHelper, which contains the inlined +// innerCheck where the require fails. +const CONTRACT_TEST_MIXED_NESTED_FUNCTIONS = ` +function innerCheck(int v) { + require(v > 0, "v must be positive"); +} + +function deepHelper(int v) returns (int) { + innerCheck(v); + return (v * 7 + 3) * (v + 11) - 5; +} + +function middle(int v) returns (int) { + return deepHelper(v) + deepHelper(v + 1); +} + +function outerHelper(int v) returns (int) { + return middle(v) * 2; +} + +contract Test() { + function spend(int x) { + require(outerHelper(x) + outerHelper(x + 1) > 0, "sum must be positive"); + } +} +`; + // The require statement inside the (inlined) function spans multiple lines, so its statement can // only be extracted through the function frame's source map rather than a single source line. const CONTRACT_TEST_MULTILINE_FUNCTION_REQUIRE = ` @@ -505,6 +597,17 @@ export const artifactTestFunctionDebugging = compileString(CONTRACT_TEST_FUNCTIO export const artifactTestFunctionIntermediateResults = compileString(CONTRACT_TEST_FUNCTION_INTERMEDIATE_RESULTS); export const artifactTestMultiReturn = compileString(CONTRACT_TEST_MULTI_RETURN); export const artifactTestMultilineFunctionRequire = compileString(CONTRACT_TEST_MULTILINE_FUNCTION_REQUIRE); +export const artifactTestNestedFunctions = compileString(CONTRACT_TEST_NESTED_FUNCTIONS); +export const artifactTestNestedFunctionsDefined = compileString( + CONTRACT_TEST_NESTED_FUNCTIONS, + { disableInlining: true }, +); +export const artifactTestNestedImportedFunctions = compileString( + CONTRACT_TEST_NESTED_IMPORTED_FUNCTIONS, + { files: { './nested_helpers.cash': NESTED_HELPERS_SOURCE } }, +); +export const artifactTestMixedNestedFunctions = compileString(CONTRACT_TEST_MIXED_NESTED_FUNCTIONS); +export const artifactTestInlinedCallingDefined = compileString(CONTRACT_TEST_INLINED_CALLING_DEFINED); // 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)); diff --git a/packages/utils/src/source-map.ts b/packages/utils/src/source-map.ts index 246feab0a..e1a4720c1 100644 --- a/packages/utils/src/source-map.ts +++ b/packages/utils/src/source-map.ts @@ -1,5 +1,5 @@ import { FullLocationData, PositionHint, SingleLocationData, SourceTagEntry, SourceTagKind } from './types.js'; -import { InlineRange } from './artifact.js'; +import { DebugFrame, InlineRange } from './artifact.js'; /* * The source mappings for the bytecode use the following notation (similar to Solidity): @@ -154,7 +154,19 @@ export function generateInlineRanges(entries: InlineRange[]): string { .join(';'); } -export function parseInlineRanges(inlineRanges: string): { startIp: number, endIp: number, frameName: string }[] { +export function parseAndResolveInlineRanges( + inlineRanges?: string, + frames?: readonly DebugFrame[], +): InlineRange[] { + if (!inlineRanges || !frames) return []; + + return parseInlineRanges(inlineRanges).flatMap(({ startIp, endIp, frameName }) => { + const frame = frames.find((candidate) => candidate.name === frameName); + return frame ? [{ startIp, endIp, frame }] : []; + }); +} + +function parseInlineRanges(inlineRanges: string): { startIp: number, endIp: number, frameName: string }[] { if (!inlineRanges) return []; return inlineRanges.split(';').map((segment) => { const [startStr, endStr, frameName] = segment.split(':'); From faa73a446339b60924cdfcefba39e9de0a5ee9af Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 30 Jul 2026 16:06:52 +0200 Subject: [PATCH 14/37] Add unused modifier support to cashc (#425) --- .cspell.json | 1 + packages/cashc/src/Errors.ts | 2 + packages/cashc/src/ast/AST.ts | 8 +- packages/cashc/src/ast/AstBuilder.ts | 6 +- packages/cashc/src/ast/Globals.ts | 1 + packages/cashc/src/ast/SymbolTable.ts | 8 + .../src/generation/GenerateTargetTraversal.ts | 28 +- packages/cashc/src/grammar/CashScript.g4 | 3 +- packages/cashc/src/grammar/CashScript.interp | 4 +- packages/cashc/src/grammar/CashScript.tokens | 44 +- .../cashc/src/grammar/CashScriptLexer.interp | 5 +- .../cashc/src/grammar/CashScriptLexer.tokens | 44 +- packages/cashc/src/grammar/CashScriptLexer.ts | 662 +++++++------ .../cashc/src/grammar/CashScriptParser.ts | 935 +++++++++--------- .../src/print/OutputSourceCodeTraversal.ts | 6 +- .../src/semantic/SymbolTableTraversal.ts | 40 +- .../constant_on_contract_parameter.cash | 5 + .../constant_on_function_parameter.cash | 5 + .../duplicate_modifier.cash | 5 + .../reference_unused_parameter.cash | 5 + .../reference_unused_variable.cash | 6 + .../unused_global_function_local.cash | 2 +- packages/cashc/test/generation/fixtures.ts | 59 ++ .../cashc/test/global-definitions.test.ts | 6 +- .../valid-contract-files/unused_modifier.cash | 11 + .../test/fixtures/bitauth-script.fixture.ts | 10 +- website/docs/compiler/grammar.md | 3 +- website/docs/language/contracts.md | 17 +- 28 files changed, 1083 insertions(+), 848 deletions(-) create mode 100644 packages/cashc/test/compiler/InvalidModifierError/constant_on_contract_parameter.cash create mode 100644 packages/cashc/test/compiler/InvalidModifierError/constant_on_function_parameter.cash create mode 100644 packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier.cash create mode 100644 packages/cashc/test/compiler/InvalidModifierError/reference_unused_parameter.cash create mode 100644 packages/cashc/test/compiler/InvalidModifierError/reference_unused_variable.cash create mode 100644 packages/cashc/test/valid-contract-files/unused_modifier.cash diff --git a/.cspell.json b/.cspell.json index a4226af31..d21a5f456 100644 --- a/.cspell.json +++ b/.cspell.json @@ -138,6 +138,7 @@ "op", "opcode", "opcodes", + "opcost", "opcount", "OUTPOINTINDEX", "OUTPOINTTXHASH", diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index 04bf08080..adac9f44a 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -275,6 +275,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 4b222d15b..60d1dee6f 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -1,5 +1,5 @@ import { Type, PrimitiveType, BytesType } from '@cashscript/utils'; -import { TimeOp } from './Globals.js'; +import { Modifier, TimeOp } from './Globals.js'; import AstVisitor from './AstVisitor.js'; import { BinaryOperator, NullaryOperator, UnaryOperator } from './Operator.js'; import { Location } from './Location.js'; @@ -50,6 +50,8 @@ export class ConstantDefinitionNode extends Node implements Named, Typed { sourceCode?: string; sourceFile?: string; + modifiers = [Modifier.CONSTANT]; + constructor( public type: Type, public name: string, @@ -120,7 +122,7 @@ export class FunctionDefinitionNode extends Node implements Named { export class ParameterNode extends Node implements Named, Typed { constructor( public type: Type, - public modifiers: string[], + public modifiers: Modifier[], public name: string, ) { super(); @@ -140,7 +142,7 @@ export abstract class NonControlStatementNode extends StatementNode { } export class VariableDefinitionNode extends NonControlStatementNode implements Named, Typed { constructor( public type: Type, - public modifiers: string[], + public modifiers: Modifier[], public name: string, public expression: ExpressionNode, ) { diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index 07a7e99dc..c76662554 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -92,6 +92,7 @@ import type { import CashScriptVisitor from '../grammar/CashScriptVisitor.js'; import { Location } from './Location.js'; import { + Modifier, NumberUnit, TimeOp, } from './Globals.js'; @@ -209,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() as Modifier); const name = ctx.Identifier().getText(); - const parameter = new ParameterNode(type, [], name); + const parameter = new ParameterNode(type, modifiers, name); parameter.location = Location.fromCtx(ctx); return parameter; } @@ -237,7 +239,7 @@ export default class AstBuilder visitVariableDefinition(ctx: VariableDefinitionContext): VariableDefinitionNode { const type = parseType(ctx.typeName().getText()); - const modifiers = ctx.modifier_list().map((modifier) => modifier.getText()); + const modifiers = ctx.modifier_list().map((modifier) => modifier.getText() as Modifier); const name = ctx.Identifier().getText(); const expression = this.visit(ctx.expression()); const variableDefinition = new VariableDefinitionNode(type, modifiers, name, expression); diff --git a/packages/cashc/src/ast/Globals.ts b/packages/cashc/src/ast/Globals.ts index 878475c69..70c7b4290 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 38baee7f5..136169b41 100644 --- a/packages/cashc/src/ast/SymbolTable.ts +++ b/packages/cashc/src/ast/SymbolTable.ts @@ -7,6 +7,7 @@ import { IdentifierNode, DefinitionNode, } from './AST.js'; +import { Modifier } from './Globals.js'; import { functionReturnType } from '../utils.js'; export class Symbol { @@ -23,6 +24,12 @@ export class Symbol { public functionId?: number, ) { } + hasModifier(modifier: Modifier): boolean { + return this.definition !== undefined + && !(this.definition instanceof FunctionDefinitionNode) + && this.definition.modifiers.includes(modifier); + } + static variable(node: VariableDefinitionNode | ParameterNode): Symbol { return new Symbol(node.name, node.type, SymbolType.VARIABLE, node); } @@ -99,6 +106,7 @@ export class SymbolTable { unusedSymbols(): Symbol[] { return Array.from(this.symbols) .map((e) => e[1]) + .filter((s) => !s.hasModifier(Modifier.UNUSED)) .filter((s) => s.references.length === 0); } } diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index f283c0caa..076c9650a 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -63,7 +63,7 @@ import { ForNode, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; -import { GlobalFunction, Class } from '../ast/Globals.js'; +import { GlobalFunction, Class, Modifier } from '../ast/Globals.js'; import { BinaryOperator } from '../ast/Operator.js'; import { compileBinaryOp, @@ -252,6 +252,7 @@ export default class GenerateTargetTraversal extends AstTraversal { for (let i = node.parameters.length - 1; i >= 0; i -= 1) { bodyTraversal.visit(node.parameters[i]); } + bodyTraversal.dropUnusedParameters(node.parameters); bodyTraversal.visit(node.body); bodyTraversal.cleanGlobalFunctionStack(node); @@ -301,6 +302,7 @@ export default class GenerateTargetTraversal extends AstTraversal { // Keep track of constructor parameter count for instructor pointer calculation this.constructorParameterCount = node.parameters.length; + this.dropUnusedParameters(node.parameters); if (node.functions.length === 1) { node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; @@ -356,6 +358,7 @@ export default class GenerateTargetTraversal extends AstTraversal { this.currentFunction = node; node.parameters = this.visitList(node.parameters) as ParameterNode[]; + this.dropUnusedParameters(node.parameters); if (this.compilerOptions.enforceFunctionParameterTypes) { this.enforceFunctionParameterTypes(node); @@ -423,6 +426,21 @@ export default class GenerateTargetTraversal extends AstTraversal { this.tagScopeCleanup(tagStartIndex); } + private dropUnusedParameters(parameters: ParameterNode[]): void { + parameters + .filter((parameter) => parameter.modifiers.includes(Modifier.UNUSED)) + .sort((a, b) => this.getStackIndex(a.name) - this.getStackIndex(b.name)) + .forEach((parameter) => { + const stackIndex = this.getStackIndex(parameter.name); + const locationData = { location: parameter.location, positionHint: PositionHint.START }; + + this.emit(encodeInt(BigInt(stackIndex)), locationData); + this.emit(Op.OP_ROLL, locationData); + this.emit(Op.OP_DROP, locationData); + this.removeFromStack(stackIndex); + }); + } + enforceFunctionParameterTypes(node: FunctionDefinitionNode): void { node.parameters.forEach((parameter) => this.enforceFunctionParameterType(parameter)); } @@ -463,6 +481,7 @@ export default class GenerateTargetTraversal extends AstTraversal { } shouldEnforceFunctionParameterType(node: ParameterNode): boolean { + if (node.modifiers.includes(Modifier.UNUSED)) return false; if (node.type === PrimitiveType.BOOL) return true; if (node.type instanceof BytesType && node.type.bound !== undefined) return true; return false; @@ -475,6 +494,13 @@ export default class GenerateTargetTraversal extends AstTraversal { visitVariableDefinition(node: VariableDefinitionNode): Node { node.expression = this.visit(node.expression); + + if (node.modifiers.includes(Modifier.UNUSED)) { + this.emit(Op.OP_DROP, { location: node.location, positionHint: PositionHint.END }); + this.popFromStack(); + return node; + } + this.popFromStack(); this.pushToStack(node.name); return node; diff --git a/packages/cashc/src/grammar/CashScript.g4 b/packages/cashc/src/grammar/CashScript.g4 index d3733ca9f..0cd133eee 100644 --- a/packages/cashc/src/grammar/CashScript.g4 +++ b/packages/cashc/src/grammar/CashScript.g4 @@ -59,7 +59,7 @@ parameterList ; parameter - : typeName Identifier + : typeName modifier* Identifier ; block @@ -199,6 +199,7 @@ expression modifier : 'constant' + | 'unused' ; literal diff --git a/packages/cashc/src/grammar/CashScript.interp b/packages/cashc/src/grammar/CashScript.interp index ddd920389..35c314a34 100644 --- a/packages/cashc/src/grammar/CashScript.interp +++ b/packages/cashc/src/grammar/CashScript.interp @@ -64,6 +64,7 @@ null '|' '&&' '||' +'unused' null null null @@ -151,6 +152,7 @@ null null null null +null VersionLiteral BooleanLiteral NumberUnit @@ -220,4 +222,4 @@ typeCast atn: -[4, 1, 84, 509, 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, 1, 0, 5, 0, 90, 8, 0, 10, 0, 12, 0, 93, 9, 0, 1, 0, 5, 0, 96, 8, 0, 10, 0, 12, 0, 99, 9, 0, 1, 0, 5, 0, 102, 8, 0, 10, 0, 12, 0, 105, 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, 118, 8, 3, 1, 4, 3, 4, 121, 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, 134, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 144, 8, 8, 10, 8, 12, 8, 147, 9, 8, 1, 8, 1, 8, 3, 8, 151, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 167, 8, 10, 10, 10, 12, 10, 170, 9, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 5, 12, 181, 8, 12, 10, 12, 12, 12, 184, 9, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 192, 8, 13, 10, 13, 12, 13, 195, 9, 13, 1, 13, 3, 13, 198, 8, 13, 3, 13, 200, 8, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 209, 8, 15, 10, 15, 12, 15, 212, 9, 15, 1, 15, 1, 15, 3, 15, 216, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 222, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 232, 8, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 240, 8, 19, 10, 19, 12, 19, 243, 9, 19, 1, 20, 1, 20, 3, 20, 247, 8, 20, 1, 21, 1, 21, 5, 21, 251, 8, 21, 10, 21, 12, 21, 254, 9, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 4, 22, 266, 8, 22, 11, 22, 12, 22, 267, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 278, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 287, 8, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 296, 8, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 310, 8, 27, 1, 28, 1, 28, 1, 28, 3, 28, 315, 8, 28, 1, 29, 1, 29, 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, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 343, 8, 32, 1, 33, 1, 33, 1, 34, 1, 34, 3, 34, 349, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 355, 8, 35, 10, 35, 12, 35, 358, 9, 35, 1, 35, 3, 35, 361, 8, 35, 3, 35, 363, 8, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 374, 8, 37, 10, 37, 12, 37, 377, 9, 37, 1, 37, 3, 37, 380, 8, 37, 3, 37, 382, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 395, 8, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 421, 8, 38, 10, 38, 12, 38, 424, 9, 38, 1, 38, 3, 38, 427, 8, 38, 3, 38, 429, 8, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 435, 8, 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, 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, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 487, 8, 38, 10, 38, 12, 38, 490, 9, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 499, 8, 40, 1, 41, 1, 41, 3, 41, 503, 8, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 0, 1, 76, 44, 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, 0, 14, 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, 1, 0, 71, 73, 2, 0, 71, 72, 79, 79, 539, 0, 91, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 4, 113, 1, 0, 0, 0, 6, 115, 1, 0, 0, 0, 8, 120, 1, 0, 0, 0, 10, 124, 1, 0, 0, 0, 12, 126, 1, 0, 0, 0, 14, 133, 1, 0, 0, 0, 16, 135, 1, 0, 0, 0, 18, 154, 1, 0, 0, 0, 20, 161, 1, 0, 0, 0, 22, 173, 1, 0, 0, 0, 24, 178, 1, 0, 0, 0, 26, 187, 1, 0, 0, 0, 28, 203, 1, 0, 0, 0, 30, 215, 1, 0, 0, 0, 32, 221, 1, 0, 0, 0, 34, 231, 1, 0, 0, 0, 36, 233, 1, 0, 0, 0, 38, 235, 1, 0, 0, 0, 40, 246, 1, 0, 0, 0, 42, 248, 1, 0, 0, 0, 44, 259, 1, 0, 0, 0, 46, 277, 1, 0, 0, 0, 48, 279, 1, 0, 0, 0, 50, 290, 1, 0, 0, 0, 52, 299, 1, 0, 0, 0, 54, 302, 1, 0, 0, 0, 56, 314, 1, 0, 0, 0, 58, 316, 1, 0, 0, 0, 60, 324, 1, 0, 0, 0, 62, 330, 1, 0, 0, 0, 64, 342, 1, 0, 0, 0, 66, 344, 1, 0, 0, 0, 68, 348, 1, 0, 0, 0, 70, 350, 1, 0, 0, 0, 72, 366, 1, 0, 0, 0, 74, 369, 1, 0, 0, 0, 76, 434, 1, 0, 0, 0, 78, 491, 1, 0, 0, 0, 80, 498, 1, 0, 0, 0, 82, 500, 1, 0, 0, 0, 84, 504, 1, 0, 0, 0, 86, 506, 1, 0, 0, 0, 88, 90, 3, 2, 1, 0, 89, 88, 1, 0, 0, 0, 90, 93, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 97, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 94, 96, 3, 12, 6, 0, 95, 94, 1, 0, 0, 0, 96, 99, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 103, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 100, 102, 3, 14, 7, 0, 101, 100, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 107, 5, 0, 0, 1, 107, 1, 1, 0, 0, 0, 108, 109, 5, 1, 0, 0, 109, 110, 3, 4, 2, 0, 110, 111, 3, 6, 3, 0, 111, 112, 5, 2, 0, 0, 112, 3, 1, 0, 0, 0, 113, 114, 5, 3, 0, 0, 114, 5, 1, 0, 0, 0, 115, 117, 3, 8, 4, 0, 116, 118, 3, 8, 4, 0, 117, 116, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 7, 1, 0, 0, 0, 119, 121, 3, 10, 5, 0, 120, 119, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 123, 5, 65, 0, 0, 123, 9, 1, 0, 0, 0, 124, 125, 7, 0, 0, 0, 125, 11, 1, 0, 0, 0, 126, 127, 5, 11, 0, 0, 127, 128, 5, 75, 0, 0, 128, 129, 5, 2, 0, 0, 129, 13, 1, 0, 0, 0, 130, 134, 3, 16, 8, 0, 131, 134, 3, 18, 9, 0, 132, 134, 3, 20, 10, 0, 133, 130, 1, 0, 0, 0, 133, 131, 1, 0, 0, 0, 133, 132, 1, 0, 0, 0, 134, 15, 1, 0, 0, 0, 135, 136, 5, 12, 0, 0, 136, 137, 5, 81, 0, 0, 137, 150, 3, 26, 13, 0, 138, 139, 5, 13, 0, 0, 139, 140, 5, 14, 0, 0, 140, 145, 3, 84, 42, 0, 141, 142, 5, 15, 0, 0, 142, 144, 3, 84, 42, 0, 143, 141, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 148, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 149, 5, 16, 0, 0, 149, 151, 1, 0, 0, 0, 150, 138, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 153, 3, 24, 12, 0, 153, 17, 1, 0, 0, 0, 154, 155, 3, 84, 42, 0, 155, 156, 5, 17, 0, 0, 156, 157, 5, 81, 0, 0, 157, 158, 5, 10, 0, 0, 158, 159, 3, 80, 40, 0, 159, 160, 5, 2, 0, 0, 160, 19, 1, 0, 0, 0, 161, 162, 5, 18, 0, 0, 162, 163, 5, 81, 0, 0, 163, 164, 3, 26, 13, 0, 164, 168, 5, 19, 0, 0, 165, 167, 3, 22, 11, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 172, 5, 20, 0, 0, 172, 21, 1, 0, 0, 0, 173, 174, 5, 12, 0, 0, 174, 175, 5, 81, 0, 0, 175, 176, 3, 26, 13, 0, 176, 177, 3, 24, 12, 0, 177, 23, 1, 0, 0, 0, 178, 182, 5, 19, 0, 0, 179, 181, 3, 32, 16, 0, 180, 179, 1, 0, 0, 0, 181, 184, 1, 0, 0, 0, 182, 180, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 185, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 186, 5, 20, 0, 0, 186, 25, 1, 0, 0, 0, 187, 199, 5, 14, 0, 0, 188, 193, 3, 28, 14, 0, 189, 190, 5, 15, 0, 0, 190, 192, 3, 28, 14, 0, 191, 189, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 198, 5, 15, 0, 0, 197, 196, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 200, 1, 0, 0, 0, 199, 188, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, 202, 5, 16, 0, 0, 202, 27, 1, 0, 0, 0, 203, 204, 3, 84, 42, 0, 204, 205, 5, 81, 0, 0, 205, 29, 1, 0, 0, 0, 206, 210, 5, 19, 0, 0, 207, 209, 3, 32, 16, 0, 208, 207, 1, 0, 0, 0, 209, 212, 1, 0, 0, 0, 210, 208, 1, 0, 0, 0, 210, 211, 1, 0, 0, 0, 211, 213, 1, 0, 0, 0, 212, 210, 1, 0, 0, 0, 213, 216, 5, 20, 0, 0, 214, 216, 3, 32, 16, 0, 215, 206, 1, 0, 0, 0, 215, 214, 1, 0, 0, 0, 216, 31, 1, 0, 0, 0, 217, 222, 3, 40, 20, 0, 218, 219, 3, 34, 17, 0, 219, 220, 5, 2, 0, 0, 220, 222, 1, 0, 0, 0, 221, 217, 1, 0, 0, 0, 221, 218, 1, 0, 0, 0, 222, 33, 1, 0, 0, 0, 223, 232, 3, 42, 21, 0, 224, 232, 3, 44, 22, 0, 225, 232, 3, 46, 23, 0, 226, 232, 3, 48, 24, 0, 227, 232, 3, 50, 25, 0, 228, 232, 3, 36, 18, 0, 229, 232, 3, 52, 26, 0, 230, 232, 3, 38, 19, 0, 231, 223, 1, 0, 0, 0, 231, 224, 1, 0, 0, 0, 231, 225, 1, 0, 0, 0, 231, 226, 1, 0, 0, 0, 231, 227, 1, 0, 0, 0, 231, 228, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 230, 1, 0, 0, 0, 232, 35, 1, 0, 0, 0, 233, 234, 3, 72, 36, 0, 234, 37, 1, 0, 0, 0, 235, 236, 5, 21, 0, 0, 236, 241, 3, 76, 38, 0, 237, 238, 5, 15, 0, 0, 238, 240, 3, 76, 38, 0, 239, 237, 1, 0, 0, 0, 240, 243, 1, 0, 0, 0, 241, 239, 1, 0, 0, 0, 241, 242, 1, 0, 0, 0, 242, 39, 1, 0, 0, 0, 243, 241, 1, 0, 0, 0, 244, 247, 3, 54, 27, 0, 245, 247, 3, 56, 28, 0, 246, 244, 1, 0, 0, 0, 246, 245, 1, 0, 0, 0, 247, 41, 1, 0, 0, 0, 248, 252, 3, 84, 42, 0, 249, 251, 3, 78, 39, 0, 250, 249, 1, 0, 0, 0, 251, 254, 1, 0, 0, 0, 252, 250, 1, 0, 0, 0, 252, 253, 1, 0, 0, 0, 253, 255, 1, 0, 0, 0, 254, 252, 1, 0, 0, 0, 255, 256, 5, 81, 0, 0, 256, 257, 5, 10, 0, 0, 257, 258, 3, 76, 38, 0, 258, 43, 1, 0, 0, 0, 259, 260, 3, 84, 42, 0, 260, 265, 5, 81, 0, 0, 261, 262, 5, 15, 0, 0, 262, 263, 3, 84, 42, 0, 263, 264, 5, 81, 0, 0, 264, 266, 1, 0, 0, 0, 265, 261, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 267, 265, 1, 0, 0, 0, 267, 268, 1, 0, 0, 0, 268, 269, 1, 0, 0, 0, 269, 270, 5, 10, 0, 0, 270, 271, 3, 76, 38, 0, 271, 45, 1, 0, 0, 0, 272, 273, 5, 81, 0, 0, 273, 274, 7, 1, 0, 0, 274, 278, 3, 76, 38, 0, 275, 276, 5, 81, 0, 0, 276, 278, 7, 2, 0, 0, 277, 272, 1, 0, 0, 0, 277, 275, 1, 0, 0, 0, 278, 47, 1, 0, 0, 0, 279, 280, 5, 26, 0, 0, 280, 281, 5, 14, 0, 0, 281, 282, 5, 78, 0, 0, 282, 283, 5, 6, 0, 0, 283, 286, 3, 76, 38, 0, 284, 285, 5, 15, 0, 0, 285, 287, 3, 66, 33, 0, 286, 284, 1, 0, 0, 0, 286, 287, 1, 0, 0, 0, 287, 288, 1, 0, 0, 0, 288, 289, 5, 16, 0, 0, 289, 49, 1, 0, 0, 0, 290, 291, 5, 26, 0, 0, 291, 292, 5, 14, 0, 0, 292, 295, 3, 76, 38, 0, 293, 294, 5, 15, 0, 0, 294, 296, 3, 66, 33, 0, 295, 293, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 297, 1, 0, 0, 0, 297, 298, 5, 16, 0, 0, 298, 51, 1, 0, 0, 0, 299, 300, 5, 27, 0, 0, 300, 301, 3, 70, 35, 0, 301, 53, 1, 0, 0, 0, 302, 303, 5, 28, 0, 0, 303, 304, 5, 14, 0, 0, 304, 305, 3, 76, 38, 0, 305, 306, 5, 16, 0, 0, 306, 309, 3, 30, 15, 0, 307, 308, 5, 29, 0, 0, 308, 310, 3, 30, 15, 0, 309, 307, 1, 0, 0, 0, 309, 310, 1, 0, 0, 0, 310, 55, 1, 0, 0, 0, 311, 315, 3, 58, 29, 0, 312, 315, 3, 60, 30, 0, 313, 315, 3, 62, 31, 0, 314, 311, 1, 0, 0, 0, 314, 312, 1, 0, 0, 0, 314, 313, 1, 0, 0, 0, 315, 57, 1, 0, 0, 0, 316, 317, 5, 30, 0, 0, 317, 318, 3, 30, 15, 0, 318, 319, 5, 31, 0, 0, 319, 320, 5, 14, 0, 0, 320, 321, 3, 76, 38, 0, 321, 322, 5, 16, 0, 0, 322, 323, 5, 2, 0, 0, 323, 59, 1, 0, 0, 0, 324, 325, 5, 31, 0, 0, 325, 326, 5, 14, 0, 0, 326, 327, 3, 76, 38, 0, 327, 328, 5, 16, 0, 0, 328, 329, 3, 30, 15, 0, 329, 61, 1, 0, 0, 0, 330, 331, 5, 32, 0, 0, 331, 332, 5, 14, 0, 0, 332, 333, 3, 64, 32, 0, 333, 334, 5, 2, 0, 0, 334, 335, 3, 76, 38, 0, 335, 336, 5, 2, 0, 0, 336, 337, 3, 46, 23, 0, 337, 338, 5, 16, 0, 0, 338, 339, 3, 30, 15, 0, 339, 63, 1, 0, 0, 0, 340, 343, 3, 42, 21, 0, 341, 343, 3, 46, 23, 0, 342, 340, 1, 0, 0, 0, 342, 341, 1, 0, 0, 0, 343, 65, 1, 0, 0, 0, 344, 345, 5, 75, 0, 0, 345, 67, 1, 0, 0, 0, 346, 349, 5, 81, 0, 0, 347, 349, 3, 80, 40, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0, 0, 349, 69, 1, 0, 0, 0, 350, 362, 5, 14, 0, 0, 351, 356, 3, 68, 34, 0, 352, 353, 5, 15, 0, 0, 353, 355, 3, 68, 34, 0, 354, 352, 1, 0, 0, 0, 355, 358, 1, 0, 0, 0, 356, 354, 1, 0, 0, 0, 356, 357, 1, 0, 0, 0, 357, 360, 1, 0, 0, 0, 358, 356, 1, 0, 0, 0, 359, 361, 5, 15, 0, 0, 360, 359, 1, 0, 0, 0, 360, 361, 1, 0, 0, 0, 361, 363, 1, 0, 0, 0, 362, 351, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 364, 1, 0, 0, 0, 364, 365, 5, 16, 0, 0, 365, 71, 1, 0, 0, 0, 366, 367, 5, 81, 0, 0, 367, 368, 3, 74, 37, 0, 368, 73, 1, 0, 0, 0, 369, 381, 5, 14, 0, 0, 370, 375, 3, 76, 38, 0, 371, 372, 5, 15, 0, 0, 372, 374, 3, 76, 38, 0, 373, 371, 1, 0, 0, 0, 374, 377, 1, 0, 0, 0, 375, 373, 1, 0, 0, 0, 375, 376, 1, 0, 0, 0, 376, 379, 1, 0, 0, 0, 377, 375, 1, 0, 0, 0, 378, 380, 5, 15, 0, 0, 379, 378, 1, 0, 0, 0, 379, 380, 1, 0, 0, 0, 380, 382, 1, 0, 0, 0, 381, 370, 1, 0, 0, 0, 381, 382, 1, 0, 0, 0, 382, 383, 1, 0, 0, 0, 383, 384, 5, 16, 0, 0, 384, 75, 1, 0, 0, 0, 385, 386, 6, 38, -1, 0, 386, 387, 5, 14, 0, 0, 387, 388, 3, 76, 38, 0, 388, 389, 5, 16, 0, 0, 389, 435, 1, 0, 0, 0, 390, 391, 3, 86, 43, 0, 391, 392, 5, 14, 0, 0, 392, 394, 3, 76, 38, 0, 393, 395, 5, 15, 0, 0, 394, 393, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 396, 1, 0, 0, 0, 396, 397, 5, 16, 0, 0, 397, 435, 1, 0, 0, 0, 398, 435, 3, 72, 36, 0, 399, 400, 5, 33, 0, 0, 400, 401, 5, 81, 0, 0, 401, 435, 3, 74, 37, 0, 402, 403, 5, 36, 0, 0, 403, 404, 5, 34, 0, 0, 404, 405, 3, 76, 38, 0, 405, 406, 5, 35, 0, 0, 406, 407, 7, 3, 0, 0, 407, 435, 1, 0, 0, 0, 408, 409, 5, 42, 0, 0, 409, 410, 5, 34, 0, 0, 410, 411, 3, 76, 38, 0, 411, 412, 5, 35, 0, 0, 412, 413, 7, 4, 0, 0, 413, 435, 1, 0, 0, 0, 414, 415, 7, 5, 0, 0, 415, 435, 3, 76, 38, 15, 416, 428, 5, 34, 0, 0, 417, 422, 3, 76, 38, 0, 418, 419, 5, 15, 0, 0, 419, 421, 3, 76, 38, 0, 420, 418, 1, 0, 0, 0, 421, 424, 1, 0, 0, 0, 422, 420, 1, 0, 0, 0, 422, 423, 1, 0, 0, 0, 423, 426, 1, 0, 0, 0, 424, 422, 1, 0, 0, 0, 425, 427, 5, 15, 0, 0, 426, 425, 1, 0, 0, 0, 426, 427, 1, 0, 0, 0, 427, 429, 1, 0, 0, 0, 428, 417, 1, 0, 0, 0, 428, 429, 1, 0, 0, 0, 429, 430, 1, 0, 0, 0, 430, 435, 5, 35, 0, 0, 431, 435, 5, 80, 0, 0, 432, 435, 5, 81, 0, 0, 433, 435, 3, 80, 40, 0, 434, 385, 1, 0, 0, 0, 434, 390, 1, 0, 0, 0, 434, 398, 1, 0, 0, 0, 434, 399, 1, 0, 0, 0, 434, 402, 1, 0, 0, 0, 434, 408, 1, 0, 0, 0, 434, 414, 1, 0, 0, 0, 434, 416, 1, 0, 0, 0, 434, 431, 1, 0, 0, 0, 434, 432, 1, 0, 0, 0, 434, 433, 1, 0, 0, 0, 435, 488, 1, 0, 0, 0, 436, 437, 10, 14, 0, 0, 437, 438, 7, 6, 0, 0, 438, 487, 3, 76, 38, 15, 439, 440, 10, 13, 0, 0, 440, 441, 7, 7, 0, 0, 441, 487, 3, 76, 38, 14, 442, 443, 10, 12, 0, 0, 443, 444, 7, 8, 0, 0, 444, 487, 3, 76, 38, 13, 445, 446, 10, 11, 0, 0, 446, 447, 7, 9, 0, 0, 447, 487, 3, 76, 38, 12, 448, 449, 10, 10, 0, 0, 449, 450, 7, 10, 0, 0, 450, 487, 3, 76, 38, 11, 451, 452, 10, 9, 0, 0, 452, 453, 5, 61, 0, 0, 453, 487, 3, 76, 38, 10, 454, 455, 10, 8, 0, 0, 455, 456, 5, 4, 0, 0, 456, 487, 3, 76, 38, 9, 457, 458, 10, 7, 0, 0, 458, 459, 5, 62, 0, 0, 459, 487, 3, 76, 38, 8, 460, 461, 10, 6, 0, 0, 461, 462, 5, 63, 0, 0, 462, 487, 3, 76, 38, 7, 463, 464, 10, 5, 0, 0, 464, 465, 5, 64, 0, 0, 465, 487, 3, 76, 38, 6, 466, 467, 10, 21, 0, 0, 467, 468, 5, 34, 0, 0, 468, 469, 5, 68, 0, 0, 469, 487, 5, 35, 0, 0, 470, 471, 10, 18, 0, 0, 471, 487, 7, 11, 0, 0, 472, 473, 10, 17, 0, 0, 473, 474, 5, 49, 0, 0, 474, 475, 5, 14, 0, 0, 475, 476, 3, 76, 38, 0, 476, 477, 5, 16, 0, 0, 477, 487, 1, 0, 0, 0, 478, 479, 10, 16, 0, 0, 479, 480, 5, 50, 0, 0, 480, 481, 5, 14, 0, 0, 481, 482, 3, 76, 38, 0, 482, 483, 5, 15, 0, 0, 483, 484, 3, 76, 38, 0, 484, 485, 5, 16, 0, 0, 485, 487, 1, 0, 0, 0, 486, 436, 1, 0, 0, 0, 486, 439, 1, 0, 0, 0, 486, 442, 1, 0, 0, 0, 486, 445, 1, 0, 0, 0, 486, 448, 1, 0, 0, 0, 486, 451, 1, 0, 0, 0, 486, 454, 1, 0, 0, 0, 486, 457, 1, 0, 0, 0, 486, 460, 1, 0, 0, 0, 486, 463, 1, 0, 0, 0, 486, 466, 1, 0, 0, 0, 486, 470, 1, 0, 0, 0, 486, 472, 1, 0, 0, 0, 486, 478, 1, 0, 0, 0, 487, 490, 1, 0, 0, 0, 488, 486, 1, 0, 0, 0, 488, 489, 1, 0, 0, 0, 489, 77, 1, 0, 0, 0, 490, 488, 1, 0, 0, 0, 491, 492, 5, 17, 0, 0, 492, 79, 1, 0, 0, 0, 493, 499, 5, 66, 0, 0, 494, 499, 3, 82, 41, 0, 495, 499, 5, 75, 0, 0, 496, 499, 5, 76, 0, 0, 497, 499, 5, 77, 0, 0, 498, 493, 1, 0, 0, 0, 498, 494, 1, 0, 0, 0, 498, 495, 1, 0, 0, 0, 498, 496, 1, 0, 0, 0, 498, 497, 1, 0, 0, 0, 499, 81, 1, 0, 0, 0, 500, 502, 5, 68, 0, 0, 501, 503, 5, 67, 0, 0, 502, 501, 1, 0, 0, 0, 502, 503, 1, 0, 0, 0, 503, 83, 1, 0, 0, 0, 504, 505, 7, 12, 0, 0, 505, 85, 1, 0, 0, 0, 506, 507, 7, 13, 0, 0, 507, 87, 1, 0, 0, 0, 43, 91, 97, 103, 117, 120, 133, 145, 150, 168, 182, 193, 197, 199, 210, 215, 221, 231, 241, 246, 252, 267, 277, 286, 295, 309, 314, 342, 348, 356, 360, 362, 375, 379, 381, 394, 422, 426, 428, 434, 486, 488, 498, 502] \ No newline at end of file +[4, 1, 85, 515, 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, 1, 0, 5, 0, 90, 8, 0, 10, 0, 12, 0, 93, 9, 0, 1, 0, 5, 0, 96, 8, 0, 10, 0, 12, 0, 99, 9, 0, 1, 0, 5, 0, 102, 8, 0, 10, 0, 12, 0, 105, 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, 118, 8, 3, 1, 4, 3, 4, 121, 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, 134, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 144, 8, 8, 10, 8, 12, 8, 147, 9, 8, 1, 8, 1, 8, 3, 8, 151, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 167, 8, 10, 10, 10, 12, 10, 170, 9, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 5, 12, 181, 8, 12, 10, 12, 12, 12, 184, 9, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 192, 8, 13, 10, 13, 12, 13, 195, 9, 13, 1, 13, 3, 13, 198, 8, 13, 3, 13, 200, 8, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 206, 8, 14, 10, 14, 12, 14, 209, 9, 14, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 215, 8, 15, 10, 15, 12, 15, 218, 9, 15, 1, 15, 1, 15, 3, 15, 222, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 228, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 238, 8, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 246, 8, 19, 10, 19, 12, 19, 249, 9, 19, 1, 20, 1, 20, 3, 20, 253, 8, 20, 1, 21, 1, 21, 5, 21, 257, 8, 21, 10, 21, 12, 21, 260, 9, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 4, 22, 272, 8, 22, 11, 22, 12, 22, 273, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 284, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 293, 8, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 302, 8, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 316, 8, 27, 1, 28, 1, 28, 1, 28, 3, 28, 321, 8, 28, 1, 29, 1, 29, 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, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 349, 8, 32, 1, 33, 1, 33, 1, 34, 1, 34, 3, 34, 355, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 361, 8, 35, 10, 35, 12, 35, 364, 9, 35, 1, 35, 3, 35, 367, 8, 35, 3, 35, 369, 8, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 380, 8, 37, 10, 37, 12, 37, 383, 9, 37, 1, 37, 3, 37, 386, 8, 37, 3, 37, 388, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 401, 8, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 427, 8, 38, 10, 38, 12, 38, 430, 9, 38, 1, 38, 3, 38, 433, 8, 38, 3, 38, 435, 8, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 441, 8, 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, 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, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 493, 8, 38, 10, 38, 12, 38, 496, 9, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 505, 8, 40, 1, 41, 1, 41, 3, 41, 509, 8, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 0, 1, 76, 44, 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, 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, 17, 17, 65, 65, 1, 0, 72, 74, 2, 0, 72, 73, 80, 80, 546, 0, 91, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 4, 113, 1, 0, 0, 0, 6, 115, 1, 0, 0, 0, 8, 120, 1, 0, 0, 0, 10, 124, 1, 0, 0, 0, 12, 126, 1, 0, 0, 0, 14, 133, 1, 0, 0, 0, 16, 135, 1, 0, 0, 0, 18, 154, 1, 0, 0, 0, 20, 161, 1, 0, 0, 0, 22, 173, 1, 0, 0, 0, 24, 178, 1, 0, 0, 0, 26, 187, 1, 0, 0, 0, 28, 203, 1, 0, 0, 0, 30, 221, 1, 0, 0, 0, 32, 227, 1, 0, 0, 0, 34, 237, 1, 0, 0, 0, 36, 239, 1, 0, 0, 0, 38, 241, 1, 0, 0, 0, 40, 252, 1, 0, 0, 0, 42, 254, 1, 0, 0, 0, 44, 265, 1, 0, 0, 0, 46, 283, 1, 0, 0, 0, 48, 285, 1, 0, 0, 0, 50, 296, 1, 0, 0, 0, 52, 305, 1, 0, 0, 0, 54, 308, 1, 0, 0, 0, 56, 320, 1, 0, 0, 0, 58, 322, 1, 0, 0, 0, 60, 330, 1, 0, 0, 0, 62, 336, 1, 0, 0, 0, 64, 348, 1, 0, 0, 0, 66, 350, 1, 0, 0, 0, 68, 354, 1, 0, 0, 0, 70, 356, 1, 0, 0, 0, 72, 372, 1, 0, 0, 0, 74, 375, 1, 0, 0, 0, 76, 440, 1, 0, 0, 0, 78, 497, 1, 0, 0, 0, 80, 504, 1, 0, 0, 0, 82, 506, 1, 0, 0, 0, 84, 510, 1, 0, 0, 0, 86, 512, 1, 0, 0, 0, 88, 90, 3, 2, 1, 0, 89, 88, 1, 0, 0, 0, 90, 93, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 97, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 94, 96, 3, 12, 6, 0, 95, 94, 1, 0, 0, 0, 96, 99, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 103, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 100, 102, 3, 14, 7, 0, 101, 100, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 107, 5, 0, 0, 1, 107, 1, 1, 0, 0, 0, 108, 109, 5, 1, 0, 0, 109, 110, 3, 4, 2, 0, 110, 111, 3, 6, 3, 0, 111, 112, 5, 2, 0, 0, 112, 3, 1, 0, 0, 0, 113, 114, 5, 3, 0, 0, 114, 5, 1, 0, 0, 0, 115, 117, 3, 8, 4, 0, 116, 118, 3, 8, 4, 0, 117, 116, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 7, 1, 0, 0, 0, 119, 121, 3, 10, 5, 0, 120, 119, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 123, 5, 66, 0, 0, 123, 9, 1, 0, 0, 0, 124, 125, 7, 0, 0, 0, 125, 11, 1, 0, 0, 0, 126, 127, 5, 11, 0, 0, 127, 128, 5, 76, 0, 0, 128, 129, 5, 2, 0, 0, 129, 13, 1, 0, 0, 0, 130, 134, 3, 16, 8, 0, 131, 134, 3, 18, 9, 0, 132, 134, 3, 20, 10, 0, 133, 130, 1, 0, 0, 0, 133, 131, 1, 0, 0, 0, 133, 132, 1, 0, 0, 0, 134, 15, 1, 0, 0, 0, 135, 136, 5, 12, 0, 0, 136, 137, 5, 82, 0, 0, 137, 150, 3, 26, 13, 0, 138, 139, 5, 13, 0, 0, 139, 140, 5, 14, 0, 0, 140, 145, 3, 84, 42, 0, 141, 142, 5, 15, 0, 0, 142, 144, 3, 84, 42, 0, 143, 141, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 148, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 149, 5, 16, 0, 0, 149, 151, 1, 0, 0, 0, 150, 138, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 153, 3, 24, 12, 0, 153, 17, 1, 0, 0, 0, 154, 155, 3, 84, 42, 0, 155, 156, 5, 17, 0, 0, 156, 157, 5, 82, 0, 0, 157, 158, 5, 10, 0, 0, 158, 159, 3, 80, 40, 0, 159, 160, 5, 2, 0, 0, 160, 19, 1, 0, 0, 0, 161, 162, 5, 18, 0, 0, 162, 163, 5, 82, 0, 0, 163, 164, 3, 26, 13, 0, 164, 168, 5, 19, 0, 0, 165, 167, 3, 22, 11, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 172, 5, 20, 0, 0, 172, 21, 1, 0, 0, 0, 173, 174, 5, 12, 0, 0, 174, 175, 5, 82, 0, 0, 175, 176, 3, 26, 13, 0, 176, 177, 3, 24, 12, 0, 177, 23, 1, 0, 0, 0, 178, 182, 5, 19, 0, 0, 179, 181, 3, 32, 16, 0, 180, 179, 1, 0, 0, 0, 181, 184, 1, 0, 0, 0, 182, 180, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 185, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 186, 5, 20, 0, 0, 186, 25, 1, 0, 0, 0, 187, 199, 5, 14, 0, 0, 188, 193, 3, 28, 14, 0, 189, 190, 5, 15, 0, 0, 190, 192, 3, 28, 14, 0, 191, 189, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 198, 5, 15, 0, 0, 197, 196, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 200, 1, 0, 0, 0, 199, 188, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, 202, 5, 16, 0, 0, 202, 27, 1, 0, 0, 0, 203, 207, 3, 84, 42, 0, 204, 206, 3, 78, 39, 0, 205, 204, 1, 0, 0, 0, 206, 209, 1, 0, 0, 0, 207, 205, 1, 0, 0, 0, 207, 208, 1, 0, 0, 0, 208, 210, 1, 0, 0, 0, 209, 207, 1, 0, 0, 0, 210, 211, 5, 82, 0, 0, 211, 29, 1, 0, 0, 0, 212, 216, 5, 19, 0, 0, 213, 215, 3, 32, 16, 0, 214, 213, 1, 0, 0, 0, 215, 218, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, 216, 217, 1, 0, 0, 0, 217, 219, 1, 0, 0, 0, 218, 216, 1, 0, 0, 0, 219, 222, 5, 20, 0, 0, 220, 222, 3, 32, 16, 0, 221, 212, 1, 0, 0, 0, 221, 220, 1, 0, 0, 0, 222, 31, 1, 0, 0, 0, 223, 228, 3, 40, 20, 0, 224, 225, 3, 34, 17, 0, 225, 226, 5, 2, 0, 0, 226, 228, 1, 0, 0, 0, 227, 223, 1, 0, 0, 0, 227, 224, 1, 0, 0, 0, 228, 33, 1, 0, 0, 0, 229, 238, 3, 42, 21, 0, 230, 238, 3, 44, 22, 0, 231, 238, 3, 46, 23, 0, 232, 238, 3, 48, 24, 0, 233, 238, 3, 50, 25, 0, 234, 238, 3, 36, 18, 0, 235, 238, 3, 52, 26, 0, 236, 238, 3, 38, 19, 0, 237, 229, 1, 0, 0, 0, 237, 230, 1, 0, 0, 0, 237, 231, 1, 0, 0, 0, 237, 232, 1, 0, 0, 0, 237, 233, 1, 0, 0, 0, 237, 234, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 236, 1, 0, 0, 0, 238, 35, 1, 0, 0, 0, 239, 240, 3, 72, 36, 0, 240, 37, 1, 0, 0, 0, 241, 242, 5, 21, 0, 0, 242, 247, 3, 76, 38, 0, 243, 244, 5, 15, 0, 0, 244, 246, 3, 76, 38, 0, 245, 243, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 39, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 253, 3, 54, 27, 0, 251, 253, 3, 56, 28, 0, 252, 250, 1, 0, 0, 0, 252, 251, 1, 0, 0, 0, 253, 41, 1, 0, 0, 0, 254, 258, 3, 84, 42, 0, 255, 257, 3, 78, 39, 0, 256, 255, 1, 0, 0, 0, 257, 260, 1, 0, 0, 0, 258, 256, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 261, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 261, 262, 5, 82, 0, 0, 262, 263, 5, 10, 0, 0, 263, 264, 3, 76, 38, 0, 264, 43, 1, 0, 0, 0, 265, 266, 3, 84, 42, 0, 266, 271, 5, 82, 0, 0, 267, 268, 5, 15, 0, 0, 268, 269, 3, 84, 42, 0, 269, 270, 5, 82, 0, 0, 270, 272, 1, 0, 0, 0, 271, 267, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 271, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 5, 10, 0, 0, 276, 277, 3, 76, 38, 0, 277, 45, 1, 0, 0, 0, 278, 279, 5, 82, 0, 0, 279, 280, 7, 1, 0, 0, 280, 284, 3, 76, 38, 0, 281, 282, 5, 82, 0, 0, 282, 284, 7, 2, 0, 0, 283, 278, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, 284, 47, 1, 0, 0, 0, 285, 286, 5, 26, 0, 0, 286, 287, 5, 14, 0, 0, 287, 288, 5, 79, 0, 0, 288, 289, 5, 6, 0, 0, 289, 292, 3, 76, 38, 0, 290, 291, 5, 15, 0, 0, 291, 293, 3, 66, 33, 0, 292, 290, 1, 0, 0, 0, 292, 293, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 295, 5, 16, 0, 0, 295, 49, 1, 0, 0, 0, 296, 297, 5, 26, 0, 0, 297, 298, 5, 14, 0, 0, 298, 301, 3, 76, 38, 0, 299, 300, 5, 15, 0, 0, 300, 302, 3, 66, 33, 0, 301, 299, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 303, 1, 0, 0, 0, 303, 304, 5, 16, 0, 0, 304, 51, 1, 0, 0, 0, 305, 306, 5, 27, 0, 0, 306, 307, 3, 70, 35, 0, 307, 53, 1, 0, 0, 0, 308, 309, 5, 28, 0, 0, 309, 310, 5, 14, 0, 0, 310, 311, 3, 76, 38, 0, 311, 312, 5, 16, 0, 0, 312, 315, 3, 30, 15, 0, 313, 314, 5, 29, 0, 0, 314, 316, 3, 30, 15, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 55, 1, 0, 0, 0, 317, 321, 3, 58, 29, 0, 318, 321, 3, 60, 30, 0, 319, 321, 3, 62, 31, 0, 320, 317, 1, 0, 0, 0, 320, 318, 1, 0, 0, 0, 320, 319, 1, 0, 0, 0, 321, 57, 1, 0, 0, 0, 322, 323, 5, 30, 0, 0, 323, 324, 3, 30, 15, 0, 324, 325, 5, 31, 0, 0, 325, 326, 5, 14, 0, 0, 326, 327, 3, 76, 38, 0, 327, 328, 5, 16, 0, 0, 328, 329, 5, 2, 0, 0, 329, 59, 1, 0, 0, 0, 330, 331, 5, 31, 0, 0, 331, 332, 5, 14, 0, 0, 332, 333, 3, 76, 38, 0, 333, 334, 5, 16, 0, 0, 334, 335, 3, 30, 15, 0, 335, 61, 1, 0, 0, 0, 336, 337, 5, 32, 0, 0, 337, 338, 5, 14, 0, 0, 338, 339, 3, 64, 32, 0, 339, 340, 5, 2, 0, 0, 340, 341, 3, 76, 38, 0, 341, 342, 5, 2, 0, 0, 342, 343, 3, 46, 23, 0, 343, 344, 5, 16, 0, 0, 344, 345, 3, 30, 15, 0, 345, 63, 1, 0, 0, 0, 346, 349, 3, 42, 21, 0, 347, 349, 3, 46, 23, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0, 0, 349, 65, 1, 0, 0, 0, 350, 351, 5, 76, 0, 0, 351, 67, 1, 0, 0, 0, 352, 355, 5, 82, 0, 0, 353, 355, 3, 80, 40, 0, 354, 352, 1, 0, 0, 0, 354, 353, 1, 0, 0, 0, 355, 69, 1, 0, 0, 0, 356, 368, 5, 14, 0, 0, 357, 362, 3, 68, 34, 0, 358, 359, 5, 15, 0, 0, 359, 361, 3, 68, 34, 0, 360, 358, 1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 366, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 365, 367, 5, 15, 0, 0, 366, 365, 1, 0, 0, 0, 366, 367, 1, 0, 0, 0, 367, 369, 1, 0, 0, 0, 368, 357, 1, 0, 0, 0, 368, 369, 1, 0, 0, 0, 369, 370, 1, 0, 0, 0, 370, 371, 5, 16, 0, 0, 371, 71, 1, 0, 0, 0, 372, 373, 5, 82, 0, 0, 373, 374, 3, 74, 37, 0, 374, 73, 1, 0, 0, 0, 375, 387, 5, 14, 0, 0, 376, 381, 3, 76, 38, 0, 377, 378, 5, 15, 0, 0, 378, 380, 3, 76, 38, 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, 15, 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, 16, 0, 0, 390, 75, 1, 0, 0, 0, 391, 392, 6, 38, -1, 0, 392, 393, 5, 14, 0, 0, 393, 394, 3, 76, 38, 0, 394, 395, 5, 16, 0, 0, 395, 441, 1, 0, 0, 0, 396, 397, 3, 86, 43, 0, 397, 398, 5, 14, 0, 0, 398, 400, 3, 76, 38, 0, 399, 401, 5, 15, 0, 0, 400, 399, 1, 0, 0, 0, 400, 401, 1, 0, 0, 0, 401, 402, 1, 0, 0, 0, 402, 403, 5, 16, 0, 0, 403, 441, 1, 0, 0, 0, 404, 441, 3, 72, 36, 0, 405, 406, 5, 33, 0, 0, 406, 407, 5, 82, 0, 0, 407, 441, 3, 74, 37, 0, 408, 409, 5, 36, 0, 0, 409, 410, 5, 34, 0, 0, 410, 411, 3, 76, 38, 0, 411, 412, 5, 35, 0, 0, 412, 413, 7, 3, 0, 0, 413, 441, 1, 0, 0, 0, 414, 415, 5, 42, 0, 0, 415, 416, 5, 34, 0, 0, 416, 417, 3, 76, 38, 0, 417, 418, 5, 35, 0, 0, 418, 419, 7, 4, 0, 0, 419, 441, 1, 0, 0, 0, 420, 421, 7, 5, 0, 0, 421, 441, 3, 76, 38, 15, 422, 434, 5, 34, 0, 0, 423, 428, 3, 76, 38, 0, 424, 425, 5, 15, 0, 0, 425, 427, 3, 76, 38, 0, 426, 424, 1, 0, 0, 0, 427, 430, 1, 0, 0, 0, 428, 426, 1, 0, 0, 0, 428, 429, 1, 0, 0, 0, 429, 432, 1, 0, 0, 0, 430, 428, 1, 0, 0, 0, 431, 433, 5, 15, 0, 0, 432, 431, 1, 0, 0, 0, 432, 433, 1, 0, 0, 0, 433, 435, 1, 0, 0, 0, 434, 423, 1, 0, 0, 0, 434, 435, 1, 0, 0, 0, 435, 436, 1, 0, 0, 0, 436, 441, 5, 35, 0, 0, 437, 441, 5, 81, 0, 0, 438, 441, 5, 82, 0, 0, 439, 441, 3, 80, 40, 0, 440, 391, 1, 0, 0, 0, 440, 396, 1, 0, 0, 0, 440, 404, 1, 0, 0, 0, 440, 405, 1, 0, 0, 0, 440, 408, 1, 0, 0, 0, 440, 414, 1, 0, 0, 0, 440, 420, 1, 0, 0, 0, 440, 422, 1, 0, 0, 0, 440, 437, 1, 0, 0, 0, 440, 438, 1, 0, 0, 0, 440, 439, 1, 0, 0, 0, 441, 494, 1, 0, 0, 0, 442, 443, 10, 14, 0, 0, 443, 444, 7, 6, 0, 0, 444, 493, 3, 76, 38, 15, 445, 446, 10, 13, 0, 0, 446, 447, 7, 7, 0, 0, 447, 493, 3, 76, 38, 14, 448, 449, 10, 12, 0, 0, 449, 450, 7, 8, 0, 0, 450, 493, 3, 76, 38, 13, 451, 452, 10, 11, 0, 0, 452, 453, 7, 9, 0, 0, 453, 493, 3, 76, 38, 12, 454, 455, 10, 10, 0, 0, 455, 456, 7, 10, 0, 0, 456, 493, 3, 76, 38, 11, 457, 458, 10, 9, 0, 0, 458, 459, 5, 61, 0, 0, 459, 493, 3, 76, 38, 10, 460, 461, 10, 8, 0, 0, 461, 462, 5, 4, 0, 0, 462, 493, 3, 76, 38, 9, 463, 464, 10, 7, 0, 0, 464, 465, 5, 62, 0, 0, 465, 493, 3, 76, 38, 8, 466, 467, 10, 6, 0, 0, 467, 468, 5, 63, 0, 0, 468, 493, 3, 76, 38, 7, 469, 470, 10, 5, 0, 0, 470, 471, 5, 64, 0, 0, 471, 493, 3, 76, 38, 6, 472, 473, 10, 21, 0, 0, 473, 474, 5, 34, 0, 0, 474, 475, 5, 69, 0, 0, 475, 493, 5, 35, 0, 0, 476, 477, 10, 18, 0, 0, 477, 493, 7, 11, 0, 0, 478, 479, 10, 17, 0, 0, 479, 480, 5, 49, 0, 0, 480, 481, 5, 14, 0, 0, 481, 482, 3, 76, 38, 0, 482, 483, 5, 16, 0, 0, 483, 493, 1, 0, 0, 0, 484, 485, 10, 16, 0, 0, 485, 486, 5, 50, 0, 0, 486, 487, 5, 14, 0, 0, 487, 488, 3, 76, 38, 0, 488, 489, 5, 15, 0, 0, 489, 490, 3, 76, 38, 0, 490, 491, 5, 16, 0, 0, 491, 493, 1, 0, 0, 0, 492, 442, 1, 0, 0, 0, 492, 445, 1, 0, 0, 0, 492, 448, 1, 0, 0, 0, 492, 451, 1, 0, 0, 0, 492, 454, 1, 0, 0, 0, 492, 457, 1, 0, 0, 0, 492, 460, 1, 0, 0, 0, 492, 463, 1, 0, 0, 0, 492, 466, 1, 0, 0, 0, 492, 469, 1, 0, 0, 0, 492, 472, 1, 0, 0, 0, 492, 476, 1, 0, 0, 0, 492, 478, 1, 0, 0, 0, 492, 484, 1, 0, 0, 0, 493, 496, 1, 0, 0, 0, 494, 492, 1, 0, 0, 0, 494, 495, 1, 0, 0, 0, 495, 77, 1, 0, 0, 0, 496, 494, 1, 0, 0, 0, 497, 498, 7, 12, 0, 0, 498, 79, 1, 0, 0, 0, 499, 505, 5, 67, 0, 0, 500, 505, 3, 82, 41, 0, 501, 505, 5, 76, 0, 0, 502, 505, 5, 77, 0, 0, 503, 505, 5, 78, 0, 0, 504, 499, 1, 0, 0, 0, 504, 500, 1, 0, 0, 0, 504, 501, 1, 0, 0, 0, 504, 502, 1, 0, 0, 0, 504, 503, 1, 0, 0, 0, 505, 81, 1, 0, 0, 0, 506, 508, 5, 69, 0, 0, 507, 509, 5, 68, 0, 0, 508, 507, 1, 0, 0, 0, 508, 509, 1, 0, 0, 0, 509, 83, 1, 0, 0, 0, 510, 511, 7, 13, 0, 0, 511, 85, 1, 0, 0, 0, 512, 513, 7, 14, 0, 0, 513, 87, 1, 0, 0, 0, 44, 91, 97, 103, 117, 120, 133, 145, 150, 168, 182, 193, 197, 199, 207, 216, 221, 227, 237, 247, 252, 258, 273, 283, 292, 301, 315, 320, 348, 354, 362, 366, 368, 381, 385, 387, 400, 428, 432, 434, 440, 492, 494, 504, 508] \ No newline at end of file diff --git a/packages/cashc/src/grammar/CashScript.tokens b/packages/cashc/src/grammar/CashScript.tokens index 074f0fc19..1ca45fe0a 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 @@ -146,4 +147,5 @@ LINE_COMMENT=84 '|'=62 '&&'=63 '||'=64 -'bytes'=72 +'unused'=65 +'bytes'=73 diff --git a/packages/cashc/src/grammar/CashScriptLexer.interp b/packages/cashc/src/grammar/CashScriptLexer.interp index 8cd270bcc..53253d139 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.interp +++ b/packages/cashc/src/grammar/CashScriptLexer.interp @@ -64,6 +64,7 @@ null '|' '&&' '||' +'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, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 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, 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, 235, 1, 0, 0, 0, 35, 244, 1, 0, 0, 0, 37, 253, 1, 0, 0, 0, 39, 255, 1, 0, 0, 0, 41, 257, 1, 0, 0, 0, 43, 264, 1, 0, 0, 0, 45, 267, 1, 0, 0, 0, 47, 270, 1, 0, 0, 0, 49, 273, 1, 0, 0, 0, 51, 276, 1, 0, 0, 0, 53, 284, 1, 0, 0, 0, 55, 296, 1, 0, 0, 0, 57, 299, 1, 0, 0, 0, 59, 304, 1, 0, 0, 0, 61, 307, 1, 0, 0, 0, 63, 313, 1, 0, 0, 0, 65, 317, 1, 0, 0, 0, 67, 321, 1, 0, 0, 0, 69, 323, 1, 0, 0, 0, 71, 325, 1, 0, 0, 0, 73, 336, 1, 0, 0, 0, 75, 343, 1, 0, 0, 0, 77, 360, 1, 0, 0, 0, 79, 375, 1, 0, 0, 0, 81, 390, 1, 0, 0, 0, 83, 403, 1, 0, 0, 0, 85, 413, 1, 0, 0, 0, 87, 438, 1, 0, 0, 0, 89, 453, 1, 0, 0, 0, 91, 472, 1, 0, 0, 0, 93, 488, 1, 0, 0, 0, 95, 499, 1, 0, 0, 0, 97, 507, 1, 0, 0, 0, 99, 514, 1, 0, 0, 0, 101, 521, 1, 0, 0, 0, 103, 523, 1, 0, 0, 0, 105, 525, 1, 0, 0, 0, 107, 527, 1, 0, 0, 0, 109, 529, 1, 0, 0, 0, 111, 531, 1, 0, 0, 0, 113, 533, 1, 0, 0, 0, 115, 536, 1, 0, 0, 0, 117, 539, 1, 0, 0, 0, 119, 542, 1, 0, 0, 0, 121, 545, 1, 0, 0, 0, 123, 547, 1, 0, 0, 0, 125, 549, 1, 0, 0, 0, 127, 552, 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, 44, 0, 0, 232, 30, 1, 0, 0, 0, 233, 234, 5, 41, 0, 0, 234, 32, 1, 0, 0, 0, 235, 236, 5, 99, 0, 0, 236, 237, 5, 111, 0, 0, 237, 238, 5, 110, 0, 0, 238, 239, 5, 115, 0, 0, 239, 240, 5, 116, 0, 0, 240, 241, 5, 97, 0, 0, 241, 242, 5, 110, 0, 0, 242, 243, 5, 116, 0, 0, 243, 34, 1, 0, 0, 0, 244, 245, 5, 99, 0, 0, 245, 246, 5, 111, 0, 0, 246, 247, 5, 110, 0, 0, 247, 248, 5, 116, 0, 0, 248, 249, 5, 114, 0, 0, 249, 250, 5, 97, 0, 0, 250, 251, 5, 99, 0, 0, 251, 252, 5, 116, 0, 0, 252, 36, 1, 0, 0, 0, 253, 254, 5, 123, 0, 0, 254, 38, 1, 0, 0, 0, 255, 256, 5, 125, 0, 0, 256, 40, 1, 0, 0, 0, 257, 258, 5, 114, 0, 0, 258, 259, 5, 101, 0, 0, 259, 260, 5, 116, 0, 0, 260, 261, 5, 117, 0, 0, 261, 262, 5, 114, 0, 0, 262, 263, 5, 110, 0, 0, 263, 42, 1, 0, 0, 0, 264, 265, 5, 43, 0, 0, 265, 266, 5, 61, 0, 0, 266, 44, 1, 0, 0, 0, 267, 268, 5, 45, 0, 0, 268, 269, 5, 61, 0, 0, 269, 46, 1, 0, 0, 0, 270, 271, 5, 43, 0, 0, 271, 272, 5, 43, 0, 0, 272, 48, 1, 0, 0, 0, 273, 274, 5, 45, 0, 0, 274, 275, 5, 45, 0, 0, 275, 50, 1, 0, 0, 0, 276, 277, 5, 114, 0, 0, 277, 278, 5, 101, 0, 0, 278, 279, 5, 113, 0, 0, 279, 280, 5, 117, 0, 0, 280, 281, 5, 105, 0, 0, 281, 282, 5, 114, 0, 0, 282, 283, 5, 101, 0, 0, 283, 52, 1, 0, 0, 0, 284, 285, 5, 99, 0, 0, 285, 286, 5, 111, 0, 0, 286, 287, 5, 110, 0, 0, 287, 288, 5, 115, 0, 0, 288, 289, 5, 111, 0, 0, 289, 290, 5, 108, 0, 0, 290, 291, 5, 101, 0, 0, 291, 292, 5, 46, 0, 0, 292, 293, 5, 108, 0, 0, 293, 294, 5, 111, 0, 0, 294, 295, 5, 103, 0, 0, 295, 54, 1, 0, 0, 0, 296, 297, 5, 105, 0, 0, 297, 298, 5, 102, 0, 0, 298, 56, 1, 0, 0, 0, 299, 300, 5, 101, 0, 0, 300, 301, 5, 108, 0, 0, 301, 302, 5, 115, 0, 0, 302, 303, 5, 101, 0, 0, 303, 58, 1, 0, 0, 0, 304, 305, 5, 100, 0, 0, 305, 306, 5, 111, 0, 0, 306, 60, 1, 0, 0, 0, 307, 308, 5, 119, 0, 0, 308, 309, 5, 104, 0, 0, 309, 310, 5, 105, 0, 0, 310, 311, 5, 108, 0, 0, 311, 312, 5, 101, 0, 0, 312, 62, 1, 0, 0, 0, 313, 314, 5, 102, 0, 0, 314, 315, 5, 111, 0, 0, 315, 316, 5, 114, 0, 0, 316, 64, 1, 0, 0, 0, 317, 318, 5, 110, 0, 0, 318, 319, 5, 101, 0, 0, 319, 320, 5, 119, 0, 0, 320, 66, 1, 0, 0, 0, 321, 322, 5, 91, 0, 0, 322, 68, 1, 0, 0, 0, 323, 324, 5, 93, 0, 0, 324, 70, 1, 0, 0, 0, 325, 326, 5, 116, 0, 0, 326, 327, 5, 120, 0, 0, 327, 328, 5, 46, 0, 0, 328, 329, 5, 111, 0, 0, 329, 330, 5, 117, 0, 0, 330, 331, 5, 116, 0, 0, 331, 332, 5, 112, 0, 0, 332, 333, 5, 117, 0, 0, 333, 334, 5, 116, 0, 0, 334, 335, 5, 115, 0, 0, 335, 72, 1, 0, 0, 0, 336, 337, 5, 46, 0, 0, 337, 338, 5, 118, 0, 0, 338, 339, 5, 97, 0, 0, 339, 340, 5, 108, 0, 0, 340, 341, 5, 117, 0, 0, 341, 342, 5, 101, 0, 0, 342, 74, 1, 0, 0, 0, 343, 344, 5, 46, 0, 0, 344, 345, 5, 108, 0, 0, 345, 346, 5, 111, 0, 0, 346, 347, 5, 99, 0, 0, 347, 348, 5, 107, 0, 0, 348, 349, 5, 105, 0, 0, 349, 350, 5, 110, 0, 0, 350, 351, 5, 103, 0, 0, 351, 352, 5, 66, 0, 0, 352, 353, 5, 121, 0, 0, 353, 354, 5, 116, 0, 0, 354, 355, 5, 101, 0, 0, 355, 356, 5, 99, 0, 0, 356, 357, 5, 111, 0, 0, 357, 358, 5, 100, 0, 0, 358, 359, 5, 101, 0, 0, 359, 76, 1, 0, 0, 0, 360, 361, 5, 46, 0, 0, 361, 362, 5, 116, 0, 0, 362, 363, 5, 111, 0, 0, 363, 364, 5, 107, 0, 0, 364, 365, 5, 101, 0, 0, 365, 366, 5, 110, 0, 0, 366, 367, 5, 67, 0, 0, 367, 368, 5, 97, 0, 0, 368, 369, 5, 116, 0, 0, 369, 370, 5, 101, 0, 0, 370, 371, 5, 103, 0, 0, 371, 372, 5, 111, 0, 0, 372, 373, 5, 114, 0, 0, 373, 374, 5, 121, 0, 0, 374, 78, 1, 0, 0, 0, 375, 376, 5, 46, 0, 0, 376, 377, 5, 110, 0, 0, 377, 378, 5, 102, 0, 0, 378, 379, 5, 116, 0, 0, 379, 380, 5, 67, 0, 0, 380, 381, 5, 111, 0, 0, 381, 382, 5, 109, 0, 0, 382, 383, 5, 109, 0, 0, 383, 384, 5, 105, 0, 0, 384, 385, 5, 116, 0, 0, 385, 386, 5, 109, 0, 0, 386, 387, 5, 101, 0, 0, 387, 388, 5, 110, 0, 0, 388, 389, 5, 116, 0, 0, 389, 80, 1, 0, 0, 0, 390, 391, 5, 46, 0, 0, 391, 392, 5, 116, 0, 0, 392, 393, 5, 111, 0, 0, 393, 394, 5, 107, 0, 0, 394, 395, 5, 101, 0, 0, 395, 396, 5, 110, 0, 0, 396, 397, 5, 65, 0, 0, 397, 398, 5, 109, 0, 0, 398, 399, 5, 111, 0, 0, 399, 400, 5, 117, 0, 0, 400, 401, 5, 110, 0, 0, 401, 402, 5, 116, 0, 0, 402, 82, 1, 0, 0, 0, 403, 404, 5, 116, 0, 0, 404, 405, 5, 120, 0, 0, 405, 406, 5, 46, 0, 0, 406, 407, 5, 105, 0, 0, 407, 408, 5, 110, 0, 0, 408, 409, 5, 112, 0, 0, 409, 410, 5, 117, 0, 0, 410, 411, 5, 116, 0, 0, 411, 412, 5, 115, 0, 0, 412, 84, 1, 0, 0, 0, 413, 414, 5, 46, 0, 0, 414, 415, 5, 111, 0, 0, 415, 416, 5, 117, 0, 0, 416, 417, 5, 116, 0, 0, 417, 418, 5, 112, 0, 0, 418, 419, 5, 111, 0, 0, 419, 420, 5, 105, 0, 0, 420, 421, 5, 110, 0, 0, 421, 422, 5, 116, 0, 0, 422, 423, 5, 84, 0, 0, 423, 424, 5, 114, 0, 0, 424, 425, 5, 97, 0, 0, 425, 426, 5, 110, 0, 0, 426, 427, 5, 115, 0, 0, 427, 428, 5, 97, 0, 0, 428, 429, 5, 99, 0, 0, 429, 430, 5, 116, 0, 0, 430, 431, 5, 105, 0, 0, 431, 432, 5, 111, 0, 0, 432, 433, 5, 110, 0, 0, 433, 434, 5, 72, 0, 0, 434, 435, 5, 97, 0, 0, 435, 436, 5, 115, 0, 0, 436, 437, 5, 104, 0, 0, 437, 86, 1, 0, 0, 0, 438, 439, 5, 46, 0, 0, 439, 440, 5, 111, 0, 0, 440, 441, 5, 117, 0, 0, 441, 442, 5, 116, 0, 0, 442, 443, 5, 112, 0, 0, 443, 444, 5, 111, 0, 0, 444, 445, 5, 105, 0, 0, 445, 446, 5, 110, 0, 0, 446, 447, 5, 116, 0, 0, 447, 448, 5, 73, 0, 0, 448, 449, 5, 110, 0, 0, 449, 450, 5, 100, 0, 0, 450, 451, 5, 101, 0, 0, 451, 452, 5, 120, 0, 0, 452, 88, 1, 0, 0, 0, 453, 454, 5, 46, 0, 0, 454, 455, 5, 117, 0, 0, 455, 456, 5, 110, 0, 0, 456, 457, 5, 108, 0, 0, 457, 458, 5, 111, 0, 0, 458, 459, 5, 99, 0, 0, 459, 460, 5, 107, 0, 0, 460, 461, 5, 105, 0, 0, 461, 462, 5, 110, 0, 0, 462, 463, 5, 103, 0, 0, 463, 464, 5, 66, 0, 0, 464, 465, 5, 121, 0, 0, 465, 466, 5, 116, 0, 0, 466, 467, 5, 101, 0, 0, 467, 468, 5, 99, 0, 0, 468, 469, 5, 111, 0, 0, 469, 470, 5, 100, 0, 0, 470, 471, 5, 101, 0, 0, 471, 90, 1, 0, 0, 0, 472, 473, 5, 46, 0, 0, 473, 474, 5, 115, 0, 0, 474, 475, 5, 101, 0, 0, 475, 476, 5, 113, 0, 0, 476, 477, 5, 117, 0, 0, 477, 478, 5, 101, 0, 0, 478, 479, 5, 110, 0, 0, 479, 480, 5, 99, 0, 0, 480, 481, 5, 101, 0, 0, 481, 482, 5, 78, 0, 0, 482, 483, 5, 117, 0, 0, 483, 484, 5, 109, 0, 0, 484, 485, 5, 98, 0, 0, 485, 486, 5, 101, 0, 0, 486, 487, 5, 114, 0, 0, 487, 92, 1, 0, 0, 0, 488, 489, 5, 46, 0, 0, 489, 490, 5, 114, 0, 0, 490, 491, 5, 101, 0, 0, 491, 492, 5, 118, 0, 0, 492, 493, 5, 101, 0, 0, 493, 494, 5, 114, 0, 0, 494, 495, 5, 115, 0, 0, 495, 496, 5, 101, 0, 0, 496, 497, 5, 40, 0, 0, 497, 498, 5, 41, 0, 0, 498, 94, 1, 0, 0, 0, 499, 500, 5, 46, 0, 0, 500, 501, 5, 108, 0, 0, 501, 502, 5, 101, 0, 0, 502, 503, 5, 110, 0, 0, 503, 504, 5, 103, 0, 0, 504, 505, 5, 116, 0, 0, 505, 506, 5, 104, 0, 0, 506, 96, 1, 0, 0, 0, 507, 508, 5, 46, 0, 0, 508, 509, 5, 115, 0, 0, 509, 510, 5, 112, 0, 0, 510, 511, 5, 108, 0, 0, 511, 512, 5, 105, 0, 0, 512, 513, 5, 116, 0, 0, 513, 98, 1, 0, 0, 0, 514, 515, 5, 46, 0, 0, 515, 516, 5, 115, 0, 0, 516, 517, 5, 108, 0, 0, 517, 518, 5, 105, 0, 0, 518, 519, 5, 99, 0, 0, 519, 520, 5, 101, 0, 0, 520, 100, 1, 0, 0, 0, 521, 522, 5, 33, 0, 0, 522, 102, 1, 0, 0, 0, 523, 524, 5, 45, 0, 0, 524, 104, 1, 0, 0, 0, 525, 526, 5, 42, 0, 0, 526, 106, 1, 0, 0, 0, 527, 528, 5, 47, 0, 0, 528, 108, 1, 0, 0, 0, 529, 530, 5, 37, 0, 0, 530, 110, 1, 0, 0, 0, 531, 532, 5, 43, 0, 0, 532, 112, 1, 0, 0, 0, 533, 534, 5, 62, 0, 0, 534, 535, 5, 62, 0, 0, 535, 114, 1, 0, 0, 0, 536, 537, 5, 60, 0, 0, 537, 538, 5, 60, 0, 0, 538, 116, 1, 0, 0, 0, 539, 540, 5, 61, 0, 0, 540, 541, 5, 61, 0, 0, 541, 118, 1, 0, 0, 0, 542, 543, 5, 33, 0, 0, 543, 544, 5, 61, 0, 0, 544, 120, 1, 0, 0, 0, 545, 546, 5, 38, 0, 0, 546, 122, 1, 0, 0, 0, 547, 548, 5, 124, 0, 0, 548, 124, 1, 0, 0, 0, 549, 550, 5, 38, 0, 0, 550, 551, 5, 38, 0, 0, 551, 126, 1, 0, 0, 0, 552, 553, 5, 124, 0, 0, 553, 554, 5, 124, 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, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 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, 231, 1, 0, 0, 0, 29, 233, 1, 0, 0, 0, 31, 235, 1, 0, 0, 0, 33, 237, 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, 102, 0, 0, 215, 216, 5, 117, 0, 0, 216, 217, 5, 110, 0, 0, 217, 218, 5, 99, 0, 0, 218, 219, 5, 116, 0, 0, 219, 220, 5, 105, 0, 0, 220, 221, 5, 111, 0, 0, 221, 222, 5, 110, 0, 0, 222, 24, 1, 0, 0, 0, 223, 224, 5, 114, 0, 0, 224, 225, 5, 101, 0, 0, 225, 226, 5, 116, 0, 0, 226, 227, 5, 117, 0, 0, 227, 228, 5, 114, 0, 0, 228, 229, 5, 110, 0, 0, 229, 230, 5, 115, 0, 0, 230, 26, 1, 0, 0, 0, 231, 232, 5, 40, 0, 0, 232, 28, 1, 0, 0, 0, 233, 234, 5, 44, 0, 0, 234, 30, 1, 0, 0, 0, 235, 236, 5, 41, 0, 0, 236, 32, 1, 0, 0, 0, 237, 238, 5, 99, 0, 0, 238, 239, 5, 111, 0, 0, 239, 240, 5, 110, 0, 0, 240, 241, 5, 115, 0, 0, 241, 242, 5, 116, 0, 0, 242, 243, 5, 97, 0, 0, 243, 244, 5, 110, 0, 0, 244, 245, 5, 116, 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 074f0fc19..1ca45fe0a 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 @@ -146,4 +147,5 @@ LINE_COMMENT=84 '|'=62 '&&'=63 '||'=64 -'bytes'=72 +'unused'=65 +'bytes'=73 diff --git a/packages/cashc/src/grammar/CashScriptLexer.ts b/packages/cashc/src/grammar/CashScriptLexer.ts index d384f897a..e5634ac55 100644 --- a/packages/cashc/src/grammar/CashScriptLexer.ts +++ b/packages/cashc/src/grammar/CashScriptLexer.ts @@ -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" ]; @@ -142,6 +143,7 @@ export default class CashScriptLexer extends Lexer { "'=='", "'!='", "'&'", "'|'", "'&&'", "'||'", + "'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,311 +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,16,1,16,1,16,1,16,1,16,1,16,1,16,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, + 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,13,1,13,1,14,1,14,1,15,1,15,1,16,1,16,1,16,1,16,1,16,1,16,1,16,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, - 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, + 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,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,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,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,235, - 1,0,0,0,35,244,1,0,0,0,37,253,1,0,0,0,39,255,1,0,0,0,41,257,1,0,0,0,43, - 264,1,0,0,0,45,267,1,0,0,0,47,270,1,0,0,0,49,273,1,0,0,0,51,276,1,0,0,0, - 53,284,1,0,0,0,55,296,1,0,0,0,57,299,1,0,0,0,59,304,1,0,0,0,61,307,1,0, - 0,0,63,313,1,0,0,0,65,317,1,0,0,0,67,321,1,0,0,0,69,323,1,0,0,0,71,325, - 1,0,0,0,73,336,1,0,0,0,75,343,1,0,0,0,77,360,1,0,0,0,79,375,1,0,0,0,81, - 390,1,0,0,0,83,403,1,0,0,0,85,413,1,0,0,0,87,438,1,0,0,0,89,453,1,0,0,0, - 91,472,1,0,0,0,93,488,1,0,0,0,95,499,1,0,0,0,97,507,1,0,0,0,99,514,1,0, - 0,0,101,521,1,0,0,0,103,523,1,0,0,0,105,525,1,0,0,0,107,527,1,0,0,0,109, - 529,1,0,0,0,111,531,1,0,0,0,113,533,1,0,0,0,115,536,1,0,0,0,117,539,1,0, - 0,0,119,542,1,0,0,0,121,545,1,0,0,0,123,547,1,0,0,0,125,549,1,0,0,0,127, - 552,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,44,0,0,232,30,1,0,0,0,233,234,5,41,0,0,234, - 32,1,0,0,0,235,236,5,99,0,0,236,237,5,111,0,0,237,238,5,110,0,0,238,239, - 5,115,0,0,239,240,5,116,0,0,240,241,5,97,0,0,241,242,5,110,0,0,242,243, - 5,116,0,0,243,34,1,0,0,0,244,245,5,99,0,0,245,246,5,111,0,0,246,247,5,110, - 0,0,247,248,5,116,0,0,248,249,5,114,0,0,249,250,5,97,0,0,250,251,5,99,0, - 0,251,252,5,116,0,0,252,36,1,0,0,0,253,254,5,123,0,0,254,38,1,0,0,0,255, - 256,5,125,0,0,256,40,1,0,0,0,257,258,5,114,0,0,258,259,5,101,0,0,259,260, - 5,116,0,0,260,261,5,117,0,0,261,262,5,114,0,0,262,263,5,110,0,0,263,42, - 1,0,0,0,264,265,5,43,0,0,265,266,5,61,0,0,266,44,1,0,0,0,267,268,5,45,0, - 0,268,269,5,61,0,0,269,46,1,0,0,0,270,271,5,43,0,0,271,272,5,43,0,0,272, - 48,1,0,0,0,273,274,5,45,0,0,274,275,5,45,0,0,275,50,1,0,0,0,276,277,5,114, - 0,0,277,278,5,101,0,0,278,279,5,113,0,0,279,280,5,117,0,0,280,281,5,105, - 0,0,281,282,5,114,0,0,282,283,5,101,0,0,283,52,1,0,0,0,284,285,5,99,0,0, - 285,286,5,111,0,0,286,287,5,110,0,0,287,288,5,115,0,0,288,289,5,111,0,0, - 289,290,5,108,0,0,290,291,5,101,0,0,291,292,5,46,0,0,292,293,5,108,0,0, - 293,294,5,111,0,0,294,295,5,103,0,0,295,54,1,0,0,0,296,297,5,105,0,0,297, - 298,5,102,0,0,298,56,1,0,0,0,299,300,5,101,0,0,300,301,5,108,0,0,301,302, - 5,115,0,0,302,303,5,101,0,0,303,58,1,0,0,0,304,305,5,100,0,0,305,306,5, - 111,0,0,306,60,1,0,0,0,307,308,5,119,0,0,308,309,5,104,0,0,309,310,5,105, - 0,0,310,311,5,108,0,0,311,312,5,101,0,0,312,62,1,0,0,0,313,314,5,102,0, - 0,314,315,5,111,0,0,315,316,5,114,0,0,316,64,1,0,0,0,317,318,5,110,0,0, - 318,319,5,101,0,0,319,320,5,119,0,0,320,66,1,0,0,0,321,322,5,91,0,0,322, - 68,1,0,0,0,323,324,5,93,0,0,324,70,1,0,0,0,325,326,5,116,0,0,326,327,5, - 120,0,0,327,328,5,46,0,0,328,329,5,111,0,0,329,330,5,117,0,0,330,331,5, - 116,0,0,331,332,5,112,0,0,332,333,5,117,0,0,333,334,5,116,0,0,334,335,5, - 115,0,0,335,72,1,0,0,0,336,337,5,46,0,0,337,338,5,118,0,0,338,339,5,97, - 0,0,339,340,5,108,0,0,340,341,5,117,0,0,341,342,5,101,0,0,342,74,1,0,0, - 0,343,344,5,46,0,0,344,345,5,108,0,0,345,346,5,111,0,0,346,347,5,99,0,0, - 347,348,5,107,0,0,348,349,5,105,0,0,349,350,5,110,0,0,350,351,5,103,0,0, - 351,352,5,66,0,0,352,353,5,121,0,0,353,354,5,116,0,0,354,355,5,101,0,0, - 355,356,5,99,0,0,356,357,5,111,0,0,357,358,5,100,0,0,358,359,5,101,0,0, - 359,76,1,0,0,0,360,361,5,46,0,0,361,362,5,116,0,0,362,363,5,111,0,0,363, - 364,5,107,0,0,364,365,5,101,0,0,365,366,5,110,0,0,366,367,5,67,0,0,367, - 368,5,97,0,0,368,369,5,116,0,0,369,370,5,101,0,0,370,371,5,103,0,0,371, - 372,5,111,0,0,372,373,5,114,0,0,373,374,5,121,0,0,374,78,1,0,0,0,375,376, - 5,46,0,0,376,377,5,110,0,0,377,378,5,102,0,0,378,379,5,116,0,0,379,380, - 5,67,0,0,380,381,5,111,0,0,381,382,5,109,0,0,382,383,5,109,0,0,383,384, - 5,105,0,0,384,385,5,116,0,0,385,386,5,109,0,0,386,387,5,101,0,0,387,388, - 5,110,0,0,388,389,5,116,0,0,389,80,1,0,0,0,390,391,5,46,0,0,391,392,5,116, - 0,0,392,393,5,111,0,0,393,394,5,107,0,0,394,395,5,101,0,0,395,396,5,110, - 0,0,396,397,5,65,0,0,397,398,5,109,0,0,398,399,5,111,0,0,399,400,5,117, - 0,0,400,401,5,110,0,0,401,402,5,116,0,0,402,82,1,0,0,0,403,404,5,116,0, - 0,404,405,5,120,0,0,405,406,5,46,0,0,406,407,5,105,0,0,407,408,5,110,0, - 0,408,409,5,112,0,0,409,410,5,117,0,0,410,411,5,116,0,0,411,412,5,115,0, - 0,412,84,1,0,0,0,413,414,5,46,0,0,414,415,5,111,0,0,415,416,5,117,0,0,416, - 417,5,116,0,0,417,418,5,112,0,0,418,419,5,111,0,0,419,420,5,105,0,0,420, - 421,5,110,0,0,421,422,5,116,0,0,422,423,5,84,0,0,423,424,5,114,0,0,424, - 425,5,97,0,0,425,426,5,110,0,0,426,427,5,115,0,0,427,428,5,97,0,0,428,429, - 5,99,0,0,429,430,5,116,0,0,430,431,5,105,0,0,431,432,5,111,0,0,432,433, - 5,110,0,0,433,434,5,72,0,0,434,435,5,97,0,0,435,436,5,115,0,0,436,437,5, - 104,0,0,437,86,1,0,0,0,438,439,5,46,0,0,439,440,5,111,0,0,440,441,5,117, - 0,0,441,442,5,116,0,0,442,443,5,112,0,0,443,444,5,111,0,0,444,445,5,105, - 0,0,445,446,5,110,0,0,446,447,5,116,0,0,447,448,5,73,0,0,448,449,5,110, - 0,0,449,450,5,100,0,0,450,451,5,101,0,0,451,452,5,120,0,0,452,88,1,0,0, - 0,453,454,5,46,0,0,454,455,5,117,0,0,455,456,5,110,0,0,456,457,5,108,0, - 0,457,458,5,111,0,0,458,459,5,99,0,0,459,460,5,107,0,0,460,461,5,105,0, - 0,461,462,5,110,0,0,462,463,5,103,0,0,463,464,5,66,0,0,464,465,5,121,0, - 0,465,466,5,116,0,0,466,467,5,101,0,0,467,468,5,99,0,0,468,469,5,111,0, - 0,469,470,5,100,0,0,470,471,5,101,0,0,471,90,1,0,0,0,472,473,5,46,0,0,473, - 474,5,115,0,0,474,475,5,101,0,0,475,476,5,113,0,0,476,477,5,117,0,0,477, - 478,5,101,0,0,478,479,5,110,0,0,479,480,5,99,0,0,480,481,5,101,0,0,481, - 482,5,78,0,0,482,483,5,117,0,0,483,484,5,109,0,0,484,485,5,98,0,0,485,486, - 5,101,0,0,486,487,5,114,0,0,487,92,1,0,0,0,488,489,5,46,0,0,489,490,5,114, - 0,0,490,491,5,101,0,0,491,492,5,118,0,0,492,493,5,101,0,0,493,494,5,114, - 0,0,494,495,5,115,0,0,495,496,5,101,0,0,496,497,5,40,0,0,497,498,5,41,0, - 0,498,94,1,0,0,0,499,500,5,46,0,0,500,501,5,108,0,0,501,502,5,101,0,0,502, - 503,5,110,0,0,503,504,5,103,0,0,504,505,5,116,0,0,505,506,5,104,0,0,506, - 96,1,0,0,0,507,508,5,46,0,0,508,509,5,115,0,0,509,510,5,112,0,0,510,511, - 5,108,0,0,511,512,5,105,0,0,512,513,5,116,0,0,513,98,1,0,0,0,514,515,5, - 46,0,0,515,516,5,115,0,0,516,517,5,108,0,0,517,518,5,105,0,0,518,519,5, - 99,0,0,519,520,5,101,0,0,520,100,1,0,0,0,521,522,5,33,0,0,522,102,1,0,0, - 0,523,524,5,45,0,0,524,104,1,0,0,0,525,526,5,42,0,0,526,106,1,0,0,0,527, - 528,5,47,0,0,528,108,1,0,0,0,529,530,5,37,0,0,530,110,1,0,0,0,531,532,5, - 43,0,0,532,112,1,0,0,0,533,534,5,62,0,0,534,535,5,62,0,0,535,114,1,0,0, - 0,536,537,5,60,0,0,537,538,5,60,0,0,538,116,1,0,0,0,539,540,5,61,0,0,540, - 541,5,61,0,0,541,118,1,0,0,0,542,543,5,33,0,0,543,544,5,61,0,0,544,120, - 1,0,0,0,545,546,5,38,0,0,546,122,1,0,0,0,547,548,5,124,0,0,548,124,1,0, - 0,0,549,550,5,38,0,0,550,551,5,38,0,0,551,126,1,0,0,0,552,553,5,124,0,0, - 553,554,5,124,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,231,1,0,0,0,29,233,1,0,0,0,31,235,1,0,0,0,33,237,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,102,0, + 0,215,216,5,117,0,0,216,217,5,110,0,0,217,218,5,99,0,0,218,219,5,116,0, + 0,219,220,5,105,0,0,220,221,5,111,0,0,221,222,5,110,0,0,222,24,1,0,0,0, + 223,224,5,114,0,0,224,225,5,101,0,0,225,226,5,116,0,0,226,227,5,117,0,0, + 227,228,5,114,0,0,228,229,5,110,0,0,229,230,5,115,0,0,230,26,1,0,0,0,231, + 232,5,40,0,0,232,28,1,0,0,0,233,234,5,44,0,0,234,30,1,0,0,0,235,236,5,41, + 0,0,236,32,1,0,0,0,237,238,5,99,0,0,238,239,5,111,0,0,239,240,5,110,0,0, + 240,241,5,115,0,0,241,242,5,116,0,0,242,243,5,97,0,0,243,244,5,110,0,0, + 244,245,5,116,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 f78d40316..668cd1794 100644 --- a/packages/cashc/src/grammar/CashScriptParser.ts +++ b/packages/cashc/src/grammar/CashScriptParser.ts @@ -82,26 +82,27 @@ 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 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 RULE_sourceFile = 0; public static readonly RULE_pragmaDirective = 1; @@ -190,6 +191,7 @@ export default class CashScriptParser extends Parser { "'=='", "'!='", "'&'", "'|'", "'&&'", "'||'", + "'unused'", null, null, null, null, null, null, @@ -226,7 +228,8 @@ export default class CashScriptParser extends Parser { null, null, null, null, null, null, - null, "VersionLiteral", + null, null, + "VersionLiteral", "BooleanLiteral", "NumberUnit", "NumberLiteral", @@ -310,7 +313,7 @@ export default class CashScriptParser extends Parser { this.state = 103; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===12 || _la===18 || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 7) !== 0)) { + while (_la===12 || _la===18 || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 7) !== 0)) { { { this.state = 100; @@ -408,7 +411,7 @@ export default class CashScriptParser extends Parser { this.state = 117; 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 = 116; this.versionConstraint(); @@ -544,9 +547,9 @@ export default class CashScriptParser extends Parser { this.globalFunctionDefinition(); } break; - case 71: case 72: case 73: + case 74: this.enterOuterAlt(localctx, 2); { this.state = 131; @@ -769,7 +772,7 @@ export default class CashScriptParser extends Parser { this.state = 182; this._errHandler.sync(this); _la = this._input.LA(1); - while (((((_la - 21)) & ~0x1F) === 0 && ((1 << (_la - 21)) & 3809) !== 0) || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 1031) !== 0)) { + while (((((_la - 21)) & ~0x1F) === 0 && ((1 << (_la - 21)) & 3809) !== 0) || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 1031) !== 0)) { { { this.state = 179; @@ -812,7 +815,7 @@ export default class CashScriptParser extends Parser { this.state = 199; 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 = 188; this.parameter(); @@ -869,12 +872,27 @@ export default class CashScriptParser extends Parser { public parameter(): ParameterContext { let localctx: ParameterContext = new ParameterContext(this, this._ctx, this.state); this.enterRule(localctx, 28, CashScriptParser.RULE_parameter); + let _la: number; try { this.enterOuterAlt(localctx, 1); { this.state = 203; this.typeName(); - this.state = 204; + this.state = 207; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===17 || _la===65) { + { + { + this.state = 204; + this.modifier(); + } + } + this.state = 209; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 210; this.match(CashScriptParser.Identifier); } } @@ -898,29 +916,29 @@ export default class CashScriptParser extends Parser { this.enterRule(localctx, 30, CashScriptParser.RULE_block); let _la: number; try { - this.state = 215; + this.state = 221; this._errHandler.sync(this); switch (this._input.LA(1)) { case 19: this.enterOuterAlt(localctx, 1); { - this.state = 206; + this.state = 212; this.match(CashScriptParser.T__18); - this.state = 210; + this.state = 216; this._errHandler.sync(this); _la = this._input.LA(1); - while (((((_la - 21)) & ~0x1F) === 0 && ((1 << (_la - 21)) & 3809) !== 0) || ((((_la - 71)) & ~0x1F) === 0 && ((1 << (_la - 71)) & 1031) !== 0)) { + while (((((_la - 21)) & ~0x1F) === 0 && ((1 << (_la - 21)) & 3809) !== 0) || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 1031) !== 0)) { { { - this.state = 207; + this.state = 213; this.statement(); } } - this.state = 212; + this.state = 218; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 213; + this.state = 219; this.match(CashScriptParser.T__19); } break; @@ -931,13 +949,13 @@ export default class CashScriptParser extends Parser { case 30: case 31: case 32: - case 71: case 72: case 73: - case 81: + case 74: + case 82: this.enterOuterAlt(localctx, 2); { - this.state = 214; + this.state = 220; this.statement(); } break; @@ -964,7 +982,7 @@ export default class CashScriptParser extends Parser { let localctx: StatementContext = new StatementContext(this, this._ctx, this.state); this.enterRule(localctx, 32, CashScriptParser.RULE_statement); try { - this.state = 221; + this.state = 227; this._errHandler.sync(this); switch (this._input.LA(1)) { case 28: @@ -973,22 +991,22 @@ export default class CashScriptParser extends Parser { case 32: this.enterOuterAlt(localctx, 1); { - this.state = 217; + this.state = 223; this.controlStatement(); } break; case 21: case 26: case 27: - case 71: case 72: case 73: - case 81: + case 74: + case 82: this.enterOuterAlt(localctx, 2); { - this.state = 218; + this.state = 224; this.nonControlStatement(); - this.state = 219; + this.state = 225; this.match(CashScriptParser.T__1); } break; @@ -1015,62 +1033,62 @@ export default class CashScriptParser extends Parser { let localctx: NonControlStatementContext = new NonControlStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 34, CashScriptParser.RULE_nonControlStatement); try { - this.state = 231; + this.state = 237; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 16, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 17, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 223; + this.state = 229; this.variableDefinition(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 224; + this.state = 230; this.tupleAssignment(); } break; case 3: this.enterOuterAlt(localctx, 3); { - this.state = 225; + this.state = 231; this.assignStatement(); } break; case 4: this.enterOuterAlt(localctx, 4); { - this.state = 226; + this.state = 232; this.timeOpStatement(); } break; case 5: this.enterOuterAlt(localctx, 5); { - this.state = 227; + this.state = 233; this.requireStatement(); } break; case 6: this.enterOuterAlt(localctx, 6); { - this.state = 228; + this.state = 234; this.functionCallStatement(); } break; case 7: this.enterOuterAlt(localctx, 7); { - this.state = 229; + this.state = 235; this.consoleStatement(); } break; case 8: this.enterOuterAlt(localctx, 8); { - this.state = 230; + this.state = 236; this.returnStatement(); } break; @@ -1097,7 +1115,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 233; + this.state = 239; this.functionCall(); } } @@ -1123,23 +1141,23 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 235; + this.state = 241; this.match(CashScriptParser.T__20); - this.state = 236; + this.state = 242; this.expression(0); - this.state = 241; + this.state = 247; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===15) { { { - this.state = 237; + this.state = 243; this.match(CashScriptParser.T__14); - this.state = 238; + this.state = 244; this.expression(0); } } - this.state = 243; + this.state = 249; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1164,13 +1182,13 @@ export default class CashScriptParser extends Parser { let localctx: ControlStatementContext = new ControlStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 40, CashScriptParser.RULE_controlStatement); try { - this.state = 246; + this.state = 252; this._errHandler.sync(this); switch (this._input.LA(1)) { case 28: this.enterOuterAlt(localctx, 1); { - this.state = 244; + this.state = 250; this.ifStatement(); } break; @@ -1179,7 +1197,7 @@ export default class CashScriptParser extends Parser { case 32: this.enterOuterAlt(localctx, 2); { - this.state = 245; + this.state = 251; this.loopStatement(); } break; @@ -1209,27 +1227,27 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 248; + this.state = 254; this.typeName(); - this.state = 252; + this.state = 258; this._errHandler.sync(this); _la = this._input.LA(1); - while (_la===17) { + while (_la===17 || _la===65) { { { - this.state = 249; + this.state = 255; this.modifier(); } } - this.state = 254; + this.state = 260; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 255; + this.state = 261; this.match(CashScriptParser.Identifier); - this.state = 256; + this.state = 262; this.match(CashScriptParser.T__9); - this.state = 257; + this.state = 263; this.expression(0); } } @@ -1255,31 +1273,31 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 259; + this.state = 265; this.typeName(); - this.state = 260; + this.state = 266; this.match(CashScriptParser.Identifier); - this.state = 265; + this.state = 271; this._errHandler.sync(this); _la = this._input.LA(1); do { { { - this.state = 261; + this.state = 267; this.match(CashScriptParser.T__14); - this.state = 262; + this.state = 268; this.typeName(); - this.state = 263; + this.state = 269; this.match(CashScriptParser.Identifier); } } - this.state = 267; + this.state = 273; this._errHandler.sync(this); _la = this._input.LA(1); } while (_la===15); - this.state = 269; + this.state = 275; this.match(CashScriptParser.T__9); - this.state = 270; + this.state = 276; this.expression(0); } } @@ -1303,15 +1321,15 @@ export default class CashScriptParser extends Parser { this.enterRule(localctx, 46, CashScriptParser.RULE_assignStatement); let _la: number; try { - this.state = 277; + this.state = 283; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 21, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 22, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 272; + this.state = 278; this.match(CashScriptParser.Identifier); - this.state = 273; + this.state = 279; localctx._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 12583936) !== 0))) { @@ -1321,16 +1339,16 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 274; + this.state = 280; this.expression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 275; + this.state = 281; this.match(CashScriptParser.Identifier); - this.state = 276; + this.state = 282; localctx._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===24 || _la===25)) { @@ -1366,29 +1384,29 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 279; + this.state = 285; this.match(CashScriptParser.T__25); - this.state = 280; + this.state = 286; this.match(CashScriptParser.T__13); - this.state = 281; + this.state = 287; this.match(CashScriptParser.TxVar); - this.state = 282; + this.state = 288; this.match(CashScriptParser.T__5); - this.state = 283; + this.state = 289; this.expression(0); - this.state = 286; + this.state = 292; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 284; + this.state = 290; this.match(CashScriptParser.T__14); - this.state = 285; + this.state = 291; this.requireMessage(); } } - this.state = 288; + this.state = 294; this.match(CashScriptParser.T__15); } } @@ -1414,25 +1432,25 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 290; + this.state = 296; this.match(CashScriptParser.T__25); - this.state = 291; + this.state = 297; this.match(CashScriptParser.T__13); - this.state = 292; + this.state = 298; this.expression(0); - this.state = 295; + this.state = 301; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 293; + this.state = 299; this.match(CashScriptParser.T__14); - this.state = 294; + this.state = 300; this.requireMessage(); } } - this.state = 297; + this.state = 303; this.match(CashScriptParser.T__15); } } @@ -1457,9 +1475,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 299; + this.state = 305; this.match(CashScriptParser.T__26); - this.state = 300; + this.state = 306; this.consoleParameterList(); } } @@ -1484,24 +1502,24 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 302; + this.state = 308; this.match(CashScriptParser.T__27); - this.state = 303; + this.state = 309; this.match(CashScriptParser.T__13); - this.state = 304; + this.state = 310; this.expression(0); - this.state = 305; + this.state = 311; this.match(CashScriptParser.T__15); - this.state = 306; + this.state = 312; localctx._ifBlock = this.block(); - this.state = 309; + this.state = 315; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 24, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 25, this._ctx) ) { case 1: { - this.state = 307; + this.state = 313; this.match(CashScriptParser.T__28); - this.state = 308; + this.state = 314; localctx._elseBlock = this.block(); } break; @@ -1527,27 +1545,27 @@ export default class CashScriptParser extends Parser { let localctx: LoopStatementContext = new LoopStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 56, CashScriptParser.RULE_loopStatement); try { - this.state = 314; + this.state = 320; this._errHandler.sync(this); switch (this._input.LA(1)) { case 30: this.enterOuterAlt(localctx, 1); { - this.state = 311; + this.state = 317; this.doWhileStatement(); } break; case 31: this.enterOuterAlt(localctx, 2); { - this.state = 312; + this.state = 318; this.whileStatement(); } break; case 32: this.enterOuterAlt(localctx, 3); { - this.state = 313; + this.state = 319; this.forStatement(); } break; @@ -1576,19 +1594,19 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 316; + this.state = 322; this.match(CashScriptParser.T__29); - this.state = 317; + this.state = 323; this.block(); - this.state = 318; + this.state = 324; this.match(CashScriptParser.T__30); - this.state = 319; + this.state = 325; this.match(CashScriptParser.T__13); - this.state = 320; + this.state = 326; this.expression(0); - this.state = 321; + this.state = 327; this.match(CashScriptParser.T__15); - this.state = 322; + this.state = 328; this.match(CashScriptParser.T__1); } } @@ -1613,15 +1631,15 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 324; + this.state = 330; this.match(CashScriptParser.T__30); - this.state = 325; + this.state = 331; this.match(CashScriptParser.T__13); - this.state = 326; + this.state = 332; this.expression(0); - this.state = 327; + this.state = 333; this.match(CashScriptParser.T__15); - this.state = 328; + this.state = 334; this.block(); } } @@ -1646,23 +1664,23 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 330; + this.state = 336; this.match(CashScriptParser.T__31); - this.state = 331; + this.state = 337; this.match(CashScriptParser.T__13); - this.state = 332; + this.state = 338; this.forInit(); - this.state = 333; + this.state = 339; this.match(CashScriptParser.T__1); - this.state = 334; + this.state = 340; this.expression(0); - this.state = 335; + this.state = 341; this.match(CashScriptParser.T__1); - this.state = 336; + this.state = 342; this.assignStatement(); - this.state = 337; + this.state = 343; this.match(CashScriptParser.T__15); - this.state = 338; + this.state = 344; this.block(); } } @@ -1685,22 +1703,22 @@ export default class CashScriptParser extends Parser { let localctx: ForInitContext = new ForInitContext(this, this._ctx, this.state); this.enterRule(localctx, 64, CashScriptParser.RULE_forInit); try { - this.state = 342; + this.state = 348; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 71: case 72: case 73: + case 74: this.enterOuterAlt(localctx, 1); { - this.state = 340; + this.state = 346; this.variableDefinition(); } break; - case 81: + case 82: this.enterOuterAlt(localctx, 2); { - this.state = 341; + this.state = 347; this.assignStatement(); } break; @@ -1729,7 +1747,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 344; + this.state = 350; this.match(CashScriptParser.StringLiteral); } } @@ -1752,24 +1770,24 @@ export default class CashScriptParser extends Parser { let localctx: ConsoleParameterContext = new ConsoleParameterContext(this, this._ctx, this.state); this.enterRule(localctx, 68, CashScriptParser.RULE_consoleParameter); try { - this.state = 348; + this.state = 354; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 81: + case 82: this.enterOuterAlt(localctx, 1); { - this.state = 346; + this.state = 352; 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 = 347; + this.state = 353; this.literal(); } break; @@ -1800,39 +1818,39 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 350; + this.state = 356; this.match(CashScriptParser.T__13); - this.state = 362; + this.state = 368; 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 = 351; + this.state = 357; this.consoleParameter(); - this.state = 356; + this.state = 362; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 29, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 352; + this.state = 358; this.match(CashScriptParser.T__14); - this.state = 353; + this.state = 359; this.consoleParameter(); } } } - this.state = 358; + this.state = 364; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 28, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 29, this._ctx); } - this.state = 360; + this.state = 366; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 359; + this.state = 365; this.match(CashScriptParser.T__14); } } @@ -1840,7 +1858,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 364; + this.state = 370; this.match(CashScriptParser.T__15); } } @@ -1865,9 +1883,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 366; + this.state = 372; this.match(CashScriptParser.Identifier); - this.state = 367; + this.state = 373; this.expressionList(); } } @@ -1894,39 +1912,39 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 369; + this.state = 375; this.match(CashScriptParser.T__13); - this.state = 381; + this.state = 387; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===5 || _la===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 61029) !== 0)) { + if (_la===5 || _la===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 61029) !== 0)) { { - this.state = 370; + this.state = 376; this.expression(0); - this.state = 375; + this.state = 381; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 31, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 371; + this.state = 377; this.match(CashScriptParser.T__14); - this.state = 372; + this.state = 378; this.expression(0); } } } - this.state = 377; + this.state = 383; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 31, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); } - this.state = 379; + this.state = 385; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 378; + this.state = 384; this.match(CashScriptParser.T__14); } } @@ -1934,7 +1952,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 383; + this.state = 389; this.match(CashScriptParser.T__15); } } @@ -1972,20 +1990,20 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 434; + this.state = 440; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 38, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 39, this._ctx) ) { case 1: { localctx = new ParenthesisedContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 386; + this.state = 392; this.match(CashScriptParser.T__13); - this.state = 387; + this.state = 393; this.expression(0); - this.state = 388; + this.state = 394; this.match(CashScriptParser.T__15); } break; @@ -1994,23 +2012,23 @@ export default class CashScriptParser extends Parser { localctx = new CastContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 390; + this.state = 396; this.typeCast(); - this.state = 391; + this.state = 397; this.match(CashScriptParser.T__13); - this.state = 392; + this.state = 398; (localctx as CastContext)._castable = this.expression(0); - this.state = 394; + this.state = 400; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 393; + this.state = 399; this.match(CashScriptParser.T__14); } } - this.state = 396; + this.state = 402; this.match(CashScriptParser.T__15); } break; @@ -2019,7 +2037,7 @@ export default class CashScriptParser extends Parser { localctx = new FunctionCallExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 398; + this.state = 404; this.functionCall(); } break; @@ -2028,11 +2046,11 @@ export default class CashScriptParser extends Parser { localctx = new InstantiationContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 399; + this.state = 405; this.match(CashScriptParser.T__32); - this.state = 400; + this.state = 406; this.match(CashScriptParser.Identifier); - this.state = 401; + this.state = 407; this.expressionList(); } break; @@ -2041,15 +2059,15 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 402; + this.state = 408; (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__35); - this.state = 403; + this.state = 409; this.match(CashScriptParser.T__33); - this.state = 404; + this.state = 410; this.expression(0); - this.state = 405; + this.state = 411; this.match(CashScriptParser.T__34); - this.state = 406; + this.state = 412; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 37)) & ~0x1F) === 0 && ((1 << (_la - 37)) & 31) !== 0))) { @@ -2066,15 +2084,15 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 408; + this.state = 414; (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__41); - this.state = 409; + this.state = 415; this.match(CashScriptParser.T__33); - this.state = 410; + this.state = 416; this.expression(0); - this.state = 411; + this.state = 417; this.match(CashScriptParser.T__34); - this.state = 412; + this.state = 418; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 37)) & ~0x1F) === 0 && ((1 << (_la - 37)) & 991) !== 0))) { @@ -2091,7 +2109,7 @@ export default class CashScriptParser extends Parser { localctx = new UnaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 414; + this.state = 420; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===5 || _la===51 || _la===52)) { @@ -2101,7 +2119,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 415; + this.state = 421; this.expression(15); } break; @@ -2110,39 +2128,39 @@ export default class CashScriptParser extends Parser { localctx = new ArrayContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 416; + this.state = 422; this.match(CashScriptParser.T__33); - this.state = 428; + this.state = 434; this._errHandler.sync(this); _la = this._input.LA(1); - if (_la===5 || _la===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 66)) & ~0x1F) === 0 && ((1 << (_la - 66)) & 61029) !== 0)) { + if (_la===5 || _la===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 61029) !== 0)) { { - this.state = 417; + this.state = 423; this.expression(0); - this.state = 422; + this.state = 428; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 36, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 418; + this.state = 424; this.match(CashScriptParser.T__14); - this.state = 419; + this.state = 425; this.expression(0); } } } - this.state = 424; + this.state = 430; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 36, this._ctx); } - this.state = 426; + this.state = 432; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 425; + this.state = 431; this.match(CashScriptParser.T__14); } } @@ -2150,7 +2168,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 430; + this.state = 436; this.match(CashScriptParser.T__34); } break; @@ -2159,7 +2177,7 @@ export default class CashScriptParser extends Parser { localctx = new NullaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 431; + this.state = 437; this.match(CashScriptParser.NullaryOp); } break; @@ -2168,7 +2186,7 @@ export default class CashScriptParser extends Parser { localctx = new IdentifierContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 432; + this.state = 438; this.match(CashScriptParser.Identifier); } break; @@ -2177,15 +2195,15 @@ export default class CashScriptParser extends Parser { localctx = new LiteralExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 433; + this.state = 439; this.literal(); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 488; + this.state = 494; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 41, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -2193,19 +2211,19 @@ export default class CashScriptParser extends Parser { } _prevctx = localctx; { - this.state = 486; + this.state = 492; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 39, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 40, 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 = 436; + this.state = 442; if (!(this.precpred(this._ctx, 14))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 14)"); } - this.state = 437; + this.state = 443; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & 7) !== 0))) { @@ -2215,7 +2233,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 438; + this.state = 444; (localctx as BinaryOpContext)._right = this.expression(15); } break; @@ -2224,11 +2242,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 = 439; + this.state = 445; if (!(this.precpred(this._ctx, 13))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 13)"); } - this.state = 440; + this.state = 446; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===52 || _la===56)) { @@ -2238,7 +2256,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 441; + this.state = 447; (localctx as BinaryOpContext)._right = this.expression(14); } break; @@ -2247,11 +2265,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 = 442; + this.state = 448; if (!(this.precpred(this._ctx, 12))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 12)"); } - this.state = 443; + this.state = 449; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===57 || _la===58)) { @@ -2261,7 +2279,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 444; + this.state = 450; (localctx as BinaryOpContext)._right = this.expression(13); } break; @@ -2270,11 +2288,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 = 445; + this.state = 451; if (!(this.precpred(this._ctx, 11))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 11)"); } - this.state = 446; + this.state = 452; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 960) !== 0))) { @@ -2284,7 +2302,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 447; + this.state = 453; (localctx as BinaryOpContext)._right = this.expression(12); } break; @@ -2293,11 +2311,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 = 448; + this.state = 454; if (!(this.precpred(this._ctx, 10))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 10)"); } - this.state = 449; + this.state = 455; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===59 || _la===60)) { @@ -2307,7 +2325,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 450; + this.state = 456; (localctx as BinaryOpContext)._right = this.expression(11); } break; @@ -2316,13 +2334,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 = 451; + this.state = 457; if (!(this.precpred(this._ctx, 9))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 9)"); } - this.state = 452; + this.state = 458; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); - this.state = 453; + this.state = 459; (localctx as BinaryOpContext)._right = this.expression(10); } break; @@ -2331,13 +2349,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 = 454; + this.state = 460; if (!(this.precpred(this._ctx, 8))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 8)"); } - this.state = 455; + this.state = 461; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__3); - this.state = 456; + this.state = 462; (localctx as BinaryOpContext)._right = this.expression(9); } break; @@ -2346,13 +2364,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 = 457; + this.state = 463; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 458; + this.state = 464; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); - this.state = 459; + this.state = 465; (localctx as BinaryOpContext)._right = this.expression(8); } break; @@ -2361,13 +2379,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 = 460; + this.state = 466; if (!(this.precpred(this._ctx, 6))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 6)"); } - this.state = 461; + this.state = 467; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); - this.state = 462; + this.state = 468; (localctx as BinaryOpContext)._right = this.expression(7); } break; @@ -2376,13 +2394,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 = 463; + this.state = 469; if (!(this.precpred(this._ctx, 5))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 5)"); } - this.state = 464; + this.state = 470; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__63); - this.state = 465; + this.state = 471; (localctx as BinaryOpContext)._right = this.expression(6); } break; @@ -2390,15 +2408,15 @@ export default class CashScriptParser extends Parser { { localctx = new TupleIndexOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 466; + this.state = 472; if (!(this.precpred(this._ctx, 21))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 21)"); } - this.state = 467; + this.state = 473; this.match(CashScriptParser.T__33); - this.state = 468; + this.state = 474; (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); - this.state = 469; + this.state = 475; this.match(CashScriptParser.T__34); } break; @@ -2406,11 +2424,11 @@ export default class CashScriptParser extends Parser { { localctx = new UnaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 470; + this.state = 476; if (!(this.precpred(this._ctx, 18))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 18)"); } - this.state = 471; + this.state = 477; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===47 || _la===48)) { @@ -2427,17 +2445,17 @@ 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 = 472; + this.state = 478; if (!(this.precpred(this._ctx, 17))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 17)"); } - this.state = 473; + this.state = 479; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__48); - this.state = 474; + this.state = 480; this.match(CashScriptParser.T__13); - this.state = 475; + this.state = 481; (localctx as BinaryOpContext)._right = this.expression(0); - this.state = 476; + this.state = 482; this.match(CashScriptParser.T__15); } break; @@ -2446,30 +2464,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 = 478; + this.state = 484; if (!(this.precpred(this._ctx, 16))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 16)"); } - this.state = 479; + this.state = 485; this.match(CashScriptParser.T__49); - this.state = 480; + this.state = 486; this.match(CashScriptParser.T__13); - this.state = 481; + this.state = 487; (localctx as SliceContext)._start = this.expression(0); - this.state = 482; + this.state = 488; this.match(CashScriptParser.T__14); - this.state = 483; + this.state = 489; (localctx as SliceContext)._end = this.expression(0); - this.state = 484; + this.state = 490; this.match(CashScriptParser.T__15); } break; } } } - this.state = 490; + this.state = 496; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 41, this._ctx); } } } @@ -2491,11 +2509,19 @@ export default class CashScriptParser extends Parser { public modifier(): ModifierContext { let localctx: ModifierContext = new ModifierContext(this, this._ctx, this.state); this.enterRule(localctx, 78, CashScriptParser.RULE_modifier); + let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 491; - this.match(CashScriptParser.T__16); + this.state = 497; + _la = this._input.LA(1); + if(!(_la===17 || _la===65)) { + this._errHandler.recoverInline(this); + } + else { + this._errHandler.reportMatch(this); + this.consume(); + } } } catch (re) { @@ -2517,41 +2543,41 @@ export default class CashScriptParser extends Parser { let localctx: LiteralContext = new LiteralContext(this, this._ctx, this.state); this.enterRule(localctx, 80, CashScriptParser.RULE_literal); try { - this.state = 498; + this.state = 504; this._errHandler.sync(this); switch (this._input.LA(1)) { - case 66: + case 67: this.enterOuterAlt(localctx, 1); { - this.state = 493; + this.state = 499; this.match(CashScriptParser.BooleanLiteral); } break; - case 68: + case 69: this.enterOuterAlt(localctx, 2); { - this.state = 494; + this.state = 500; this.numberLiteral(); } break; - case 75: + case 76: this.enterOuterAlt(localctx, 3); { - this.state = 495; + this.state = 501; this.match(CashScriptParser.StringLiteral); } break; - case 76: + case 77: this.enterOuterAlt(localctx, 4); { - this.state = 496; + this.state = 502; this.match(CashScriptParser.DateLiteral); } break; - case 77: + case 78: this.enterOuterAlt(localctx, 5); { - this.state = 497; + this.state = 503; this.match(CashScriptParser.HexLiteral); } break; @@ -2580,14 +2606,14 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 500; + this.state = 506; this.match(CashScriptParser.NumberLiteral); - this.state = 502; + this.state = 508; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 42, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 43, this._ctx) ) { case 1: { - this.state = 501; + this.state = 507; this.match(CashScriptParser.NumberUnit); } break; @@ -2616,9 +2642,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 504; + this.state = 510; _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 { @@ -2649,9 +2675,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 506; + this.state = 512; _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 { @@ -2716,7 +2742,7 @@ export default class CashScriptParser extends Parser { return true; } - public static readonly _serializedATN: number[] = [4,1,84,509,2,0,7,0,2, + public static readonly _serializedATN: number[] = [4,1,85,515,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, @@ -2731,159 +2757,162 @@ export default class CashScriptParser extends Parser { 10,10,12,10,170,9,10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,12,1,12,5,12, 181,8,12,10,12,12,12,184,9,12,1,12,1,12,1,13,1,13,1,13,1,13,5,13,192,8, 13,10,13,12,13,195,9,13,1,13,3,13,198,8,13,3,13,200,8,13,1,13,1,13,1,14, - 1,14,1,14,1,15,1,15,5,15,209,8,15,10,15,12,15,212,9,15,1,15,1,15,3,15,216, - 8,15,1,16,1,16,1,16,1,16,3,16,222,8,16,1,17,1,17,1,17,1,17,1,17,1,17,1, - 17,1,17,3,17,232,8,17,1,18,1,18,1,19,1,19,1,19,1,19,5,19,240,8,19,10,19, - 12,19,243,9,19,1,20,1,20,3,20,247,8,20,1,21,1,21,5,21,251,8,21,10,21,12, - 21,254,9,21,1,21,1,21,1,21,1,21,1,22,1,22,1,22,1,22,1,22,1,22,4,22,266, - 8,22,11,22,12,22,267,1,22,1,22,1,22,1,23,1,23,1,23,1,23,1,23,3,23,278,8, - 23,1,24,1,24,1,24,1,24,1,24,1,24,1,24,3,24,287,8,24,1,24,1,24,1,25,1,25, - 1,25,1,25,1,25,3,25,296,8,25,1,25,1,25,1,26,1,26,1,26,1,27,1,27,1,27,1, - 27,1,27,1,27,1,27,3,27,310,8,27,1,28,1,28,1,28,3,28,315,8,28,1,29,1,29, - 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,31,1,31,1, - 31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,32,1,32,3,32,343,8,32,1,33,1,33, - 1,34,1,34,3,34,349,8,34,1,35,1,35,1,35,1,35,5,35,355,8,35,10,35,12,35,358, - 9,35,1,35,3,35,361,8,35,3,35,363,8,35,1,35,1,35,1,36,1,36,1,36,1,37,1,37, - 1,37,1,37,5,37,374,8,37,10,37,12,37,377,9,37,1,37,3,37,380,8,37,3,37,382, - 8,37,1,37,1,37,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,3,38,395,8, - 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,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,5,38,421,8,38,10,38,12, - 38,424,9,38,1,38,3,38,427,8,38,3,38,429,8,38,1,38,1,38,1,38,1,38,3,38,435, - 8,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, + 1,14,5,14,206,8,14,10,14,12,14,209,9,14,1,14,1,14,1,15,1,15,5,15,215,8, + 15,10,15,12,15,218,9,15,1,15,1,15,3,15,222,8,15,1,16,1,16,1,16,1,16,3,16, + 228,8,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,3,17,238,8,17,1,18,1,18, + 1,19,1,19,1,19,1,19,5,19,246,8,19,10,19,12,19,249,9,19,1,20,1,20,3,20,253, + 8,20,1,21,1,21,5,21,257,8,21,10,21,12,21,260,9,21,1,21,1,21,1,21,1,21,1, + 22,1,22,1,22,1,22,1,22,1,22,4,22,272,8,22,11,22,12,22,273,1,22,1,22,1,22, + 1,23,1,23,1,23,1,23,1,23,3,23,284,8,23,1,24,1,24,1,24,1,24,1,24,1,24,1, + 24,3,24,293,8,24,1,24,1,24,1,25,1,25,1,25,1,25,1,25,3,25,302,8,25,1,25, + 1,25,1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,27,1,27,3,27,316,8,27,1, + 28,1,28,1,28,3,28,321,8,28,1,29,1,29,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,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1, + 31,1,32,1,32,3,32,349,8,32,1,33,1,33,1,34,1,34,3,34,355,8,34,1,35,1,35, + 1,35,1,35,5,35,361,8,35,10,35,12,35,364,9,35,1,35,3,35,367,8,35,3,35,369, + 8,35,1,35,1,35,1,36,1,36,1,36,1,37,1,37,1,37,1,37,5,37,380,8,37,10,37,12, + 37,383,9,37,1,37,3,37,386,8,37,3,37,388,8,37,1,37,1,37,1,38,1,38,1,38,1, + 38,1,38,1,38,1,38,1,38,1,38,3,38,401,8,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,38,1,38,1,38,1,38,1,38,1,38,1, + 38,1,38,1,38,1,38,5,38,427,8,38,10,38,12,38,430,9,38,1,38,3,38,433,8,38, + 3,38,435,8,38,1,38,1,38,1,38,1,38,3,38,441,8,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,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,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,38,1,38,1,38,1,38,1, - 38,1,38,1,38,1,38,1,38,1,38,1,38,1,38,5,38,487,8,38,10,38,12,38,490,9,38, - 1,39,1,39,1,40,1,40,1,40,1,40,1,40,3,40,499,8,40,1,41,1,41,3,41,503,8,41, - 1,42,1,42,1,43,1,43,1,43,0,1,76,44,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,0,14,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,1,0,71,73,2,0,71,72,79,79,539,0,91,1,0,0,0,2,108,1,0, - 0,0,4,113,1,0,0,0,6,115,1,0,0,0,8,120,1,0,0,0,10,124,1,0,0,0,12,126,1,0, - 0,0,14,133,1,0,0,0,16,135,1,0,0,0,18,154,1,0,0,0,20,161,1,0,0,0,22,173, - 1,0,0,0,24,178,1,0,0,0,26,187,1,0,0,0,28,203,1,0,0,0,30,215,1,0,0,0,32, - 221,1,0,0,0,34,231,1,0,0,0,36,233,1,0,0,0,38,235,1,0,0,0,40,246,1,0,0,0, - 42,248,1,0,0,0,44,259,1,0,0,0,46,277,1,0,0,0,48,279,1,0,0,0,50,290,1,0, - 0,0,52,299,1,0,0,0,54,302,1,0,0,0,56,314,1,0,0,0,58,316,1,0,0,0,60,324, - 1,0,0,0,62,330,1,0,0,0,64,342,1,0,0,0,66,344,1,0,0,0,68,348,1,0,0,0,70, - 350,1,0,0,0,72,366,1,0,0,0,74,369,1,0,0,0,76,434,1,0,0,0,78,491,1,0,0,0, - 80,498,1,0,0,0,82,500,1,0,0,0,84,504,1,0,0,0,86,506,1,0,0,0,88,90,3,2,1, - 0,89,88,1,0,0,0,90,93,1,0,0,0,91,89,1,0,0,0,91,92,1,0,0,0,92,97,1,0,0,0, - 93,91,1,0,0,0,94,96,3,12,6,0,95,94,1,0,0,0,96,99,1,0,0,0,97,95,1,0,0,0, - 97,98,1,0,0,0,98,103,1,0,0,0,99,97,1,0,0,0,100,102,3,14,7,0,101,100,1,0, - 0,0,102,105,1,0,0,0,103,101,1,0,0,0,103,104,1,0,0,0,104,106,1,0,0,0,105, - 103,1,0,0,0,106,107,5,0,0,1,107,1,1,0,0,0,108,109,5,1,0,0,109,110,3,4,2, - 0,110,111,3,6,3,0,111,112,5,2,0,0,112,3,1,0,0,0,113,114,5,3,0,0,114,5,1, - 0,0,0,115,117,3,8,4,0,116,118,3,8,4,0,117,116,1,0,0,0,117,118,1,0,0,0,118, - 7,1,0,0,0,119,121,3,10,5,0,120,119,1,0,0,0,120,121,1,0,0,0,121,122,1,0, - 0,0,122,123,5,65,0,0,123,9,1,0,0,0,124,125,7,0,0,0,125,11,1,0,0,0,126,127, - 5,11,0,0,127,128,5,75,0,0,128,129,5,2,0,0,129,13,1,0,0,0,130,134,3,16,8, - 0,131,134,3,18,9,0,132,134,3,20,10,0,133,130,1,0,0,0,133,131,1,0,0,0,133, - 132,1,0,0,0,134,15,1,0,0,0,135,136,5,12,0,0,136,137,5,81,0,0,137,150,3, - 26,13,0,138,139,5,13,0,0,139,140,5,14,0,0,140,145,3,84,42,0,141,142,5,15, - 0,0,142,144,3,84,42,0,143,141,1,0,0,0,144,147,1,0,0,0,145,143,1,0,0,0,145, - 146,1,0,0,0,146,148,1,0,0,0,147,145,1,0,0,0,148,149,5,16,0,0,149,151,1, - 0,0,0,150,138,1,0,0,0,150,151,1,0,0,0,151,152,1,0,0,0,152,153,3,24,12,0, - 153,17,1,0,0,0,154,155,3,84,42,0,155,156,5,17,0,0,156,157,5,81,0,0,157, - 158,5,10,0,0,158,159,3,80,40,0,159,160,5,2,0,0,160,19,1,0,0,0,161,162,5, - 18,0,0,162,163,5,81,0,0,163,164,3,26,13,0,164,168,5,19,0,0,165,167,3,22, - 11,0,166,165,1,0,0,0,167,170,1,0,0,0,168,166,1,0,0,0,168,169,1,0,0,0,169, - 171,1,0,0,0,170,168,1,0,0,0,171,172,5,20,0,0,172,21,1,0,0,0,173,174,5,12, - 0,0,174,175,5,81,0,0,175,176,3,26,13,0,176,177,3,24,12,0,177,23,1,0,0,0, - 178,182,5,19,0,0,179,181,3,32,16,0,180,179,1,0,0,0,181,184,1,0,0,0,182, - 180,1,0,0,0,182,183,1,0,0,0,183,185,1,0,0,0,184,182,1,0,0,0,185,186,5,20, - 0,0,186,25,1,0,0,0,187,199,5,14,0,0,188,193,3,28,14,0,189,190,5,15,0,0, - 190,192,3,28,14,0,191,189,1,0,0,0,192,195,1,0,0,0,193,191,1,0,0,0,193,194, - 1,0,0,0,194,197,1,0,0,0,195,193,1,0,0,0,196,198,5,15,0,0,197,196,1,0,0, - 0,197,198,1,0,0,0,198,200,1,0,0,0,199,188,1,0,0,0,199,200,1,0,0,0,200,201, - 1,0,0,0,201,202,5,16,0,0,202,27,1,0,0,0,203,204,3,84,42,0,204,205,5,81, - 0,0,205,29,1,0,0,0,206,210,5,19,0,0,207,209,3,32,16,0,208,207,1,0,0,0,209, - 212,1,0,0,0,210,208,1,0,0,0,210,211,1,0,0,0,211,213,1,0,0,0,212,210,1,0, - 0,0,213,216,5,20,0,0,214,216,3,32,16,0,215,206,1,0,0,0,215,214,1,0,0,0, - 216,31,1,0,0,0,217,222,3,40,20,0,218,219,3,34,17,0,219,220,5,2,0,0,220, - 222,1,0,0,0,221,217,1,0,0,0,221,218,1,0,0,0,222,33,1,0,0,0,223,232,3,42, - 21,0,224,232,3,44,22,0,225,232,3,46,23,0,226,232,3,48,24,0,227,232,3,50, - 25,0,228,232,3,36,18,0,229,232,3,52,26,0,230,232,3,38,19,0,231,223,1,0, - 0,0,231,224,1,0,0,0,231,225,1,0,0,0,231,226,1,0,0,0,231,227,1,0,0,0,231, - 228,1,0,0,0,231,229,1,0,0,0,231,230,1,0,0,0,232,35,1,0,0,0,233,234,3,72, - 36,0,234,37,1,0,0,0,235,236,5,21,0,0,236,241,3,76,38,0,237,238,5,15,0,0, - 238,240,3,76,38,0,239,237,1,0,0,0,240,243,1,0,0,0,241,239,1,0,0,0,241,242, - 1,0,0,0,242,39,1,0,0,0,243,241,1,0,0,0,244,247,3,54,27,0,245,247,3,56,28, - 0,246,244,1,0,0,0,246,245,1,0,0,0,247,41,1,0,0,0,248,252,3,84,42,0,249, - 251,3,78,39,0,250,249,1,0,0,0,251,254,1,0,0,0,252,250,1,0,0,0,252,253,1, - 0,0,0,253,255,1,0,0,0,254,252,1,0,0,0,255,256,5,81,0,0,256,257,5,10,0,0, - 257,258,3,76,38,0,258,43,1,0,0,0,259,260,3,84,42,0,260,265,5,81,0,0,261, - 262,5,15,0,0,262,263,3,84,42,0,263,264,5,81,0,0,264,266,1,0,0,0,265,261, - 1,0,0,0,266,267,1,0,0,0,267,265,1,0,0,0,267,268,1,0,0,0,268,269,1,0,0,0, - 269,270,5,10,0,0,270,271,3,76,38,0,271,45,1,0,0,0,272,273,5,81,0,0,273, - 274,7,1,0,0,274,278,3,76,38,0,275,276,5,81,0,0,276,278,7,2,0,0,277,272, - 1,0,0,0,277,275,1,0,0,0,278,47,1,0,0,0,279,280,5,26,0,0,280,281,5,14,0, - 0,281,282,5,78,0,0,282,283,5,6,0,0,283,286,3,76,38,0,284,285,5,15,0,0,285, - 287,3,66,33,0,286,284,1,0,0,0,286,287,1,0,0,0,287,288,1,0,0,0,288,289,5, - 16,0,0,289,49,1,0,0,0,290,291,5,26,0,0,291,292,5,14,0,0,292,295,3,76,38, - 0,293,294,5,15,0,0,294,296,3,66,33,0,295,293,1,0,0,0,295,296,1,0,0,0,296, - 297,1,0,0,0,297,298,5,16,0,0,298,51,1,0,0,0,299,300,5,27,0,0,300,301,3, - 70,35,0,301,53,1,0,0,0,302,303,5,28,0,0,303,304,5,14,0,0,304,305,3,76,38, - 0,305,306,5,16,0,0,306,309,3,30,15,0,307,308,5,29,0,0,308,310,3,30,15,0, - 309,307,1,0,0,0,309,310,1,0,0,0,310,55,1,0,0,0,311,315,3,58,29,0,312,315, - 3,60,30,0,313,315,3,62,31,0,314,311,1,0,0,0,314,312,1,0,0,0,314,313,1,0, - 0,0,315,57,1,0,0,0,316,317,5,30,0,0,317,318,3,30,15,0,318,319,5,31,0,0, - 319,320,5,14,0,0,320,321,3,76,38,0,321,322,5,16,0,0,322,323,5,2,0,0,323, - 59,1,0,0,0,324,325,5,31,0,0,325,326,5,14,0,0,326,327,3,76,38,0,327,328, - 5,16,0,0,328,329,3,30,15,0,329,61,1,0,0,0,330,331,5,32,0,0,331,332,5,14, - 0,0,332,333,3,64,32,0,333,334,5,2,0,0,334,335,3,76,38,0,335,336,5,2,0,0, - 336,337,3,46,23,0,337,338,5,16,0,0,338,339,3,30,15,0,339,63,1,0,0,0,340, - 343,3,42,21,0,341,343,3,46,23,0,342,340,1,0,0,0,342,341,1,0,0,0,343,65, - 1,0,0,0,344,345,5,75,0,0,345,67,1,0,0,0,346,349,5,81,0,0,347,349,3,80,40, - 0,348,346,1,0,0,0,348,347,1,0,0,0,349,69,1,0,0,0,350,362,5,14,0,0,351,356, - 3,68,34,0,352,353,5,15,0,0,353,355,3,68,34,0,354,352,1,0,0,0,355,358,1, - 0,0,0,356,354,1,0,0,0,356,357,1,0,0,0,357,360,1,0,0,0,358,356,1,0,0,0,359, - 361,5,15,0,0,360,359,1,0,0,0,360,361,1,0,0,0,361,363,1,0,0,0,362,351,1, - 0,0,0,362,363,1,0,0,0,363,364,1,0,0,0,364,365,5,16,0,0,365,71,1,0,0,0,366, - 367,5,81,0,0,367,368,3,74,37,0,368,73,1,0,0,0,369,381,5,14,0,0,370,375, - 3,76,38,0,371,372,5,15,0,0,372,374,3,76,38,0,373,371,1,0,0,0,374,377,1, - 0,0,0,375,373,1,0,0,0,375,376,1,0,0,0,376,379,1,0,0,0,377,375,1,0,0,0,378, - 380,5,15,0,0,379,378,1,0,0,0,379,380,1,0,0,0,380,382,1,0,0,0,381,370,1, - 0,0,0,381,382,1,0,0,0,382,383,1,0,0,0,383,384,5,16,0,0,384,75,1,0,0,0,385, - 386,6,38,-1,0,386,387,5,14,0,0,387,388,3,76,38,0,388,389,5,16,0,0,389,435, - 1,0,0,0,390,391,3,86,43,0,391,392,5,14,0,0,392,394,3,76,38,0,393,395,5, - 15,0,0,394,393,1,0,0,0,394,395,1,0,0,0,395,396,1,0,0,0,396,397,5,16,0,0, - 397,435,1,0,0,0,398,435,3,72,36,0,399,400,5,33,0,0,400,401,5,81,0,0,401, - 435,3,74,37,0,402,403,5,36,0,0,403,404,5,34,0,0,404,405,3,76,38,0,405,406, - 5,35,0,0,406,407,7,3,0,0,407,435,1,0,0,0,408,409,5,42,0,0,409,410,5,34, - 0,0,410,411,3,76,38,0,411,412,5,35,0,0,412,413,7,4,0,0,413,435,1,0,0,0, - 414,415,7,5,0,0,415,435,3,76,38,15,416,428,5,34,0,0,417,422,3,76,38,0,418, - 419,5,15,0,0,419,421,3,76,38,0,420,418,1,0,0,0,421,424,1,0,0,0,422,420, - 1,0,0,0,422,423,1,0,0,0,423,426,1,0,0,0,424,422,1,0,0,0,425,427,5,15,0, - 0,426,425,1,0,0,0,426,427,1,0,0,0,427,429,1,0,0,0,428,417,1,0,0,0,428,429, - 1,0,0,0,429,430,1,0,0,0,430,435,5,35,0,0,431,435,5,80,0,0,432,435,5,81, - 0,0,433,435,3,80,40,0,434,385,1,0,0,0,434,390,1,0,0,0,434,398,1,0,0,0,434, - 399,1,0,0,0,434,402,1,0,0,0,434,408,1,0,0,0,434,414,1,0,0,0,434,416,1,0, - 0,0,434,431,1,0,0,0,434,432,1,0,0,0,434,433,1,0,0,0,435,488,1,0,0,0,436, - 437,10,14,0,0,437,438,7,6,0,0,438,487,3,76,38,15,439,440,10,13,0,0,440, - 441,7,7,0,0,441,487,3,76,38,14,442,443,10,12,0,0,443,444,7,8,0,0,444,487, - 3,76,38,13,445,446,10,11,0,0,446,447,7,9,0,0,447,487,3,76,38,12,448,449, - 10,10,0,0,449,450,7,10,0,0,450,487,3,76,38,11,451,452,10,9,0,0,452,453, - 5,61,0,0,453,487,3,76,38,10,454,455,10,8,0,0,455,456,5,4,0,0,456,487,3, - 76,38,9,457,458,10,7,0,0,458,459,5,62,0,0,459,487,3,76,38,8,460,461,10, - 6,0,0,461,462,5,63,0,0,462,487,3,76,38,7,463,464,10,5,0,0,464,465,5,64, - 0,0,465,487,3,76,38,6,466,467,10,21,0,0,467,468,5,34,0,0,468,469,5,68,0, - 0,469,487,5,35,0,0,470,471,10,18,0,0,471,487,7,11,0,0,472,473,10,17,0,0, - 473,474,5,49,0,0,474,475,5,14,0,0,475,476,3,76,38,0,476,477,5,16,0,0,477, - 487,1,0,0,0,478,479,10,16,0,0,479,480,5,50,0,0,480,481,5,14,0,0,481,482, - 3,76,38,0,482,483,5,15,0,0,483,484,3,76,38,0,484,485,5,16,0,0,485,487,1, - 0,0,0,486,436,1,0,0,0,486,439,1,0,0,0,486,442,1,0,0,0,486,445,1,0,0,0,486, - 448,1,0,0,0,486,451,1,0,0,0,486,454,1,0,0,0,486,457,1,0,0,0,486,460,1,0, - 0,0,486,463,1,0,0,0,486,466,1,0,0,0,486,470,1,0,0,0,486,472,1,0,0,0,486, - 478,1,0,0,0,487,490,1,0,0,0,488,486,1,0,0,0,488,489,1,0,0,0,489,77,1,0, - 0,0,490,488,1,0,0,0,491,492,5,17,0,0,492,79,1,0,0,0,493,499,5,66,0,0,494, - 499,3,82,41,0,495,499,5,75,0,0,496,499,5,76,0,0,497,499,5,77,0,0,498,493, - 1,0,0,0,498,494,1,0,0,0,498,495,1,0,0,0,498,496,1,0,0,0,498,497,1,0,0,0, - 499,81,1,0,0,0,500,502,5,68,0,0,501,503,5,67,0,0,502,501,1,0,0,0,502,503, - 1,0,0,0,503,83,1,0,0,0,504,505,7,12,0,0,505,85,1,0,0,0,506,507,7,13,0,0, - 507,87,1,0,0,0,43,91,97,103,117,120,133,145,150,168,182,193,197,199,210, - 215,221,231,241,246,252,267,277,286,295,309,314,342,348,356,360,362,375, - 379,381,394,422,426,428,434,486,488,498,502]; + 38,1,38,5,38,493,8,38,10,38,12,38,496,9,38,1,39,1,39,1,40,1,40,1,40,1,40, + 1,40,3,40,505,8,40,1,41,1,41,3,41,509,8,41,1,42,1,42,1,43,1,43,1,43,0,1, + 76,44,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,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,17,17, + 65,65,1,0,72,74,2,0,72,73,80,80,546,0,91,1,0,0,0,2,108,1,0,0,0,4,113,1, + 0,0,0,6,115,1,0,0,0,8,120,1,0,0,0,10,124,1,0,0,0,12,126,1,0,0,0,14,133, + 1,0,0,0,16,135,1,0,0,0,18,154,1,0,0,0,20,161,1,0,0,0,22,173,1,0,0,0,24, + 178,1,0,0,0,26,187,1,0,0,0,28,203,1,0,0,0,30,221,1,0,0,0,32,227,1,0,0,0, + 34,237,1,0,0,0,36,239,1,0,0,0,38,241,1,0,0,0,40,252,1,0,0,0,42,254,1,0, + 0,0,44,265,1,0,0,0,46,283,1,0,0,0,48,285,1,0,0,0,50,296,1,0,0,0,52,305, + 1,0,0,0,54,308,1,0,0,0,56,320,1,0,0,0,58,322,1,0,0,0,60,330,1,0,0,0,62, + 336,1,0,0,0,64,348,1,0,0,0,66,350,1,0,0,0,68,354,1,0,0,0,70,356,1,0,0,0, + 72,372,1,0,0,0,74,375,1,0,0,0,76,440,1,0,0,0,78,497,1,0,0,0,80,504,1,0, + 0,0,82,506,1,0,0,0,84,510,1,0,0,0,86,512,1,0,0,0,88,90,3,2,1,0,89,88,1, + 0,0,0,90,93,1,0,0,0,91,89,1,0,0,0,91,92,1,0,0,0,92,97,1,0,0,0,93,91,1,0, + 0,0,94,96,3,12,6,0,95,94,1,0,0,0,96,99,1,0,0,0,97,95,1,0,0,0,97,98,1,0, + 0,0,98,103,1,0,0,0,99,97,1,0,0,0,100,102,3,14,7,0,101,100,1,0,0,0,102,105, + 1,0,0,0,103,101,1,0,0,0,103,104,1,0,0,0,104,106,1,0,0,0,105,103,1,0,0,0, + 106,107,5,0,0,1,107,1,1,0,0,0,108,109,5,1,0,0,109,110,3,4,2,0,110,111,3, + 6,3,0,111,112,5,2,0,0,112,3,1,0,0,0,113,114,5,3,0,0,114,5,1,0,0,0,115,117, + 3,8,4,0,116,118,3,8,4,0,117,116,1,0,0,0,117,118,1,0,0,0,118,7,1,0,0,0,119, + 121,3,10,5,0,120,119,1,0,0,0,120,121,1,0,0,0,121,122,1,0,0,0,122,123,5, + 66,0,0,123,9,1,0,0,0,124,125,7,0,0,0,125,11,1,0,0,0,126,127,5,11,0,0,127, + 128,5,76,0,0,128,129,5,2,0,0,129,13,1,0,0,0,130,134,3,16,8,0,131,134,3, + 18,9,0,132,134,3,20,10,0,133,130,1,0,0,0,133,131,1,0,0,0,133,132,1,0,0, + 0,134,15,1,0,0,0,135,136,5,12,0,0,136,137,5,82,0,0,137,150,3,26,13,0,138, + 139,5,13,0,0,139,140,5,14,0,0,140,145,3,84,42,0,141,142,5,15,0,0,142,144, + 3,84,42,0,143,141,1,0,0,0,144,147,1,0,0,0,145,143,1,0,0,0,145,146,1,0,0, + 0,146,148,1,0,0,0,147,145,1,0,0,0,148,149,5,16,0,0,149,151,1,0,0,0,150, + 138,1,0,0,0,150,151,1,0,0,0,151,152,1,0,0,0,152,153,3,24,12,0,153,17,1, + 0,0,0,154,155,3,84,42,0,155,156,5,17,0,0,156,157,5,82,0,0,157,158,5,10, + 0,0,158,159,3,80,40,0,159,160,5,2,0,0,160,19,1,0,0,0,161,162,5,18,0,0,162, + 163,5,82,0,0,163,164,3,26,13,0,164,168,5,19,0,0,165,167,3,22,11,0,166,165, + 1,0,0,0,167,170,1,0,0,0,168,166,1,0,0,0,168,169,1,0,0,0,169,171,1,0,0,0, + 170,168,1,0,0,0,171,172,5,20,0,0,172,21,1,0,0,0,173,174,5,12,0,0,174,175, + 5,82,0,0,175,176,3,26,13,0,176,177,3,24,12,0,177,23,1,0,0,0,178,182,5,19, + 0,0,179,181,3,32,16,0,180,179,1,0,0,0,181,184,1,0,0,0,182,180,1,0,0,0,182, + 183,1,0,0,0,183,185,1,0,0,0,184,182,1,0,0,0,185,186,5,20,0,0,186,25,1,0, + 0,0,187,199,5,14,0,0,188,193,3,28,14,0,189,190,5,15,0,0,190,192,3,28,14, + 0,191,189,1,0,0,0,192,195,1,0,0,0,193,191,1,0,0,0,193,194,1,0,0,0,194,197, + 1,0,0,0,195,193,1,0,0,0,196,198,5,15,0,0,197,196,1,0,0,0,197,198,1,0,0, + 0,198,200,1,0,0,0,199,188,1,0,0,0,199,200,1,0,0,0,200,201,1,0,0,0,201,202, + 5,16,0,0,202,27,1,0,0,0,203,207,3,84,42,0,204,206,3,78,39,0,205,204,1,0, + 0,0,206,209,1,0,0,0,207,205,1,0,0,0,207,208,1,0,0,0,208,210,1,0,0,0,209, + 207,1,0,0,0,210,211,5,82,0,0,211,29,1,0,0,0,212,216,5,19,0,0,213,215,3, + 32,16,0,214,213,1,0,0,0,215,218,1,0,0,0,216,214,1,0,0,0,216,217,1,0,0,0, + 217,219,1,0,0,0,218,216,1,0,0,0,219,222,5,20,0,0,220,222,3,32,16,0,221, + 212,1,0,0,0,221,220,1,0,0,0,222,31,1,0,0,0,223,228,3,40,20,0,224,225,3, + 34,17,0,225,226,5,2,0,0,226,228,1,0,0,0,227,223,1,0,0,0,227,224,1,0,0,0, + 228,33,1,0,0,0,229,238,3,42,21,0,230,238,3,44,22,0,231,238,3,46,23,0,232, + 238,3,48,24,0,233,238,3,50,25,0,234,238,3,36,18,0,235,238,3,52,26,0,236, + 238,3,38,19,0,237,229,1,0,0,0,237,230,1,0,0,0,237,231,1,0,0,0,237,232,1, + 0,0,0,237,233,1,0,0,0,237,234,1,0,0,0,237,235,1,0,0,0,237,236,1,0,0,0,238, + 35,1,0,0,0,239,240,3,72,36,0,240,37,1,0,0,0,241,242,5,21,0,0,242,247,3, + 76,38,0,243,244,5,15,0,0,244,246,3,76,38,0,245,243,1,0,0,0,246,249,1,0, + 0,0,247,245,1,0,0,0,247,248,1,0,0,0,248,39,1,0,0,0,249,247,1,0,0,0,250, + 253,3,54,27,0,251,253,3,56,28,0,252,250,1,0,0,0,252,251,1,0,0,0,253,41, + 1,0,0,0,254,258,3,84,42,0,255,257,3,78,39,0,256,255,1,0,0,0,257,260,1,0, + 0,0,258,256,1,0,0,0,258,259,1,0,0,0,259,261,1,0,0,0,260,258,1,0,0,0,261, + 262,5,82,0,0,262,263,5,10,0,0,263,264,3,76,38,0,264,43,1,0,0,0,265,266, + 3,84,42,0,266,271,5,82,0,0,267,268,5,15,0,0,268,269,3,84,42,0,269,270,5, + 82,0,0,270,272,1,0,0,0,271,267,1,0,0,0,272,273,1,0,0,0,273,271,1,0,0,0, + 273,274,1,0,0,0,274,275,1,0,0,0,275,276,5,10,0,0,276,277,3,76,38,0,277, + 45,1,0,0,0,278,279,5,82,0,0,279,280,7,1,0,0,280,284,3,76,38,0,281,282,5, + 82,0,0,282,284,7,2,0,0,283,278,1,0,0,0,283,281,1,0,0,0,284,47,1,0,0,0,285, + 286,5,26,0,0,286,287,5,14,0,0,287,288,5,79,0,0,288,289,5,6,0,0,289,292, + 3,76,38,0,290,291,5,15,0,0,291,293,3,66,33,0,292,290,1,0,0,0,292,293,1, + 0,0,0,293,294,1,0,0,0,294,295,5,16,0,0,295,49,1,0,0,0,296,297,5,26,0,0, + 297,298,5,14,0,0,298,301,3,76,38,0,299,300,5,15,0,0,300,302,3,66,33,0,301, + 299,1,0,0,0,301,302,1,0,0,0,302,303,1,0,0,0,303,304,5,16,0,0,304,51,1,0, + 0,0,305,306,5,27,0,0,306,307,3,70,35,0,307,53,1,0,0,0,308,309,5,28,0,0, + 309,310,5,14,0,0,310,311,3,76,38,0,311,312,5,16,0,0,312,315,3,30,15,0,313, + 314,5,29,0,0,314,316,3,30,15,0,315,313,1,0,0,0,315,316,1,0,0,0,316,55,1, + 0,0,0,317,321,3,58,29,0,318,321,3,60,30,0,319,321,3,62,31,0,320,317,1,0, + 0,0,320,318,1,0,0,0,320,319,1,0,0,0,321,57,1,0,0,0,322,323,5,30,0,0,323, + 324,3,30,15,0,324,325,5,31,0,0,325,326,5,14,0,0,326,327,3,76,38,0,327,328, + 5,16,0,0,328,329,5,2,0,0,329,59,1,0,0,0,330,331,5,31,0,0,331,332,5,14,0, + 0,332,333,3,76,38,0,333,334,5,16,0,0,334,335,3,30,15,0,335,61,1,0,0,0,336, + 337,5,32,0,0,337,338,5,14,0,0,338,339,3,64,32,0,339,340,5,2,0,0,340,341, + 3,76,38,0,341,342,5,2,0,0,342,343,3,46,23,0,343,344,5,16,0,0,344,345,3, + 30,15,0,345,63,1,0,0,0,346,349,3,42,21,0,347,349,3,46,23,0,348,346,1,0, + 0,0,348,347,1,0,0,0,349,65,1,0,0,0,350,351,5,76,0,0,351,67,1,0,0,0,352, + 355,5,82,0,0,353,355,3,80,40,0,354,352,1,0,0,0,354,353,1,0,0,0,355,69,1, + 0,0,0,356,368,5,14,0,0,357,362,3,68,34,0,358,359,5,15,0,0,359,361,3,68, + 34,0,360,358,1,0,0,0,361,364,1,0,0,0,362,360,1,0,0,0,362,363,1,0,0,0,363, + 366,1,0,0,0,364,362,1,0,0,0,365,367,5,15,0,0,366,365,1,0,0,0,366,367,1, + 0,0,0,367,369,1,0,0,0,368,357,1,0,0,0,368,369,1,0,0,0,369,370,1,0,0,0,370, + 371,5,16,0,0,371,71,1,0,0,0,372,373,5,82,0,0,373,374,3,74,37,0,374,73,1, + 0,0,0,375,387,5,14,0,0,376,381,3,76,38,0,377,378,5,15,0,0,378,380,3,76, + 38,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,15,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,16,0,0,390,75,1,0,0,0,391,392,6,38,-1,0,392,393,5,14,0,0,393,394, + 3,76,38,0,394,395,5,16,0,0,395,441,1,0,0,0,396,397,3,86,43,0,397,398,5, + 14,0,0,398,400,3,76,38,0,399,401,5,15,0,0,400,399,1,0,0,0,400,401,1,0,0, + 0,401,402,1,0,0,0,402,403,5,16,0,0,403,441,1,0,0,0,404,441,3,72,36,0,405, + 406,5,33,0,0,406,407,5,82,0,0,407,441,3,74,37,0,408,409,5,36,0,0,409,410, + 5,34,0,0,410,411,3,76,38,0,411,412,5,35,0,0,412,413,7,3,0,0,413,441,1,0, + 0,0,414,415,5,42,0,0,415,416,5,34,0,0,416,417,3,76,38,0,417,418,5,35,0, + 0,418,419,7,4,0,0,419,441,1,0,0,0,420,421,7,5,0,0,421,441,3,76,38,15,422, + 434,5,34,0,0,423,428,3,76,38,0,424,425,5,15,0,0,425,427,3,76,38,0,426,424, + 1,0,0,0,427,430,1,0,0,0,428,426,1,0,0,0,428,429,1,0,0,0,429,432,1,0,0,0, + 430,428,1,0,0,0,431,433,5,15,0,0,432,431,1,0,0,0,432,433,1,0,0,0,433,435, + 1,0,0,0,434,423,1,0,0,0,434,435,1,0,0,0,435,436,1,0,0,0,436,441,5,35,0, + 0,437,441,5,81,0,0,438,441,5,82,0,0,439,441,3,80,40,0,440,391,1,0,0,0,440, + 396,1,0,0,0,440,404,1,0,0,0,440,405,1,0,0,0,440,408,1,0,0,0,440,414,1,0, + 0,0,440,420,1,0,0,0,440,422,1,0,0,0,440,437,1,0,0,0,440,438,1,0,0,0,440, + 439,1,0,0,0,441,494,1,0,0,0,442,443,10,14,0,0,443,444,7,6,0,0,444,493,3, + 76,38,15,445,446,10,13,0,0,446,447,7,7,0,0,447,493,3,76,38,14,448,449,10, + 12,0,0,449,450,7,8,0,0,450,493,3,76,38,13,451,452,10,11,0,0,452,453,7,9, + 0,0,453,493,3,76,38,12,454,455,10,10,0,0,455,456,7,10,0,0,456,493,3,76, + 38,11,457,458,10,9,0,0,458,459,5,61,0,0,459,493,3,76,38,10,460,461,10,8, + 0,0,461,462,5,4,0,0,462,493,3,76,38,9,463,464,10,7,0,0,464,465,5,62,0,0, + 465,493,3,76,38,8,466,467,10,6,0,0,467,468,5,63,0,0,468,493,3,76,38,7,469, + 470,10,5,0,0,470,471,5,64,0,0,471,493,3,76,38,6,472,473,10,21,0,0,473,474, + 5,34,0,0,474,475,5,69,0,0,475,493,5,35,0,0,476,477,10,18,0,0,477,493,7, + 11,0,0,478,479,10,17,0,0,479,480,5,49,0,0,480,481,5,14,0,0,481,482,3,76, + 38,0,482,483,5,16,0,0,483,493,1,0,0,0,484,485,10,16,0,0,485,486,5,50,0, + 0,486,487,5,14,0,0,487,488,3,76,38,0,488,489,5,15,0,0,489,490,3,76,38,0, + 490,491,5,16,0,0,491,493,1,0,0,0,492,442,1,0,0,0,492,445,1,0,0,0,492,448, + 1,0,0,0,492,451,1,0,0,0,492,454,1,0,0,0,492,457,1,0,0,0,492,460,1,0,0,0, + 492,463,1,0,0,0,492,466,1,0,0,0,492,469,1,0,0,0,492,472,1,0,0,0,492,476, + 1,0,0,0,492,478,1,0,0,0,492,484,1,0,0,0,493,496,1,0,0,0,494,492,1,0,0,0, + 494,495,1,0,0,0,495,77,1,0,0,0,496,494,1,0,0,0,497,498,7,12,0,0,498,79, + 1,0,0,0,499,505,5,67,0,0,500,505,3,82,41,0,501,505,5,76,0,0,502,505,5,77, + 0,0,503,505,5,78,0,0,504,499,1,0,0,0,504,500,1,0,0,0,504,501,1,0,0,0,504, + 502,1,0,0,0,504,503,1,0,0,0,505,81,1,0,0,0,506,508,5,69,0,0,507,509,5,68, + 0,0,508,507,1,0,0,0,508,509,1,0,0,0,509,83,1,0,0,0,510,511,7,13,0,0,511, + 85,1,0,0,0,512,513,7,14,0,0,513,87,1,0,0,0,44,91,97,103,117,120,133,145, + 150,168,182,193,197,199,207,216,221,227,237,247,252,258,273,283,292,301, + 315,320,348,354,362,366,368,381,385,387,400,428,432,434,440,492,494,504, + 508]; private static __ATN: ATN; public static get _ATN(): ATN { @@ -3284,6 +3313,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; } diff --git a/packages/cashc/src/print/OutputSourceCodeTraversal.ts b/packages/cashc/src/print/OutputSourceCodeTraversal.ts index b94406128..bfb1e5a22 100644 --- a/packages/cashc/src/print/OutputSourceCodeTraversal.ts +++ b/packages/cashc/src/print/OutputSourceCodeTraversal.ts @@ -128,12 +128,14 @@ export default class OutputSourceCodeTraversal extends AstTraversal { } visitParameter(node: ParameterNode): Node { - this.addOutput(`${node.type} ${node.name}`); + const modifiers = node.modifiers.length > 0 ? `${node.modifiers.join(' ')} ` : ''; + this.addOutput(`${node.type} ${modifiers}${node.name}`); return node; } visitVariableDefinition(node: VariableDefinitionNode): Node { - this.addOutput(`${node.type} ${node.name} = `, true); + const modifiers = node.modifiers.length > 0 ? `${node.modifiers.join(' ')} ` : ''; + this.addOutput(`${node.type} ${modifiers}${node.name} = `, true); this.visit(node.expression); return node; diff --git a/packages/cashc/src/semantic/SymbolTableTraversal.ts b/packages/cashc/src/semantic/SymbolTableTraversal.ts index 29480b665..11c380a02 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -29,6 +29,7 @@ import { UnusedVariableError, InvalidSymbolTypeError, ConstantModificationError, + InvalidModifierError, } from '../Errors.js'; export default class SymbolTableTraversal extends AstTraversal { @@ -82,6 +83,8 @@ export default class SymbolTableTraversal extends AstTraversal { throw new RedefinitionError(node, node.name); } + validateModifiers(node, node.modifiers, [Modifier.UNUSED]); + this.symbolTables[0].set(Symbol.variable(node)); return node; } @@ -149,6 +152,8 @@ export default class SymbolTableTraversal extends AstTraversal { throw new RedefinitionError(node, node.name); } + validateModifiers(node, node.modifiers, [Modifier.CONSTANT, Modifier.UNUSED]); + node.expression = this.visit(node.expression); this.symbolTables[0].set(Symbol.variable(node)); @@ -157,17 +162,13 @@ export default class SymbolTableTraversal extends AstTraversal { } visitAssign(node: AssignNode): Node { - const definition = this.symbolTables[0].get(node.identifier.name)?.definition; + const symbol = this.symbolTables[0].get(node.identifier.name); - if (definition === undefined || definition instanceof FunctionDefinitionNode) { + if (symbol?.definition === undefined || symbol.definition instanceof FunctionDefinitionNode) { throw new UndefinedReferenceError(node.identifier); } - if (definition instanceof ConstantDefinitionNode) { - throw new ConstantModificationError(node, node.identifier.name); - } - - if (definition.modifiers?.includes(Modifier.CONSTANT)) { + if (symbol.hasModifier(Modifier.CONSTANT)) { throw new ConstantModificationError(node, node.identifier.name); } @@ -227,6 +228,10 @@ export default class SymbolTableTraversal extends AstTraversal { throw new InvalidSymbolTypeError(node, this.expectedSymbolType); } + if (symbol.hasModifier(Modifier.UNUSED)) { + throw new InvalidModifierError(node, `Cannot reference variable '${node.name}' because it is marked 'unused'`); + } + // Global constant references are replaced by their literal value, so all later passes // (type checking, literal-driven analysis, codegen) see a plain literal at the use site. if (symbol.definition instanceof ConstantDefinitionNode) { @@ -245,6 +250,27 @@ export default class SymbolTableTraversal extends AstTraversal { } } +function validateModifiers( + node: ParameterNode | VariableDefinitionNode, + modifiers: Modifier[], + allowed: Modifier[], +): void { + const seen = new Set(); + + modifiers.forEach((modifier) => { + if (seen.has(modifier)) { + throw new InvalidModifierError(node, `Duplicate modifier '${modifier}'`); + } + + if (!allowed.includes(modifier)) { + const target = node instanceof ParameterNode ? 'parameters' : 'variables'; + throw new InvalidModifierError(node, `Modifier '${modifier}' is not allowed on ${target}`); + } + + seen.add(modifier); + }); +} + function createTupleVariableDefinition( node: TupleAssignmentNode, variable: TupleAssignmentTarget, 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 000000000..bc070dfd1 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/constant_on_contract_parameter.cash @@ -0,0 +1,5 @@ +contract Test(int constant value) { + function spend() { + require(true); + } +} 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 000000000..5f92f84a3 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/constant_on_function_parameter.cash @@ -0,0 +1,5 @@ +contract Test() { + function spend(int constant value) { + require(value == 1); + } +} 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 000000000..42be6e649 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier.cash @@ -0,0 +1,5 @@ +contract Test() { + function spend(bytes unused unused padding) { + require(true); + } +} diff --git a/packages/cashc/test/compiler/InvalidModifierError/reference_unused_parameter.cash b/packages/cashc/test/compiler/InvalidModifierError/reference_unused_parameter.cash new file mode 100644 index 000000000..c36d4380b --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/reference_unused_parameter.cash @@ -0,0 +1,5 @@ +contract Test() { + function spend(int unused value) { + require(value == 1); + } +} diff --git a/packages/cashc/test/compiler/InvalidModifierError/reference_unused_variable.cash b/packages/cashc/test/compiler/InvalidModifierError/reference_unused_variable.cash new file mode 100644 index 000000000..179605e60 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/reference_unused_variable.cash @@ -0,0 +1,6 @@ +contract Test() { + function spend(int value) { + int unused scratch = value + 1; + require(scratch == 1); + } +} 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 a37120dd3..f49662013 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/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts index 3283c5059..83301fcbf 100644 --- a/packages/cashc/test/generation/fixtures.ts +++ b/packages/cashc/test/generation/fixtures.ts @@ -1817,4 +1817,63 @@ export const fixtures: Fixture[] = [ fingerprint: 'f747468c9408ec52949a22dc2f271a944ee5793eabaa913c9c2b1b4c3fbd0a56', }, }, + { + // The `unused` modifier — unused parameters keep their slot in constructorInputs / abi / frame + // inputs, but are dropped from the stack: constructor and contract function parameters in the + // contract prologue (rolled up first if buried), locals right after their initialiser, and + // global-function parameters in the function-body prologue. + fn: 'unused_modifier.cash', + compilerOptions: { disableInlining: true }, + artifact: { + contractName: 'UnusedModifier', + constructorInputs: [{ name: 'salt', type: 'int' }], + abi: [{ + name: 'spend', + inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }, { name: 'zeroPadding', type: 'bytes' }], + }], + bytecode: + // OP_DEFINE pad (id 0): drop unused param `padding`, leaving `value` as the return value + '75 OP_0 OP_DEFINE ' + // drop unused constructor param `salt` (top of stack) + + 'OP_DROP ' + // roll up and drop unused function param `zeroPadding` + + 'OP_ROT OP_DROP ' + // int unused scratch = a + b — initialiser is evaluated, then dropped + + 'OP_2DUP OP_ADD OP_DROP ' + // int constant unused magic = 42 — dropped as well + + '2a OP_DROP ' + // require(pad(a, 100) + b == 5) + + '64 OP_0 OP_INVOKE OP_ADD OP_5 OP_NUMEQUAL', + debug: { + bytecode: '01750089757b756e9375012a750164008a93559c', + logs: [], + requires: [ + { ip: 18, line: 9 }, + ], + sourceMap: '1::3:1;;::::1;5:24:5:39:0;6:33:6:57;;7:29:7:34;::::1;:8::35;8:36:8:38:0;:8::39:1;9:23:9:26:0;:16::27:1;;:::31;:35::36:0;:8::38:1', + functions: [ + { + id: 0, + name: 'pad', + inputs: [{ name: 'value', type: 'int' }, { name: 'padding', type: 'int' }], + bytecode: '75', + sourceMap: '1:24:1:42', + logs: [], + requires: [], + }, + ], + }, + source: fs.readFileSync(new URL('../valid-contract-files/unused_modifier.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: '4fcac7e0c885a2d3d6a344866c39c4febdffcaf9bb658ac08a87ed7dea9808b6', + }, + }, ]; diff --git a/packages/cashc/test/global-definitions.test.ts b/packages/cashc/test/global-definitions.test.ts index bbb735deb..b1c00b14a 100644 --- a/packages/cashc/test/global-definitions.test.ts +++ b/packages/cashc/test/global-definitions.test.ts @@ -18,7 +18,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 notUsed(int a) returns (int) { return a * 2; } contract Test() { function spend(int x) { @@ -180,11 +180,11 @@ describe('Inlining and shared definitions', () => { it('ignores call sites inside eliminated functions when deciding to inline', () => { const code = ` function big(int x) returns (int) { return (x * 7 + 3) * (x + 11) - 5; } - function unused(int x) returns (int) { return big(x) + big(x + 1) + big(x + 2); } + function notUsed(int x) returns (int) { return big(x) + big(x + 1) + big(x + 2); } contract C() { function spend(int n) { require(big(n) > 0); } }`; // big is multi-use on paper, but all extra call sites live in the eliminated function - // unused — only the single reachable call counts, so big is inlined + // notUsed — only the single reachable call counts, so big is inlined const { bytecode } = compileString(code); expect(bytecode).not.toContain('OP_DEFINE'); expect(bytecode).not.toContain('OP_INVOKE'); 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 000000000..344d451c5 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/unused_modifier.cash @@ -0,0 +1,11 @@ +function pad(int value, int unused padding) returns (int) { + return value; +} + +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(pad(a, 100) + b == 5); + } +} diff --git a/packages/utils/test/fixtures/bitauth-script.fixture.ts b/packages/utils/test/fixtures/bitauth-script.fixture.ts index eca0f858e..e3bea837d 100644 --- a/packages/utils/test/fixtures/bitauth-script.fixture.ts +++ b/packages/utils/test/fixtures/bitauth-script.fixture.ts @@ -311,21 +311,23 @@ OP_ADD OP_12 OP_NUMEQUAL `.replace(/^\n+/, '').replace(/\n+$/, ''), }, { - name: 'ParameterCheck (parameter type check)', + name: 'ParameterCheck (parameter type check + unused parameter drop)', sourceCode: `contract ParameterCheck() { function spend( bytes8 tag, + bytes8 unused padding, ) { require(tag.length == 8); } }`, - asmBytecode: 'OP_SIZE OP_8 OP_EQUALVERIFY OP_SIZE OP_NIP OP_8 OP_NUMEQUAL', - sourceMap: '3:8:3:18;;;5:16:5:26:1;;:30::31:0;:8::33:1', - sourceTags: '0:2:pv', + asmBytecode: 'OP_NIP OP_SIZE OP_8 OP_EQUALVERIFY OP_SIZE OP_NIP OP_8 OP_NUMEQUAL', + sourceMap: '4:8:4:29;3::3:18;;;6:16:6:26:1;;:30::31:0;:8::33:1', + sourceTags: '1:3:pv', expectedBitAuthScript: ` /* contract ParameterCheck() { */ /* function spend( */ /* bytes8 tag, */ +OP_NIP /* bytes8 unused padding, */ /* ) { */ OP_SIZE OP_8 OP_EQUALVERIFY /* >>> parameter type check (bytes8 tag) */ OP_SIZE OP_NIP OP_8 OP_NUMEQUAL /* require(tag.length == 8); */ diff --git a/website/docs/compiler/grammar.md b/website/docs/compiler/grammar.md index 6d28bb806..105345bdd 100644 --- a/website/docs/compiler/grammar.md +++ b/website/docs/compiler/grammar.md @@ -61,7 +61,7 @@ parameterList ; parameter - : typeName Identifier + : typeName modifier* Identifier ; block @@ -201,6 +201,7 @@ expression modifier : 'constant' + | 'unused' ; literal diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index 3baba574b..f3f19b52d 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -243,7 +243,7 @@ contract P2PKH(bytes20 pkh) { Variables can be declared by specifying their type and name. All variables need to be initialised at the time of their declaration, but can be reassigned later on — unless specifying the `constant` keyword. Since CashScript is strongly typed and has no type inference, it is not possible to use keywords such as `var` or `let` to declare variables. :::note -CashScript disallows variable shadowing and unused variables. +CashScript disallows variable shadowing and unused variables unless they are explicitly marked `unused`. ::: #### Example @@ -252,6 +252,21 @@ int myNumber = 3000; string constant myString = 'Bitcoin Cash'; ``` +### Intentionally unused values + +Parameters and local variables that intentionally have no references can use the `unused` modifier. These values are dropped from the stack immediately after their declaration. A declaration marked `unused` cannot be referenced later. Some use cases for this include padding the contract bytecode in order to get a higher opcost budget, or nonces in order to differentiate between similar contracts. + +#### Example + +```solidity +contract Versioned(bytes unused reserved) { + function spend(int value, bytes unused padding) { + int unused discarded = value + 1; + require(value == 1); + } +} +``` + ### Variable assignment After their initial declaration, any variable can be reassigned later on. CashScript supports regular assignment with `=`, the compound assignment operators `+=` and `-=`, and the increment and decrement operators `++` and `--`. The compound and increment/decrement operators are only valid on `int` variables. From 1903a34761fa0d538d99d38544c9fde2f8ca99d2 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 30 Jul 2026 16:46:20 +0200 Subject: [PATCH 15/37] Allow for simple arithmetic in global constant definitions (#431) --- packages/cashc/src/Errors.ts | 20 +++ packages/cashc/src/ast/AST.ts | 2 +- packages/cashc/src/ast/AstBuilder.ts | 2 +- packages/cashc/src/ast/AstTraversal.ts | 4 +- packages/cashc/src/compiler.ts | 2 + packages/cashc/src/dependency-resolution.ts | 15 +- packages/cashc/src/grammar/CashScript.g4 | 2 +- packages/cashc/src/grammar/CashScript.interp | 2 +- .../cashc/src/grammar/CashScriptParser.ts | 8 +- .../src/print/OutputSourceCodeTraversal.ts | 3 +- .../semantic/FoldGlobalConstantsTraversal.ts | 149 ++++++++++++++++++ .../semantic/LowerGlobalConstantsTraversal.ts | 17 +- .../cashc/src/semantic/TypeCheckTraversal.ts | 1 + .../global_constant_division_by_zero.cash | 7 + ...lobal_constant_unsupported_expression.cash | 7 + .../global_constant_non_literal.cash | 7 - .../global_constant_forward_reference.cash | 8 + .../global_constant_mixed_operands.cash | 7 + .../cashc/test/global-definitions.test.ts | 52 +++++- packages/cashc/test/imports.test.ts | 10 +- .../global_constant_arithmetic.cash | 17 ++ website/docs/compiler/grammar.md | 2 +- website/docs/language/contracts.md | 61 +++---- 23 files changed, 331 insertions(+), 74 deletions(-) create mode 100644 packages/cashc/src/semantic/FoldGlobalConstantsTraversal.ts create mode 100644 packages/cashc/test/compiler/DivisionByZeroError/global_constant_division_by_zero.cash create mode 100644 packages/cashc/test/compiler/InvalidConstantExpressionError/global_constant_unsupported_expression.cash delete mode 100644 packages/cashc/test/compiler/ParseError/global_constant_non_literal.cash create mode 100644 packages/cashc/test/compiler/UndefinedReferenceError/global_constant_forward_reference.cash create mode 100644 packages/cashc/test/compiler/UnequalTypeError/global_constant_mixed_operands.cash create mode 100644 packages/cashc/test/valid-contract-files/global_constant_arithmetic.cash diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index adac9f44a..aca72ce5d 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -263,6 +263,26 @@ export class AssignTypeError extends TypeError { } } +export class InvalidConstantExpressionError extends CashScriptError { + constructor( + public node: Node, + ) { + super( + node, + 'Global constant definitions only support literals, references to other constants, ' + + 'integer arithmetic and concatenation', + ); + } +} + +export class DivisionByZeroError extends CashScriptError { + constructor( + public node: BinaryOpNode, + ) { + super(node, 'Division by zero'); + } +} + export class ConstantModificationError extends CashScriptError { constructor(node: VariableDefinitionNode | ConstantDefinitionNode); constructor(node: Node, name: string); diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index 60d1dee6f..01f08e16c 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -55,7 +55,7 @@ export class ConstantDefinitionNode extends Node implements Named, Typed { constructor( public type: Type, public name: string, - public value: LiteralNode, + public value: ExpressionNode, ) { super(); } diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index c76662554..05db951d4 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -144,7 +144,7 @@ export default class AstBuilder visitConstantDefinition(ctx: ConstantDefinitionContext): ConstantDefinitionNode { const type = parseType(ctx.typeName().getText()); const name = ctx.Identifier().getText(); - const value = this.createLiteral(ctx.literal()); + const value = this.visit(ctx.expression()) as ExpressionNode; const constantDefinition = new ConstantDefinitionNode(type, name, value); constantDefinition.location = Location.fromCtx(ctx); return constantDefinition; diff --git a/packages/cashc/src/ast/AstTraversal.ts b/packages/cashc/src/ast/AstTraversal.ts index b671528e9..0dca299eb 100644 --- a/packages/cashc/src/ast/AstTraversal.ts +++ b/packages/cashc/src/ast/AstTraversal.ts @@ -30,7 +30,7 @@ import { NullaryOpNode, ConsoleStatementNode, ConsoleParameterNode, - LiteralNode, + ExpressionNode, FunctionCallStatementNode, SliceNode, DoWhileNode, @@ -64,7 +64,7 @@ export default class AstTraversal extends AstVisitor { } visitConstantDefinition(node: ConstantDefinitionNode): Node { - node.value = this.visit(node.value) as LiteralNode; + node.value = this.visit(node.value) as ExpressionNode; return node; } diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index 3a6b538ce..29e5b5056 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -28,6 +28,7 @@ import { resolveDependencies, } from './dependency-resolution.js'; import GenerateTargetTraversal from './generation/GenerateTargetTraversal.js'; +import { FoldGlobalConstantsTraversal } from './semantic/FoldGlobalConstantsTraversal.js'; import SymbolTableTraversal from './semantic/SymbolTableTraversal.js'; import TypeCheckTraversal from './semantic/TypeCheckTraversal.js'; import EnsureFinalRequireTraversal from './semantic/EnsureFinalRequireTraversal.js'; @@ -115,6 +116,7 @@ function compileCode( const constructorParamLength = ast.contract.parameters.length; // Semantic analysis + ast = ast.accept(new FoldGlobalConstantsTraversal()) as Ast; ast = ast.accept(new SymbolTableTraversal()) as Ast; ast = ast.accept(new TypeCheckTraversal()) as Ast; ast = ast.accept(new EnsureFunctionsSafeTraversal()) as Ast; diff --git a/packages/cashc/src/dependency-resolution.ts b/packages/cashc/src/dependency-resolution.ts index 363938982..7ce8a9856 100644 --- a/packages/cashc/src/dependency-resolution.ts +++ b/packages/cashc/src/dependency-resolution.ts @@ -81,19 +81,22 @@ interface ImportedDefinitions { } // Depth-first walk of the import graph, returning every global definition 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. +// de-duplicates files by canonical path so a diamond's shared leaf is read once, while `activePaths` +// tracks the files currently being resolved so cyclic imports are rejected. function collectImports( imports: ImportNode[], resolver: ImportResolver, errorListener?: CashScriptErrorListener, ): ImportedDefinitions { const visitedPaths = new Set(); + const activePaths = new Set(); const collect = (currentImports: ImportNode[], currentDir: string): ImportedDefinitions[] => currentImports.flatMap((importNode) => { const canonicalPath = resolver.resolve(currentDir, importNode.path); + if (activePaths.has(canonicalPath)) { + throw new ImportResolutionError(importNode, `Cyclic import of '${importNode.path}'`); + } if (visitedPaths.has(canonicalPath)) return []; visitedPaths.add(canonicalPath); @@ -118,8 +121,12 @@ function collectImports( constant.sourceFile = resolver.sourceName(canonicalPath); }); + activePaths.add(canonicalPath); + const transitiveDefinitions = collect(importedAst.imports, resolver.dirname(canonicalPath)); + activePaths.delete(canonicalPath); + return [ - ...collect(importedAst.imports, resolver.dirname(canonicalPath)), + ...transitiveDefinitions, { functions: importedAst.functions, constants: importedAst.constants }, ]; }); diff --git a/packages/cashc/src/grammar/CashScript.g4 b/packages/cashc/src/grammar/CashScript.g4 index 0cd133eee..7800db392 100644 --- a/packages/cashc/src/grammar/CashScript.g4 +++ b/packages/cashc/src/grammar/CashScript.g4 @@ -39,7 +39,7 @@ globalFunctionDefinition ; constantDefinition - : typeName 'constant' Identifier '=' literal ';' + : typeName 'constant' Identifier '=' expression ';' ; contractDefinition diff --git a/packages/cashc/src/grammar/CashScript.interp b/packages/cashc/src/grammar/CashScript.interp index 35c314a34..63f11d9df 100644 --- a/packages/cashc/src/grammar/CashScript.interp +++ b/packages/cashc/src/grammar/CashScript.interp @@ -222,4 +222,4 @@ typeCast atn: -[4, 1, 85, 515, 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, 1, 0, 5, 0, 90, 8, 0, 10, 0, 12, 0, 93, 9, 0, 1, 0, 5, 0, 96, 8, 0, 10, 0, 12, 0, 99, 9, 0, 1, 0, 5, 0, 102, 8, 0, 10, 0, 12, 0, 105, 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, 118, 8, 3, 1, 4, 3, 4, 121, 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, 134, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 144, 8, 8, 10, 8, 12, 8, 147, 9, 8, 1, 8, 1, 8, 3, 8, 151, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 167, 8, 10, 10, 10, 12, 10, 170, 9, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 5, 12, 181, 8, 12, 10, 12, 12, 12, 184, 9, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 192, 8, 13, 10, 13, 12, 13, 195, 9, 13, 1, 13, 3, 13, 198, 8, 13, 3, 13, 200, 8, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 206, 8, 14, 10, 14, 12, 14, 209, 9, 14, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 215, 8, 15, 10, 15, 12, 15, 218, 9, 15, 1, 15, 1, 15, 3, 15, 222, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 228, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 238, 8, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 246, 8, 19, 10, 19, 12, 19, 249, 9, 19, 1, 20, 1, 20, 3, 20, 253, 8, 20, 1, 21, 1, 21, 5, 21, 257, 8, 21, 10, 21, 12, 21, 260, 9, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 4, 22, 272, 8, 22, 11, 22, 12, 22, 273, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 284, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 293, 8, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 302, 8, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 316, 8, 27, 1, 28, 1, 28, 1, 28, 3, 28, 321, 8, 28, 1, 29, 1, 29, 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, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 349, 8, 32, 1, 33, 1, 33, 1, 34, 1, 34, 3, 34, 355, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 361, 8, 35, 10, 35, 12, 35, 364, 9, 35, 1, 35, 3, 35, 367, 8, 35, 3, 35, 369, 8, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 380, 8, 37, 10, 37, 12, 37, 383, 9, 37, 1, 37, 3, 37, 386, 8, 37, 3, 37, 388, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 401, 8, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 427, 8, 38, 10, 38, 12, 38, 430, 9, 38, 1, 38, 3, 38, 433, 8, 38, 3, 38, 435, 8, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 441, 8, 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, 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, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 493, 8, 38, 10, 38, 12, 38, 496, 9, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 505, 8, 40, 1, 41, 1, 41, 3, 41, 509, 8, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 0, 1, 76, 44, 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, 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, 17, 17, 65, 65, 1, 0, 72, 74, 2, 0, 72, 73, 80, 80, 546, 0, 91, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 4, 113, 1, 0, 0, 0, 6, 115, 1, 0, 0, 0, 8, 120, 1, 0, 0, 0, 10, 124, 1, 0, 0, 0, 12, 126, 1, 0, 0, 0, 14, 133, 1, 0, 0, 0, 16, 135, 1, 0, 0, 0, 18, 154, 1, 0, 0, 0, 20, 161, 1, 0, 0, 0, 22, 173, 1, 0, 0, 0, 24, 178, 1, 0, 0, 0, 26, 187, 1, 0, 0, 0, 28, 203, 1, 0, 0, 0, 30, 221, 1, 0, 0, 0, 32, 227, 1, 0, 0, 0, 34, 237, 1, 0, 0, 0, 36, 239, 1, 0, 0, 0, 38, 241, 1, 0, 0, 0, 40, 252, 1, 0, 0, 0, 42, 254, 1, 0, 0, 0, 44, 265, 1, 0, 0, 0, 46, 283, 1, 0, 0, 0, 48, 285, 1, 0, 0, 0, 50, 296, 1, 0, 0, 0, 52, 305, 1, 0, 0, 0, 54, 308, 1, 0, 0, 0, 56, 320, 1, 0, 0, 0, 58, 322, 1, 0, 0, 0, 60, 330, 1, 0, 0, 0, 62, 336, 1, 0, 0, 0, 64, 348, 1, 0, 0, 0, 66, 350, 1, 0, 0, 0, 68, 354, 1, 0, 0, 0, 70, 356, 1, 0, 0, 0, 72, 372, 1, 0, 0, 0, 74, 375, 1, 0, 0, 0, 76, 440, 1, 0, 0, 0, 78, 497, 1, 0, 0, 0, 80, 504, 1, 0, 0, 0, 82, 506, 1, 0, 0, 0, 84, 510, 1, 0, 0, 0, 86, 512, 1, 0, 0, 0, 88, 90, 3, 2, 1, 0, 89, 88, 1, 0, 0, 0, 90, 93, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 97, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 94, 96, 3, 12, 6, 0, 95, 94, 1, 0, 0, 0, 96, 99, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 103, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 100, 102, 3, 14, 7, 0, 101, 100, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 107, 5, 0, 0, 1, 107, 1, 1, 0, 0, 0, 108, 109, 5, 1, 0, 0, 109, 110, 3, 4, 2, 0, 110, 111, 3, 6, 3, 0, 111, 112, 5, 2, 0, 0, 112, 3, 1, 0, 0, 0, 113, 114, 5, 3, 0, 0, 114, 5, 1, 0, 0, 0, 115, 117, 3, 8, 4, 0, 116, 118, 3, 8, 4, 0, 117, 116, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 7, 1, 0, 0, 0, 119, 121, 3, 10, 5, 0, 120, 119, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 123, 5, 66, 0, 0, 123, 9, 1, 0, 0, 0, 124, 125, 7, 0, 0, 0, 125, 11, 1, 0, 0, 0, 126, 127, 5, 11, 0, 0, 127, 128, 5, 76, 0, 0, 128, 129, 5, 2, 0, 0, 129, 13, 1, 0, 0, 0, 130, 134, 3, 16, 8, 0, 131, 134, 3, 18, 9, 0, 132, 134, 3, 20, 10, 0, 133, 130, 1, 0, 0, 0, 133, 131, 1, 0, 0, 0, 133, 132, 1, 0, 0, 0, 134, 15, 1, 0, 0, 0, 135, 136, 5, 12, 0, 0, 136, 137, 5, 82, 0, 0, 137, 150, 3, 26, 13, 0, 138, 139, 5, 13, 0, 0, 139, 140, 5, 14, 0, 0, 140, 145, 3, 84, 42, 0, 141, 142, 5, 15, 0, 0, 142, 144, 3, 84, 42, 0, 143, 141, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 148, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 149, 5, 16, 0, 0, 149, 151, 1, 0, 0, 0, 150, 138, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 153, 3, 24, 12, 0, 153, 17, 1, 0, 0, 0, 154, 155, 3, 84, 42, 0, 155, 156, 5, 17, 0, 0, 156, 157, 5, 82, 0, 0, 157, 158, 5, 10, 0, 0, 158, 159, 3, 80, 40, 0, 159, 160, 5, 2, 0, 0, 160, 19, 1, 0, 0, 0, 161, 162, 5, 18, 0, 0, 162, 163, 5, 82, 0, 0, 163, 164, 3, 26, 13, 0, 164, 168, 5, 19, 0, 0, 165, 167, 3, 22, 11, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 172, 5, 20, 0, 0, 172, 21, 1, 0, 0, 0, 173, 174, 5, 12, 0, 0, 174, 175, 5, 82, 0, 0, 175, 176, 3, 26, 13, 0, 176, 177, 3, 24, 12, 0, 177, 23, 1, 0, 0, 0, 178, 182, 5, 19, 0, 0, 179, 181, 3, 32, 16, 0, 180, 179, 1, 0, 0, 0, 181, 184, 1, 0, 0, 0, 182, 180, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 185, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 186, 5, 20, 0, 0, 186, 25, 1, 0, 0, 0, 187, 199, 5, 14, 0, 0, 188, 193, 3, 28, 14, 0, 189, 190, 5, 15, 0, 0, 190, 192, 3, 28, 14, 0, 191, 189, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 198, 5, 15, 0, 0, 197, 196, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 200, 1, 0, 0, 0, 199, 188, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, 202, 5, 16, 0, 0, 202, 27, 1, 0, 0, 0, 203, 207, 3, 84, 42, 0, 204, 206, 3, 78, 39, 0, 205, 204, 1, 0, 0, 0, 206, 209, 1, 0, 0, 0, 207, 205, 1, 0, 0, 0, 207, 208, 1, 0, 0, 0, 208, 210, 1, 0, 0, 0, 209, 207, 1, 0, 0, 0, 210, 211, 5, 82, 0, 0, 211, 29, 1, 0, 0, 0, 212, 216, 5, 19, 0, 0, 213, 215, 3, 32, 16, 0, 214, 213, 1, 0, 0, 0, 215, 218, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, 216, 217, 1, 0, 0, 0, 217, 219, 1, 0, 0, 0, 218, 216, 1, 0, 0, 0, 219, 222, 5, 20, 0, 0, 220, 222, 3, 32, 16, 0, 221, 212, 1, 0, 0, 0, 221, 220, 1, 0, 0, 0, 222, 31, 1, 0, 0, 0, 223, 228, 3, 40, 20, 0, 224, 225, 3, 34, 17, 0, 225, 226, 5, 2, 0, 0, 226, 228, 1, 0, 0, 0, 227, 223, 1, 0, 0, 0, 227, 224, 1, 0, 0, 0, 228, 33, 1, 0, 0, 0, 229, 238, 3, 42, 21, 0, 230, 238, 3, 44, 22, 0, 231, 238, 3, 46, 23, 0, 232, 238, 3, 48, 24, 0, 233, 238, 3, 50, 25, 0, 234, 238, 3, 36, 18, 0, 235, 238, 3, 52, 26, 0, 236, 238, 3, 38, 19, 0, 237, 229, 1, 0, 0, 0, 237, 230, 1, 0, 0, 0, 237, 231, 1, 0, 0, 0, 237, 232, 1, 0, 0, 0, 237, 233, 1, 0, 0, 0, 237, 234, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 236, 1, 0, 0, 0, 238, 35, 1, 0, 0, 0, 239, 240, 3, 72, 36, 0, 240, 37, 1, 0, 0, 0, 241, 242, 5, 21, 0, 0, 242, 247, 3, 76, 38, 0, 243, 244, 5, 15, 0, 0, 244, 246, 3, 76, 38, 0, 245, 243, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 39, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 253, 3, 54, 27, 0, 251, 253, 3, 56, 28, 0, 252, 250, 1, 0, 0, 0, 252, 251, 1, 0, 0, 0, 253, 41, 1, 0, 0, 0, 254, 258, 3, 84, 42, 0, 255, 257, 3, 78, 39, 0, 256, 255, 1, 0, 0, 0, 257, 260, 1, 0, 0, 0, 258, 256, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 261, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 261, 262, 5, 82, 0, 0, 262, 263, 5, 10, 0, 0, 263, 264, 3, 76, 38, 0, 264, 43, 1, 0, 0, 0, 265, 266, 3, 84, 42, 0, 266, 271, 5, 82, 0, 0, 267, 268, 5, 15, 0, 0, 268, 269, 3, 84, 42, 0, 269, 270, 5, 82, 0, 0, 270, 272, 1, 0, 0, 0, 271, 267, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 271, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 5, 10, 0, 0, 276, 277, 3, 76, 38, 0, 277, 45, 1, 0, 0, 0, 278, 279, 5, 82, 0, 0, 279, 280, 7, 1, 0, 0, 280, 284, 3, 76, 38, 0, 281, 282, 5, 82, 0, 0, 282, 284, 7, 2, 0, 0, 283, 278, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, 284, 47, 1, 0, 0, 0, 285, 286, 5, 26, 0, 0, 286, 287, 5, 14, 0, 0, 287, 288, 5, 79, 0, 0, 288, 289, 5, 6, 0, 0, 289, 292, 3, 76, 38, 0, 290, 291, 5, 15, 0, 0, 291, 293, 3, 66, 33, 0, 292, 290, 1, 0, 0, 0, 292, 293, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 295, 5, 16, 0, 0, 295, 49, 1, 0, 0, 0, 296, 297, 5, 26, 0, 0, 297, 298, 5, 14, 0, 0, 298, 301, 3, 76, 38, 0, 299, 300, 5, 15, 0, 0, 300, 302, 3, 66, 33, 0, 301, 299, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 303, 1, 0, 0, 0, 303, 304, 5, 16, 0, 0, 304, 51, 1, 0, 0, 0, 305, 306, 5, 27, 0, 0, 306, 307, 3, 70, 35, 0, 307, 53, 1, 0, 0, 0, 308, 309, 5, 28, 0, 0, 309, 310, 5, 14, 0, 0, 310, 311, 3, 76, 38, 0, 311, 312, 5, 16, 0, 0, 312, 315, 3, 30, 15, 0, 313, 314, 5, 29, 0, 0, 314, 316, 3, 30, 15, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 55, 1, 0, 0, 0, 317, 321, 3, 58, 29, 0, 318, 321, 3, 60, 30, 0, 319, 321, 3, 62, 31, 0, 320, 317, 1, 0, 0, 0, 320, 318, 1, 0, 0, 0, 320, 319, 1, 0, 0, 0, 321, 57, 1, 0, 0, 0, 322, 323, 5, 30, 0, 0, 323, 324, 3, 30, 15, 0, 324, 325, 5, 31, 0, 0, 325, 326, 5, 14, 0, 0, 326, 327, 3, 76, 38, 0, 327, 328, 5, 16, 0, 0, 328, 329, 5, 2, 0, 0, 329, 59, 1, 0, 0, 0, 330, 331, 5, 31, 0, 0, 331, 332, 5, 14, 0, 0, 332, 333, 3, 76, 38, 0, 333, 334, 5, 16, 0, 0, 334, 335, 3, 30, 15, 0, 335, 61, 1, 0, 0, 0, 336, 337, 5, 32, 0, 0, 337, 338, 5, 14, 0, 0, 338, 339, 3, 64, 32, 0, 339, 340, 5, 2, 0, 0, 340, 341, 3, 76, 38, 0, 341, 342, 5, 2, 0, 0, 342, 343, 3, 46, 23, 0, 343, 344, 5, 16, 0, 0, 344, 345, 3, 30, 15, 0, 345, 63, 1, 0, 0, 0, 346, 349, 3, 42, 21, 0, 347, 349, 3, 46, 23, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0, 0, 349, 65, 1, 0, 0, 0, 350, 351, 5, 76, 0, 0, 351, 67, 1, 0, 0, 0, 352, 355, 5, 82, 0, 0, 353, 355, 3, 80, 40, 0, 354, 352, 1, 0, 0, 0, 354, 353, 1, 0, 0, 0, 355, 69, 1, 0, 0, 0, 356, 368, 5, 14, 0, 0, 357, 362, 3, 68, 34, 0, 358, 359, 5, 15, 0, 0, 359, 361, 3, 68, 34, 0, 360, 358, 1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 366, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 365, 367, 5, 15, 0, 0, 366, 365, 1, 0, 0, 0, 366, 367, 1, 0, 0, 0, 367, 369, 1, 0, 0, 0, 368, 357, 1, 0, 0, 0, 368, 369, 1, 0, 0, 0, 369, 370, 1, 0, 0, 0, 370, 371, 5, 16, 0, 0, 371, 71, 1, 0, 0, 0, 372, 373, 5, 82, 0, 0, 373, 374, 3, 74, 37, 0, 374, 73, 1, 0, 0, 0, 375, 387, 5, 14, 0, 0, 376, 381, 3, 76, 38, 0, 377, 378, 5, 15, 0, 0, 378, 380, 3, 76, 38, 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, 15, 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, 16, 0, 0, 390, 75, 1, 0, 0, 0, 391, 392, 6, 38, -1, 0, 392, 393, 5, 14, 0, 0, 393, 394, 3, 76, 38, 0, 394, 395, 5, 16, 0, 0, 395, 441, 1, 0, 0, 0, 396, 397, 3, 86, 43, 0, 397, 398, 5, 14, 0, 0, 398, 400, 3, 76, 38, 0, 399, 401, 5, 15, 0, 0, 400, 399, 1, 0, 0, 0, 400, 401, 1, 0, 0, 0, 401, 402, 1, 0, 0, 0, 402, 403, 5, 16, 0, 0, 403, 441, 1, 0, 0, 0, 404, 441, 3, 72, 36, 0, 405, 406, 5, 33, 0, 0, 406, 407, 5, 82, 0, 0, 407, 441, 3, 74, 37, 0, 408, 409, 5, 36, 0, 0, 409, 410, 5, 34, 0, 0, 410, 411, 3, 76, 38, 0, 411, 412, 5, 35, 0, 0, 412, 413, 7, 3, 0, 0, 413, 441, 1, 0, 0, 0, 414, 415, 5, 42, 0, 0, 415, 416, 5, 34, 0, 0, 416, 417, 3, 76, 38, 0, 417, 418, 5, 35, 0, 0, 418, 419, 7, 4, 0, 0, 419, 441, 1, 0, 0, 0, 420, 421, 7, 5, 0, 0, 421, 441, 3, 76, 38, 15, 422, 434, 5, 34, 0, 0, 423, 428, 3, 76, 38, 0, 424, 425, 5, 15, 0, 0, 425, 427, 3, 76, 38, 0, 426, 424, 1, 0, 0, 0, 427, 430, 1, 0, 0, 0, 428, 426, 1, 0, 0, 0, 428, 429, 1, 0, 0, 0, 429, 432, 1, 0, 0, 0, 430, 428, 1, 0, 0, 0, 431, 433, 5, 15, 0, 0, 432, 431, 1, 0, 0, 0, 432, 433, 1, 0, 0, 0, 433, 435, 1, 0, 0, 0, 434, 423, 1, 0, 0, 0, 434, 435, 1, 0, 0, 0, 435, 436, 1, 0, 0, 0, 436, 441, 5, 35, 0, 0, 437, 441, 5, 81, 0, 0, 438, 441, 5, 82, 0, 0, 439, 441, 3, 80, 40, 0, 440, 391, 1, 0, 0, 0, 440, 396, 1, 0, 0, 0, 440, 404, 1, 0, 0, 0, 440, 405, 1, 0, 0, 0, 440, 408, 1, 0, 0, 0, 440, 414, 1, 0, 0, 0, 440, 420, 1, 0, 0, 0, 440, 422, 1, 0, 0, 0, 440, 437, 1, 0, 0, 0, 440, 438, 1, 0, 0, 0, 440, 439, 1, 0, 0, 0, 441, 494, 1, 0, 0, 0, 442, 443, 10, 14, 0, 0, 443, 444, 7, 6, 0, 0, 444, 493, 3, 76, 38, 15, 445, 446, 10, 13, 0, 0, 446, 447, 7, 7, 0, 0, 447, 493, 3, 76, 38, 14, 448, 449, 10, 12, 0, 0, 449, 450, 7, 8, 0, 0, 450, 493, 3, 76, 38, 13, 451, 452, 10, 11, 0, 0, 452, 453, 7, 9, 0, 0, 453, 493, 3, 76, 38, 12, 454, 455, 10, 10, 0, 0, 455, 456, 7, 10, 0, 0, 456, 493, 3, 76, 38, 11, 457, 458, 10, 9, 0, 0, 458, 459, 5, 61, 0, 0, 459, 493, 3, 76, 38, 10, 460, 461, 10, 8, 0, 0, 461, 462, 5, 4, 0, 0, 462, 493, 3, 76, 38, 9, 463, 464, 10, 7, 0, 0, 464, 465, 5, 62, 0, 0, 465, 493, 3, 76, 38, 8, 466, 467, 10, 6, 0, 0, 467, 468, 5, 63, 0, 0, 468, 493, 3, 76, 38, 7, 469, 470, 10, 5, 0, 0, 470, 471, 5, 64, 0, 0, 471, 493, 3, 76, 38, 6, 472, 473, 10, 21, 0, 0, 473, 474, 5, 34, 0, 0, 474, 475, 5, 69, 0, 0, 475, 493, 5, 35, 0, 0, 476, 477, 10, 18, 0, 0, 477, 493, 7, 11, 0, 0, 478, 479, 10, 17, 0, 0, 479, 480, 5, 49, 0, 0, 480, 481, 5, 14, 0, 0, 481, 482, 3, 76, 38, 0, 482, 483, 5, 16, 0, 0, 483, 493, 1, 0, 0, 0, 484, 485, 10, 16, 0, 0, 485, 486, 5, 50, 0, 0, 486, 487, 5, 14, 0, 0, 487, 488, 3, 76, 38, 0, 488, 489, 5, 15, 0, 0, 489, 490, 3, 76, 38, 0, 490, 491, 5, 16, 0, 0, 491, 493, 1, 0, 0, 0, 492, 442, 1, 0, 0, 0, 492, 445, 1, 0, 0, 0, 492, 448, 1, 0, 0, 0, 492, 451, 1, 0, 0, 0, 492, 454, 1, 0, 0, 0, 492, 457, 1, 0, 0, 0, 492, 460, 1, 0, 0, 0, 492, 463, 1, 0, 0, 0, 492, 466, 1, 0, 0, 0, 492, 469, 1, 0, 0, 0, 492, 472, 1, 0, 0, 0, 492, 476, 1, 0, 0, 0, 492, 478, 1, 0, 0, 0, 492, 484, 1, 0, 0, 0, 493, 496, 1, 0, 0, 0, 494, 492, 1, 0, 0, 0, 494, 495, 1, 0, 0, 0, 495, 77, 1, 0, 0, 0, 496, 494, 1, 0, 0, 0, 497, 498, 7, 12, 0, 0, 498, 79, 1, 0, 0, 0, 499, 505, 5, 67, 0, 0, 500, 505, 3, 82, 41, 0, 501, 505, 5, 76, 0, 0, 502, 505, 5, 77, 0, 0, 503, 505, 5, 78, 0, 0, 504, 499, 1, 0, 0, 0, 504, 500, 1, 0, 0, 0, 504, 501, 1, 0, 0, 0, 504, 502, 1, 0, 0, 0, 504, 503, 1, 0, 0, 0, 505, 81, 1, 0, 0, 0, 506, 508, 5, 69, 0, 0, 507, 509, 5, 68, 0, 0, 508, 507, 1, 0, 0, 0, 508, 509, 1, 0, 0, 0, 509, 83, 1, 0, 0, 0, 510, 511, 7, 13, 0, 0, 511, 85, 1, 0, 0, 0, 512, 513, 7, 14, 0, 0, 513, 87, 1, 0, 0, 0, 44, 91, 97, 103, 117, 120, 133, 145, 150, 168, 182, 193, 197, 199, 207, 216, 221, 227, 237, 247, 252, 258, 273, 283, 292, 301, 315, 320, 348, 354, 362, 366, 368, 381, 385, 387, 400, 428, 432, 434, 440, 492, 494, 504, 508] \ No newline at end of file +[4, 1, 85, 515, 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, 1, 0, 5, 0, 90, 8, 0, 10, 0, 12, 0, 93, 9, 0, 1, 0, 5, 0, 96, 8, 0, 10, 0, 12, 0, 99, 9, 0, 1, 0, 5, 0, 102, 8, 0, 10, 0, 12, 0, 105, 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, 118, 8, 3, 1, 4, 3, 4, 121, 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, 134, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 144, 8, 8, 10, 8, 12, 8, 147, 9, 8, 1, 8, 1, 8, 3, 8, 151, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 167, 8, 10, 10, 10, 12, 10, 170, 9, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 5, 12, 181, 8, 12, 10, 12, 12, 12, 184, 9, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 192, 8, 13, 10, 13, 12, 13, 195, 9, 13, 1, 13, 3, 13, 198, 8, 13, 3, 13, 200, 8, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 206, 8, 14, 10, 14, 12, 14, 209, 9, 14, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 215, 8, 15, 10, 15, 12, 15, 218, 9, 15, 1, 15, 1, 15, 3, 15, 222, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 228, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 238, 8, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 246, 8, 19, 10, 19, 12, 19, 249, 9, 19, 1, 20, 1, 20, 3, 20, 253, 8, 20, 1, 21, 1, 21, 5, 21, 257, 8, 21, 10, 21, 12, 21, 260, 9, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 4, 22, 272, 8, 22, 11, 22, 12, 22, 273, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 284, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 293, 8, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 302, 8, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 316, 8, 27, 1, 28, 1, 28, 1, 28, 3, 28, 321, 8, 28, 1, 29, 1, 29, 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, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 349, 8, 32, 1, 33, 1, 33, 1, 34, 1, 34, 3, 34, 355, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 361, 8, 35, 10, 35, 12, 35, 364, 9, 35, 1, 35, 3, 35, 367, 8, 35, 3, 35, 369, 8, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 380, 8, 37, 10, 37, 12, 37, 383, 9, 37, 1, 37, 3, 37, 386, 8, 37, 3, 37, 388, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 401, 8, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 427, 8, 38, 10, 38, 12, 38, 430, 9, 38, 1, 38, 3, 38, 433, 8, 38, 3, 38, 435, 8, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 441, 8, 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, 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, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 493, 8, 38, 10, 38, 12, 38, 496, 9, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 505, 8, 40, 1, 41, 1, 41, 3, 41, 509, 8, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 0, 1, 76, 44, 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, 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, 17, 17, 65, 65, 1, 0, 72, 74, 2, 0, 72, 73, 80, 80, 546, 0, 91, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 4, 113, 1, 0, 0, 0, 6, 115, 1, 0, 0, 0, 8, 120, 1, 0, 0, 0, 10, 124, 1, 0, 0, 0, 12, 126, 1, 0, 0, 0, 14, 133, 1, 0, 0, 0, 16, 135, 1, 0, 0, 0, 18, 154, 1, 0, 0, 0, 20, 161, 1, 0, 0, 0, 22, 173, 1, 0, 0, 0, 24, 178, 1, 0, 0, 0, 26, 187, 1, 0, 0, 0, 28, 203, 1, 0, 0, 0, 30, 221, 1, 0, 0, 0, 32, 227, 1, 0, 0, 0, 34, 237, 1, 0, 0, 0, 36, 239, 1, 0, 0, 0, 38, 241, 1, 0, 0, 0, 40, 252, 1, 0, 0, 0, 42, 254, 1, 0, 0, 0, 44, 265, 1, 0, 0, 0, 46, 283, 1, 0, 0, 0, 48, 285, 1, 0, 0, 0, 50, 296, 1, 0, 0, 0, 52, 305, 1, 0, 0, 0, 54, 308, 1, 0, 0, 0, 56, 320, 1, 0, 0, 0, 58, 322, 1, 0, 0, 0, 60, 330, 1, 0, 0, 0, 62, 336, 1, 0, 0, 0, 64, 348, 1, 0, 0, 0, 66, 350, 1, 0, 0, 0, 68, 354, 1, 0, 0, 0, 70, 356, 1, 0, 0, 0, 72, 372, 1, 0, 0, 0, 74, 375, 1, 0, 0, 0, 76, 440, 1, 0, 0, 0, 78, 497, 1, 0, 0, 0, 80, 504, 1, 0, 0, 0, 82, 506, 1, 0, 0, 0, 84, 510, 1, 0, 0, 0, 86, 512, 1, 0, 0, 0, 88, 90, 3, 2, 1, 0, 89, 88, 1, 0, 0, 0, 90, 93, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 97, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 94, 96, 3, 12, 6, 0, 95, 94, 1, 0, 0, 0, 96, 99, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 103, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 100, 102, 3, 14, 7, 0, 101, 100, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 107, 5, 0, 0, 1, 107, 1, 1, 0, 0, 0, 108, 109, 5, 1, 0, 0, 109, 110, 3, 4, 2, 0, 110, 111, 3, 6, 3, 0, 111, 112, 5, 2, 0, 0, 112, 3, 1, 0, 0, 0, 113, 114, 5, 3, 0, 0, 114, 5, 1, 0, 0, 0, 115, 117, 3, 8, 4, 0, 116, 118, 3, 8, 4, 0, 117, 116, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 7, 1, 0, 0, 0, 119, 121, 3, 10, 5, 0, 120, 119, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 123, 5, 66, 0, 0, 123, 9, 1, 0, 0, 0, 124, 125, 7, 0, 0, 0, 125, 11, 1, 0, 0, 0, 126, 127, 5, 11, 0, 0, 127, 128, 5, 76, 0, 0, 128, 129, 5, 2, 0, 0, 129, 13, 1, 0, 0, 0, 130, 134, 3, 16, 8, 0, 131, 134, 3, 18, 9, 0, 132, 134, 3, 20, 10, 0, 133, 130, 1, 0, 0, 0, 133, 131, 1, 0, 0, 0, 133, 132, 1, 0, 0, 0, 134, 15, 1, 0, 0, 0, 135, 136, 5, 12, 0, 0, 136, 137, 5, 82, 0, 0, 137, 150, 3, 26, 13, 0, 138, 139, 5, 13, 0, 0, 139, 140, 5, 14, 0, 0, 140, 145, 3, 84, 42, 0, 141, 142, 5, 15, 0, 0, 142, 144, 3, 84, 42, 0, 143, 141, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 148, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 149, 5, 16, 0, 0, 149, 151, 1, 0, 0, 0, 150, 138, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 153, 3, 24, 12, 0, 153, 17, 1, 0, 0, 0, 154, 155, 3, 84, 42, 0, 155, 156, 5, 17, 0, 0, 156, 157, 5, 82, 0, 0, 157, 158, 5, 10, 0, 0, 158, 159, 3, 76, 38, 0, 159, 160, 5, 2, 0, 0, 160, 19, 1, 0, 0, 0, 161, 162, 5, 18, 0, 0, 162, 163, 5, 82, 0, 0, 163, 164, 3, 26, 13, 0, 164, 168, 5, 19, 0, 0, 165, 167, 3, 22, 11, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 172, 5, 20, 0, 0, 172, 21, 1, 0, 0, 0, 173, 174, 5, 12, 0, 0, 174, 175, 5, 82, 0, 0, 175, 176, 3, 26, 13, 0, 176, 177, 3, 24, 12, 0, 177, 23, 1, 0, 0, 0, 178, 182, 5, 19, 0, 0, 179, 181, 3, 32, 16, 0, 180, 179, 1, 0, 0, 0, 181, 184, 1, 0, 0, 0, 182, 180, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 185, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 186, 5, 20, 0, 0, 186, 25, 1, 0, 0, 0, 187, 199, 5, 14, 0, 0, 188, 193, 3, 28, 14, 0, 189, 190, 5, 15, 0, 0, 190, 192, 3, 28, 14, 0, 191, 189, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 198, 5, 15, 0, 0, 197, 196, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 200, 1, 0, 0, 0, 199, 188, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, 202, 5, 16, 0, 0, 202, 27, 1, 0, 0, 0, 203, 207, 3, 84, 42, 0, 204, 206, 3, 78, 39, 0, 205, 204, 1, 0, 0, 0, 206, 209, 1, 0, 0, 0, 207, 205, 1, 0, 0, 0, 207, 208, 1, 0, 0, 0, 208, 210, 1, 0, 0, 0, 209, 207, 1, 0, 0, 0, 210, 211, 5, 82, 0, 0, 211, 29, 1, 0, 0, 0, 212, 216, 5, 19, 0, 0, 213, 215, 3, 32, 16, 0, 214, 213, 1, 0, 0, 0, 215, 218, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, 216, 217, 1, 0, 0, 0, 217, 219, 1, 0, 0, 0, 218, 216, 1, 0, 0, 0, 219, 222, 5, 20, 0, 0, 220, 222, 3, 32, 16, 0, 221, 212, 1, 0, 0, 0, 221, 220, 1, 0, 0, 0, 222, 31, 1, 0, 0, 0, 223, 228, 3, 40, 20, 0, 224, 225, 3, 34, 17, 0, 225, 226, 5, 2, 0, 0, 226, 228, 1, 0, 0, 0, 227, 223, 1, 0, 0, 0, 227, 224, 1, 0, 0, 0, 228, 33, 1, 0, 0, 0, 229, 238, 3, 42, 21, 0, 230, 238, 3, 44, 22, 0, 231, 238, 3, 46, 23, 0, 232, 238, 3, 48, 24, 0, 233, 238, 3, 50, 25, 0, 234, 238, 3, 36, 18, 0, 235, 238, 3, 52, 26, 0, 236, 238, 3, 38, 19, 0, 237, 229, 1, 0, 0, 0, 237, 230, 1, 0, 0, 0, 237, 231, 1, 0, 0, 0, 237, 232, 1, 0, 0, 0, 237, 233, 1, 0, 0, 0, 237, 234, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 236, 1, 0, 0, 0, 238, 35, 1, 0, 0, 0, 239, 240, 3, 72, 36, 0, 240, 37, 1, 0, 0, 0, 241, 242, 5, 21, 0, 0, 242, 247, 3, 76, 38, 0, 243, 244, 5, 15, 0, 0, 244, 246, 3, 76, 38, 0, 245, 243, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 39, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 253, 3, 54, 27, 0, 251, 253, 3, 56, 28, 0, 252, 250, 1, 0, 0, 0, 252, 251, 1, 0, 0, 0, 253, 41, 1, 0, 0, 0, 254, 258, 3, 84, 42, 0, 255, 257, 3, 78, 39, 0, 256, 255, 1, 0, 0, 0, 257, 260, 1, 0, 0, 0, 258, 256, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 261, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 261, 262, 5, 82, 0, 0, 262, 263, 5, 10, 0, 0, 263, 264, 3, 76, 38, 0, 264, 43, 1, 0, 0, 0, 265, 266, 3, 84, 42, 0, 266, 271, 5, 82, 0, 0, 267, 268, 5, 15, 0, 0, 268, 269, 3, 84, 42, 0, 269, 270, 5, 82, 0, 0, 270, 272, 1, 0, 0, 0, 271, 267, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 271, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 5, 10, 0, 0, 276, 277, 3, 76, 38, 0, 277, 45, 1, 0, 0, 0, 278, 279, 5, 82, 0, 0, 279, 280, 7, 1, 0, 0, 280, 284, 3, 76, 38, 0, 281, 282, 5, 82, 0, 0, 282, 284, 7, 2, 0, 0, 283, 278, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, 284, 47, 1, 0, 0, 0, 285, 286, 5, 26, 0, 0, 286, 287, 5, 14, 0, 0, 287, 288, 5, 79, 0, 0, 288, 289, 5, 6, 0, 0, 289, 292, 3, 76, 38, 0, 290, 291, 5, 15, 0, 0, 291, 293, 3, 66, 33, 0, 292, 290, 1, 0, 0, 0, 292, 293, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 295, 5, 16, 0, 0, 295, 49, 1, 0, 0, 0, 296, 297, 5, 26, 0, 0, 297, 298, 5, 14, 0, 0, 298, 301, 3, 76, 38, 0, 299, 300, 5, 15, 0, 0, 300, 302, 3, 66, 33, 0, 301, 299, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 303, 1, 0, 0, 0, 303, 304, 5, 16, 0, 0, 304, 51, 1, 0, 0, 0, 305, 306, 5, 27, 0, 0, 306, 307, 3, 70, 35, 0, 307, 53, 1, 0, 0, 0, 308, 309, 5, 28, 0, 0, 309, 310, 5, 14, 0, 0, 310, 311, 3, 76, 38, 0, 311, 312, 5, 16, 0, 0, 312, 315, 3, 30, 15, 0, 313, 314, 5, 29, 0, 0, 314, 316, 3, 30, 15, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 55, 1, 0, 0, 0, 317, 321, 3, 58, 29, 0, 318, 321, 3, 60, 30, 0, 319, 321, 3, 62, 31, 0, 320, 317, 1, 0, 0, 0, 320, 318, 1, 0, 0, 0, 320, 319, 1, 0, 0, 0, 321, 57, 1, 0, 0, 0, 322, 323, 5, 30, 0, 0, 323, 324, 3, 30, 15, 0, 324, 325, 5, 31, 0, 0, 325, 326, 5, 14, 0, 0, 326, 327, 3, 76, 38, 0, 327, 328, 5, 16, 0, 0, 328, 329, 5, 2, 0, 0, 329, 59, 1, 0, 0, 0, 330, 331, 5, 31, 0, 0, 331, 332, 5, 14, 0, 0, 332, 333, 3, 76, 38, 0, 333, 334, 5, 16, 0, 0, 334, 335, 3, 30, 15, 0, 335, 61, 1, 0, 0, 0, 336, 337, 5, 32, 0, 0, 337, 338, 5, 14, 0, 0, 338, 339, 3, 64, 32, 0, 339, 340, 5, 2, 0, 0, 340, 341, 3, 76, 38, 0, 341, 342, 5, 2, 0, 0, 342, 343, 3, 46, 23, 0, 343, 344, 5, 16, 0, 0, 344, 345, 3, 30, 15, 0, 345, 63, 1, 0, 0, 0, 346, 349, 3, 42, 21, 0, 347, 349, 3, 46, 23, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0, 0, 349, 65, 1, 0, 0, 0, 350, 351, 5, 76, 0, 0, 351, 67, 1, 0, 0, 0, 352, 355, 5, 82, 0, 0, 353, 355, 3, 80, 40, 0, 354, 352, 1, 0, 0, 0, 354, 353, 1, 0, 0, 0, 355, 69, 1, 0, 0, 0, 356, 368, 5, 14, 0, 0, 357, 362, 3, 68, 34, 0, 358, 359, 5, 15, 0, 0, 359, 361, 3, 68, 34, 0, 360, 358, 1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 366, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 365, 367, 5, 15, 0, 0, 366, 365, 1, 0, 0, 0, 366, 367, 1, 0, 0, 0, 367, 369, 1, 0, 0, 0, 368, 357, 1, 0, 0, 0, 368, 369, 1, 0, 0, 0, 369, 370, 1, 0, 0, 0, 370, 371, 5, 16, 0, 0, 371, 71, 1, 0, 0, 0, 372, 373, 5, 82, 0, 0, 373, 374, 3, 74, 37, 0, 374, 73, 1, 0, 0, 0, 375, 387, 5, 14, 0, 0, 376, 381, 3, 76, 38, 0, 377, 378, 5, 15, 0, 0, 378, 380, 3, 76, 38, 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, 15, 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, 16, 0, 0, 390, 75, 1, 0, 0, 0, 391, 392, 6, 38, -1, 0, 392, 393, 5, 14, 0, 0, 393, 394, 3, 76, 38, 0, 394, 395, 5, 16, 0, 0, 395, 441, 1, 0, 0, 0, 396, 397, 3, 86, 43, 0, 397, 398, 5, 14, 0, 0, 398, 400, 3, 76, 38, 0, 399, 401, 5, 15, 0, 0, 400, 399, 1, 0, 0, 0, 400, 401, 1, 0, 0, 0, 401, 402, 1, 0, 0, 0, 402, 403, 5, 16, 0, 0, 403, 441, 1, 0, 0, 0, 404, 441, 3, 72, 36, 0, 405, 406, 5, 33, 0, 0, 406, 407, 5, 82, 0, 0, 407, 441, 3, 74, 37, 0, 408, 409, 5, 36, 0, 0, 409, 410, 5, 34, 0, 0, 410, 411, 3, 76, 38, 0, 411, 412, 5, 35, 0, 0, 412, 413, 7, 3, 0, 0, 413, 441, 1, 0, 0, 0, 414, 415, 5, 42, 0, 0, 415, 416, 5, 34, 0, 0, 416, 417, 3, 76, 38, 0, 417, 418, 5, 35, 0, 0, 418, 419, 7, 4, 0, 0, 419, 441, 1, 0, 0, 0, 420, 421, 7, 5, 0, 0, 421, 441, 3, 76, 38, 15, 422, 434, 5, 34, 0, 0, 423, 428, 3, 76, 38, 0, 424, 425, 5, 15, 0, 0, 425, 427, 3, 76, 38, 0, 426, 424, 1, 0, 0, 0, 427, 430, 1, 0, 0, 0, 428, 426, 1, 0, 0, 0, 428, 429, 1, 0, 0, 0, 429, 432, 1, 0, 0, 0, 430, 428, 1, 0, 0, 0, 431, 433, 5, 15, 0, 0, 432, 431, 1, 0, 0, 0, 432, 433, 1, 0, 0, 0, 433, 435, 1, 0, 0, 0, 434, 423, 1, 0, 0, 0, 434, 435, 1, 0, 0, 0, 435, 436, 1, 0, 0, 0, 436, 441, 5, 35, 0, 0, 437, 441, 5, 81, 0, 0, 438, 441, 5, 82, 0, 0, 439, 441, 3, 80, 40, 0, 440, 391, 1, 0, 0, 0, 440, 396, 1, 0, 0, 0, 440, 404, 1, 0, 0, 0, 440, 405, 1, 0, 0, 0, 440, 408, 1, 0, 0, 0, 440, 414, 1, 0, 0, 0, 440, 420, 1, 0, 0, 0, 440, 422, 1, 0, 0, 0, 440, 437, 1, 0, 0, 0, 440, 438, 1, 0, 0, 0, 440, 439, 1, 0, 0, 0, 441, 494, 1, 0, 0, 0, 442, 443, 10, 14, 0, 0, 443, 444, 7, 6, 0, 0, 444, 493, 3, 76, 38, 15, 445, 446, 10, 13, 0, 0, 446, 447, 7, 7, 0, 0, 447, 493, 3, 76, 38, 14, 448, 449, 10, 12, 0, 0, 449, 450, 7, 8, 0, 0, 450, 493, 3, 76, 38, 13, 451, 452, 10, 11, 0, 0, 452, 453, 7, 9, 0, 0, 453, 493, 3, 76, 38, 12, 454, 455, 10, 10, 0, 0, 455, 456, 7, 10, 0, 0, 456, 493, 3, 76, 38, 11, 457, 458, 10, 9, 0, 0, 458, 459, 5, 61, 0, 0, 459, 493, 3, 76, 38, 10, 460, 461, 10, 8, 0, 0, 461, 462, 5, 4, 0, 0, 462, 493, 3, 76, 38, 9, 463, 464, 10, 7, 0, 0, 464, 465, 5, 62, 0, 0, 465, 493, 3, 76, 38, 8, 466, 467, 10, 6, 0, 0, 467, 468, 5, 63, 0, 0, 468, 493, 3, 76, 38, 7, 469, 470, 10, 5, 0, 0, 470, 471, 5, 64, 0, 0, 471, 493, 3, 76, 38, 6, 472, 473, 10, 21, 0, 0, 473, 474, 5, 34, 0, 0, 474, 475, 5, 69, 0, 0, 475, 493, 5, 35, 0, 0, 476, 477, 10, 18, 0, 0, 477, 493, 7, 11, 0, 0, 478, 479, 10, 17, 0, 0, 479, 480, 5, 49, 0, 0, 480, 481, 5, 14, 0, 0, 481, 482, 3, 76, 38, 0, 482, 483, 5, 16, 0, 0, 483, 493, 1, 0, 0, 0, 484, 485, 10, 16, 0, 0, 485, 486, 5, 50, 0, 0, 486, 487, 5, 14, 0, 0, 487, 488, 3, 76, 38, 0, 488, 489, 5, 15, 0, 0, 489, 490, 3, 76, 38, 0, 490, 491, 5, 16, 0, 0, 491, 493, 1, 0, 0, 0, 492, 442, 1, 0, 0, 0, 492, 445, 1, 0, 0, 0, 492, 448, 1, 0, 0, 0, 492, 451, 1, 0, 0, 0, 492, 454, 1, 0, 0, 0, 492, 457, 1, 0, 0, 0, 492, 460, 1, 0, 0, 0, 492, 463, 1, 0, 0, 0, 492, 466, 1, 0, 0, 0, 492, 469, 1, 0, 0, 0, 492, 472, 1, 0, 0, 0, 492, 476, 1, 0, 0, 0, 492, 478, 1, 0, 0, 0, 492, 484, 1, 0, 0, 0, 493, 496, 1, 0, 0, 0, 494, 492, 1, 0, 0, 0, 494, 495, 1, 0, 0, 0, 495, 77, 1, 0, 0, 0, 496, 494, 1, 0, 0, 0, 497, 498, 7, 12, 0, 0, 498, 79, 1, 0, 0, 0, 499, 505, 5, 67, 0, 0, 500, 505, 3, 82, 41, 0, 501, 505, 5, 76, 0, 0, 502, 505, 5, 77, 0, 0, 503, 505, 5, 78, 0, 0, 504, 499, 1, 0, 0, 0, 504, 500, 1, 0, 0, 0, 504, 501, 1, 0, 0, 0, 504, 502, 1, 0, 0, 0, 504, 503, 1, 0, 0, 0, 505, 81, 1, 0, 0, 0, 506, 508, 5, 69, 0, 0, 507, 509, 5, 68, 0, 0, 508, 507, 1, 0, 0, 0, 508, 509, 1, 0, 0, 0, 509, 83, 1, 0, 0, 0, 510, 511, 7, 13, 0, 0, 511, 85, 1, 0, 0, 0, 512, 513, 7, 14, 0, 0, 513, 87, 1, 0, 0, 0, 44, 91, 97, 103, 117, 120, 133, 145, 150, 168, 182, 193, 197, 199, 207, 216, 221, 227, 237, 247, 252, 258, 273, 283, 292, 301, 315, 320, 348, 354, 362, 366, 368, 381, 385, 387, 400, 428, 432, 434, 440, 492, 494, 504, 508] \ No newline at end of file diff --git a/packages/cashc/src/grammar/CashScriptParser.ts b/packages/cashc/src/grammar/CashScriptParser.ts index 668cd1794..c94f6b254 100644 --- a/packages/cashc/src/grammar/CashScriptParser.ts +++ b/packages/cashc/src/grammar/CashScriptParser.ts @@ -661,7 +661,7 @@ export default class CashScriptParser extends Parser { this.state = 157; this.match(CashScriptParser.T__9); this.state = 158; - this.literal(); + this.expression(0); this.state = 159; this.match(CashScriptParser.T__1); } @@ -2812,7 +2812,7 @@ export default class CashScriptParser extends Parser { 0,146,148,1,0,0,0,147,145,1,0,0,0,148,149,5,16,0,0,149,151,1,0,0,0,150, 138,1,0,0,0,150,151,1,0,0,0,151,152,1,0,0,0,152,153,3,24,12,0,153,17,1, 0,0,0,154,155,3,84,42,0,155,156,5,17,0,0,156,157,5,82,0,0,157,158,5,10, - 0,0,158,159,3,80,40,0,159,160,5,2,0,0,160,19,1,0,0,0,161,162,5,18,0,0,162, + 0,0,158,159,3,76,38,0,159,160,5,2,0,0,160,19,1,0,0,0,161,162,5,18,0,0,162, 163,5,82,0,0,163,164,3,26,13,0,164,168,5,19,0,0,165,167,3,22,11,0,166,165, 1,0,0,0,167,170,1,0,0,0,168,166,1,0,0,0,168,169,1,0,0,0,169,171,1,0,0,0, 170,168,1,0,0,0,171,172,5,20,0,0,172,21,1,0,0,0,173,174,5,12,0,0,174,175, @@ -3176,8 +3176,8 @@ export class ConstantDefinitionContext extends ParserRuleContext { public Identifier(): TerminalNode { return this.getToken(CashScriptParser.Identifier, 0); } - public literal(): LiteralContext { - return this.getTypedRuleContext(LiteralContext, 0) as LiteralContext; + public expression(): ExpressionContext { + return this.getTypedRuleContext(ExpressionContext, 0) as ExpressionContext; } public get ruleIndex(): number { return CashScriptParser.RULE_constantDefinition; diff --git a/packages/cashc/src/print/OutputSourceCodeTraversal.ts b/packages/cashc/src/print/OutputSourceCodeTraversal.ts index bfb1e5a22..b6921d3ba 100644 --- a/packages/cashc/src/print/OutputSourceCodeTraversal.ts +++ b/packages/cashc/src/print/OutputSourceCodeTraversal.ts @@ -38,7 +38,6 @@ import { ForNode, NonControlStatementNode, ExpressionNode, - LiteralNode, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; @@ -112,7 +111,7 @@ export default class OutputSourceCodeTraversal extends AstTraversal { visitConstantDefinition(node: ConstantDefinitionNode): Node { this.addOutput(`${node.type} constant ${node.name} = `, true); - node.value = this.visit(node.value) as LiteralNode; + node.value = this.visit(node.value) as ExpressionNode; this.addOutput(';\n'); return node; } diff --git a/packages/cashc/src/semantic/FoldGlobalConstantsTraversal.ts b/packages/cashc/src/semantic/FoldGlobalConstantsTraversal.ts new file mode 100644 index 000000000..a75890077 --- /dev/null +++ b/packages/cashc/src/semantic/FoldGlobalConstantsTraversal.ts @@ -0,0 +1,149 @@ +import { PrimitiveType } from '@cashscript/utils'; +import { + BinaryOpNode, + ConstantDefinitionNode, + ExpressionNode, + HexLiteralNode, + IdentifierNode, + IntLiteralNode, + LiteralNode, + Node, + SourceFileNode, + StringLiteralNode, + UnaryOpNode, +} from '../ast/AST.js'; +import AstTraversal from '../ast/AstTraversal.js'; +import { GLOBAL_SYMBOL_TABLE } from '../ast/Globals.js'; +import { BinaryOperator, UnaryOperator } from '../ast/Operator.js'; +import { cloneConstantValue } from './LowerGlobalConstantsTraversal.js'; +import { resultingTypeForBinaryOp } from '../utils.js'; +import { + CashScriptError, + DivisionByZeroError, + InvalidConstantExpressionError, + UndefinedReferenceError, + UnequalTypeError, + UnsupportedTypeError, +} from '../Errors.js'; + +// Supports literals, references to other constants, integer arithmetic (+, -, *, /, %, unary -) and concatenation (+) +export class FoldGlobalConstantsTraversal extends AstTraversal { + private foldedConstants: Map = new Map(); + private functionNames: Set = new Set(); + + visitSourceFile(node: SourceFileNode): Node { + this.functionNames = new Set(node.functions.map((func) => func.name)); + node.constants = this.visitList(node.constants) as ConstantDefinitionNode[]; + return node; + } + + visitConstantDefinition(node: ConstantDefinitionNode): Node { + node.value = this.visitExpression(node.value); + this.foldedConstants.set(node.name, node); + return node; + } + + // Folds an expression through the regular visitor dispatch and rejects any expression kind + // that did not fold down to a single literal + private visitExpression(node: ExpressionNode): LiteralNode { + const folded = this.visit(node); + if (!(folded instanceof LiteralNode)) throw new InvalidConstantExpressionError(node); + return folded; + } + + visitIdentifier(node: IdentifierNode): Node { + const constant = this.foldedConstants.get(node.name); + if (constant) return cloneConstantValue(constant, node); + + // Existing names (except previously declared constants) are invalid in a constant initialiser + if (this.functionNames.has(node.name) || GLOBAL_SYMBOL_TABLE.get(node.name)) { + throw new InvalidConstantExpressionError(node); + } + + throw new UndefinedReferenceError(node); + } + + visitUnaryOp(node: UnaryOpNode): Node { + if (!FOLDABLE_UNARY_OPERATORS.includes(node.operator)) throw new InvalidConstantExpressionError(node); + + node.expression = this.visitExpression(node.expression); + if (!(node.expression instanceof IntLiteralNode)) { + throw new UnsupportedTypeError(node, node.expression.type, PrimitiveType.INT); + } + + return withLocation(new IntLiteralNode(-node.expression.value), node); + } + + visitBinaryOp(node: BinaryOpNode): Node { + if (!FOLDABLE_BINARY_OPERATORS.includes(node.operator)) throw new InvalidConstantExpressionError(node); + + // The folded operands are written back so the type errors below report the resolved operand types + node.left = this.visitExpression(node.left); + node.right = this.visitExpression(node.right); + + if (node.operator === BinaryOperator.PLUS) return foldPlus(node); + return foldIntArithmetic(node); + } +} + +const FOLDABLE_UNARY_OPERATORS = [ + UnaryOperator.NEGATE, +]; + +const FOLDABLE_BINARY_OPERATORS = [ + BinaryOperator.PLUS, + BinaryOperator.MINUS, + BinaryOperator.MUL, + BinaryOperator.DIV, + BinaryOperator.MOD, +]; + +function foldPlus(node: BinaryOpNode): LiteralNode { + const { left, right } = node; + + if (left instanceof IntLiteralNode && right instanceof IntLiteralNode) { + return withLocation(new IntLiteralNode(left.value + right.value), node); + } + + if (left instanceof StringLiteralNode && right instanceof StringLiteralNode) { + return withLocation(new StringLiteralNode(left.value + right.value, left.quote), node); + } + + if (left instanceof HexLiteralNode && right instanceof HexLiteralNode) { + return withLocation(new HexLiteralNode(new Uint8Array([...left.value, ...right.value])), node); + } + + throw typeMismatchError(node, PrimitiveType.INT); +} + +function foldIntArithmetic(node: BinaryOpNode): LiteralNode { + const { left, right, operator } = node; + + if (!(left instanceof IntLiteralNode) || !(right instanceof IntLiteralNode)) { + throw typeMismatchError(node, PrimitiveType.INT); + } + + if ((operator === BinaryOperator.DIV || operator === BinaryOperator.MOD) && right.value === 0n) { + throw new DivisionByZeroError(node); + } + + switch (operator) { + case BinaryOperator.MINUS: return withLocation(new IntLiteralNode(left.value - right.value), node); + case BinaryOperator.MUL: return withLocation(new IntLiteralNode(left.value * right.value), node); + // Note: BigInt division and modulo truncate towards zero, matching OP_DIV / OP_MOD semantics + case BinaryOperator.DIV: return withLocation(new IntLiteralNode(left.value / right.value), node); + case BinaryOperator.MOD: return withLocation(new IntLiteralNode(left.value % right.value), node); + default: throw new InvalidConstantExpressionError(node); + } +} + +function typeMismatchError(node: BinaryOpNode, expected: PrimitiveType): CashScriptError { + const resultingType = resultingTypeForBinaryOp(node.operator, node.left.type!, node.right.type!); + if (resultingType) return new UnsupportedTypeError(node, resultingType, expected); + return new UnequalTypeError(node); +} + +function withLocation(literal: T, source: Node): T { + literal.location = source.location; + return literal; +} diff --git a/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts b/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts index 56845d1bc..c6f4e68f9 100644 --- a/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts +++ b/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts @@ -4,6 +4,7 @@ import { ConsoleStatementNode, ConstantDefinitionNode, ContractNode, + ExpressionNode, FunctionCallNode, FunctionDefinitionNode, FunctionKind, @@ -96,17 +97,25 @@ function createConstantFunction(constant: ConstantDefinitionNode): FunctionDefin return definition; } -// Create a synthetic LiteralNode that represents a reference to a lowered constant function, -// so later passes can treat it as a literal -export function createConstantLiteral(constant: ConstantDefinitionNode, reference: IdentifierNode): LiteralNode { +// Clone a constant's literal value, adopting the reference's location and the constant's declared type +export function cloneConstantValue(constant: ConstantDefinitionNode, reference: IdentifierNode): LiteralNode { const literal = cloneLiteral(constant.value); literal.location = reference.location; literal.type = constant.type; + return literal; +} + +// Create a synthetic LiteralNode that represents a reference to a lowered constant function, +// so later passes can treat it as a literal +export function createConstantLiteral(constant: ConstantDefinitionNode, reference: IdentifierNode): LiteralNode { + const literal = cloneConstantValue(constant, reference); literal.constant = constant; return literal; } -function cloneLiteral(node: LiteralNode): LiteralNode { +// SymbolTableTraversal folds every constant's value to a literal before constants are lowered or referenced +function cloneLiteral(node: ExpressionNode): LiteralNode { + if (!(node instanceof LiteralNode)) throw new Error('Expected constant value to be folded to a literal'); // Shouldn't happen const clone: LiteralNode = Object.assign(Object.create(Object.getPrototypeOf(node)), node); if (clone instanceof HexLiteralNode) clone.value = clone.value.slice(); return clone; diff --git a/packages/cashc/src/semantic/TypeCheckTraversal.ts b/packages/cashc/src/semantic/TypeCheckTraversal.ts index f0b89b2af..8a5af6637 100644 --- a/packages/cashc/src/semantic/TypeCheckTraversal.ts +++ b/packages/cashc/src/semantic/TypeCheckTraversal.ts @@ -64,6 +64,7 @@ export default class TypeCheckTraversal extends AstTraversal { private currentFunctionReturnTypes: Type[] = []; visitConstantDefinition(node: ConstantDefinitionNode): Node { + // The constant's value has already been folded to a literal by SymbolTableTraversal node.value = this.visit(node.value) as LiteralNode; expectAssignable(node, node.value.type, node.type); return node; diff --git a/packages/cashc/test/compiler/DivisionByZeroError/global_constant_division_by_zero.cash b/packages/cashc/test/compiler/DivisionByZeroError/global_constant_division_by_zero.cash new file mode 100644 index 000000000..464478aa7 --- /dev/null +++ b/packages/cashc/test/compiler/DivisionByZeroError/global_constant_division_by_zero.cash @@ -0,0 +1,7 @@ +int constant DIVIDED = 10 / 0; + +contract GlobalConstantDivisionByZero() { + function spend() { + require(DIVIDED == 0); + } +} diff --git a/packages/cashc/test/compiler/InvalidConstantExpressionError/global_constant_unsupported_expression.cash b/packages/cashc/test/compiler/InvalidConstantExpressionError/global_constant_unsupported_expression.cash new file mode 100644 index 000000000..cd8f91ff2 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidConstantExpressionError/global_constant_unsupported_expression.cash @@ -0,0 +1,7 @@ +int constant LOCKTIME = tx.locktime; + +contract GlobalConstantUnsupportedExpression() { + function spend() { + require(LOCKTIME == 0); + } +} diff --git a/packages/cashc/test/compiler/ParseError/global_constant_non_literal.cash b/packages/cashc/test/compiler/ParseError/global_constant_non_literal.cash deleted file mode 100644 index c9ee4ec45..000000000 --- a/packages/cashc/test/compiler/ParseError/global_constant_non_literal.cash +++ /dev/null @@ -1,7 +0,0 @@ -int constant VALUE = 4 + 9; - -contract GlobalConstantNonLiteral() { - function spend() { - require(VALUE == 13); - } -} diff --git a/packages/cashc/test/compiler/UndefinedReferenceError/global_constant_forward_reference.cash b/packages/cashc/test/compiler/UndefinedReferenceError/global_constant_forward_reference.cash new file mode 100644 index 000000000..15b8d7c43 --- /dev/null +++ b/packages/cashc/test/compiler/UndefinedReferenceError/global_constant_forward_reference.cash @@ -0,0 +1,8 @@ +int constant DERIVED = BASE + 1; +int constant BASE = 41; + +contract GlobalConstantForwardReference() { + function spend() { + require(DERIVED == 42); + } +} diff --git a/packages/cashc/test/compiler/UnequalTypeError/global_constant_mixed_operands.cash b/packages/cashc/test/compiler/UnequalTypeError/global_constant_mixed_operands.cash new file mode 100644 index 000000000..b297cb48c --- /dev/null +++ b/packages/cashc/test/compiler/UnequalTypeError/global_constant_mixed_operands.cash @@ -0,0 +1,7 @@ +int constant MIXED = 10 + true; + +contract GlobalConstantMixedOperands() { + function spend() { + require(MIXED == 0); + } +} diff --git a/packages/cashc/test/global-definitions.test.ts b/packages/cashc/test/global-definitions.test.ts index b1c00b14a..f2a61d872 100644 --- a/packages/cashc/test/global-definitions.test.ts +++ b/packages/cashc/test/global-definitions.test.ts @@ -143,7 +143,7 @@ describe('Dead-code elimination', () => { } }`; - const withConstant = compileString(`string constant MESSAGE = "debug only";\n${contract('MESSAGE')}`); + const withConstant = compileString(`string constant MESSAGE = "debug" + " only";\n${contract('MESSAGE')}`); expect(withConstant.bytecode).toEqual(compileString(contract('"debug only"')).bytecode); }); }); @@ -372,6 +372,56 @@ describe('Global constants', () => { sourceFile: 'constants.cash', }); }); + + it('folds constant definitions to literals at compile time', () => { + const contract = ` + contract Computed(int number, int derived, string text, bytes4 data) { + function spend() { + require(number == NUMBER); + require(derived == DERIVED); + require(text == TEXT); + require(data == DATA); + } + }`; + + const computed = compileString(` + int constant NUMBER = (10 + 10) * 5 - 30 / 4 % 5; + int constant DERIVED = -NUMBER * 2 + 4; + string constant TEXT = "debug" + " " + "only"; + bytes4 constant DATA = 0x0102 + 0x0304; + ${contract}`); + + const literal = compileString(` + int constant NUMBER = 98; + int constant DERIVED = -192; + string constant TEXT = "debug only"; + bytes4 constant DATA = 0x01020304; + ${contract}`); + + expect(computed.bytecode).toEqual(literal.bytecode); + }); + + it('folds references to imported constants', () => { + const importedSource = 'int constant BASE = 20 + 1;'; + const source = ` + import "./constants.cash"; + int constant DERIVED = BASE * 2; + contract Imported(int number) { + function spend() { + require(number == DERIVED); + } + }`; + + const contract = ` + contract Imported(int number) { + function spend() { + require(number == 42); + } + }`; + + const artifact = compileString(source, { files: { './constants.cash': importedSource } }); + expect(artifact.bytecode).toEqual(compileString(contract).bytecode); + }); }); describe('Stable function ID assignment', () => { diff --git a/packages/cashc/test/imports.test.ts b/packages/cashc/test/imports.test.ts index d0c1c1674..01f59394e 100644 --- a/packages/cashc/test/imports.test.ts +++ b/packages/cashc/test/imports.test.ts @@ -44,12 +44,10 @@ describe('Imports from the filesystem (compileFile)', () => { expect(() => compileFile(fixture('duplicate_import_main.cash'))).toThrow(RedefinitionError); }); - 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'), { disableInlining: true }); - expect(artifact.contractName).toEqual('Cycle'); - expect(countOpDefines(artifact.bytecode)).toEqual(2); + it('throws on cyclic imports', () => { + // cycle_a imports cycle_b which imports cycle_a back + expect(() => compileFile(fixture('cycle_main.cash'))).toThrow(ImportResolutionError); + expect(() => compileFile(fixture('cycle_main.cash'))).toThrow(/Cyclic import of '\.\/cycle_a\.cash'/); }); it('records provenance as the path relative to the main file', () => { diff --git a/packages/cashc/test/valid-contract-files/global_constant_arithmetic.cash b/packages/cashc/test/valid-contract-files/global_constant_arithmetic.cash new file mode 100644 index 000000000..be41fe11b --- /dev/null +++ b/packages/cashc/test/valid-contract-files/global_constant_arithmetic.cash @@ -0,0 +1,17 @@ +int constant BASE = 10 + 10; +int constant DERIVED = BASE - 5; +int constant NEGATED = -DERIVED * 2; +int constant COMPLEX = (BASE * 100 + 50) / 4 % 1000; +string constant GREETING = "hello" + " " + "world"; +bytes4 constant MAGIC = 0x0102 + 0x0304; + +contract GlobalConstantArithmetic() { + function spend(int base, int derived, int negated, int complex, string greeting, bytes4 magic) { + require(base == BASE); + require(derived == DERIVED); + require(negated == NEGATED); + require(complex == COMPLEX); + require(greeting == GREETING); + require(magic == MAGIC); + } +} diff --git a/website/docs/compiler/grammar.md b/website/docs/compiler/grammar.md index 105345bdd..fa483f8bf 100644 --- a/website/docs/compiler/grammar.md +++ b/website/docs/compiler/grammar.md @@ -229,7 +229,7 @@ typeCast ; constantDefinition - : typeName 'constant' Identifier '=' literal ';' + : typeName 'constant' Identifier '=' expression ';' ; VersionLiteral diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index f3f19b52d..4f0c8762e 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -41,26 +41,6 @@ The typings for the constructor arguments are only semantic and used when initia Upon initialization of the contract, constructor parameters are encoded and added to the contract's bytecode in the reversed order of their declaration. This can be important when manually constructing the contract locking script for debugging or optimization purposes. ::: -## Global constants -Global constants are declared at the **top level** of a `.cash` file, outside the contract, and can be used by contract functions and user-defined functions. Their initialiser must currently be a literal; expressions and casts are not supported. - -```solidity -int constant MAX_ATTEMPTS = 3; -int constant TIMEOUT = 12; // 12 blocks -bytes32 constant EMPTY_HASH = 0x0000000000000000000000000000000000000000000000000000000000000000; - -contract Example() { - function spend(int attempts) { - require(attempts < MAX_ATTEMPTS); - require(this.age >= TIMEOUT); - } -} -``` - -The literal must be assignable to the declared type. Global constants are immutable, and their names share the global namespace with user-defined functions and built-in symbols. Parameters and local variables cannot shadow them. - -Global constants do not become constructor arguments or mutable stack variables. The compiler treats them like zero-argument value-returning functions internally: small values and one-use constants are generally inlined, while larger values used repeatedly can be shared with `OP_DEFINE`/`OP_INVOKE`. - ## Functions The main construct in a CashScript contract is the function. A contract can contain one or multiple functions that can be executed to trigger transactions that spend money from the contract. At its core, the result of a function is just a yes or no answer to the question 'Can money be sent out of this contract?'. However, by using 'covenants it's possible to specify additional conditions — like restricting *where* money can be sent. To learn more about covenants, refer to the [CashScript Covenants Guide](/docs/guides/covenants). @@ -153,26 +133,43 @@ contract Example() { } ``` +:::info +`checkSig`, `checkMultiSig` and `this.activeBytecode` cannot be used inside a user-defined function, since they would apply to the function body rather than the contract. Use them in a contract function instead (`checkDataSig` is allowed). +::: + +### Limitations +This first version of user-defined functions is intentionally limited in scope: + +- A value-returning function must end with a single `return` statement (no early or conditional returns — compute into a variable and return it at the end). +- A void function must end with a `require` statement, just like contract functions (when it ends with an if-statement or loop, every branch must end with a `require`). + +:::note +Recursive and mutually recursive functions are allowed and compile fine. At runtime the VM control stack is limited to 100 entries, shared between recursion depth and nested `if` and loop blocks, so excessively deep recursion will fail when the contract gets spent. +::: + ## Global constants -Global constants are declared at the **top level** of a `.cash` file, outside the contract, and can be used by contract functions and user-defined functions. Their initialiser must be a literal: expressions and casts are not supported. +Global constants are declared at the **top level** of a `.cash` file, outside the contract, and can be used by contract functions and user-defined functions. Their initialiser is evaluated at compile time and must resolve to a single constant value: literals, references to previously declared constants, integer arithmetic (`+`, `-`, `*`, `/`, `%`) and string/bytes concatenation (`+`) are supported. Other expressions, such as casts, comparisons or function calls, are not. ```solidity int constant MAX_ATTEMPTS = 3; int constant TIMEOUT = 2 hours; +int constant EXTENDED_TIMEOUT = TIMEOUT + 30 minutes; bytes32 constant EMPTY_HASH = 0x0000000000000000000000000000000000000000000000000000000000000000; contract Example() { function spend(int attempts) { require(attempts < MAX_ATTEMPTS); - require(tx.time >= TIMEOUT); + require(tx.time >= EXTENDED_TIMEOUT); } } ``` -The literal must be assignable to the declared type. Global constants are immutable, and their names share the global namespace with user-defined functions and built-in symbols. Parameters and local variables cannot shadow them. +The resolved value must be assignable to the declared type. Constants may reference other constants, as long as those are declared (or imported) before they are used. Global constants are immutable, and their names share the global namespace with user-defined functions and built-in symbols. Parameters and local variables cannot shadow them. + +Global constants do not become constructor arguments or mutable stack variables. The compiler treats them like zero-argument value-returning functions internally: small values and one-use constants are generally inlined, while larger values used repeatedly can be shared with `OP_DEFINE`/`OP_INVOKE`. -### Importing functions and constants from other files -Top-level functions and constants can be split across files and pulled in with an `import` directive, which makes the imported functions and constants available as if they were declared locally. All `import` directives must appear at the **top of the file** after any `pragma` directives and before any constant, function or contract definitions. +## Importing functions and constants from other files +Top-level functions and constants can be split across files and pulled in with an `import` directive, which makes the imported functions and constants available as if they were declared locally. All `import` directives must appear at the **top of the file** after any `pragma` directives and before any constant, function or contract definitions. Cyclic imports are not allowed and result in a compile error. Imports are resolved relative to the importing file: from the filesystem when compiling with [`compileFile`](/docs/compiler#compilefile), or from the `files` compiler option when using [`compileString`](/docs/compiler#compilestring). @@ -201,20 +198,6 @@ Imported function and constant names share a single global namespace, so a name Imported files can declare their own [`pragma` directives](#pragma), and every pragma across the whole import graph — the main file and all (transitively) imported files — must be satisfied by the compiler version. -:::info -`checkSig`, `checkMultiSig` and `this.activeBytecode` cannot be used inside a user-defined function, since they would apply to the function body rather than the contract. Use them in a contract function instead (`checkDataSig` is allowed). -::: - -### Limitations -This first version of user-defined functions is intentionally limited in scope: - -- A value-returning function must end with a single `return` statement (no early or conditional returns — compute into a variable and return it at the end). -- A void function must end with a `require` statement, just like contract functions (when it ends with an if-statement or loop, every branch must end with a `require`). - -:::note -Recursive and mutually recursive functions are allowed and compile fine. At runtime the VM control stack is limited to 100 entries, shared between recursion depth and nested `if` and loop blocks, so excessively deep recursion will fail when the contract gets spent. -::: - ## Statements CashScript functions are made up of a collection of statements that determine whether money may be spent from the contract. From 5c16940e70944fa96d57abd9b96c5f79d30a3388 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 30 Jul 2026 16:52:15 +0200 Subject: [PATCH 16/37] Bump version to 0.14.0-next.3 & update release notes --- examples/package.json | 6 +++--- examples/testing-suite/package.json | 6 +++--- packages/cashc/package.json | 4 ++-- packages/cashc/src/index.ts | 2 +- packages/cashscript/package.json | 4 ++-- packages/utils/package.json | 2 +- website/docs/releases/release-notes.md | 5 ++++- 7 files changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/package.json b/examples/package.json index ba4f6d055..c9c06968f 100644 --- a/examples/package.json +++ b/examples/package.json @@ -1,7 +1,7 @@ { "name": "cashscript-examples", "private": true, - "version": "0.14.0-next.2", + "version": "0.14.0-next.3", "description": "Usage examples of the CashScript SDK", "main": "p2pkh.js", "type": "module", @@ -13,8 +13,8 @@ "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", "@types/node": "^22.17.0", - "cashc": "^0.14.0-next.2", - "cashscript": "^0.14.0-next.2", + "cashc": "^0.14.0-next.3", + "cashscript": "^0.14.0-next.3", "eslint": "^8.56.0", "typescript": "^5.9.2" } diff --git a/examples/testing-suite/package.json b/examples/testing-suite/package.json index 187a0c413..0ea25cc5d 100644 --- a/examples/testing-suite/package.json +++ b/examples/testing-suite/package.json @@ -1,6 +1,6 @@ { "name": "testing-suite", - "version": "0.14.0-next.2", + "version": "0.14.0-next.3", "description": "Example project to develop and test CashScript contracts", "main": "index.js", "type": "module", @@ -18,8 +18,8 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "cashc": "^0.14.0-next.2", - "cashscript": "^0.14.0-next.2" + "cashc": "^0.14.0-next.3", + "cashscript": "^0.14.0-next.3" }, "devDependencies": { "tsx": "^4.20.3", diff --git a/packages/cashc/package.json b/packages/cashc/package.json index aeaa5d8dd..26afbca83 100644 --- a/packages/cashc/package.json +++ b/packages/cashc/package.json @@ -1,6 +1,6 @@ { "name": "cashc", - "version": "0.14.0-next.2", + "version": "0.14.0-next.3", "description": "Compile Bitcoin Cash contracts to Bitcoin Cash Script or artifacts", "keywords": [ "bitcoin", @@ -48,7 +48,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.2", + "@cashscript/utils": "^0.14.0-next.3", "antlr4": "^4.13.2", "commander": "^14.0.0", "semver": "^7.7.2" diff --git a/packages/cashc/src/index.ts b/packages/cashc/src/index.ts index 039b94389..f647e3413 100644 --- a/packages/cashc/src/index.ts +++ b/packages/cashc/src/index.ts @@ -6,4 +6,4 @@ export { export * from './ast/Location.js'; export * from './ast/error-listeners.js'; -export const version = '0.14.0-next.2'; +export const version = '0.14.0-next.3'; diff --git a/packages/cashscript/package.json b/packages/cashscript/package.json index 07d34d87e..b910b76d8 100644 --- a/packages/cashscript/package.json +++ b/packages/cashscript/package.json @@ -1,6 +1,6 @@ { "name": "cashscript", - "version": "0.14.0-next.2", + "version": "0.14.0-next.3", "description": "Easily write and interact with Bitcoin Cash contracts", "keywords": [ "bitcoin cash", @@ -42,7 +42,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.2", + "@cashscript/utils": "^0.14.0-next.3", "@electrum-cash/network": "^4.1.3", "fflate": "^0.8.2", "semver": "^7.7.2" diff --git a/packages/utils/package.json b/packages/utils/package.json index de2eb6ed7..224612275 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@cashscript/utils", - "version": "0.14.0-next.2", + "version": "0.14.0-next.3", "description": "CashScript utilities and types", "keywords": [ "bitcoin cash", diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index dac6805b7..51d504564 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -2,7 +2,7 @@ title: Release Notes --- -## v0.14.0-next.2 +## v0.14.0-next.3 ⚠️ Note that this is a pre-release version and is not yet stable. There will likely be breaking changes to the APIs and compiler output in subsequent pre-releases. @@ -10,6 +10,8 @@ title: Release Notes - :sparkles: Add support for user-defined reusable functions. - :sparkles: Add support for multiple return values in user-defined functions, destructured at the call site. - :sparkles: Add support for top-level global constants. +- :sparkles: Allow for simple arithmetic / concatenation operations in global constant definitions. +- :sparkles: Add `unused` modifier for parameters or variables that are intentionally unused. - :sparkles: Add support for `import` directives to share user-defined functions across files. - :hammer_and_wrench: Update `compileString` to take an optional `files` object for filesystem-free import resolution. - :racehorse: Inline global functions and constants when this is no larger than `OP_DEFINE`/`OP_INVOKE`. @@ -17,6 +19,7 @@ title: Release Notes #### CashScript SDK - :sparkles: Add support for debugging user-defined functions. +- :sparkles: Add stack trace when debugging failed requires inside nested functions. ## v0.13.2 From 14f7c06b27fa51155af6bd05d0021b63cbab5872 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 4 Aug 2026 10:32:21 +0200 Subject: [PATCH 17/37] Update docs to mention 'unused' parameters to buy op-cost budget --- website/docs/compiler/script-limits.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/website/docs/compiler/script-limits.md b/website/docs/compiler/script-limits.md index f13d43cf3..6ba9b62b3 100644 --- a/website/docs/compiler/script-limits.md +++ b/website/docs/compiler/script-limits.md @@ -28,18 +28,27 @@ If your local state grows larger than the allowed maximum, one option is to hash ### Operation cost limit -Bitcoin Cash enforces an operation cost limit (op-cost) per transaction input. This determines the computational budget available for operations in a contract. The op-cost is based on script length: longer input scripts allow for a higher compute budget. +Bitcoin Cash enforces an operation cost limit (op-cost) per transaction input. This determines the computational budget available for operations in a contract. The op-cost is based on script length: longer input scripts allow for a higher compute budget. You can find the exact op-cost per operation in the [op-cost-table][op-cost-table]. #### Buying compute budget -Since longer input scripts allow for a larger compute budget, some contracts use zero-padding (adding non-functional bytes) to "buy" more computation power without changing logic. You can find the exact op-cost per operation in the [op-cost-table][op-cost-table]. +When running into op-cost limits, one option is to "buy" more compute budget by adding padding to the unlocking bytecode, since op-cost is calculated as `(41 + unlockingBytecodeLength) * 800`, adding 800 op-cost budget per byte. Because this increases the transaction size, this also increases the transaction fee. -```ts -function maxOperationCost(unlockingBytecodeLength) { - return (41n + unlockingBytecodeLength) * 800n; +In CashScript, this padding can be added with an [`unused` parameter](/docs/language/contracts#intentionally-unused-values) in the constructor or spending function. An `unused` constructor parameter becomes part of the contract bytecode, so it buys a fixed amount of extra budget. An `unused` function parameter is provided by the spender at transaction time, so the amount of padding can be chosen dynamically per transaction. + +```solidity +contract HeavyComputation(pubkey pk, bytes unused fixedPadding) { + function spend(sig s, bytes unused dynamicPadding) { + // ... heavy computation ... + require(checkSig(s, pk)); + } } ``` +:::tip +Due to compiler optimisations, it is most efficient to place `unused` parameters at the end of the parameter list. +::: + ### Other contract-related limits - Signature operation count (SigChecks): Limits the number of signature verifications (`OP_CHECKSIG`, `OP_CHECKDATASIG`) per transaction to ensure efficient validation. From 687f70e1e2233008d35fcd2be9945a798907bbd6 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 6 Aug 2026 10:26:30 +0200 Subject: [PATCH 18/37] Add support for importing from node_modules --- .cspell.json | 3 + .gitignore | 3 + packages/cashc/src/compiler.ts | 4 +- packages/cashc/src/dependency-resolution.ts | 60 +++++++++++- .../nested/nm_nested_main.cash | 7 ++ .../cashc/test/import-fixtures/nm_main.cash | 7 ++ .../test/import-fixtures/nm_missing_main.cash | 7 ++ .../import-fixtures/nm_package_deps_main.cash | 7 ++ .../test/import-fixtures/nm_scoped_main.cash | 7 ++ .../import-fixtures/nm_transitive_main.cash | 7 ++ .../node_modules/@cashlibs/utils/util.cash | 3 + .../node_modules/mathlib/combined.cash | 5 + .../node_modules/mathlib/helper.cash | 3 + .../node_modules/mathlib/main.cash | 5 + .../node_modules/mathlib/math.cash | 3 + .../shadow/nm_shadow_main.cash | 7 ++ .../shadow/node_modules/mathlib/math.cash | 3 + packages/cashc/test/imports.test.ts | 94 +++++++++++++++++++ website/docs/compiler/compiler.md | 4 +- website/docs/language/contracts.md | 20 +++- 20 files changed, 250 insertions(+), 9 deletions(-) create mode 100644 packages/cashc/test/import-fixtures/nested/nm_nested_main.cash create mode 100644 packages/cashc/test/import-fixtures/nm_main.cash create mode 100644 packages/cashc/test/import-fixtures/nm_missing_main.cash create mode 100644 packages/cashc/test/import-fixtures/nm_package_deps_main.cash create mode 100644 packages/cashc/test/import-fixtures/nm_scoped_main.cash create mode 100644 packages/cashc/test/import-fixtures/nm_transitive_main.cash create mode 100644 packages/cashc/test/import-fixtures/node_modules/@cashlibs/utils/util.cash create mode 100644 packages/cashc/test/import-fixtures/node_modules/mathlib/combined.cash create mode 100644 packages/cashc/test/import-fixtures/node_modules/mathlib/helper.cash create mode 100644 packages/cashc/test/import-fixtures/node_modules/mathlib/main.cash create mode 100644 packages/cashc/test/import-fixtures/node_modules/mathlib/math.cash create mode 100644 packages/cashc/test/import-fixtures/shadow/nm_shadow_main.cash create mode 100644 packages/cashc/test/import-fixtures/shadow/node_modules/mathlib/math.cash diff --git a/.cspell.json b/.cspell.json index d21a5f456..4764b7ab6 100644 --- a/.cspell.json +++ b/.cspell.json @@ -35,6 +35,7 @@ "callees", "cashaddress", "cashc", + "cashlibs", "cashproof", "cashscript", "cashtokens", @@ -116,6 +117,7 @@ "LSHIFTNUM", "LSHIFTBIN", "math", + "mathlib", "mecenas", "meep", "minimaldata", @@ -124,6 +126,7 @@ "n", "narrowings", "noncompressed", + "nonexistent", "nonfinal", "nonschnorr", "nops", diff --git a/.gitignore b/.gitignore index 05c8b47fe..339562340 100644 --- a/.gitignore +++ b/.gitignore @@ -108,3 +108,6 @@ typings/ manual-test.ts .claude/ + +# Test fixtures that emulate installed packages (re-included despite the node_modules ignore above) +!packages/cashc/test/import-fixtures/**/node_modules/ diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index 29e5b5056..168c5bb99 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -64,7 +64,9 @@ export const compileString: (code: string, compilerOptions?: CompileStringOption /** * Read a `.cash` source file from disk and compile it to an `Artifact`. * - * Import directives are resolved from the filesystem, relative to the importing file's directory. + * Import directives are resolved from the filesystem: file paths (starting with './', '../' or '/') + * relative to the importing file's directory, and package imports (e.g. 'pkg/math.cash') + * from node_modules directories, walking up from the importing file's directory. * * @param codeFile - The path to the `.cash` source file. * @param compilerOptions - Optional compiler options that override the defaults. diff --git a/packages/cashc/src/dependency-resolution.ts b/packages/cashc/src/dependency-resolution.ts index 7ce8a9856..aaa621fc4 100644 --- a/packages/cashc/src/dependency-resolution.ts +++ b/packages/cashc/src/dependency-resolution.ts @@ -13,10 +13,11 @@ import { parseCode } from './parser.js'; // A minimal virtual filesystem used to resolve import directives. Canonical paths are opaque keys: // absolute filesystem paths for the disk resolver, normalised POSIX paths relative to the main -// source for the in-memory resolver. +// source for the in-memory resolver. `resolve` returns undefined when a package import +// cannot be located. export interface ImportResolver { rootDir: string; - resolve(fromDir: string, importPath: string): string; + resolve(fromDir: string, importPath: string): string | undefined; read(canonicalPath: string): string | undefined; dirname(canonicalPath: string): string; sourceName(canonicalPath: string): string; @@ -25,7 +26,9 @@ export interface ImportResolver { export function createDiskResolver(rootDir: string): ImportResolver { return { rootDir, - resolve: (fromDir, importPath) => path.resolve(fromDir, importPath), + resolve: (fromDir, importPath) => (isPackageImport(importPath) + ? resolveFromNodeModules(fromDir, importPath) + : path.resolve(fromDir, importPath)), read: (canonicalPath) => { try { return fs.readFileSync(canonicalPath, { encoding: 'utf-8' }); @@ -34,7 +37,10 @@ export function createDiskResolver(rootDir: string): ImportResolver { } }, dirname: (canonicalPath) => path.dirname(canonicalPath), - sourceName: (canonicalPath) => path.relative(rootDir, canonicalPath).split(path.sep).join(path.posix.sep), + sourceName: (canonicalPath) => { + const relativePath = getPackageImportPath(canonicalPath) ?? path.relative(rootDir, canonicalPath); + return relativePath.split(path.sep).join(path.posix.sep); + }, }; } @@ -46,7 +52,10 @@ export function createMemoryResolver(files: Record): ImportResol return { rootDir: '.', - resolve: (fromDir, importPath) => path.posix.normalize(path.posix.join(fromDir, importPath)), + // Package imports are looked up verbatim ('pkg/math.cash'), regardless of the importing file + resolve: (fromDir, importPath) => (isPackageImport(importPath) + ? path.posix.normalize(importPath) + : path.posix.normalize(path.posix.join(fromDir, importPath))), read: (canonicalPath) => normalisedFiles[canonicalPath], dirname: (canonicalPath) => path.posix.dirname(canonicalPath), sourceName: (canonicalPath) => canonicalPath, @@ -94,6 +103,12 @@ function collectImports( const collect = (currentImports: ImportNode[], currentDir: string): ImportedDefinitions[] => currentImports.flatMap((importNode) => { const canonicalPath = resolver.resolve(currentDir, importNode.path); + if (canonicalPath === undefined) { + throw new ImportResolutionError( + importNode, + `Could not find imported file '${importNode.path}' in any node_modules directory`, + ); + } if (activePaths.has(canonicalPath)) { throw new ImportResolutionError(importNode, `Cyclic import of '${importNode.path}'`); } @@ -137,3 +152,38 @@ function collectImports( constants: collected.flatMap((definitions) => definitions.constants), }; } + + +function isPackageImport(importPath: string): boolean { + return !importPath.startsWith('./') && !importPath.startsWith('../') && !importPath.startsWith('/'); +} + +// Walk up from the importing file's directory looking for node_modules/, so +// contract libraries can be installed and imported as regular npm packages +function resolveFromNodeModules(fromDir: string, importPath: string): string | undefined { + const currentDir = path.resolve(fromDir); + const nodeModulesDir = path.join(currentDir, 'node_modules'); + const candidate = path.join(nodeModulesDir, importPath); + + if (isValidCandidate(nodeModulesDir, candidate)) return candidate; + + const parentDir = path.dirname(currentDir); + if (parentDir === currentDir) return undefined; + + return resolveFromNodeModules(parentDir, importPath); +} + +function isValidCandidate(nodeModulesDir: string, candidate: string): boolean { + // The prefix check stops '..' segments in a specifier from escaping the node_modules directory + if (!candidate.startsWith(nodeModulesDir + path.sep)) return false; + const stats = fs.statSync(candidate, { throwIfNoEntry: false }); + return stats?.isFile() ?? false; +} + +// A file inside node_modules is named by its package import path ('pkg/math.cash') +function getPackageImportPath(canonicalPath: string): string | undefined { + const nodeModulesSegment = `${path.sep}node_modules${path.sep}`; + const nodeModulesIndex = canonicalPath.lastIndexOf(nodeModulesSegment); + if (nodeModulesIndex === -1) return undefined; + return canonicalPath.slice(nodeModulesIndex + nodeModulesSegment.length); +} diff --git a/packages/cashc/test/import-fixtures/nested/nm_nested_main.cash b/packages/cashc/test/import-fixtures/nested/nm_nested_main.cash new file mode 100644 index 000000000..470bd6f45 --- /dev/null +++ b/packages/cashc/test/import-fixtures/nested/nm_nested_main.cash @@ -0,0 +1,7 @@ +import "mathlib/math.cash"; + +contract NodeModulesNested() { + function spend(int x) { + require(nmAdd(x, 3) == 8); + } +} diff --git a/packages/cashc/test/import-fixtures/nm_main.cash b/packages/cashc/test/import-fixtures/nm_main.cash new file mode 100644 index 000000000..4fb87641e --- /dev/null +++ b/packages/cashc/test/import-fixtures/nm_main.cash @@ -0,0 +1,7 @@ +import "mathlib/math.cash"; + +contract NodeModulesMain() { + function spend(int x) { + require(nmAdd(x, 3) == 8); + } +} diff --git a/packages/cashc/test/import-fixtures/nm_missing_main.cash b/packages/cashc/test/import-fixtures/nm_missing_main.cash new file mode 100644 index 000000000..896612fb1 --- /dev/null +++ b/packages/cashc/test/import-fixtures/nm_missing_main.cash @@ -0,0 +1,7 @@ +import "nonexistent-cashscript-pkg/foo.cash"; + +contract NodeModulesMissing() { + function spend(int x) { + require(x == 1); + } +} diff --git a/packages/cashc/test/import-fixtures/nm_package_deps_main.cash b/packages/cashc/test/import-fixtures/nm_package_deps_main.cash new file mode 100644 index 000000000..b6883a2cd --- /dev/null +++ b/packages/cashc/test/import-fixtures/nm_package_deps_main.cash @@ -0,0 +1,7 @@ +import "mathlib/combined.cash"; + +contract NodeModulesPackageDeps() { + function spend(int x) { + require(nmCombined(x) == 10); + } +} diff --git a/packages/cashc/test/import-fixtures/nm_scoped_main.cash b/packages/cashc/test/import-fixtures/nm_scoped_main.cash new file mode 100644 index 000000000..6ca733609 --- /dev/null +++ b/packages/cashc/test/import-fixtures/nm_scoped_main.cash @@ -0,0 +1,7 @@ +import "@cashlibs/utils/util.cash"; + +contract NodeModulesScoped() { + function spend(int x) { + require(scopedUtil(x) == 9); + } +} diff --git a/packages/cashc/test/import-fixtures/nm_transitive_main.cash b/packages/cashc/test/import-fixtures/nm_transitive_main.cash new file mode 100644 index 000000000..e0d0cf48d --- /dev/null +++ b/packages/cashc/test/import-fixtures/nm_transitive_main.cash @@ -0,0 +1,7 @@ +import "mathlib/main.cash"; + +contract NodeModulesTransitive() { + function spend(int x) { + require(nmMain(x) == 16); + } +} diff --git a/packages/cashc/test/import-fixtures/node_modules/@cashlibs/utils/util.cash b/packages/cashc/test/import-fixtures/node_modules/@cashlibs/utils/util.cash new file mode 100644 index 000000000..d911d7f46 --- /dev/null +++ b/packages/cashc/test/import-fixtures/node_modules/@cashlibs/utils/util.cash @@ -0,0 +1,3 @@ +function scopedUtil(int a) returns (int) { + return a * 3; +} diff --git a/packages/cashc/test/import-fixtures/node_modules/mathlib/combined.cash b/packages/cashc/test/import-fixtures/node_modules/mathlib/combined.cash new file mode 100644 index 000000000..38603e68d --- /dev/null +++ b/packages/cashc/test/import-fixtures/node_modules/mathlib/combined.cash @@ -0,0 +1,5 @@ +import "@cashlibs/utils/util.cash"; + +function nmCombined(int a) returns (int) { + return scopedUtil(a) + 1; +} diff --git a/packages/cashc/test/import-fixtures/node_modules/mathlib/helper.cash b/packages/cashc/test/import-fixtures/node_modules/mathlib/helper.cash new file mode 100644 index 000000000..43b9a6253 --- /dev/null +++ b/packages/cashc/test/import-fixtures/node_modules/mathlib/helper.cash @@ -0,0 +1,3 @@ +function nmHelper(int a) returns (int) { + return a + 5; +} diff --git a/packages/cashc/test/import-fixtures/node_modules/mathlib/main.cash b/packages/cashc/test/import-fixtures/node_modules/mathlib/main.cash new file mode 100644 index 000000000..7715b3aad --- /dev/null +++ b/packages/cashc/test/import-fixtures/node_modules/mathlib/main.cash @@ -0,0 +1,5 @@ +import "./helper.cash"; + +function nmMain(int a) returns (int) { + return nmHelper(a) * 2; +} diff --git a/packages/cashc/test/import-fixtures/node_modules/mathlib/math.cash b/packages/cashc/test/import-fixtures/node_modules/mathlib/math.cash new file mode 100644 index 000000000..12ff81286 --- /dev/null +++ b/packages/cashc/test/import-fixtures/node_modules/mathlib/math.cash @@ -0,0 +1,3 @@ +function nmAdd(int a, int b) returns (int) { + return a + b; +} diff --git a/packages/cashc/test/import-fixtures/shadow/nm_shadow_main.cash b/packages/cashc/test/import-fixtures/shadow/nm_shadow_main.cash new file mode 100644 index 000000000..a46dcd69a --- /dev/null +++ b/packages/cashc/test/import-fixtures/shadow/nm_shadow_main.cash @@ -0,0 +1,7 @@ +import "mathlib/math.cash"; + +contract NodeModulesShadow() { + function spend(int x) { + require(nmNearest(x) == 4); + } +} diff --git a/packages/cashc/test/import-fixtures/shadow/node_modules/mathlib/math.cash b/packages/cashc/test/import-fixtures/shadow/node_modules/mathlib/math.cash new file mode 100644 index 000000000..82d638be1 --- /dev/null +++ b/packages/cashc/test/import-fixtures/shadow/node_modules/mathlib/math.cash @@ -0,0 +1,3 @@ +function nmNearest(int a) returns (int) { + return a - 1; +} diff --git a/packages/cashc/test/imports.test.ts b/packages/cashc/test/imports.test.ts index 01f59394e..862522f8e 100644 --- a/packages/cashc/test/imports.test.ts +++ b/packages/cashc/test/imports.test.ts @@ -161,6 +161,100 @@ describe('Imports from in-memory files (compileString)', () => { }); }); +describe('Imports from node_modules (package imports)', () => { + it('resolves a package import from the nearest node_modules directory', () => { + const artifact = compileFile(fixture('nm_main.cash'), { disableInlining: true }); + expect(artifact.contractName).toEqual('NodeModulesMain'); + expect(artifact.bytecode).toContain('OP_INVOKE'); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('walks up parent directories to find node_modules', () => { + // nested/nm_nested_main.cash has no nested/node_modules, so resolution walks up to + // import-fixtures/node_modules + const artifact = compileFile(fixture('nested/nm_nested_main.cash'), { disableInlining: true }); + expect(artifact.contractName).toEqual('NodeModulesNested'); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('prefers the nearest node_modules over an ancestor one', () => { + // shadow/node_modules/mathlib/math.cash defines nmNearest, the ancestor copy defines nmAdd. + // The contract calls nmNearest, so it only compiles if the nearest copy is resolved. + const artifact = compileFile(fixture('shadow/nm_shadow_main.cash'), { disableInlining: true }); + expect(artifact.contractName).toEqual('NodeModulesShadow'); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('resolves relative imports inside an imported package relative to the package file', () => { + // mathlib/main.cash imports './helper.cash', which lives inside the package + const artifact = compileFile(fixture('nm_transitive_main.cash'), { disableInlining: true }); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + }); + + it('resolves package imports inside an imported package (transitive dependencies)', () => { + // mathlib/combined.cash itself contains a package import of @cashlibs/utils/util.cash, which is + // resolved by walking up from mathlib's own directory to the shared node_modules + const artifact = compileFile(fixture('nm_package_deps_main.cash'), { disableInlining: true }); + expect(artifact.contractName).toEqual('NodeModulesPackageDeps'); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + expect(artifact.debug?.functions?.map((func) => func.sourceFile).sort()) + .toEqual(['@cashlibs/utils/util.cash', 'mathlib/combined.cash']); + }); + + it('resolves scoped package imports', () => { + const artifact = compileFile(fixture('nm_scoped_main.cash'), { disableInlining: true }); + expect(artifact.contractName).toEqual('NodeModulesScoped'); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + }); + + it('records provenance as the package import path rather than a filesystem path', () => { + const artifact = compileFile(fixture('nm_transitive_main.cash'), { disableInlining: true }); + expect(artifact.debug?.functions?.map((func) => func.sourceFile).sort()) + .toEqual(['mathlib/helper.cash', 'mathlib/main.cash']); + }); + + it('throws when a package import cannot be found in any node_modules directory', () => { + expect(() => compileFile(fixture('nm_missing_main.cash'))).toThrow(ImportResolutionError); + expect(() => compileFile(fixture('nm_missing_main.cash'))).toThrow( + /Could not find imported file 'nonexistent-cashscript-pkg\/foo\.cash' in any node_modules directory/, + ); + }); + + it('resolves package imports verbatim from the files option when compiling from a string', () => { + const code = 'import "mathlib/math.cash";\n' + + 'contract C() { function spend(int x) { require(nmAdd(x, 3) == 8); } }'; + const files = { 'mathlib/math.cash': readFixture('node_modules/mathlib/math.cash') }; + + const artifact = compileString(code, { files, disableInlining: true }); + expect(countOpDefines(artifact.bytecode)).toEqual(1); + expect(artifact.debug?.functions?.map((func) => func.sourceFile)).toEqual(['mathlib/math.cash']); + }); + + it('resolves relative imports inside an in-memory package relative to the package file', () => { + const code = 'import "pkg/main.cash";\n' + + 'contract C() { function spend(int x) { require(pkgMain(x) == 12); } }'; + const files = { + 'pkg/main.cash': 'import "./helper.cash";\nfunction pkgMain(int n) returns (int) { return pkgHelper(n) * 2; }', + 'pkg/helper.cash': 'function pkgHelper(int n) returns (int) { return n + 1; }', + }; + + const artifact = compileString(code, { files, disableInlining: true }); + expect(countOpDefines(artifact.bytecode)).toEqual(2); + }); + + it('compiles a node_modules import to the exact same artifact from disk and from memory', () => { + const fromDisk = compileFile(fixture('nm_transitive_main.cash'), { disableInlining: true }); + + const files = { + 'mathlib/main.cash': readFixture('node_modules/mathlib/main.cash'), + 'mathlib/helper.cash': readFixture('node_modules/mathlib/helper.cash'), + }; + const fromString = compileString(readFixture('nm_transitive_main.cash'), { files, disableInlining: true }); + + expect(fromString).toEqual({ ...fromDisk, updatedAt: expect.any(String) }); + }); +}); + describe('compileFile / compileString equivalence', () => { it('compiles a complex import graph to the exact same artifact from disk and from memory', () => { // complex/main.cash exercises nested directories, a diamond (a and b both import util/leaf), diff --git a/website/docs/compiler/compiler.md b/website/docs/compiler/compiler.md index a8341823b..3f509b762 100644 --- a/website/docs/compiler/compiler.md +++ b/website/docs/compiler/compiler.md @@ -83,7 +83,7 @@ const P2PKH = compileFile(new URL('p2pkh.cash', import.meta.url)); ``` :::note -If the contract uses `import` directives to pull in [user-defined functions](/docs/language/contracts#user-defined-functions) from other files, `compileFile` resolves those imports relative to the source file's directory automatically. +If the contract uses `import` directives to pull in [user-defined functions](/docs/language/contracts#user-defined-functions) from other files, `compileFile` resolves those imports relative to the source file's directory automatically. Package imports such as `import "@example/math-lib/math.cash"` are resolved from `node_modules` directories, walking up from the importing file's directory like Node.js module resolution. ::: ### compileString() @@ -124,7 +124,7 @@ const Doubler = compileString(source, { files: { './math.cash': mathSource } }); ``` :::note -Imports inside imported files are resolved relative to the *importing* file, but their keys in `files` remain relative to the main source. For example, if `lib/a.cash` contains `import "./b.cash";`, that file must be provided under the key `lib/b.cash`. +Imports inside imported files are resolved relative to the *importing* file, but their keys in `files` remain relative to the main source. For example, if `lib/a.cash` contains `import "./b.cash";`, that file must be provided under the key `lib/b.cash`. Package imports such as `import "@example/math-lib/math.cash"` are looked up verbatim, so they must be provided under exactly that key. ::: ### Compiler Options diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index 4f0c8762e..a60cf8ac6 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -171,7 +171,7 @@ Global constants do not become constructor arguments or mutable stack variables. ## Importing functions and constants from other files Top-level functions and constants can be split across files and pulled in with an `import` directive, which makes the imported functions and constants available as if they were declared locally. All `import` directives must appear at the **top of the file** after any `pragma` directives and before any constant, function or contract definitions. Cyclic imports are not allowed and result in a compile error. -Imports are resolved relative to the importing file: from the filesystem when compiling with [`compileFile`](/docs/compiler#compilefile), or from the `files` compiler option when using [`compileString`](/docs/compiler#compilestring). +Import paths starting with `./`, `../` or `/` are resolved relative to the importing file: from the filesystem when compiling with [`compileFile`](/docs/compiler#compilefile), or from the `files` compiler option when using [`compileString`](/docs/compiler#compilestring). ```solidity // math.cash @@ -198,6 +198,24 @@ Imported function and constant names share a single global namespace, so a name Imported files can declare their own [`pragma` directives](#pragma), and every pragma across the whole import graph — the main file and all (transitively) imported files — must be satisfied by the compiler version. +### Importing from npm packages +Import paths that do *not* start with `./`, `../` or `/` are treated as package imports and are resolved from `node_modules`, mirroring Node.js module resolution. This makes it possible to publish reusable CashScript functions as npm packages and import them by package name. The import path must contain the full path of the `.cash` file within the package. + +```solidity +pragma cashscript ^0.14.0; +import "@example/math-lib/math.cash"; + +contract Main() { + function spend(int x) { + require(double(x) == 8); + } +} +``` + +Relative imports *inside* an imported package are resolved relative to the package's own files, so packages can split their functions across multiple internal files. + +When compiling with [`compileString`](/docs/compiler#compilestring), package imports are looked up verbatim in the `files` compiler option. The example above would require a `files` key of `@example/math-lib/math.cash`. + ## Statements CashScript functions are made up of a collection of statements that determine whether money may be spent from the contract. From e491f8fcd0e82e0c492599baf00c5c4e4e5371cd Mon Sep 17 00:00:00 2001 From: Mathieu Geukens Date: Thu, 6 Aug 2026 10:36:59 +0200 Subject: [PATCH 19/37] Include push overhead in function inlining size check --- packages/cashc/src/generation/inlining.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/cashc/src/generation/inlining.ts b/packages/cashc/src/generation/inlining.ts index 3ecad1f50..a25e40bcb 100644 --- a/packages/cashc/src/generation/inlining.ts +++ b/packages/cashc/src/generation/inlining.ts @@ -1,5 +1,6 @@ import { encodeInt, + Op, OptimiseBytecodeResult, Script, scriptToBytecode, @@ -24,11 +25,14 @@ export const shouldInline = ( }; function isWorthInlining(candidateFunctionId: number, bodyScript: Script, callCount: number): boolean { - const bodyBytes = scriptToBytecode(bodyScript).length; - const idBytes = scriptToBytecode([encodeInt(BigInt(candidateFunctionId))]).length; + const bodyBytecode = scriptToBytecode(bodyScript); + const functionId = encodeInt(BigInt(candidateFunctionId)); - const bytesWhenDefined = bodyBytes + idBytes + 1 + callCount * (idBytes + 1); - const bytesWhenInlined = callCount * bodyBytes; + const defineBytes = scriptToBytecode([bodyBytecode, functionId, Op.OP_DEFINE]).length; + const invokeBytes = scriptToBytecode([functionId, Op.OP_INVOKE]).length; + + const bytesWhenDefined = defineBytes + callCount * invokeBytes; + const bytesWhenInlined = callCount * bodyBytecode.length; return bytesWhenInlined <= bytesWhenDefined; } From 3bef546c16ddc320105e10d7eb8a795824c84caa Mon Sep 17 00:00:00 2001 From: Mathieu Geukens Date: Tue, 11 Aug 2026 10:52:13 +0200 Subject: [PATCH 20/37] update dependencies --- examples/package.json | 2 +- examples/testing-suite/package.json | 4 +- package.json | 9 +- packages/cashc/package.json | 13 +- packages/cashscript/package.json | 12 +- packages/utils/package.json | 4 +- yarn.lock | 2195 ++++++++++++--------------- 7 files changed, 986 insertions(+), 1253 deletions(-) diff --git a/examples/package.json b/examples/package.json index c9c06968f..9ab91215b 100644 --- a/examples/package.json +++ b/examples/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@types/node": "^22.17.0", + "@types/node": "^24.13.3", "cashc": "^0.14.0-next.3", "cashscript": "^0.14.0-next.3", "eslint": "^8.56.0", diff --git a/examples/testing-suite/package.json b/examples/testing-suite/package.json index 0ea25cc5d..91cfb45a2 100644 --- a/examples/testing-suite/package.json +++ b/examples/testing-suite/package.json @@ -22,8 +22,8 @@ "cashscript": "^0.14.0-next.3" }, "devDependencies": { - "tsx": "^4.20.3", + "tsx": "^4.23.12", "typescript": "^5.9.2", - "vitest": "^4.0.15" + "vitest": "^4.1.10" } } diff --git a/package.json b/package.json index 003bae23d..64b1fc307 100644 --- a/package.json +++ b/package.json @@ -8,17 +8,20 @@ "examples/testing-suite" ], "devDependencies": { - "@types/node": "^22.17.0", + "@types/node": "^24", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^7.0.0", - "cspell": "^9.2.0", + "cspell": "^10.0.1", "eslint": "^8.54.0", "eslint-config-airbnb-typescript": "^18.0.0", "eslint-plugin-import": "^2.31.0", "lerna": "^3.22.1", - "tsx": "^4.20.3", + "tsx": "^4.23.12", "typescript": "^5.9.2" }, + "resolutions": { + "ws": "^8.21.3" + }, "scripts": { "test": "lerna run test --ignore cashscript-examples --ignore testing-suite", "lint": "lerna run lint --ignore cashscript-examples --ignore testing-suite", diff --git a/packages/cashc/package.json b/packages/cashc/package.json index 26afbca83..d75e19c61 100644 --- a/packages/cashc/package.json +++ b/packages/cashc/package.json @@ -51,18 +51,17 @@ "@cashscript/utils": "^0.14.0-next.3", "antlr4": "^4.13.2", "commander": "^14.0.0", - "semver": "^7.7.2" + "semver": "^7.8.5" }, "devDependencies": { - "@types/node": "^22.17.0", - "@types/semver": "^7.7.0", - "@vitest/coverage-v8": "^4.0.15", - "cpy-cli": "^5.0.0", + "@types/node": "^24.13.3", + "@types/semver": "^7.8.0", + "@vitest/coverage-v8": "^4.1.10", "eslint": "^8.54.0", "eslint-plugin-import": "^2.31.0", - "tsx": "^4.20.3", + "tsx": "^4.23.12", "typescript": "^5.9.2", - "vitest": "^4.0.15" + "vitest": "^4.1.10" }, "gitHead": "bf02a4b641d5d03c035d052247a545109c17b708" } diff --git a/packages/cashscript/package.json b/packages/cashscript/package.json index b910b76d8..d6fe9cc95 100644 --- a/packages/cashscript/package.json +++ b/packages/cashscript/package.json @@ -43,18 +43,18 @@ "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", "@cashscript/utils": "^0.14.0-next.3", - "@electrum-cash/network": "^4.1.3", - "fflate": "^0.8.2", - "semver": "^7.7.2" + "@electrum-cash/network": "^4.2.2", + "fflate": "^0.8.3", + "semver": "^7.8.5" }, "devDependencies": { - "@types/semver": "^7.5.8", - "@vitest/coverage-v8": "^4.0.15", + "@types/semver": "^7.8.0", + "@vitest/coverage-v8": "^4.1.10", "eslint": "^8.54.0", "p-queue": "^9.1.2", "p-retry": "^8.0.0", "typescript": "^5.9.2", - "vitest": "^4.0.15" + "vitest": "^4.1.10" }, "gitHead": "bf02a4b641d5d03c035d052247a545109c17b708" } diff --git a/packages/utils/package.json b/packages/utils/package.json index 224612275..c0954e593 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -43,10 +43,10 @@ "@bitauth/libauth": "^3.1.0-next.8" }, "devDependencies": { - "@vitest/coverage-v8": "^4.0.15", + "@vitest/coverage-v8": "^4.1.10", "eslint": "^8.54.0", "typescript": "^5.9.2", - "vitest": "^4.0.15" + "vitest": "^4.1.10" }, "gitHead": "bf02a4b641d5d03c035d052247a545109c17b708" } diff --git a/yarn.lock b/yarn.lock index a8290daa9..6403d44da 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9,20 +9,20 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/helper-string-parser@^7.27.1": - version "7.27.1" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz#54da796097ab19ce67ed9f88b47bb2ec49367687" - integrity sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA== +"@babel/helper-string-parser@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f" + integrity sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw== "@babel/helper-validator-identifier@^7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2" integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw== -"@babel/helper-validator-identifier@^7.28.5": - version "7.28.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" - integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== +"@babel/helper-validator-identifier@^7.29.7": + version "7.29.7" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2" + integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg== "@babel/highlight@^7.10.4": version "7.10.4" @@ -33,20 +33,20 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.28.5": - version "7.28.5" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.5.tgz#0b0225ee90362f030efd644e8034c99468893b08" - integrity sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ== +"@babel/parser@^7.29.7": + version "7.29.8" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.8.tgz#9653716a2f10c677b98fbc63d4bfb000c302cf17" + integrity sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA== dependencies: - "@babel/types" "^7.28.5" + "@babel/types" "^7.29.8" -"@babel/types@^7.28.5": - version "7.28.5" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.5.tgz#10fc405f60897c35f07e85493c932c7b5ca0592b" - integrity sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA== +"@babel/types@^7.29.7", "@babel/types@^7.29.8": + version "7.29.8" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.8.tgz#1229eef31d85156d70fa3f4cd859376d0eaf6863" + integrity sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg== dependencies: - "@babel/helper-string-parser" "^7.27.1" - "@babel/helper-validator-identifier" "^7.28.5" + "@babel/helper-string-parser" "^7.29.7" + "@babel/helper-validator-identifier" "^7.29.7" "@bcoe/v8-coverage@^1.0.2": version "1.0.2" @@ -58,98 +58,111 @@ resolved "https://registry.yarnpkg.com/@bitauth/libauth/-/libauth-3.1.0-next.8.tgz#d130e5db6c3c8b24731c8d04c4091be07f48b0ee" integrity sha512-Pm+Ju+YP3JeBLLTiVrBnia2wwE4G17r4XqpvPRMcklElJTe8J6x3JgKRg1by0Xm3ZY6UFxACkEAoSA+x419/zA== -"@cspell/cspell-bundled-dicts@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-9.2.0.tgz#5bbc41142d03038457c637a99689e83e88014dbe" - integrity sha512-e4qb78SQWqHkRw47W8qFJ3RPijhSLkADF+T0oH8xl3r/golq1RGp2/KrWOqGRRofUSTiIKYqaMX7mbAyFnOxyA== +"@cspell/cspell-bundled-dicts@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-bundled-dicts/-/cspell-bundled-dicts-10.0.1.tgz#c85650d13a208ab31173dcdc6809ada1983d7cde" + integrity sha512-WvkSDNX4Uyyj/ZgbPO6L38iFNMfK1EqsH1FteRiI2qLz6QZMXRFrIt12OqiWIplzZDDaVpBH9FCJOPJll0fjCQ== dependencies: "@cspell/dict-ada" "^4.1.1" "@cspell/dict-al" "^1.1.1" - "@cspell/dict-aws" "^4.0.12" - "@cspell/dict-bash" "^4.2.1" - "@cspell/dict-companies" "^3.2.2" - "@cspell/dict-cpp" "^6.0.9" + "@cspell/dict-aws" "^4.0.17" + "@cspell/dict-bash" "^4.2.2" + "@cspell/dict-companies" "^3.2.11" + "@cspell/dict-cpp" "^7.0.2" "@cspell/dict-cryptocurrencies" "^5.0.5" - "@cspell/dict-csharp" "^4.0.7" - "@cspell/dict-css" "^4.0.18" - "@cspell/dict-dart" "^2.3.1" - "@cspell/dict-data-science" "^2.0.9" - "@cspell/dict-django" "^4.1.5" - "@cspell/dict-docker" "^1.1.15" - "@cspell/dict-dotnet" "^5.0.10" + "@cspell/dict-csharp" "^4.0.8" + "@cspell/dict-css" "^4.1.1" + "@cspell/dict-dart" "^2.3.2" + "@cspell/dict-data-science" "^2.0.13" + "@cspell/dict-django" "^4.1.6" + "@cspell/dict-docker" "^1.1.17" + "@cspell/dict-dotnet" "^5.0.13" "@cspell/dict-elixir" "^4.0.8" - "@cspell/dict-en-common-misspellings" "^2.1.3" - "@cspell/dict-en-gb-mit" "^3.1.5" - "@cspell/dict-en_us" "^4.4.15" - "@cspell/dict-filetypes" "^3.0.13" + "@cspell/dict-en-common-misspellings" "^2.1.12" + "@cspell/dict-en-gb-mit" "^3.1.22" + "@cspell/dict-en_us" "^4.4.33" + "@cspell/dict-filetypes" "^3.0.18" "@cspell/dict-flutter" "^1.1.1" - "@cspell/dict-fonts" "^4.0.5" + "@cspell/dict-fonts" "^4.0.6" "@cspell/dict-fsharp" "^1.1.1" - "@cspell/dict-fullstack" "^3.2.7" + "@cspell/dict-fullstack" "^3.2.9" "@cspell/dict-gaming-terms" "^1.1.2" - "@cspell/dict-git" "^3.0.7" - "@cspell/dict-golang" "^6.0.23" + "@cspell/dict-git" "^3.1.0" + "@cspell/dict-golang" "^6.0.26" "@cspell/dict-google" "^1.0.9" "@cspell/dict-haskell" "^4.0.6" - "@cspell/dict-html" "^4.0.12" - "@cspell/dict-html-symbol-entities" "^4.0.4" + "@cspell/dict-html" "^4.0.15" + "@cspell/dict-html-symbol-entities" "^4.0.5" "@cspell/dict-java" "^5.0.12" "@cspell/dict-julia" "^1.1.1" "@cspell/dict-k8s" "^1.0.12" "@cspell/dict-kotlin" "^1.1.1" - "@cspell/dict-latex" "^4.0.4" + "@cspell/dict-latex" "^5.1.0" "@cspell/dict-lorem-ipsum" "^4.0.5" "@cspell/dict-lua" "^4.0.8" "@cspell/dict-makefile" "^1.0.5" - "@cspell/dict-markdown" "^2.0.12" - "@cspell/dict-monkeyc" "^1.0.11" - "@cspell/dict-node" "^5.0.8" - "@cspell/dict-npm" "^5.2.12" - "@cspell/dict-php" "^4.0.15" + "@cspell/dict-markdown" "^2.0.16" + "@cspell/dict-monkeyc" "^1.0.12" + "@cspell/dict-node" "^5.0.9" + "@cspell/dict-npm" "^5.2.38" + "@cspell/dict-php" "^4.1.1" "@cspell/dict-powershell" "^5.0.15" - "@cspell/dict-public-licenses" "^2.0.14" - "@cspell/dict-python" "^4.2.19" + "@cspell/dict-public-licenses" "^2.0.16" + "@cspell/dict-python" "^4.2.26" "@cspell/dict-r" "^2.1.1" - "@cspell/dict-ruby" "^5.0.9" - "@cspell/dict-rust" "^4.0.12" - "@cspell/dict-scala" "^5.0.8" - "@cspell/dict-shell" "^1.1.1" - "@cspell/dict-software-terms" "^5.1.4" + "@cspell/dict-ruby" "^5.1.1" + "@cspell/dict-rust" "^4.1.2" + "@cspell/dict-scala" "^5.0.9" + "@cspell/dict-shell" "^1.1.2" + "@cspell/dict-software-terms" "^5.2.2" "@cspell/dict-sql" "^2.2.1" "@cspell/dict-svelte" "^1.0.7" "@cspell/dict-swift" "^2.0.6" "@cspell/dict-terraform" "^1.1.3" "@cspell/dict-typescript" "^3.2.3" "@cspell/dict-vue" "^3.0.5" + "@cspell/dict-zig" "^1.0.0" -"@cspell/cspell-json-reporter@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-json-reporter/-/cspell-json-reporter-9.2.0.tgz#c602929ca904dfd0d6e6377cebe79b7eddeef0a0" - integrity sha512-qHdkW8eyknCSDEsqCG8OHBMal03LQf21H2LVWhtwszEQ4BQRKcWctc+VIgkO69F/jLaN2wi/yhhMufXWHAEzIg== +"@cspell/cspell-json-reporter@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-json-reporter/-/cspell-json-reporter-10.0.1.tgz#d64f9f4fe7c6ab70c5f8c625879e5e13a7fa4669" + integrity sha512-/nes1RGILec3WCBcoMOd0byNTBtnJuPaVz/+ZzqYkLtY7x58VMcBG5kyP6hPyN8cIwjRADE/SR43gwdXuqk/FA== dependencies: - "@cspell/cspell-types" "9.2.0" + "@cspell/cspell-types" "10.0.1" -"@cspell/cspell-pipe@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-pipe/-/cspell-pipe-9.2.0.tgz#271ec44c0b64d55fd053c6410ca3604c91ba4a93" - integrity sha512-RO3adcsr7Ek+4511nyEOWDhOYYU1ogRs1Mo5xx3kDIdcKAJzhFdGry35T2wqft4dPASLCXcemBrhoS+hdQ+z+Q== +"@cspell/cspell-performance-monitor@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-performance-monitor/-/cspell-performance-monitor-10.0.1.tgz#944e3ad0cf0b7b03755c807146c394b09d3d1560" + integrity sha512-9tVcHXwRnbazUv4WSG0h3MqV4+LgmLNgSALAQUflPPW0EMxTf7C4Dmv9cgxJyCEQrdnVKCr58nPPaahhz9LJUg== -"@cspell/cspell-resolver@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-resolver/-/cspell-resolver-9.2.0.tgz#c6ab91877abb812ef9f87c4d361b1a14f60bef16" - integrity sha512-0Xvwq0iezfO71Alw+DjsGxacAzydqOAxdXnY4JknHuxt2l8GTSMjRwj65QAflv3PN6h1QoRZEeWdiKtusceWAw== +"@cspell/cspell-pipe@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-pipe/-/cspell-pipe-10.0.1.tgz#caccc9dc8f937d7f7b4ffa949de48152bb3f9659" + integrity sha512-HPeXMD9AZ3V/qPkvQaPcak+C7cJ2z7JTHN8smd6J8L2aThLRky2cHc2OyeaHPSHB7WA47b4z2n5u5nawZhv5VQ== + +"@cspell/cspell-resolver@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-resolver/-/cspell-resolver-10.0.1.tgz#8efc586e10e85f165a0e817ddbfd8774af73e99b" + integrity sha512-PIzkZHD1fGUQx1XteK2d1iQ0Mzq/maYcoB4jkvAiiR6WqP3MWYNKFdI9z+R5pOq5KgMfW+5Ig1q0oSR6h8irlA== dependencies: - global-directory "^4.0.1" + global-directory "^5.0.0" -"@cspell/cspell-service-bus@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-service-bus/-/cspell-service-bus-9.2.0.tgz#72b960f37f74b26aba2910143c832b2b8732335c" - integrity sha512-ZDvcOTFk3cCVW+OjlkljeP7aSuV8tIguVn+GMco1/A+961hsEP20hngK9zJtyfpXqyvJKtvCVlyzS+z8VRrZGg== +"@cspell/cspell-service-bus@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-service-bus/-/cspell-service-bus-10.0.1.tgz#3eaa35cc075a4fd5273833c9c8993e0f1891d307" + integrity sha512-y6NcIGP2IdXaBL4PVH8vxsr7K27wzz3Ech87UtUtrDSXAiVEOvXgAIknEOUVp59rTlUE8Rn4IRURC6f/hgMyfw== -"@cspell/cspell-types@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-9.2.0.tgz#5767b839722f9402dc5ad4e8bea86138ecb84eeb" - integrity sha512-hL4ltFwiARpFxlfXt4GiTWQxIFyZp4wrlp7dozZbitYO6QlYc5fwQ8jBc5zFUqknuH4gx/sCMLNXhAv3enNGZQ== +"@cspell/cspell-types@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-types/-/cspell-types-10.0.1.tgz#607361589364d41313b005650313aab6e7c26b03" + integrity sha512-kLgLShnWADDVreKC63pBrWkcvxgZzFIfO34Jhx/SWfuOIA3cD8AXT+HjyuLfoGJ7mUb58hv2kUziKzEy4INb1w== + +"@cspell/cspell-worker@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/cspell-worker/-/cspell-worker-10.0.1.tgz#bdf5050b9678b6f5a9a0aefd6218ca57402bbf92" + integrity sha512-L2bJerfuYOls2wEknm8FmynLtj/G7O4UqX9I/HznRggEW6i2yZIxagDetpVDNowpyavNHJ3SJtUFiyMiZc16Sw== + dependencies: + cspell-lib "10.0.1" "@cspell/dict-ada@^4.1.1": version "4.1.1" @@ -161,127 +174,127 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-al/-/dict-al-1.1.1.tgz#d6581e7801daa0f4e7512d3431e7f00c1e7d53e1" integrity sha512-sD8GCaZetgQL4+MaJLXqbzWcRjfKVp8x+px3HuCaaiATAAtvjwUQ5/Iubiqwfd1boIh2Y1/3EgM3TLQ7Q8e0wQ== -"@cspell/dict-aws@^4.0.12": - version "4.0.14" - resolved "https://registry.yarnpkg.com/@cspell/dict-aws/-/dict-aws-4.0.14.tgz#80c81765ebea0e9b755326d281af084b282a4f7e" - integrity sha512-qLPR+OFmpzyUcuUYyCQFIURDDUGIlQsdGirPyvaIrXxs2giCKG97cAuFz5EleL3/Lo7uJAVDw0lt4Ka7wIRhjQ== +"@cspell/dict-aws@^4.0.17": + version "4.0.17" + resolved "https://registry.yarnpkg.com/@cspell/dict-aws/-/dict-aws-4.0.17.tgz#73dba92ce69868babe114d6e436a5e4dd45b6c6c" + integrity sha512-ORcblTWcdlGjIbWrgKF+8CNEBQiLVKdUOFoTn0KPNkAYnFcdPP0muT4892h7H4Xafh3j72wqB4/loQ6Nti9E/w== -"@cspell/dict-bash@^4.2.1": - version "4.2.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-bash/-/dict-bash-4.2.1.tgz#0666f547bb7fa0c62c0e5b65a87e64a852864a71" - integrity sha512-SBnzfAyEAZLI9KFS7DUG6Xc1vDFuLllY3jz0WHvmxe8/4xV3ufFE3fGxalTikc1VVeZgZmxYiABw4iGxVldYEg== +"@cspell/dict-bash@^4.2.2": + version "4.2.3" + resolved "https://registry.yarnpkg.com/@cspell/dict-bash/-/dict-bash-4.2.3.tgz#43d62dfa879ed6c5941d20ca6655b24392aea388" + integrity sha512-ljUZoKHbDqw5Sx0qpL2qTUlmkmr+vhZH/sCNrNaBZKTbdgiswErSnIF1jRbGmEitJNxHRHWsuZyVgnTGfVO1Yw== dependencies: - "@cspell/dict-shell" "1.1.1" + "@cspell/dict-shell" "1.2.0" -"@cspell/dict-companies@^3.2.2": - version "3.2.3" - resolved "https://registry.yarnpkg.com/@cspell/dict-companies/-/dict-companies-3.2.3.tgz#7b4eb9d9122ccd7379ed221d74433b6011327748" - integrity sha512-7ekwamRYeS7G3I3LEKM3t0WIyAytCbsx2I2h2z2eEvF+b3TmtJVcV7UI7BScLue3bep4sPB/b4CV3BUv3QfyzQ== +"@cspell/dict-companies@^3.2.11": + version "3.2.12" + resolved "https://registry.yarnpkg.com/@cspell/dict-companies/-/dict-companies-3.2.12.tgz#d49d74e9f98d3bbdc48ac9c5a24b4d601886c6c1" + integrity sha512-mjiz/N3zWOCsz5VfwMUydSl7uW0OU9H2PnbCNc3RV44Vj6Q59CSp6EYGSGZQxrXU1gpsuZUrwr6QCjNjFOOg5A== -"@cspell/dict-cpp@^6.0.9": - version "6.0.9" - resolved "https://registry.yarnpkg.com/@cspell/dict-cpp/-/dict-cpp-6.0.9.tgz#965ae9f7cf9e45bce8eb742ab39550183223ab9b" - integrity sha512-Xdq9MwGh0D5rsnbOqFW24NIClXXRhN11KJdySMibpcqYGeomxB2ODFBuhj1H7azO7kVGkGH0Okm4yQ2TRzBx0g== +"@cspell/dict-cpp@^7.0.2": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-cpp/-/dict-cpp-7.1.0.tgz#286c1ae63e4401c2b44a652b1d5d283ffed1ce0a" + integrity sha512-rcjycobioQUd9Jm/Y1n8U+sq6ytpZ0iV8AYIo+vyEFfutC5x7g6hL6Fh3bCdh6IporGHRqfEutGK/4sfopD2ZA== "@cspell/dict-cryptocurrencies@^5.0.5": version "5.0.5" resolved "https://registry.yarnpkg.com/@cspell/dict-cryptocurrencies/-/dict-cryptocurrencies-5.0.5.tgz#843a6ac45216227f5436c442a8683c1571e57160" integrity sha512-R68hYYF/rtlE6T/dsObStzN5QZw+0aQBinAXuWCVqwdS7YZo0X33vGMfChkHaiCo3Z2+bkegqHlqxZF4TD3rUA== -"@cspell/dict-csharp@^4.0.7": - version "4.0.7" - resolved "https://registry.yarnpkg.com/@cspell/dict-csharp/-/dict-csharp-4.0.7.tgz#5c6d4c3cc55173d0891f66864df4fc9c2561c115" - integrity sha512-H16Hpu8O/1/lgijFt2lOk4/nnldFtQ4t8QHbyqphqZZVE5aS4J/zD/WvduqnLY21aKhZS6jo/xF5PX9jyqPKUA== +"@cspell/dict-csharp@^4.0.8": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@cspell/dict-csharp/-/dict-csharp-4.0.8.tgz#27f6d5873f4dde77c03c78bb7d3c51bc8d8d78c1" + integrity sha512-qmk45pKFHSxckl5mSlbHxmDitSsGMlk/XzFgt7emeTJWLNSTUK//MbYAkBNRtfzB4uD7pAFiKgpKgtJrTMRnrQ== -"@cspell/dict-css@^4.0.18": - version "4.0.18" - resolved "https://registry.yarnpkg.com/@cspell/dict-css/-/dict-css-4.0.18.tgz#fd88cf2742a75d3fab2fbfdc6fc48fa79a6ebb13" - integrity sha512-EF77RqROHL+4LhMGW5NTeKqfUd/e4OOv6EDFQ/UQQiFyWuqkEKyEz0NDILxOFxWUEVdjT2GQ2cC7t12B6pESwg== +"@cspell/dict-css@^4.1.1": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-css/-/dict-css-4.1.2.tgz#d913cee821acf75616d1298d152341638ef3d85d" + integrity sha512-+ylGoKdwZ2sVOCOnU2Eq5wDZx+RaVX3HoKyNHGGsFvhSw6IidQ6tH/mAPKBDofViHJoWCPNlklE0lTr6MDG3QA== -"@cspell/dict-dart@^2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-dart/-/dict-dart-2.3.1.tgz#46bb78863fd72d59bdbd370a082b0f5044dfb1f3" - integrity sha512-xoiGnULEcWdodXI6EwVyqpZmpOoh8RA2Xk9BNdR7DLamV/QMvEYn8KJ7NlRiTSauJKPNkHHQ5EVHRM6sTS7jdg== +"@cspell/dict-dart@^2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-dart/-/dict-dart-2.3.2.tgz#aae782dcf6c673857945b9bbe03beeaa79649222" + integrity sha512-sUiLW56t9gfZcu8iR/5EUg+KYyRD83Cjl3yjDEA2ApVuJvK1HhX+vn4e4k4YfjpUQMag8XO2AaRhARE09+/rqw== -"@cspell/dict-data-science@^2.0.9": - version "2.0.9" - resolved "https://registry.yarnpkg.com/@cspell/dict-data-science/-/dict-data-science-2.0.9.tgz#d943de6f569f2cb3ae9cead5c72c92ad75d657ff" - integrity sha512-wTOFMlxv06veIwKdXUwdGxrQcK44Zqs426m6JGgHIB/GqvieZQC5n0UI+tUm5OCxuNyo4OV6mylT4cRMjtKtWQ== +"@cspell/dict-data-science@^2.0.13", "@cspell/dict-data-science@^2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@cspell/dict-data-science/-/dict-data-science-2.0.16.tgz#370d4fdfcfaadb7176b6ca47e2e8603166e1c4a1" + integrity sha512-M72mxv5asuAnORurz4iXRJ+Tw9XBq6eu7D2Ne7biP0Z1RciKGNxXWu9JycA/KlVvK1hAlKj/fANlXhuEWpXKFg== -"@cspell/dict-django@^4.1.5": - version "4.1.5" - resolved "https://registry.yarnpkg.com/@cspell/dict-django/-/dict-django-4.1.5.tgz#47b25dfcb24b2891e16e14223169dd978989ffca" - integrity sha512-AvTWu99doU3T8ifoMYOMLW2CXKvyKLukPh1auOPwFGHzueWYvBBN+OxF8wF7XwjTBMMeRleVdLh3aWCDEX/ZWg== +"@cspell/dict-django@^4.1.6": + version "4.1.6" + resolved "https://registry.yarnpkg.com/@cspell/dict-django/-/dict-django-4.1.6.tgz#a92408ba8971ca3df3c602b9e3750a14be69a8f6" + integrity sha512-SdbSFDGy9ulETqNz15oWv2+kpWLlk8DJYd573xhIkeRdcXOjskRuxjSZPKfW7O3NxN/KEf3gm3IevVOiNuFS+w== -"@cspell/dict-docker@^1.1.15": - version "1.1.16" - resolved "https://registry.yarnpkg.com/@cspell/dict-docker/-/dict-docker-1.1.16.tgz#09aa60469fd8db3fca7b2297ddc0848095763c33" - integrity sha512-UiVQ5RmCg6j0qGIxrBnai3pIB+aYKL3zaJGvXk1O/ertTKJif9RZikKXCEgqhaCYMweM4fuLqWSVmw3hU164Iw== +"@cspell/dict-docker@^1.1.17": + version "1.1.17" + resolved "https://registry.yarnpkg.com/@cspell/dict-docker/-/dict-docker-1.1.17.tgz#8674b3613dfa9c7d2922f6ec29ff845cb16e6650" + integrity sha512-OcnVTIpHIYYKhztNTyK8ShAnXTfnqs43hVH6p0py0wlcwRIXe5uj4f12n7zPf2CeBI7JAlPjEsV0Rlf4hbz/xQ== -"@cspell/dict-dotnet@^5.0.10": - version "5.0.10" - resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-5.0.10.tgz#7c1a4ba2174ead6e4c9cbe8f45ab80ecb1e37acc" - integrity sha512-ooar8BP/RBNP1gzYfJPStKEmpWy4uv/7JCq6FOnJLeD1yyfG3d/LFMVMwiJo+XWz025cxtkM3wuaikBWzCqkmg== +"@cspell/dict-dotnet@^5.0.13": + version "5.0.13" + resolved "https://registry.yarnpkg.com/@cspell/dict-dotnet/-/dict-dotnet-5.0.13.tgz#c75b4cdba79462398c4098739e699ea4144c85e5" + integrity sha512-xPp7jMnFpOri7tzmqmm/dXMolXz1t2bhNqxYkOyMqXhvs08oc7BFs+EsbDY0X7hqiISgeFZGNqn0dOCr+ncPYw== "@cspell/dict-elixir@^4.0.8": version "4.0.8" resolved "https://registry.yarnpkg.com/@cspell/dict-elixir/-/dict-elixir-4.0.8.tgz#c1b2a30d0fc654a001f718f196beb60c01e0e1f6" integrity sha512-CyfphrbMyl4Ms55Vzuj+mNmd693HjBFr9hvU+B2YbFEZprE5AG+EXLYTMRWrXbpds4AuZcvN3deM2XVB80BN/Q== -"@cspell/dict-en-common-misspellings@^2.1.3": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.1.3.tgz#6ee2a034999f2b302c35274317dca76afe3f2ae1" - integrity sha512-v1I97Hr1OrK+mwHsVzbY4vsPxx6mA5quhxzanF6XuRofz00wH4HPz8Q3llzRHxka5Wl/59gyan04UkUrvP4gdA== +"@cspell/dict-en-common-misspellings@^2.1.12": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-en-common-misspellings/-/dict-en-common-misspellings-2.2.0.tgz#a7ba55b9064f0219a78c9963064115ea98295258" + integrity sha512-5PmCHv+AhY0LVNo3bE1FdRKMmw1esKj83GPwLymnVPYNtlI2Jf6y27EjC0azg4zny5keWmku0GQiMf55Fi+qeA== -"@cspell/dict-en-gb-mit@^3.1.5": - version "3.1.6" - resolved "https://registry.yarnpkg.com/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.6.tgz#ed7c43690dd2577ab43435d8fa8a1685c5a5bf15" - integrity sha512-3JJGxuPhDK5rMDYPzJYAdjjsBddEyV54rXfUQpOCl7c7weMhNDWfC2q4h3cKNDj7Isud1q2RM+DlSxQWf40OTw== +"@cspell/dict-en-gb-mit@^3.1.22": + version "3.1.25" + resolved "https://registry.yarnpkg.com/@cspell/dict-en-gb-mit/-/dict-en-gb-mit-3.1.25.tgz#f33bb024ffb4f52b0d4f263882e11bffcf338f8a" + integrity sha512-zGODptk24CMrXi49ieG2SUm94CKxEsVF0dYNF+1ZYH0MSsQDZ/PKDlrrbvtBqSupKdPSj0Z9sjOmMNfHHW9ZSg== -"@cspell/dict-en_us@^4.4.15": - version "4.4.16" - resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-4.4.16.tgz#124987e86c8fe3fc81f1386c0a4d37cb03450a74" - integrity sha512-/R47sUbUmba2dG/0LZyE6P6gX/DRF1sCcYNQNWyPk/KeidQRNZG+FH9U0KRvX42/2ZzMge6ebXH3WAJ52w0Vqw== +"@cspell/dict-en_us@^4.4.33": + version "4.4.36" + resolved "https://registry.yarnpkg.com/@cspell/dict-en_us/-/dict-en_us-4.4.36.tgz#fdfd0e722b6d9f234364c08c72149fb305c2131e" + integrity sha512-2yOhI/+7d1DbfvMljGW4jw8pLqDEsVmnvUXBOCFXtLU2BWgQkrqOJDCNseYjEiEbTp0OtdrWEWWPFSP1TNugQw== -"@cspell/dict-filetypes@^3.0.13": - version "3.0.13" - resolved "https://registry.yarnpkg.com/@cspell/dict-filetypes/-/dict-filetypes-3.0.13.tgz#119211401e7718c0af82614968352280e20da3af" - integrity sha512-g6rnytIpQlMNKGJT1JKzWkC+b3xCliDKpQ3ANFSq++MnR4GaLiifaC4JkVON11Oh/UTplYOR1nY3BR4X30bswA== +"@cspell/dict-filetypes@^3.0.18": + version "3.0.18" + resolved "https://registry.yarnpkg.com/@cspell/dict-filetypes/-/dict-filetypes-3.0.18.tgz#b798a5321d8a4a254a9998920db4b91491e51ebf" + integrity sha512-yU7RKD/x1IWmDLzWeiItMwgV+6bUcU/af23uS0+uGiFUbsY1qWV/D4rxlAAO6Z7no3J2z8aZOkYIOvUrJq0Rcw== "@cspell/dict-flutter@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@cspell/dict-flutter/-/dict-flutter-1.1.1.tgz#fab57cf189a8012e870d2e1f21526b18345038d7" integrity sha512-UlOzRcH2tNbFhZmHJN48Za/2/MEdRHl2BMkCWZBYs+30b91mWvBfzaN4IJQU7dUZtowKayVIF9FzvLZtZokc5A== -"@cspell/dict-fonts@^4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@cspell/dict-fonts/-/dict-fonts-4.0.5.tgz#21ff391df20722c7d370ce79c89665e4b8980200" - integrity sha512-BbpkX10DUX/xzHs6lb7yzDf/LPjwYIBJHJlUXSBXDtK/1HaeS+Wqol4Mlm2+NAgZ7ikIE5DQMViTgBUY3ezNoQ== +"@cspell/dict-fonts@^4.0.6": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@cspell/dict-fonts/-/dict-fonts-4.0.6.tgz#efdda213b4c876053aea51bafc7cd882c6379563" + integrity sha512-aR/0csY01dNb0A1tw/UmN9rKgHruUxsYsvXu6YlSBJFu60s26SKr/k1o4LavpHTQ+lznlYMqAvuxGkE4Flliqw== "@cspell/dict-fsharp@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@cspell/dict-fsharp/-/dict-fsharp-1.1.1.tgz#46414a8177b1c3373f1edb156df446088147cc22" integrity sha512-imhs0u87wEA4/cYjgzS0tAyaJpwG7vwtC8UyMFbwpmtw+/bgss+osNfyqhYRyS/ehVCWL17Ewx2UPkexjKyaBA== -"@cspell/dict-fullstack@^3.2.7": - version "3.2.7" - resolved "https://registry.yarnpkg.com/@cspell/dict-fullstack/-/dict-fullstack-3.2.7.tgz#b5cc10c8e93093b124811a3af8d7169e52133723" - integrity sha512-IxEk2YAwAJKYCUEgEeOg3QvTL4XLlyArJElFuMQevU1dPgHgzWElFevN5lsTFnvMFA1riYsVinqJJX0BanCFEg== +"@cspell/dict-fullstack@^3.2.9": + version "3.2.9" + resolved "https://registry.yarnpkg.com/@cspell/dict-fullstack/-/dict-fullstack-3.2.9.tgz#e8baf9382b6006921684c9408dcad2c1de5ae4bc" + integrity sha512-diZX+usW5aZ4/b2T0QM/H/Wl9aNMbdODa1Jq0ReBr/jazmNeWjd+PyqeVgzd1joEaHY+SAnjrf/i9CwKd2ZtWQ== "@cspell/dict-gaming-terms@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@cspell/dict-gaming-terms/-/dict-gaming-terms-1.1.2.tgz#459aa470b43eacbd3cbf7b32bd5bbb259cb78812" integrity sha512-9XnOvaoTBscq0xuD6KTEIkk9hhdfBkkvJAIsvw3JMcnp1214OCGW8+kako5RqQ2vTZR3Tnf3pc57o7VgkM0q1Q== -"@cspell/dict-git@^3.0.7": - version "3.0.7" - resolved "https://registry.yarnpkg.com/@cspell/dict-git/-/dict-git-3.0.7.tgz#382093019e8fa446f5cf2b347a9aef1cf7a30316" - integrity sha512-odOwVKgfxCQfiSb+nblQZc4ErXmnWEnv8XwkaI4sNJ7cNmojnvogYVeMqkXPjvfrgEcizEEA4URRD2Ms5PDk1w== +"@cspell/dict-git@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-git/-/dict-git-3.1.0.tgz#7ac48114425c74e0a1c00f154138cf81b04f250b" + integrity sha512-KEt9zGkxqGy2q1nwH4CbyqTSv5nadpn8BAlDnzlRcnL0Xb3LX9xTgSGShKvzb0bw35lHoYyLWN2ZKAqbC4pgGQ== -"@cspell/dict-golang@^6.0.23": - version "6.0.23" - resolved "https://registry.yarnpkg.com/@cspell/dict-golang/-/dict-golang-6.0.23.tgz#e5f0bca4acb088a314a04229c691f89570e971f4" - integrity sha512-oXqUh/9dDwcmVlfUF5bn3fYFqbUzC46lXFQmi5emB0vYsyQXdNWsqi6/yH3uE7bdRE21nP7Yo0mR1jjFNyLamg== +"@cspell/dict-golang@^6.0.26": + version "6.0.26" + resolved "https://registry.yarnpkg.com/@cspell/dict-golang/-/dict-golang-6.0.26.tgz#8d0a6f09ade1c489a92b594475bba2b6020b6d28" + integrity sha512-YKA7Xm5KeOd14v5SQ4ll6afe9VSy3a2DWM7L9uBq4u3lXToRBQ1W5PRa+/Q9udd+DTURyVVnQ+7b9cnOlNxaRg== "@cspell/dict-google@^1.0.9": version "1.0.9" @@ -293,15 +306,15 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-haskell/-/dict-haskell-4.0.6.tgz#881436f944a6901cff8fab1af776277ca96f1b8c" integrity sha512-ib8SA5qgftExpYNjWhpYIgvDsZ/0wvKKxSP+kuSkkak520iPvTJumEpIE+qPcmJQo4NzdKMN8nEfaeci4OcFAQ== -"@cspell/dict-html-symbol-entities@^4.0.4": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.4.tgz#e6e2819b0930df6d14de3e706cac838c9d5f5839" - integrity sha512-afea+0rGPDeOV9gdO06UW183Qg6wRhWVkgCFwiO3bDupAoyXRuvupbb5nUyqSTsLXIKL8u8uXQlJ9pkz07oVXw== +"@cspell/dict-html-symbol-entities@^4.0.5": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@cspell/dict-html-symbol-entities/-/dict-html-symbol-entities-4.0.5.tgz#cbdd8c133c7d649d32e10f48b58bd4a9304b5cb6" + integrity sha512-429alTD4cE0FIwpMucvSN35Ld87HCyuM8mF731KU5Rm4Je2SG6hmVx7nkBsLyrmH3sQukTcr1GaiZsiEg8svPA== -"@cspell/dict-html@^4.0.12": - version "4.0.12" - resolved "https://registry.yarnpkg.com/@cspell/dict-html/-/dict-html-4.0.12.tgz#5932e2b9e3cb1c668aa5ef054c24b38b0baadf08" - integrity sha512-JFffQ1dDVEyJq6tCDWv0r/RqkdSnV43P2F/3jJ9rwLgdsOIXwQbXrz6QDlvQLVvNSnORH9KjDtenFTGDyzfCaA== +"@cspell/dict-html@^4.0.15": + version "4.0.15" + resolved "https://registry.yarnpkg.com/@cspell/dict-html/-/dict-html-4.0.15.tgz#4ccd850cff30cc65b2eb372d8b96ec9a55afd177" + integrity sha512-GJYnYKoD9fmo2OI0aySEGZOjThnx3upSUvV7mmqUu8oG+mGgzqm82P/f7OqsuvTaInZZwZbo+PwJQd/yHcyFIw== "@cspell/dict-java@^5.0.12": version "5.0.12" @@ -323,10 +336,10 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-kotlin/-/dict-kotlin-1.1.1.tgz#830d7b3d33685c0998ef5b922b0d7779f6669706" integrity sha512-J3NzzfgmxRvEeOe3qUXnSJQCd38i/dpF9/t3quuWh6gXM+krsAXP75dY1CzDmS8mrJAlBdVBeAW5eAZTD8g86Q== -"@cspell/dict-latex@^4.0.4": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@cspell/dict-latex/-/dict-latex-4.0.4.tgz#ce058efd274dac8936db0ac9c8134599a2bdaf9f" - integrity sha512-YdTQhnTINEEm/LZgTzr9Voz4mzdOXH7YX+bSFs3hnkUHCUUtX/mhKgf1CFvZ0YNM2afjhQcmLaR9bDQVyYBvpA== +"@cspell/dict-latex@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-latex/-/dict-latex-5.1.0.tgz#c607cfb349ea73378ab5ae79592d389a3cc47c3e" + integrity sha512-qxT4guhysyBt0gzoliXYEBYinkAdEtR2M7goRaUH0a7ltCsoqqAeEV8aXYRIdZGcV77gYSobvu3jJL038tlPAw== "@cspell/dict-lorem-ipsum@^4.0.5": version "4.0.5" @@ -343,77 +356,77 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-makefile/-/dict-makefile-1.0.5.tgz#fe6e7df2360ff694ef41c90a0d4b422e81f560ef" integrity sha512-4vrVt7bGiK8Rx98tfRbYo42Xo2IstJkAF4tLLDMNQLkQ86msDlYSKG1ZCk8Abg+EdNcFAjNhXIiNO+w4KflGAQ== -"@cspell/dict-markdown@^2.0.12": - version "2.0.12" - resolved "https://registry.yarnpkg.com/@cspell/dict-markdown/-/dict-markdown-2.0.12.tgz#9c2e3533d6a850c5986bd3074e94cd6ef099a24e" - integrity sha512-ufwoliPijAgWkD/ivAMC+A9QD895xKiJRF/fwwknQb7kt7NozTLKFAOBtXGPJAB4UjhGBpYEJVo2elQ0FCAH9A== +"@cspell/dict-markdown@^2.0.16": + version "2.0.17" + resolved "https://registry.yarnpkg.com/@cspell/dict-markdown/-/dict-markdown-2.0.17.tgz#6f9115195202e83d4a6763b50468207a2a410c8f" + integrity sha512-H8bAxih6U8NOnSPL7R8My+tqjaB4tmnJTjERuz4zYqmf+cH+5xshX3UVgKlwWFcyjsYfv/zEDuRdMctQv1q6HQ== -"@cspell/dict-monkeyc@^1.0.11": - version "1.0.11" - resolved "https://registry.yarnpkg.com/@cspell/dict-monkeyc/-/dict-monkeyc-1.0.11.tgz#166bb61c86a2ff95707078db209ee73408d15bae" - integrity sha512-7Q1Ncu0urALI6dPTrEbSTd//UK0qjRBeaxhnm8uY5fgYNFYAG+u4gtnTIo59S6Bw5P++4H3DiIDYoQdY/lha8w== +"@cspell/dict-monkeyc@^1.0.12": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-monkeyc/-/dict-monkeyc-1.1.0.tgz#c7f2ca2dac90668d961df866115ec5229372d0fd" + integrity sha512-mc/hgvSy/emOIYtc8kuVEaLUlnaERunfAubfJ5plUXq6s0A69bcukJzUzSt9C0UTCwS28641ILRPv80m3L9QbA== -"@cspell/dict-node@^5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@cspell/dict-node/-/dict-node-5.0.8.tgz#5c732e6d9a71a8c857456abc26be2ee836cb720e" - integrity sha512-AirZcN2i84ynev3p2/1NCPEhnNsHKMz9zciTngGoqpdItUb2bDt1nJBjwlsrFI78GZRph/VaqTVFwYikmncpXg== +"@cspell/dict-node@^5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@cspell/dict-node/-/dict-node-5.0.9.tgz#ca894e62b85deaf2f55e9d9c86fdbb260ba923eb" + integrity sha512-hO+ga+uYZ/WA4OtiMEyKt5rDUlUyu3nXMf8KVEeqq2msYvAPdldKBGH7lGONg6R/rPhv53Rb+0Y1SLdoK1+7wQ== -"@cspell/dict-npm@^5.2.12": - version "5.2.13" - resolved "https://registry.yarnpkg.com/@cspell/dict-npm/-/dict-npm-5.2.13.tgz#f7768b895122cc8c2d2b0b33bbefbeb514f4d44c" - integrity sha512-yE7DfpiQjDFW6TLr5/fsSj4BlUy1A8lsuz2LQQHv4lQAAkZ4RsePYFL9DkRRfEtxn8CZYetUnU74/jQbfsnyrA== +"@cspell/dict-npm@^5.2.38": + version "5.2.45" + resolved "https://registry.yarnpkg.com/@cspell/dict-npm/-/dict-npm-5.2.45.tgz#8782586680b601cf7d3ecdf5a1d82d138a43c3d8" + integrity sha512-BXUmMMspl+AhPIk/ZOjxlNu5k1yCRAzSMzdNPYM+2vaBL8ffev7ZFfOyBCDk8kgcpsHotz8/3fLNX+xwWaDR2w== -"@cspell/dict-php@^4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@cspell/dict-php/-/dict-php-4.0.15.tgz#06a1e184ded5a7889d9f8e6922889d04299dc3d6" - integrity sha512-iepGB2gtToMWSTvybesn4/lUp4LwXcEm0s8vasJLP76WWVkq1zYjmeS+WAIzNgsuURyZ/9mGqhS0CWMuo74ODw== +"@cspell/dict-php@^4.1.1": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-php/-/dict-php-4.1.1.tgz#39117cde87706f843a0476c56b807c16d71a9e4b" + integrity sha512-EXelI+4AftmdIGtA8HL8kr4WlUE11OqCSVlnIgZekmTkEGSZdYnkFdiJ5IANSALtlQ1mghKjz+OFqVs6yowgWA== "@cspell/dict-powershell@^5.0.15": version "5.0.15" resolved "https://registry.yarnpkg.com/@cspell/dict-powershell/-/dict-powershell-5.0.15.tgz#4ad8b6a741c96508f7b5acbcda2a15978be351c6" integrity sha512-l4S5PAcvCFcVDMJShrYD0X6Huv9dcsQPlsVsBGbH38wvuN7gS7+GxZFAjTNxDmTY1wrNi1cCatSg6Pu2BW4rgg== -"@cspell/dict-public-licenses@^2.0.14": - version "2.0.14" - resolved "https://registry.yarnpkg.com/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.14.tgz#1231ae3d0440fcbf9e110c0706bfbe302bc8b052" - integrity sha512-8NhNzQWALF6+NlLeKZKilSHbeW9MWeiD+NcrjehMAcovKFbsn8smmQG/bVxw+Ymtd6WEgNpLgswAqNsbSQQ4og== +"@cspell/dict-public-licenses@^2.0.16": + version "2.0.16" + resolved "https://registry.yarnpkg.com/@cspell/dict-public-licenses/-/dict-public-licenses-2.0.16.tgz#8eb3c467c24526460543a24edf55a979a4f34f39" + integrity sha512-EQRrPvEOmwhwWezV+W7LjXbIBjiy6y/shrET6Qcpnk3XANTzfvWflf9PnJ5kId/oKWvihFy0za0AV1JHd03pSQ== -"@cspell/dict-python@^4.2.19": - version "4.2.19" - resolved "https://registry.yarnpkg.com/@cspell/dict-python/-/dict-python-4.2.19.tgz#51d4cd0981f24ff547e6444df67989a3d76e34ba" - integrity sha512-9S2gTlgILp1eb6OJcVZeC8/Od83N8EqBSg5WHVpx97eMMJhifOzePkE0kDYjyHMtAFznCQTUu0iQEJohNQ5B0A== +"@cspell/dict-python@^4.2.26": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-python/-/dict-python-4.3.0.tgz#92a63f76ef5cb47096a67d6fa4a2a39aeeb4eee9" + integrity sha512-afVcbsCOYtpdvu8I4ANiIXVcxqxzrno+oEuObNx9hwpvEmf/AbXQBk9CMjFR9QZllcfnOfpjCSXgGuTna5hKQA== dependencies: - "@cspell/dict-data-science" "^2.0.9" + "@cspell/dict-data-science" "^2.0.16" "@cspell/dict-r@^2.1.1": version "2.1.1" resolved "https://registry.yarnpkg.com/@cspell/dict-r/-/dict-r-2.1.1.tgz#ace8d66799cae4148411bb6483d9c8a8a3c8a50f" integrity sha512-71Ka+yKfG4ZHEMEmDxc6+blFkeTTvgKbKAbwiwQAuKl3zpqs1Y0vUtwW2N4b3LgmSPhV3ODVY0y4m5ofqDuKMw== -"@cspell/dict-ruby@^5.0.9": - version "5.0.9" - resolved "https://registry.yarnpkg.com/@cspell/dict-ruby/-/dict-ruby-5.0.9.tgz#844d6214a7c2132696eacc8f741d5950307d48e1" - integrity sha512-H2vMcERMcANvQshAdrVx0XoWaNX8zmmiQN11dZZTQAZaNJ0xatdJoSqY8C8uhEMW89bfgpN+NQgGuDXW2vmXEw== +"@cspell/dict-ruby@^5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@cspell/dict-ruby/-/dict-ruby-5.1.1.tgz#73c5c48cb20402b1ba5589b08c904b11e2f12ccb" + integrity sha512-LHrp84oEV6q1ZxPPyj4z+FdKyq1XAKYPtmGptrd+uwHbrF/Ns5+fy6gtSi7pS+uc0zk3JdO9w/tPK+8N1/7WUA== -"@cspell/dict-rust@^4.0.12": - version "4.0.12" - resolved "https://registry.yarnpkg.com/@cspell/dict-rust/-/dict-rust-4.0.12.tgz#058cc67066f9c9bec1a503f221a131097493b797" - integrity sha512-z2QiH+q9UlNhobBJArvILRxV8Jz0pKIK7gqu4TgmEYyjiu1TvnGZ1tbYHeu9w3I/wOP6UMDoCBTty5AlYfW0mw== +"@cspell/dict-rust@^4.1.2": + version "4.1.2" + resolved "https://registry.yarnpkg.com/@cspell/dict-rust/-/dict-rust-4.1.2.tgz#6a151e72dc3be916c040111bba7358401ba57e15" + integrity sha512-O1FHrumYcO+HZti3dHfBPUdnDFkI+nbYK3pxYmiM1sr+G0ebOd6qchmswS0Wsc6ZdEVNiPYJY/gZQR6jfW3uOg== -"@cspell/dict-scala@^5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@cspell/dict-scala/-/dict-scala-5.0.8.tgz#6b274dc2fad5d2829337f7c9e800f1d4262a2ded" - integrity sha512-YdftVmumv8IZq9zu1gn2U7A4bfM2yj9Vaupydotyjuc+EEZZSqAafTpvW/jKLWji2TgybM1L2IhmV0s/Iv9BTw== +"@cspell/dict-scala@^5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@cspell/dict-scala/-/dict-scala-5.0.9.tgz#181d6b9cad0596bec2f8df198a79576f97112b6e" + integrity sha512-AjVcVAELgllybr1zk93CJ5wSUNu/Zb5kIubymR/GAYkMyBdYFCZ3Zbwn4Zz8GJlFFAbazABGOu0JPVbeY59vGg== -"@cspell/dict-shell@1.1.1", "@cspell/dict-shell@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@cspell/dict-shell/-/dict-shell-1.1.1.tgz#2274798fefaf6bab354cfec4d1169cc8d0f2a2b1" - integrity sha512-T37oYxE7OV1x/1D4/13Y8JZGa1QgDCXV7AVt3HLXjn0Fe3TaNDvf5sU0fGnXKmBPqFFrHdpD3uutAQb1dlp15g== +"@cspell/dict-shell@1.2.0", "@cspell/dict-shell@^1.1.2": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-shell/-/dict-shell-1.2.0.tgz#5702fe3f8fc8813448e98dcec9df9e34934b0f21" + integrity sha512-PVctvT22lJ49niMiakO8xieY7ELCAzjSqhejWR7bAMb5AZ9F4WDEs+XdGMnoVHWeXq7K5rcepLPmEJb+37zzIw== -"@cspell/dict-software-terms@^5.1.4": - version "5.1.5" - resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-5.1.5.tgz#b83440158c1a2c3ecc1bf463da93142279321de5" - integrity sha512-MX5beBP3pLmIM0mjqfrHbie3EEfyLWZ8ZqW56jcLuRlLoDcfC0FZsr66NCARgCgEwsWiidHFe87+7fFsnwqY6A== +"@cspell/dict-software-terms@^5.2.2": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-software-terms/-/dict-software-terms-5.3.0.tgz#cee14993bc3470121c3dfa18c7fa3996ecd71167" + integrity sha512-HEMvFWeItTA5A/MFxrH5fpOz9DU7ormXaGp1PJPsd0jt+qqaYNpevGIgTfIhfp/hsabPyAGa51N/DeDT0ZMg2Q== "@cspell/dict-sql@^2.2.1": version "2.2.1" @@ -445,28 +458,38 @@ resolved "https://registry.yarnpkg.com/@cspell/dict-vue/-/dict-vue-3.0.5.tgz#e915b6a004d0352f5c27a2e4583c42dba62b6ce0" integrity sha512-Mqutb8jbM+kIcywuPQCCaK5qQHTdaByoEO2J9LKFy3sqAdiBogNkrplqUK0HyyRFgCfbJUgjz3N85iCMcWH0JA== -"@cspell/dynamic-import@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/dynamic-import/-/dynamic-import-9.2.0.tgz#d46ae6779029985b581348df433661592530df41" - integrity sha512-2/k4LR8CQqbgIPQGELbCdt9xgg9+aQ7pMwOtllKvnFYBtwNiwqcZjlzAam2gtvD5DghKX2qrcSHG5A7YP5cX9A== +"@cspell/dict-zig@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@cspell/dict-zig/-/dict-zig-1.0.0.tgz#f75fef19f2fdad6f5bc4d02b95b8bec824e82ab9" + integrity sha512-XibBIxBlVosU06+M6uHWkFeT0/pW5WajDRYdXG2CgHnq85b0TI/Ks0FuBJykmsgi2CAD3Qtx8UHFEtl/DSFnAQ== + +"@cspell/dynamic-import@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/dynamic-import/-/dynamic-import-10.0.1.tgz#816a7806cbb5285a3654e6aae9409c751918e6d1" + integrity sha512-mP1gdq00aIcH8HxNMqnH11X6BKxLcneDtFgl/ecjIKnaGKwi44m8AndP5Kr4ODaYdl8UUw9O3dJh7KaQXnLHZQ== dependencies: - "@cspell/url" "9.2.0" - import-meta-resolve "^4.1.0" + "@cspell/url" "10.0.1" + import-meta-resolve "^4.2.0" -"@cspell/filetypes@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/filetypes/-/filetypes-9.2.0.tgz#bd111a1bdc3660c579153cf9630fe2d263cc33f0" - integrity sha512-6wmCa3ZyI647H7F4w6kb9PCJ703JKSgFTB8EERTdIoGySbgVp5+qMIIoZ//wELukdjgcufcFZ5pBrhRDRsemRA== +"@cspell/filetypes@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/filetypes/-/filetypes-10.0.1.tgz#ff877980caebb41fc1c8b4d5a2d411b4ca2c22b4" + integrity sha512-Z5S35giU5IW49fBBq6BksUbE8PC4IYPfaKuwl5Nl9jkf/OkAKiBmCowKX45NzRUQInwK/GSqqIUifrNeI6LdLw== -"@cspell/strong-weak-map@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/strong-weak-map/-/strong-weak-map-9.2.0.tgz#80c153a980c72a4a2a36ec67d0803a59235e787a" - integrity sha512-5mpIMiIOCu4cBqy1oCTXISgJuOCQ6R/e38AkvnYWfmMIx7fCdx8n+mF52wX9m61Ng28Sq8VL253xybsWcCxHug== +"@cspell/rpc@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/rpc/-/rpc-10.0.1.tgz#6bb88f18253faf1f4599d89555c2ba238174221c" + integrity sha512-axSRKv3zEAmBm66iD/FV/MPmE4/Yf7c3PZiwTW894Yd3iEhtn3KPKeTrqQ2/tDrhB1Z2qTsap/Hue0MK4o5WXg== -"@cspell/url@9.2.0": - version "9.2.0" - resolved "https://registry.yarnpkg.com/@cspell/url/-/url-9.2.0.tgz#225070a8f553f80357e67ff11b0dd232645a81a0" - integrity sha512-plB0wwdAESqBl4xDAT2db2/K1FZHJXfYlJTiV6pkn0XffTGyg4UGLaSCm15NzUoPxdSmzqj5jQb7y+mB9kFK8g== +"@cspell/strong-weak-map@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/strong-weak-map/-/strong-weak-map-10.0.1.tgz#55a206076ab9d8957db5ffbf188cc73d422a3a14" + integrity sha512-lenN1DVyPi8nJLSMSJJ670ddTjyiruLueuSZO1qLcxBqUhgxDt/mALu9N/1m6WdOVcg6m/5cLiZVg2KOo2UzRw== + +"@cspell/url@10.0.1": + version "10.0.1" + resolved "https://registry.yarnpkg.com/@cspell/url/-/url-10.0.1.tgz#b7eeefe6f4c84b8f2748d510127e85a3eacbb86b" + integrity sha512-abYYgI29wJhWIfWTYrYuzRYDcHQUQ1N5ylnhxYn1NJnIQMqUWGLbDmt12JABtZ+R6h6UNatQrS7rhP86etvJyQ== "@electrum-cash/debug-logs@^1.0.0": version "1.0.0" @@ -475,22 +498,22 @@ dependencies: debug "^4.3.7" -"@electrum-cash/network@^4.1.3": - version "4.1.3" - resolved "https://registry.yarnpkg.com/@electrum-cash/network/-/network-4.1.3.tgz#195a96e8bb34493c622223992da0649c753aafff" - integrity sha512-amMvdcEfHhquoUkhN7x/H04KPYfqd5LilOGcg6O1OdUks1Mcrcah8WfHICHW/qyZ3Rgoos9o7Wx8gKz8qcSNzg== +"@electrum-cash/network@^4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@electrum-cash/network/-/network-4.2.2.tgz#867b849938d196e887d56cf2cbecb8a1f2c9ea71" + integrity sha512-v2Wwt2o0VBBALPArx2dJEDvSqewKjiTW5KAd+jEXxxgdSxFygjJIrFcXryKOCv2CDbpE5+lXAogPAjx6FqW/nw== dependencies: "@electrum-cash/debug-logs" "^1.0.0" - "@electrum-cash/web-socket" "^1.0.0" + "@electrum-cash/web-socket" "^1.2.3" async-mutex "^0.5.0" debug "^4.3.2" eventemitter3 "^5.0.1" lossless-json "^4.0.1" -"@electrum-cash/web-socket@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@electrum-cash/web-socket/-/web-socket-1.0.0.tgz#0ab57e46d41e941ffb57deff86afea3ae1379d5d" - integrity sha512-+VQ6aPE7nUysyDn9SB7/uqKuVJmjrhvr0LRK2ANTeR1DfmXBnv5z29e/0zK5A7ZoAz0gdZZuLDzN46r8S5Cxig== +"@electrum-cash/web-socket@^1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@electrum-cash/web-socket/-/web-socket-1.2.3.tgz#473b6ddb4dba513e1c4e62b163da219205e7b31b" + integrity sha512-sFWujTt98mvsMvE6gWjG44evkF3PcZhG1JffkkEUAVan+c9X51wkiWr3hkjPeIW0WfNpMTrFkvpGqVYmRj1RCA== dependencies: "@electrum-cash/debug-logs" "^1.0.0" "@monsterbitar/isomorphic-ws" "^5.3.0" @@ -500,265 +523,135 @@ lossless-json "^4.0.1" ws "^8.13.0" -"@esbuild/aix-ppc64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.8.tgz#a1414903bb38027382f85f03dda6065056757727" - integrity sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA== - -"@esbuild/aix-ppc64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz#bef96351f16520055c947aba28802eede3c9e9a9" - integrity sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA== - -"@esbuild/android-arm64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.8.tgz#c859994089e9767224269884061f89dae6fb51c6" - integrity sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w== - -"@esbuild/android-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz#d2e70be7d51a529425422091e0dcb90374c1546c" - integrity sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg== - -"@esbuild/android-arm@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.8.tgz#96a8f2ca91c6cd29ea90b1af79d83761c8ba0059" - integrity sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw== - -"@esbuild/android-arm@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.9.tgz#d2a753fe2a4c73b79437d0ba1480e2d760097419" - integrity sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ== - -"@esbuild/android-x64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.8.tgz#a3a626c4fec4a024a9fa8c7679c39996e92916f0" - integrity sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA== - -"@esbuild/android-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.9.tgz#5278836e3c7ae75761626962f902a0d55352e683" - integrity sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw== - -"@esbuild/darwin-arm64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.8.tgz#a5e1252ca2983d566af1c0ea39aded65736fc66d" - integrity sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw== - -"@esbuild/darwin-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz#f1513eaf9ec8fa15dcaf4c341b0f005d3e8b47ae" - integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg== - -"@esbuild/darwin-x64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.8.tgz#5271b0df2bb12ce8df886704bfdd1c7cc01385d2" - integrity sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg== - -"@esbuild/darwin-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz#e27dbc3b507b3a1cea3b9280a04b8b6b725f82be" - integrity sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ== - -"@esbuild/freebsd-arm64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.8.tgz#d0a0e7fdf19733b8bb1566b81df1aa0bb7e46ada" - integrity sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA== - -"@esbuild/freebsd-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz#364e3e5b7a1fd45d92be08c6cc5d890ca75908ca" - integrity sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q== - -"@esbuild/freebsd-x64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.8.tgz#2de8b2e0899d08f1cb1ef3128e159616e7e85343" - integrity sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw== - -"@esbuild/freebsd-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz#7c869b45faeb3df668e19ace07335a0711ec56ab" - integrity sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg== - -"@esbuild/linux-arm64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.8.tgz#a4209efadc0c2975716458484a4e90c237c48ae9" - integrity sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w== - -"@esbuild/linux-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz#48d42861758c940b61abea43ba9a29b186d6cb8b" - integrity sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw== - -"@esbuild/linux-arm@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.8.tgz#ccd9e291c24cd8d9142d819d463e2e7200d25b19" - integrity sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg== - -"@esbuild/linux-arm@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz#6ce4b9cabf148274101701d112b89dc67cc52f37" - integrity sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw== - -"@esbuild/linux-ia32@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.8.tgz#006ad1536d0c2b28fb3a1cf0b53bcb85aaf92c4d" - integrity sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg== - -"@esbuild/linux-ia32@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz#207e54899b79cac9c26c323fc1caa32e3143f1c4" - integrity sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A== - -"@esbuild/linux-loong64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.8.tgz#127b3fbfb2c2e08b1397e985932f718f09a8f5c4" - integrity sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ== - -"@esbuild/linux-loong64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz#0ba48a127159a8f6abb5827f21198b999ffd1fc0" - integrity sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ== - -"@esbuild/linux-mips64el@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.8.tgz#837d1449517791e3fa7d82675a2d06d9f56cb340" - integrity sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw== - -"@esbuild/linux-mips64el@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz#a4d4cc693d185f66a6afde94f772b38ce5d64eb5" - integrity sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA== - -"@esbuild/linux-ppc64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.8.tgz#aa2e3bd93ab8df084212f1895ca4b03c42d9e0fe" - integrity sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ== - -"@esbuild/linux-ppc64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz#0f5805c1c6d6435a1dafdc043cb07a19050357db" - integrity sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w== - -"@esbuild/linux-riscv64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.8.tgz#a340620e31093fef72767dd28ab04214b3442083" - integrity sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg== - -"@esbuild/linux-riscv64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz#6776edece0f8fca79f3386398b5183ff2a827547" - integrity sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg== - -"@esbuild/linux-s390x@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.8.tgz#ddfed266c8c13f5efb3105a0cd47f6dcd0e79e71" - integrity sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg== - -"@esbuild/linux-s390x@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz#3f6f29ef036938447c2218d309dc875225861830" - integrity sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA== - -"@esbuild/linux-x64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.8.tgz#9a4f78c75c051e8c060183ebb39a269ba936a2ac" - integrity sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ== - -"@esbuild/linux-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz#831fe0b0e1a80a8b8391224ea2377d5520e1527f" - integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg== - -"@esbuild/netbsd-arm64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.8.tgz#902c80e1d678047926387230bc037e63e00697d0" - integrity sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw== - -"@esbuild/netbsd-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz#06f99d7eebe035fbbe43de01c9d7e98d2a0aa548" - integrity sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q== - -"@esbuild/netbsd-x64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.8.tgz#2d9eb4692add2681ff05a14ce99de54fbed7079c" - integrity sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg== - -"@esbuild/netbsd-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz#db99858e6bed6e73911f92a88e4edd3a8c429a52" - integrity sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g== - -"@esbuild/openbsd-arm64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.8.tgz#89c3b998c6de739db38ab7fb71a8a76b3fa84a45" - integrity sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ== - -"@esbuild/openbsd-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz#afb886c867e36f9d86bb21e878e1185f5d5a0935" - integrity sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ== - -"@esbuild/openbsd-x64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.8.tgz#2f01615cf472b0e48c077045cfd96b5c149365cc" - integrity sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ== - -"@esbuild/openbsd-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz#30855c9f8381fac6a0ef5b5f31ac6e7108a66ecf" - integrity sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA== - -"@esbuild/openharmony-arm64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.8.tgz#a201f720cd2c3ebf9a6033fcc3feb069a54b509a" - integrity sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg== - -"@esbuild/openharmony-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz#2f2144af31e67adc2a8e3705c20c2bd97bd88314" - integrity sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg== - -"@esbuild/sunos-x64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.8.tgz#07046c977985a3334667f19e6ab3a01a80862afb" - integrity sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w== - -"@esbuild/sunos-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz#69b99a9b5bd226c9eb9c6a73f990fddd497d732e" - integrity sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw== - -"@esbuild/win32-arm64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.8.tgz#4a5470caf0d16127c05d4833d4934213c69392d1" - integrity sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ== - -"@esbuild/win32-arm64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz#d789330a712af916c88325f4ffe465f885719c6b" - integrity sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ== - -"@esbuild/win32-ia32@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.8.tgz#3de3e8470b7b328d99dbc3e9ec1eace207e5bbc4" - integrity sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg== - -"@esbuild/win32-ia32@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz#52fc735406bd49688253e74e4e837ac2ba0789e3" - integrity sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww== - -"@esbuild/win32-x64@0.25.8": - version "0.25.8" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.8.tgz#610d7ea539d2fcdbe39237b5cc175eb2c4451f9c" - integrity sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw== - -"@esbuild/win32-x64@0.25.9": - version "0.25.9" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz#585624dc829cfb6e7c0aa6c3ca7d7e6daa87e34f" - integrity sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ== +"@esbuild/aix-ppc64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.28.2.tgz#bf6e10303bcf2e7c686975fa52f937ec2728d8bc" + integrity sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ== + +"@esbuild/android-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.28.2.tgz#0c6246bc8d2c4d172aac2db3fb1190d72bd65504" + integrity sha512-5YfKeeI8qWfBZIX+u2xZC3Zlb3Os/gLS2sbEKM+I4ZOcsWmHS2WLysCcQZDAFRslDUU5Oiq44gf6PYN1vGwG5A== + +"@esbuild/android-arm@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.28.2.tgz#2d84ece6a4e2684d92be26ee13d42757d831c381" + integrity sha512-kXXoiPVVGQcnIYGOeaovwOURpniDBpSq4A03qkQ+BMQqtGG6HYap3xne9C1O1yo4TR3qxlCX5IqqmX6fFo2Lqg== + +"@esbuild/android-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.28.2.tgz#fc38d4d6358d8dc1cf53f09f7589fe436eb64801" + integrity sha512-O387ite7SzUyCcy3JQX4P4bLtEA7bLLkx+esve5JHnyYfNTxcVpXZo9jhdB0lTKN44gztELTdU7nS8Nr16Fs1Q== + +"@esbuild/darwin-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.28.2.tgz#f83afeeac1d7dac01c7a2fd012b3e451a0591fcc" + integrity sha512-n4KqkOQrraxHJcgjM1RvwbigfQKIKJVpM7xp+KsxiyUSrRdIXnt73VhrPAx0fV44hgfmIVKjxMN9J1t5jySVkw== + +"@esbuild/darwin-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.28.2.tgz#510147c055a795588dbbe14fd6b1b8ad0a2f30de" + integrity sha512-uq6suIWYP37qzGddBKPw5QEQPi6HiLGsO7UmkpfyaYNQ3D+rN6w6WfwH+nuqcGXWvawGwxOEroO4YGnFh95azw== + +"@esbuild/freebsd-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.2.tgz#093b9200ecf0b115ba4e5e248a7485c9c5f8bd5e" + integrity sha512-n+I0BTSRIoy+d6RPKnEVwql5UwBJolytvY4mAOIEJorKlqgPII8ix6slVVrfZ5Tnj7glIZvloylbB/EJPMWEXw== + +"@esbuild/freebsd-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.28.2.tgz#0be22b6df925d213e841ea87123af5df80b0faf7" + integrity sha512-78XJTJkvPs0kz2w61301PJjXl4g7q3JqiYMZ/M/yVI73EHBrCRTgkhu9oqG7vPqq+a/yadEW8aD+agKlk5xrmg== + +"@esbuild/linux-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.28.2.tgz#1bdbc651cda9ba9995c53ed9c71ceaa65094762d" + integrity sha512-pW4AC0P3it8c7do9MVM4p51FzHzdM/TZrerurgRcHJ2WTa1VQ1CIq18xncfpBJw4ojkiZZrKW2yIBWBP92j6Ug== + +"@esbuild/linux-arm@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.28.2.tgz#beb12ad72b84f72d28488cc1b8ee9f7eb141d753" + integrity sha512-XlDnu2q5yoqems+xay6wSAcg9DDD7K9RLKZEBOMZm3ckNpJBvOX20tSfby8KfrrhINDyv9V2YVZKY/SpoGJI8w== + +"@esbuild/linux-ia32@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.28.2.tgz#b81f9d55529b45c206a46a138214b1aa6879696b" + integrity sha512-CYbnj78HsIeA+DhgUKgFCfvNsTHFhMMrinUrMZpDXJXKN8T3XViTZ/+wtHeVxEWY8ewSzTFN+nRmSwO2tZaLUQ== + +"@esbuild/linux-loong64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.28.2.tgz#598667241a04c99b76ed6ef940ac50038c419f98" + integrity sha512-buwkd8nsph4R+ajRvw0qM5Hja/TXQow3ptzWO2EbG/cqcIkHloRrdlBtQlshyYGTNFvfkfJ5tpPLVkY4DtsPfQ== + +"@esbuild/linux-mips64el@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.28.2.tgz#1c51eb9cea903f53d97b5af3b1841db70f5596ca" + integrity sha512-ZVykbDyk7519VwiNb9Lcj9m8XM6v5V9uKPvrEMkkEedVewf+0itkhahp4HDpgERXhwLRpWFypsGbG/J8s0QjJA== + +"@esbuild/linux-ppc64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.28.2.tgz#63dd61f17ceb31a81227f413feac8a71bc2c51f2" + integrity sha512-CAXl+Dtd9UUuJd8pKKdwh6MLm3MUMiqMPmhZ3tTSXPqfyQ3vDl6R5hZdZ/kYojK4ofXtdfSv1tFq8XzWx3heNQ== + +"@esbuild/linux-riscv64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.28.2.tgz#3763b08fde5cf25ab1facb8e7752edfe45fbfc27" + integrity sha512-GeXCej4IQtU1B+QlDV8W/RRvbzI3O/Stss+/bCXv4lZls5WGRtu2a+3JkA3i4qIUlMXpcHebWpF8AkJhATowuA== + +"@esbuild/linux-s390x@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.28.2.tgz#1a137ff293a82906eb3176385bd7e8e0e5cfb7cb" + integrity sha512-3H1weTYZPxt/WOhByszQZybS9w5lKzUn1FDMsgEChbHWQwHYQQRfBxgCcZvPhjHfKyJjIievvMmEUawJrdY9Dg== + +"@esbuild/linux-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.28.2.tgz#268b36211c146ca54f8fe12c578a8d6ef8979485" + integrity sha512-4xTZr1FUmSoQW4XIWmit3tzQrUTZM+N3P0XV8xROKYF50XfI7xeO90+1bZvNwxIufQ9hDQVRJH5YhgPVF8A/HQ== + +"@esbuild/netbsd-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.2.tgz#22571ad951d62bb6accc82d8d1fad5c8c1ac0ba1" + integrity sha512-sSATRjPeDBg3pdgHoQfoYBob11Kk1FGa9lui5RIHZCoCkJa9QKlvl3/vKz2usCmYYjs7ymJR/2Nnsqe+Hjt5nw== + +"@esbuild/netbsd-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.28.2.tgz#42fcc57297eb0a0ca3f5fc475291f4c1a3f7c0de" + integrity sha512-lqnzCV+mM0gIADaKihiCg6ifgfU2L3h5E33rNQBN1Y4MaVGnzryzmvvf7UHxprpQdE8hpqLolJ9Rl+SkIRDpyw== + +"@esbuild/openbsd-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.2.tgz#9eb32af104ac3dacf4edca01f596664aab0c73ef" + integrity sha512-AL2qJILH7lNjrDmCQDvdxMfAUIv8KMNZOvrwAQ8i8//ntL9FflhOyMJ8OZSMBb8/AWXe3/5v5S20y3zCoZWKoQ== + +"@esbuild/openbsd-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.28.2.tgz#febed2402d6088225e91f20fb4ce2522ad0a4efd" + integrity sha512-QtiuPytchRyC4rwUKhexJdQKvDuZ6hWloi3igqPQNUJCS1/v9EiO3UTOXR6A3FoMo4fnAKbWJdqaIwhOzh8qEw== + +"@esbuild/openharmony-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.2.tgz#85641c3d466428bfbccea5f21c26836663fef5ce" + integrity sha512-WkhYDmpTjLvGlScA1rwjRUmhl4k8oXR3cIbtqWmELgU/dFeHHlEllxDvdWcNJV9rbzCexB5vz8gtNewWLgCT7Q== + +"@esbuild/sunos-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.28.2.tgz#a736f9d8962481045fc4c3e54f5479f22c870fb4" + integrity sha512-GPMSkTOtMnv2U2F8gxe4Io6qmVs+YKyp832Etqqxr0hFngmXQ3rzwytelm3GIn7T4VviRUlf3sOgBOiTdvaf7g== + +"@esbuild/win32-arm64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.28.2.tgz#ee5ab40fad186201b652a33f8a5eb149e9e42532" + integrity sha512-PIhhEkE9uPBleRBrQEJpUn7MBnibZzbGzYWPmY3x+YoVg/95zbjB4CxPPOQ8l5tYYM4mMaCthF8/1DIfBQQyWQ== + +"@esbuild/win32-ia32@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.28.2.tgz#c40d28a6d99a127da6711f2afd74b11cb63b06a7" + integrity sha512-YmJbfTlvU7Sdn9BB+4PRES4oB6pxgS37MAONj+hBr/cpXS1aBPKXxNnDbu+QCWPj0o9dgyxeq79g6c5P8KeuYA== + +"@esbuild/win32-x64@0.28.2": + version "0.28.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.28.2.tgz#b21affb804cc167c133d95f45b3a1dc1323b9a87" + integrity sha512-5ebpxr3nWMzrL/rnUI755Jkuee0bHL/Gq0WTF9lvcpv73wAp5eu8MfBUgWK9bhWvZjj7yX8etf/8tI8Ney695g== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" @@ -900,7 +793,7 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== -"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.31": +"@jridgewell/trace-mapping@^0.3.31": version "0.3.31" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0" integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== @@ -1741,115 +1634,95 @@ dependencies: "@types/node" ">= 8" -"@rollup/rollup-android-arm-eabi@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.48.1.tgz#13cccb90969f7ca3d1354129c859a3b05e90beed" - integrity sha512-rGmb8qoG/zdmKoYELCBwu7vt+9HxZ7Koos3pD0+sH5fR3u3Wb/jGcpnqxcnWsPEKDUyzeLSqksN8LJtgXjqBYw== - -"@rollup/rollup-android-arm64@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.48.1.tgz#0d01925255bb27b56edd095ba1764c3f91f28048" - integrity sha512-4e9WtTxrk3gu1DFE+imNJr4WsL13nWbD/Y6wQcyku5qadlKHY3OQ3LJ/INrrjngv2BJIHnIzbqMk1GTAC2P8yQ== - -"@rollup/rollup-darwin-arm64@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.48.1.tgz#5b11bca1da78d68f26aa98754cecd1887b683689" - integrity sha512-+XjmyChHfc4TSs6WUQGmVf7Hkg8ferMAE2aNYYWjiLzAS/T62uOsdfnqv+GHRjq7rKRnYh4mwWb4Hz7h/alp8A== - -"@rollup/rollup-darwin-x64@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.48.1.tgz#00039989c4cd27ead349c313dc5562c3897c0524" - integrity sha512-upGEY7Ftw8M6BAJyGwnwMw91rSqXTcOKZnnveKrVWsMTF8/k5mleKSuh7D4v4IV1pLxKAk3Tbs0Lo9qYmii5mQ== - -"@rollup/rollup-freebsd-arm64@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.48.1.tgz#1e5aca23d8171313f408759c71342bbee7889f22" - integrity sha512-P9ViWakdoynYFUOZhqq97vBrhuvRLAbN/p2tAVJvhLb8SvN7rbBnJQcBu8e/rQts42pXGLVhfsAP0k9KXWa3nQ== - -"@rollup/rollup-freebsd-x64@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.48.1.tgz#04af010d99ccba84db10d4498cadaac8529ee738" - integrity sha512-VLKIwIpnBya5/saccM8JshpbxfyJt0Dsli0PjXozHwbSVaHTvWXJH1bbCwPXxnMzU4zVEfgD1HpW3VQHomi2AQ== - -"@rollup/rollup-linux-arm-gnueabihf@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.48.1.tgz#67747af83a2dd092144d643caf20b0d1eb817681" - integrity sha512-3zEuZsXfKaw8n/yF7t8N6NNdhyFw3s8xJTqjbTDXlipwrEHo4GtIKcMJr5Ed29leLpB9AugtAQpAHW0jvtKKaQ== - -"@rollup/rollup-linux-arm-musleabihf@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.48.1.tgz#b4bed820cfc5efec00a13190e3d53c0b5240f3b1" - integrity sha512-leo9tOIlKrcBmmEypzunV/2w946JeLbTdDlwEZ7OnnsUyelZ72NMnT4B2vsikSgwQifjnJUbdXzuW4ToN1wV+Q== - -"@rollup/rollup-linux-arm64-gnu@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.48.1.tgz#6b4a7af7e53e7d95c8c1975945d8f8dc8f6d74a9" - integrity sha512-Vy/WS4z4jEyvnJm+CnPfExIv5sSKqZrUr98h03hpAMbE2aI0aD2wvK6GiSe8Gx2wGp3eD81cYDpLLBqNb2ydwQ== - -"@rollup/rollup-linux-arm64-musl@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.48.1.tgz#dd08c8174cfb95d4fa90663dd6be8db27039ad51" - integrity sha512-x5Kzn7XTwIssU9UYqWDB9VpLpfHYuXw5c6bJr4Mzv9kIv242vmJHbI5PJJEnmBYitUIfoMCODDhR7KoZLot2VQ== - -"@rollup/rollup-linux-loongarch64-gnu@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.48.1.tgz#997248c983d2272d1b810e5817cc3c885ebde5ff" - integrity sha512-yzCaBbwkkWt/EcgJOKDUdUpMHjhiZT/eDktOPWvSRpqrVE04p0Nd6EGV4/g7MARXXeOqstflqsKuXVM3H9wOIQ== - -"@rollup/rollup-linux-ppc64-gnu@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.48.1.tgz#57d020583a314741d17b653419d1dbc3fe99bc52" - integrity sha512-UK0WzWUjMAJccHIeOpPhPcKBqax7QFg47hwZTp6kiMhQHeOYJeaMwzeRZe1q5IiTKsaLnHu9s6toSYVUlZ2QtQ== - -"@rollup/rollup-linux-riscv64-gnu@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.48.1.tgz#bbd381e5f99658de9baa0193b89e286767c6e029" - integrity sha512-3NADEIlt+aCdCbWVZ7D3tBjBX1lHpXxcvrLt/kdXTiBrOds8APTdtk2yRL2GgmnSVeX4YS1JIf0imFujg78vpw== - -"@rollup/rollup-linux-riscv64-musl@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.48.1.tgz#2866abbea1e702246900414f878203fea350ccee" - integrity sha512-euuwm/QTXAMOcyiFCcrx0/S2jGvFlKJ2Iro8rsmYL53dlblp3LkUQVFzEidHhvIPPvcIsxDhl2wkBE+I6YVGzA== - -"@rollup/rollup-linux-s390x-gnu@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.48.1.tgz#02f6a1b0f207bf9b6c8f76fca3bd394ad1a5e800" - integrity sha512-w8mULUjmPdWLJgmTYJx/W6Qhln1a+yqvgwmGXcQl2vFBkWsKGUBRbtLRuKJUln8Uaimf07zgJNxOhHOvjSQmBQ== - -"@rollup/rollup-linux-x64-gnu@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.48.1.tgz#867a70767a3e45c1a49b26310548e7861f980016" - integrity sha512-90taWXCWxTbClWuMZD0DKYohY1EovA+W5iytpE89oUPmT5O1HFdf8cuuVIylE6vCbrGdIGv85lVRzTcpTRZ+kA== - -"@rollup/rollup-linux-x64-musl@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.48.1.tgz#4b676c79d85c3ae58e706d44d4be3bc4eb6315cd" - integrity sha512-2Gu29SkFh1FfTRuN1GR1afMuND2GKzlORQUP3mNMJbqdndOg7gNsa81JnORctazHRokiDzQ5+MLE5XYmZW5VWg== - -"@rollup/rollup-win32-arm64-msvc@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.48.1.tgz#0106a573d0c7b82e95c6f57894b65f11bc0c7873" - integrity sha512-6kQFR1WuAO50bxkIlAVeIYsz3RUx+xymwhTo9j94dJ+kmHe9ly7muH23sdfWduD0BA8pD9/yhonUvAjxGh34jQ== - -"@rollup/rollup-win32-ia32-msvc@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.48.1.tgz#351eee360c21415c1efb01d402f53c2a1f5f1a53" - integrity sha512-RUyZZ/mga88lMI3RlXFs4WQ7n3VyU07sPXmMG7/C1NOi8qisUg57Y7LRarqoGoAiopmGmChUhSwfpvQ3H5iGSQ== - -"@rollup/rollup-win32-x64-msvc@4.48.1": - version "4.48.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.48.1.tgz#6821b48385af21ba55c7a5f9f64d19f38ea26014" - integrity sha512-8a/caCUN4vkTChxkaIJcMtwIVcBhi4X2PQRoT+yCK3qRYaZ7cURrmJFL5Ux9H9RaMIXj9RuihckdmkBX3zZsgg== +"@oxc-project/types@=0.143.0": + version "0.143.0" + resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.143.0.tgz#c3e4f3178b7b54e4dd194eac6d45258a60f0092b" + integrity sha512-u6JZdLBTLotrNC9Vd6vPssINdzcCzleKAH6EJKImQb7GtYvX5keN2dxkoK44stCc4tffE6QQRtZTXVSzsLUlWA== + +"@rolldown/binding-android-arm64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.3.tgz#001b8b0b01844701efda1bb6bed84b681c4a488b" + integrity sha512-zrJtHDcaZJ1Fp7xf4hNl+7seH9Cn/N5TwLYkhgXREtBwAd/jaqW3uqeHxpDugJLVICWg4eW44kOQEGJ1r6jCGw== + +"@rolldown/binding-darwin-arm64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.3.tgz#5e87c602ed634a6fef092e2162e24fbfb881c4ec" + integrity sha512-ieIiibVCp0tX7TLu2cafoNPv8wJyYi01ekXpbf8q2j7F4rGAhhXb/eQh7ge9DRBY78GwmRQtvjZDux7EDbA8kA== + +"@rolldown/binding-darwin-x64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.3.tgz#f32e0b286714bd03a421d693415d05d97d265b77" + integrity sha512-Zh9tCon19eDXJoihx0rqKhMUlMYqzwj3aPsSuHmI4RWZh62dWUL+DJN4C5YQya5TcQBJU/Fe8+rY0jhXTQITqA== + +"@rolldown/binding-freebsd-x64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.3.tgz#5f38ad5761b6b7b21b57a99566bb52634c60ab19" + integrity sha512-nGbJWewA1wrXXZiQhjAT5rhibGfns5ZNkDVqxsO6zJ3f3YvpoDNNmGMSbbhLuXKjNScaBJVOAboztAWVespQMg== + +"@rolldown/binding-linux-arm-gnueabihf@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.3.tgz#ab4dcd07f1bd88e8d659ae0c3bb9d2f290adb897" + integrity sha512-QNniJr5Kml0kDEB98jiDOJjXNroxIIi0IXIbdYzY26Xt1pVbeP62+KnoIZLwirOymX/0jDk/2gI/bNUv7A7OIw== + +"@rolldown/binding-linux-arm64-gnu@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.3.tgz#d279b7016039a725fb66d82784b9841f42df83da" + integrity sha512-TkqEAcmmvH3I/q4114NB4RVt6241Dao48pF45uLcFGrwAaIn0iITgTAKP/dLjbN0R4buJjGb91+UHSoFmpgIWw== + +"@rolldown/binding-linux-arm64-musl@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.3.tgz#d08bbc93d2742214548c5adf7df7788944e5a89a" + integrity sha512-NHqjnxpsndf4MPymxteFAWHHfkTL8HjWh1KB7z23ofZ6QO2euONuxDXjat69dKZRALnGypg8k8SsK8vZJoXv1Q== + +"@rolldown/binding-linux-ppc64-gnu@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.3.tgz#6418e63745b3193f26ab3bb88744b3a4a1356d7c" + integrity sha512-6tbrbwfz5GB9DQ4Jwo6hy9v+vR31xZlvzZ6n5Xut6Hhx5PvrA9q/HsK8KMaYQp063iqZGXwNvZtYNLD7EM/x0w== + +"@rolldown/binding-linux-s390x-gnu@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.3.tgz#77ec30d0704cf4eb1cb4a63f501c9852c6728cf4" + integrity sha512-oyuXxXmoZHjXC917IAPFAAv4wWAa0cM9afk8nx1+9/jNNOX1uPf8yDA6p7G0RypOfw/X0PQt5IfoquY1um+zSg== + +"@rolldown/binding-linux-x64-gnu@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.3.tgz#3b9b6e0dd3e86c597f42858748ca25f1dfd58ed8" + integrity sha512-TytMwF2KVGqP2tgd0I1OY0PAv78dZRAYcF5ssDzjM34SUXCED3uXvSd5+lHoC0bTD6eEdFz7LdQNCO1y0oVk9w== + +"@rolldown/binding-linux-x64-musl@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.3.tgz#f78033c592c8bd2af48284a45f8e4baaa0befbf5" + integrity sha512-/E9m3qstrJFVPoULV25mVQblSNExY2+kBsYe4sy0Tn0yOOgJ8wZbZt3KnRbF/XeU2Gl1STKUQnDNTqhIE5MD4A== + +"@rolldown/binding-openharmony-arm64@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.3.tgz#36e951f5a6fca922a5205e283d0a82b9f98199ca" + integrity sha512-Kr0OcsoQI816i6HOl3vFHpd1K0eZyh76zgfj4c1nTyaTsd5r2Mj1lwM4R90y/qaCfmTn9eHy0SKwi98eitRxug== + +"@rolldown/binding-win32-arm64-msvc@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.3.tgz#c1e494ac47e13bd857fca0b3ad59c33580241f7e" + integrity sha512-hOtMwTqnME+/gJcH/PCZ0wn0zPUjiWOgkHpxbSJpfGKMezHltx1S7/k1SitzVa7Ww2cqrDDaFbZEhcJZO8o+Jw== + +"@rolldown/binding-win32-x64-msvc@1.2.3": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.3.tgz#b0effffcd6872f8a021373eb437916b1b52283a4" + integrity sha512-ekcqMMkI2PlhYnfzQnB/cEdYUVVJViWvoUyLrbzgDoi3Snfc1mVBwdnc306ufA5ejy8JSPjT2RlW1nQSjW7efg== + +"@rolldown/pluginutils@^1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz#e3fcee093fbb5ce765e1ad088ff4de2889f6f9be" + integrity sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw== "@rtsao/scc@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@standard-schema/spec@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.0.0.tgz#f193b73dc316c4170f2e82a881da0f550d551b9c" - integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== +"@standard-schema/spec@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8" + integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w== "@types/chai@^5.2.2": version "5.2.2" @@ -1863,7 +1736,7 @@ resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== -"@types/estree@1.0.8", "@types/estree@^1.0.0": +"@types/estree@^1.0.0": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== @@ -1903,27 +1776,22 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.6.0.tgz#7d4411bf5157339337d7cff864d9ff45f177b499" integrity sha512-mikldZQitV94akrc4sCcSjtJfsTKt4p+e/s0AGscVA6XArQ9kFclP+ZiYUMnq987rc6QlYxXv/EivqlfSLxpKA== -"@types/node@^22.17.0": - version "22.17.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.17.0.tgz#e8c9090e957bd4d9860efb323eb92d297347eac7" - integrity sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ== +"@types/node@^24", "@types/node@^24.13.3": + version "24.13.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.13.3.tgz#49f18bd3c647866dcda51a0756c145e14590ce16" + integrity sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q== dependencies: - undici-types "~6.21.0" + undici-types "~7.18.0" "@types/normalize-package-data@^2.4.0": version "2.4.0" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz#e486d0d97396d79beedd0a6e33f4534ff6b4973e" integrity sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA== -"@types/semver@^7.5.8": - version "7.5.8" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" - integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== - -"@types/semver@^7.7.0": - version "7.7.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.7.0.tgz#64c441bdae033b378b6eef7d0c3d77c329b9378e" - integrity sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA== +"@types/semver@^7.8.0": + version "7.8.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.8.0.tgz#0bfe3ec51f5e9615bc317174cd5b88ea08b7fc2f" + integrity sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ== "@types/ws@^8.5.5": version "8.5.14" @@ -2018,80 +1886,81 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== -"@vitest/coverage-v8@^4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.0.15.tgz#5daef6798ced6ed15f4f06f1caf789e1e0da8a11" - integrity sha512-FUJ+1RkpTFW7rQITdgTi93qOCWJobWhBirEPCeXh2SW2wsTlFxy51apDz5gzG+ZEYt/THvWeNmhdAoS9DTwpCw== +"@vitest/coverage-v8@^4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.1.10.tgz#037cd5e7ea8a2f448f4c2e10db1411c2b0c927bd" + integrity sha512-IM49HmthevbgAO4anp1hwtoT9wYe59w0LR00gr+eagHE+ZJ5lK4sLPeO0ubgoJcwLk6dehU3R24N+FbEEKDc8g== dependencies: "@bcoe/v8-coverage" "^1.0.2" - "@vitest/utils" "4.0.15" - ast-v8-to-istanbul "^0.3.8" + "@vitest/utils" "4.1.10" + ast-v8-to-istanbul "^1.0.0" istanbul-lib-coverage "^3.2.2" istanbul-lib-report "^3.0.1" - istanbul-lib-source-maps "^5.0.6" istanbul-reports "^3.2.0" - magicast "^0.5.1" + magicast "^0.5.2" obug "^2.1.1" - std-env "^3.10.0" - tinyrainbow "^3.0.3" + std-env "^4.0.0-rc.1" + tinyrainbow "^3.1.0" -"@vitest/expect@4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.0.15.tgz#8e7e1daf54b7bc9ef6db4d989563c1d55ce424f5" - integrity sha512-Gfyva9/GxPAWXIWjyGDli9O+waHDC0Q0jaLdFP1qPAUUfo1FEXPXUfUkp3eZA0sSq340vPycSyOlYUeM15Ft1w== +"@vitest/expect@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.1.10.tgz#799c06fc44bb0cf7e2784137b627c5cc173285d4" + integrity sha512-YsCn+qAk1GWjQOWFEsEcL2gNQ0zmVmQu3T03qP6UyjhtmdtwtbuI+DASn/7iQB3HGTXkdBwGddzxPlmiql5vlA== dependencies: - "@standard-schema/spec" "^1.0.0" + "@standard-schema/spec" "^1.1.0" "@types/chai" "^5.2.2" - "@vitest/spy" "4.0.15" - "@vitest/utils" "4.0.15" - chai "^6.2.1" - tinyrainbow "^3.0.3" + "@vitest/spy" "4.1.10" + "@vitest/utils" "4.1.10" + chai "^6.2.2" + tinyrainbow "^3.1.0" -"@vitest/mocker@4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.0.15.tgz#5aca5f9c4691efdd2397763efcbde9c680f79caf" - integrity sha512-CZ28GLfOEIFkvCFngN8Sfx5h+Se0zN+h4B7yOsPVCcgtiO7t5jt9xQh2E1UkFep+eb9fjyMfuC5gBypwb07fvQ== +"@vitest/mocker@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.1.10.tgz#2413987ab4cd7fa1c2b614b404c407bf6ad1ead1" + integrity sha512-v0xaezt+DKEmKfaxg133ldzADrwLGd7Ze1MfQQTYfvs8OqZIwbxyxaYURivwV7sWy5fqn3rH5uOrSp07bp44Ow== dependencies: - "@vitest/spy" "4.0.15" + "@vitest/spy" "4.1.10" estree-walker "^3.0.3" magic-string "^0.30.21" -"@vitest/pretty-format@4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.0.15.tgz#2cd8e1bcb4fc8e24124d889a23d1140aecca5744" - integrity sha512-SWdqR8vEv83WtZcrfLNqlqeQXlQLh2iilO1Wk1gv4eiHKjEzvgHb2OVc3mIPyhZE6F+CtfYjNlDJwP5MN6Km7A== +"@vitest/pretty-format@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.1.10.tgz#75542e7273a08cc10fd4d8dad4e3eb1f16cd958c" + integrity sha512-W1HsjSH4MXQ9YfmmhLAoIYf1HRfekQCGngeIgcei6MP5QQGWUe0gkopdZQaVCFO+JDJMrAJGwa5pRpNpvy4P8Q== dependencies: - tinyrainbow "^3.0.3" + tinyrainbow "^3.1.0" -"@vitest/runner@4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.0.15.tgz#fdd4e5d05a4c6b73be9746845d29c7329c37ae3b" - integrity sha512-+A+yMY8dGixUhHmNdPUxOh0la6uVzun86vAbuMT3hIDxMrAOmn5ILBHm8ajrqHE0t8R9T1dGnde1A5DTnmi3qw== +"@vitest/runner@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.1.10.tgz#febf0a21a9168421422d1955370e606feab60355" + integrity sha512-IKI6kpIH+LmpROplyLwBBaCfMgOZOMsygVa6BARD6ahA04VRuJSa6OaVG7kRvSEMD870Vd91rSSw0eegtWyLGg== dependencies: - "@vitest/utils" "4.0.15" + "@vitest/utils" "4.1.10" pathe "^2.0.3" -"@vitest/snapshot@4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.0.15.tgz#52f686d7f314bae53657c1404f8ce7b0b99d2cec" - integrity sha512-A7Ob8EdFZJIBjLjeO0DZF4lqR6U7Ydi5/5LIZ0xcI+23lYlsYJAfGn8PrIWTYdZQRNnSRlzhg0zyGu37mVdy5g== +"@vitest/snapshot@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.1.10.tgz#7e3e9fec7d4d47232e493cfdcbd2170de4371c04" + integrity sha512-xRkfOT1qpTAi/Ti4Y1LtfRc3kEuqxGw59eN2jN9pRWMtS/XDevekhcFSqvQqjUNGksfjMJu3Y+oJ+4Ypn2OaJw== dependencies: - "@vitest/pretty-format" "4.0.15" + "@vitest/pretty-format" "4.1.10" + "@vitest/utils" "4.1.10" magic-string "^0.30.21" pathe "^2.0.3" -"@vitest/spy@4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.0.15.tgz#57987c857c3f1bcea5513b379e8dfc8f06b37b8f" - integrity sha512-+EIjOJmnY6mIfdXtE/bnozKEvTC4Uczg19yeZ2vtCz5Yyb0QQ31QWVQ8hswJ3Ysx/K2EqaNsVanjr//2+P3FHw== +"@vitest/spy@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.1.10.tgz#5c0bfa97b56bba9e37403c976db776ff6ab56f65" + integrity sha512-PLf/Ugvoq5wO/b4rwYCR1h2PSIdXz7wnkQFMiUpLdtM7l6pqVFcQIBEHyT1+l+cj7mNwAfZHzqXqDyjvOuwbDw== -"@vitest/utils@4.0.15": - version "4.0.15" - resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.0.15.tgz#2e36d5c34656a1ce1a057d8595a835bff524f1bc" - integrity sha512-HXjPW2w5dxhTD0dLwtYHDnelK3j8sR8cWIaLxr22evTyY6q8pRCjZSmhRWVjBaOVXChQd6AwMzi9pucorXCPZA== +"@vitest/utils@4.1.10": + version "4.1.10" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.1.10.tgz#ffc71055f18bfccb1fd0586365ebc2824892e403" + integrity sha512-fy9am/HWxbaGt/Sawrp90vt6Y6jQwf1RX77cz3uwoJwJVMli/e1IEwRPnMNJ7vKfPTwo0diXifkpPvwH9v7nGA== dependencies: - "@vitest/pretty-format" "4.0.15" - tinyrainbow "^3.0.3" + "@vitest/pretty-format" "4.1.10" + convert-source-map "^2.0.0" + tinyrainbow "^3.1.0" "@zkochan/cmd-shim@^3.1.0": version "3.1.0" @@ -2146,14 +2015,6 @@ agentkeepalive@^3.4.1: dependencies: humanize-ms "^1.2.1" -aggregate-error@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-4.0.1.tgz#25091fe1573b9e0be892aeda15c7c66a545f758e" - integrity sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w== - dependencies: - clean-stack "^4.0.0" - indent-string "^5.0.0" - ajv@^6.12.3: version "6.12.4" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.4.tgz#0614facc4522127fa713445c6bfd3ebd376e2234" @@ -2199,6 +2060,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.2.tgz#60216eea464d864597ce2832000738a0589650c1" + integrity sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg== + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -2380,11 +2246,6 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= -arrify@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-3.0.0.tgz#ccdefb8eaf2a1d2ab0da1ca2ce53118759fd46bc" - integrity sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw== - asap@^2.0.0: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" @@ -2407,14 +2268,14 @@ assign-symbols@^1.0.0: resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= -ast-v8-to-istanbul@^0.3.8: - version "0.3.8" - resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-0.3.8.tgz#0a3faf070dc780dcebdf9d48af78dbd174a497a9" - integrity sha512-szgSZqUxI5T8mLKvS7WTjF9is+MVbOeLADU73IseOcrqhxr/VAvy6wfoVE39KnKzA7JRhjF5eUagNlHwvZPlKQ== +ast-v8-to-istanbul@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.5.tgz#708baeb6f5c879226d112a341ffa821c43881d2d" + integrity sha512-UPAgKJFSEGMWSDr3LX4tqnAb4f7KGT8O40Tyx8wbYmmZ/yn58lNCm8h3svs3eXgiGd5AXxz8NDOvXWvicq+rJA== dependencies: "@jridgewell/trace-mapping" "^0.3.31" estree-walker "^3.0.3" - js-tokens "^9.0.1" + js-tokens "^10.0.0" async-mutex@^0.5.0: version "0.5.0" @@ -2650,7 +2511,7 @@ callsites@^2.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= -callsites@^3.0.0, callsites@^3.1.0: +callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== @@ -2701,15 +2562,15 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= -chai@^6.2.1: - version "6.2.1" - resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.1.tgz#d1e64bc42433fbee6175ad5346799682060b5b6a" - integrity sha512-p4Z49OGG5W/WBCPSS/dH3jQ73kD6tiMmUM+bckNK6Jr5JHMG3k9bg/BvKR8lKmtVBKmOiuVaV2ws8s9oSbwysg== +chai@^6.2.2: + version "6.2.2" + resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.2.tgz#ae41b52c9aca87734505362717f3255facda360e" + integrity sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg== -chalk-template@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-1.1.0.tgz#ffc55db6dd745e9394b85327c8ac8466edb7a7b1" - integrity sha512-T2VJbcDuZQ0Tb2EWwSotMPJjgpy1/tGee1BTpUNsGZ/qgNjV2t7Mvu+d4600U564nbLesN1x2dPL+xii174Ekg== +chalk-template@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-1.1.2.tgz#88ff13e75a333d232304e13abc48c5b5be15f1ce" + integrity sha512-2bxTP2yUH7AJj/VAXfcA+4IcWGdQ87HwBANLt5XxGTeomo8yG0y95N1um9i5StvhT/Bl0/2cARA5v1PpPXUxUA== dependencies: chalk "^5.2.0" @@ -2730,11 +2591,16 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -chalk@^5.2.0, chalk@^5.4.1: +chalk@^5.2.0: version "5.4.1" resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.4.1.tgz#1b48bf0963ec158dce2aacf69c093ae2dd2092d8" integrity sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w== +chalk@^5.6.2: + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -2760,21 +2626,6 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -clean-stack@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-4.2.0.tgz#c464e4cde4ac789f4e0735c5d75beb49d7b30b31" - integrity sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg== - dependencies: - escape-string-regexp "5.0.0" - -clear-module@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/clear-module/-/clear-module-4.1.2.tgz#5a58a5c9f8dccf363545ad7284cad3c887352a80" - integrity sha512-LWAxzHqdHsAZlPlEyJ2Poz6AIs384mPeqLVCru2p0BrP9G/kVGuhNyZYClLO6cXlnuJjzC8xtsJIuMjKqLXoAw== - dependencies: - parent-module "^2.0.0" - resolve-from "^5.0.0" - cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -2867,16 +2718,18 @@ commander@^14.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.0.tgz#f244fc74a92343514e56229f16ef5c5e22ced5e9" integrity sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA== -comment-json@^4.2.5: - version "4.2.5" - resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-4.2.5.tgz#482e085f759c2704b60bc6f97f55b8c01bc41e70" - integrity sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw== +commander@^14.0.3: + version "14.0.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.3.tgz#425d79b48f9af82fcd9e4fc1ea8af6c5ec07bbc2" + integrity sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw== + +comment-json@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/comment-json/-/comment-json-5.0.0.tgz#3b0cba63da30b31f8b3ea8d75f4d79bfa8346896" + integrity sha512-uiqLcOiVDJtBP8WGkZHEP+FZIhTzP1dxvn59EfoYUi9gqupjrBWVQkO2atDrbnKPwLeotFYDsuNb26uBMqB+hw== dependencies: array-timsort "^1.0.3" - core-util-is "^1.0.3" esprima "^4.0.1" - has-own-prop "^2.0.0" - repeat-string "^1.6.1" compare-func@^2.0.0: version "2.0.0" @@ -3017,6 +2870,11 @@ conventional-recommended-bump@^5.0.0: meow "^4.0.0" q "^1.5.1" +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -3039,11 +2897,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -core-util-is@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" - integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== - cosmiconfig@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" @@ -3054,37 +2907,6 @@ cosmiconfig@^5.1.0: js-yaml "^3.13.1" parse-json "^4.0.0" -cp-file@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/cp-file/-/cp-file-10.0.0.tgz#bbae9ecb9f505951b862880d2901e1f56de7a4dc" - integrity sha512-vy2Vi1r2epK5WqxOLnskeKeZkdZvTKfFZQCplE3XWsP+SUJyd5XAUFC9lFgTjjXJF2GMne/UML14iEmkAaDfFg== - dependencies: - graceful-fs "^4.2.10" - nested-error-stacks "^2.1.1" - p-event "^5.0.1" - -cpy-cli@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cpy-cli/-/cpy-cli-5.0.0.tgz#facd60da2e98d9a830f93162f9769d2a86667a16" - integrity sha512-fb+DZYbL9KHc0BC4NYqGRrDIJZPXUmjjtqdw4XRRg8iV8dIfghUX/WiL+q4/B/KFTy3sK6jsbUhBaz0/Hxg7IQ== - dependencies: - cpy "^10.1.0" - meow "^12.0.1" - -cpy@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/cpy/-/cpy-10.1.0.tgz#85517387036b9be480f6424e54089261fc6f4bab" - integrity sha512-VC2Gs20JcTyeQob6UViBLnyP0bYHkBh6EiKzot9vi2DmeGlFT9Wd7VG3NBrkNx/jYvFBeyDOMMHdHQhbtKLgHQ== - dependencies: - arrify "^3.0.0" - cp-file "^10.0.0" - globby "^13.1.4" - junk "^4.0.1" - micromatch "^4.0.5" - nested-error-stacks "^2.1.1" - p-filter "^3.0.0" - p-map "^6.0.0" - cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -3105,121 +2927,120 @@ cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" -cspell-config-lib@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell-config-lib/-/cspell-config-lib-9.2.0.tgz#dc85330fae8aab6f1f362c678a698b8816ddbdf0" - integrity sha512-Yc8+hT+uIWWCi6WMhOL6HDYbBCP2qig1tgKGThHVeOx6GviieV10TZ5kQ+P7ONgoqw2nmm7uXIC19dGYx3DblQ== - dependencies: - "@cspell/cspell-types" "9.2.0" - comment-json "^4.2.5" - smol-toml "^1.4.1" - yaml "^2.8.0" - -cspell-dictionary@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell-dictionary/-/cspell-dictionary-9.2.0.tgz#f4f13ee22e0207da6a4c8ec76eedb6672e16a345" - integrity sha512-lV4VtjsDtxu8LyCcb6DY7Br4e/Aw1xfR8QvjYhHaJ8t03xry9STey5Rkfp+lz+hlVevNcn3lfCaacGuXyD+lLg== - dependencies: - "@cspell/cspell-pipe" "9.2.0" - "@cspell/cspell-types" "9.2.0" - cspell-trie-lib "9.2.0" - fast-equals "^5.2.2" - -cspell-gitignore@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell-gitignore/-/cspell-gitignore-9.2.0.tgz#34ee91bc741f6efa0fa86a1d1565cc4311bc9ffa" - integrity sha512-gXDQZ7czTPwmEg1qtsUIjVEFm9IfgTO8rA02O8eYIveqjFixbSV3fIYOgoxZSZYxjt3O44m8+/zAFC1RE4CM/Q== - dependencies: - "@cspell/url" "9.2.0" - cspell-glob "9.2.0" - cspell-io "9.2.0" - -cspell-glob@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-9.2.0.tgz#adc61596c96b3572c77dabe5da0d71320e714ab3" - integrity sha512-viycZDyegzW2AKPFqvX5RveqTrB0sKgexlCu2A8z8eumpYYor5sD1NP05VDOqkAF4hDuiGqkHn6iNo0L1wNgLw== - dependencies: - "@cspell/url" "9.2.0" - picomatch "^4.0.3" - -cspell-grammar@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell-grammar/-/cspell-grammar-9.2.0.tgz#c29aabf67e99506d15f7d52e9c2ad99466b7e8f2" - integrity sha512-qthAmWcNHpYAmufy7YWVg9xwrYANkVlI40bgC2uGd8EnKssm/qOPhqXXNS+kLf+q0NmJM5nMgRLhCC23xSp3JA== - dependencies: - "@cspell/cspell-pipe" "9.2.0" - "@cspell/cspell-types" "9.2.0" - -cspell-io@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-9.2.0.tgz#ee18fcbd94a67feae0a8938c2d81d7b577d1d48e" - integrity sha512-oxKiqFLcz629FmOId8UpdDznpMvCgpuktg4nkD2G9pYpRh+fRLZpP4QtZPyvJqvpUIzFhIOznMeHjsiBYHOZUA== - dependencies: - "@cspell/cspell-service-bus" "9.2.0" - "@cspell/url" "9.2.0" - -cspell-lib@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-9.2.0.tgz#f7d5dd20d2b1d2a30f44c35dc8f06d25daaff79c" - integrity sha512-RnhDIsETw6Ex0UaK3PFoJ2FwWMWfJPtdpNpv1qgmJwoGD4CzwtIqPOLtZ24zqdCP8ZnNTF/lwV/9rZVqifYjsw== - dependencies: - "@cspell/cspell-bundled-dicts" "9.2.0" - "@cspell/cspell-pipe" "9.2.0" - "@cspell/cspell-resolver" "9.2.0" - "@cspell/cspell-types" "9.2.0" - "@cspell/dynamic-import" "9.2.0" - "@cspell/filetypes" "9.2.0" - "@cspell/strong-weak-map" "9.2.0" - "@cspell/url" "9.2.0" - clear-module "^4.1.2" - comment-json "^4.2.5" - cspell-config-lib "9.2.0" - cspell-dictionary "9.2.0" - cspell-glob "9.2.0" - cspell-grammar "9.2.0" - cspell-io "9.2.0" - cspell-trie-lib "9.2.0" - env-paths "^3.0.0" - fast-equals "^5.2.2" - gensequence "^7.0.0" - import-fresh "^3.3.1" +cspell-config-lib@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell-config-lib/-/cspell-config-lib-10.0.1.tgz#863860db3a0b9e93f0f63ece283b44333bbaa9ed" + integrity sha512-hMpo/0j6k7pbiqrLDOLJKD2IGP9XwhjKf2miiM6p84Xeo4nyuFZaxxDCQ68R851HSYFrrdltgpoipMbj1h2Tnw== + dependencies: + "@cspell/cspell-types" "10.0.1" + comment-json "^5.0.0" + smol-toml "^1.6.1" + yaml "^2.9.0" + +cspell-dictionary@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell-dictionary/-/cspell-dictionary-10.0.1.tgz#a4947f20fc2bf07cdfad0370400c9e2e8fba4c17" + integrity sha512-3cZ659vgsZWkzGQJR/sNqGDVt/OnvTSieLKI76V++4t1bHJfochb9ZrrwsuMsb1VPGiyqClUP1/O6WrefF/FVg== + dependencies: + "@cspell/cspell-performance-monitor" "10.0.1" + "@cspell/cspell-pipe" "10.0.1" + "@cspell/cspell-types" "10.0.1" + cspell-trie-lib "10.0.1" + fast-equals "^6.0.0" + +cspell-gitignore@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell-gitignore/-/cspell-gitignore-10.0.1.tgz#3ade523387114c18d434be174031aa5ac3917fc0" + integrity sha512-wN23U61Mx6qPJN3CesOmBU9vnbJ0jQm/ylK0iaVui3CcnO7Zzl5qLu5mPHUzGQGm8yso6qjyxqo16Ho7LpZGOQ== + dependencies: + "@cspell/url" "10.0.1" + cspell-glob "10.0.1" + cspell-io "10.0.1" + +cspell-glob@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell-glob/-/cspell-glob-10.0.1.tgz#1bf73a85b408f2cc459e0c0491558713c4bcd2a0" + integrity sha512-7bII9J3aSSpZDwhx7w+zfQXbMxHZQ3be0ilUp5bHrsjz6o07v/NqOHMGcwKdPn1sw2dxDz9sv057xE5pqXnSdw== + dependencies: + "@cspell/url" "10.0.1" + picomatch "^4.0.4" + +cspell-grammar@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell-grammar/-/cspell-grammar-10.0.1.tgz#d31b97bf7f9469490c09a99fe969dd0ca0cc54c2" + integrity sha512-xC9AFYmaI9wsO//a7S5tdDGKGJVD5UEEsTg+Up2fi7lPfXIryisYmV6tePNL1SEg0idYss4ja8LUZ3Mib09BjQ== + dependencies: + "@cspell/cspell-pipe" "10.0.1" + "@cspell/cspell-types" "10.0.1" + +cspell-io@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell-io/-/cspell-io-10.0.1.tgz#3f362ea44d235f5e63f458c3ed0b578139316cca" + integrity sha512-8C2ka07faxflnaqEBO3pektS21XViE/SEHT7F5ZD1ou7FyMR5u3xawTBJSczClfsxLt/WYeztBYrpmGAjmjksw== + dependencies: + "@cspell/cspell-service-bus" "10.0.1" + "@cspell/url" "10.0.1" + +cspell-lib@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell-lib/-/cspell-lib-10.0.1.tgz#794d9d5088051ec5e4088b4a3c10cd309cbe158c" + integrity sha512-RpsIPiLzc4/YMW8BMRKpyJ81x439qjYWcqgdKeXnMkbKM88J9PexzutfFf/4v97v96KzfNitEzMpbI0uj8OeUg== + dependencies: + "@cspell/cspell-bundled-dicts" "10.0.1" + "@cspell/cspell-performance-monitor" "10.0.1" + "@cspell/cspell-pipe" "10.0.1" + "@cspell/cspell-resolver" "10.0.1" + "@cspell/cspell-types" "10.0.1" + "@cspell/dynamic-import" "10.0.1" + "@cspell/filetypes" "10.0.1" + "@cspell/rpc" "10.0.1" + "@cspell/strong-weak-map" "10.0.1" + "@cspell/url" "10.0.1" + cspell-config-lib "10.0.1" + cspell-dictionary "10.0.1" + cspell-glob "10.0.1" + cspell-grammar "10.0.1" + cspell-io "10.0.1" + cspell-trie-lib "10.0.1" + env-paths "^4.0.0" + gensequence "^8.0.8" + import-fresh "^4.0.0" resolve-from "^5.0.0" vscode-languageserver-textdocument "^1.0.12" vscode-uri "^3.1.0" xdg-basedir "^5.1.0" -cspell-trie-lib@9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-9.2.0.tgz#968b42cc60681e8fad36e601edf4c11985c70950" - integrity sha512-6GHL1KvLQzcPBSNY6QWOabq8YwRJAnNKamA0O/tRKy+11Hy99ysD4xvfu3kKYPAcobp5ZykX4nudHxy8yrEvng== - dependencies: - "@cspell/cspell-pipe" "9.2.0" - "@cspell/cspell-types" "9.2.0" - gensequence "^7.0.0" - -cspell@^9.2.0: - version "9.2.0" - resolved "https://registry.yarnpkg.com/cspell/-/cspell-9.2.0.tgz#a3197a7583f632c0d16ef3c24da5c0009a43ef49" - integrity sha512-AKzaFMem2jRcGpAY2spKP0z15jpZeX1WTDNHCDsB8/YvnhnOfWXc0S5AF+4sfU1cQgHWYGFOolMuTri0ZQdV+Q== - dependencies: - "@cspell/cspell-json-reporter" "9.2.0" - "@cspell/cspell-pipe" "9.2.0" - "@cspell/cspell-types" "9.2.0" - "@cspell/dynamic-import" "9.2.0" - "@cspell/url" "9.2.0" - chalk "^5.4.1" - chalk-template "^1.1.0" - commander "^14.0.0" - cspell-config-lib "9.2.0" - cspell-dictionary "9.2.0" - cspell-gitignore "9.2.0" - cspell-glob "9.2.0" - cspell-io "9.2.0" - cspell-lib "9.2.0" +cspell-trie-lib@10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell-trie-lib/-/cspell-trie-lib-10.0.1.tgz#d93adf6c104f584d1b7af2f0a76b014407a22cf2" + integrity sha512-BFvhalSkRQFjKrZ//FKK7fRGrZFpifnxB5AwCkzsIsBZqicsfafcQ1xP21qpb0QqyV/IomjNgviG+tRJs+0rMw== + +cspell@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/cspell/-/cspell-10.0.1.tgz#c6b58ff7bee40f7151f5e3258bbac8a31e963d64" + integrity sha512-Gg6w/flT3fKfl3la62hfTnhtNnDQ+9mU7kUhVqw/axl/Ms4oENw0oJMkWFIoj4f6nL/SDPz7KcPXd2XbkKFNmQ== + dependencies: + "@cspell/cspell-json-reporter" "10.0.1" + "@cspell/cspell-performance-monitor" "10.0.1" + "@cspell/cspell-pipe" "10.0.1" + "@cspell/cspell-types" "10.0.1" + "@cspell/cspell-worker" "10.0.1" + "@cspell/dynamic-import" "10.0.1" + "@cspell/url" "10.0.1" + ansi-regex "^6.2.2" + chalk "^5.6.2" + chalk-template "^1.1.2" + commander "^14.0.3" + cspell-config-lib "10.0.1" + cspell-dictionary "10.0.1" + cspell-gitignore "10.0.1" + cspell-glob "10.0.1" + cspell-io "10.0.1" + cspell-lib "10.0.1" fast-json-stable-stringify "^2.1.0" - flatted "^3.3.3" - semver "^7.7.2" - tinyglobby "^0.2.14" + flatted "^3.4.2" + semver "^7.8.1" + tinyglobby "^0.2.16" currently-unhandled@^0.4.1: version "0.4.1" @@ -3307,13 +3128,6 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.1.1: - version "4.4.3" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a" - integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== - dependencies: - ms "^2.1.3" - debug@^4.3.1, debug@^4.3.2, debug@^4.3.4: version "4.3.6" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" @@ -3435,6 +3249,11 @@ detect-indent@^5.0.0: resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-5.0.0.tgz#3871cc0a6a002e8c3e5b3cf7f336264675f06b9d" integrity sha1-OHHMCmoALow+Wzz38zYmRnXwa50= +detect-libc@^2.0.3: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + dezalgo@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.3.tgz#7f742de066fc748bc8db820569dddce49bf0d456" @@ -3541,10 +3360,12 @@ env-paths@^2.2.0: resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== -env-paths@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-3.0.0.tgz#2f1e89c2f6dbd3408e1b1711dd82d62e317f58da" - integrity sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A== +env-paths@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-4.0.0.tgz#d0bb1f84a81d2542581bf7b7e8085d0683b39097" + integrity sha512-pxP8eL2SwwaTRi/KHYwLYXinDs7gL3jxFcBYmEdYfZmZXbaVDvdppd0XBU8qVz03rDfKZMXg1omHCbsJjZrMsw== + dependencies: + is-safe-filename "^0.1.0" envinfo@^7.3.1: version "7.7.3" @@ -3647,10 +3468,10 @@ es-errors@^1.3.0: resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-module-lexer@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" - integrity sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA== +es-module-lexer@^2.0.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-2.3.1.tgz#5bf2df06999dbbe5f006a5f46a11fb9f5b7b391b" + integrity sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA== es-object-atoms@^1.0.0: version "1.1.1" @@ -3697,74 +3518,37 @@ es6-promisify@^5.0.0: dependencies: es6-promise "^4.0.3" -esbuild@^0.25.0: - version "0.25.9" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.9.tgz#15ab8e39ae6cdc64c24ff8a2c0aef5b3fd9fa976" - integrity sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g== - optionalDependencies: - "@esbuild/aix-ppc64" "0.25.9" - "@esbuild/android-arm" "0.25.9" - "@esbuild/android-arm64" "0.25.9" - "@esbuild/android-x64" "0.25.9" - "@esbuild/darwin-arm64" "0.25.9" - "@esbuild/darwin-x64" "0.25.9" - "@esbuild/freebsd-arm64" "0.25.9" - "@esbuild/freebsd-x64" "0.25.9" - "@esbuild/linux-arm" "0.25.9" - "@esbuild/linux-arm64" "0.25.9" - "@esbuild/linux-ia32" "0.25.9" - "@esbuild/linux-loong64" "0.25.9" - "@esbuild/linux-mips64el" "0.25.9" - "@esbuild/linux-ppc64" "0.25.9" - "@esbuild/linux-riscv64" "0.25.9" - "@esbuild/linux-s390x" "0.25.9" - "@esbuild/linux-x64" "0.25.9" - "@esbuild/netbsd-arm64" "0.25.9" - "@esbuild/netbsd-x64" "0.25.9" - "@esbuild/openbsd-arm64" "0.25.9" - "@esbuild/openbsd-x64" "0.25.9" - "@esbuild/openharmony-arm64" "0.25.9" - "@esbuild/sunos-x64" "0.25.9" - "@esbuild/win32-arm64" "0.25.9" - "@esbuild/win32-ia32" "0.25.9" - "@esbuild/win32-x64" "0.25.9" - -esbuild@~0.25.0: - version "0.25.8" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.8.tgz#482d42198b427c9c2f3a81b63d7663aecb1dda07" - integrity sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q== +esbuild@~0.28.0: + version "0.28.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.28.2.tgz#0f43bd1bad955b72d24e2261e3abe5957ccf0816" + integrity sha512-HKVLS8dvII+xoKW9kmqxbRKrnWEXfJJr/FZhhJmiqIB0e053QNYFqOBouTMO/k5sID4MvCiUCvv8b9M4h32wIA== optionalDependencies: - "@esbuild/aix-ppc64" "0.25.8" - "@esbuild/android-arm" "0.25.8" - "@esbuild/android-arm64" "0.25.8" - "@esbuild/android-x64" "0.25.8" - "@esbuild/darwin-arm64" "0.25.8" - "@esbuild/darwin-x64" "0.25.8" - "@esbuild/freebsd-arm64" "0.25.8" - "@esbuild/freebsd-x64" "0.25.8" - "@esbuild/linux-arm" "0.25.8" - "@esbuild/linux-arm64" "0.25.8" - "@esbuild/linux-ia32" "0.25.8" - "@esbuild/linux-loong64" "0.25.8" - "@esbuild/linux-mips64el" "0.25.8" - "@esbuild/linux-ppc64" "0.25.8" - "@esbuild/linux-riscv64" "0.25.8" - "@esbuild/linux-s390x" "0.25.8" - "@esbuild/linux-x64" "0.25.8" - "@esbuild/netbsd-arm64" "0.25.8" - "@esbuild/netbsd-x64" "0.25.8" - "@esbuild/openbsd-arm64" "0.25.8" - "@esbuild/openbsd-x64" "0.25.8" - "@esbuild/openharmony-arm64" "0.25.8" - "@esbuild/sunos-x64" "0.25.8" - "@esbuild/win32-arm64" "0.25.8" - "@esbuild/win32-ia32" "0.25.8" - "@esbuild/win32-x64" "0.25.8" - -escape-string-regexp@5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz#4683126b500b61762f2dbebace1806e8be31b1c8" - integrity sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw== + "@esbuild/aix-ppc64" "0.28.2" + "@esbuild/android-arm" "0.28.2" + "@esbuild/android-arm64" "0.28.2" + "@esbuild/android-x64" "0.28.2" + "@esbuild/darwin-arm64" "0.28.2" + "@esbuild/darwin-x64" "0.28.2" + "@esbuild/freebsd-arm64" "0.28.2" + "@esbuild/freebsd-x64" "0.28.2" + "@esbuild/linux-arm" "0.28.2" + "@esbuild/linux-arm64" "0.28.2" + "@esbuild/linux-ia32" "0.28.2" + "@esbuild/linux-loong64" "0.28.2" + "@esbuild/linux-mips64el" "0.28.2" + "@esbuild/linux-ppc64" "0.28.2" + "@esbuild/linux-riscv64" "0.28.2" + "@esbuild/linux-s390x" "0.28.2" + "@esbuild/linux-x64" "0.28.2" + "@esbuild/netbsd-arm64" "0.28.2" + "@esbuild/netbsd-x64" "0.28.2" + "@esbuild/openbsd-arm64" "0.28.2" + "@esbuild/openbsd-x64" "0.28.2" + "@esbuild/openharmony-arm64" "0.28.2" + "@esbuild/sunos-x64" "0.28.2" + "@esbuild/win32-arm64" "0.28.2" + "@esbuild/win32-ia32" "0.28.2" + "@esbuild/win32-x64" "0.28.2" escape-string-regexp@^1.0.5: version "1.0.5" @@ -4016,10 +3800,10 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expect-type@^1.2.2: - version "1.3.0" - resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.3.0.tgz#0d58ed361877a31bbc4dd6cf71bbfef7faf6bd68" - integrity sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA== +expect-type@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.4.0.tgz#24edf7f0cc69a44d008567ba4594ab96f3c3a3d6" + integrity sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA== extend-shallow@^2.0.1: version "2.0.1" @@ -4079,10 +3863,10 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-equals@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-5.2.2.tgz#885d7bfb079fac0ce0e8450374bce29e9b742484" - integrity sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw== +fast-equals@^6.0.0: + version "6.0.2" + resolved "https://registry.yarnpkg.com/fast-equals/-/fast-equals-6.0.2.tgz#36b0a0289a927f48a3c99b773970a077b2deb57f" + integrity sha512-sAjhj9ZhOxYCGiNMnZLaucOqf5ZeFnHNoKoAZiD9thhJ0N8RP85qJK759/97C/3L7NzzmGVB5uiX9AUpySZmUQ== fast-glob@^2.2.6: version "2.2.7" @@ -4107,17 +3891,6 @@ fast-glob@^3.2.9: merge2 "^1.3.0" micromatch "^4.0.4" -fast-glob@^3.3.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" - integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== - dependencies: - "@nodelib/fs.stat" "^2.0.2" - "@nodelib/fs.walk" "^1.2.3" - glob-parent "^5.1.2" - merge2 "^1.3.0" - micromatch "^4.0.8" - fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -4135,20 +3908,15 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -fdir@^6.4.4: - version "6.4.6" - resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.6.tgz#2b268c0232697063111bbf3f64810a2a741ba281" - integrity sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w== - fdir@^6.5.0: version "6.5.0" resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== -fflate@^0.8.2: - version "0.8.2" - resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" - integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== +fflate@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.3.tgz#bc27d8eb30343d4d512abb03480202ce65d825fc" + integrity sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA== figgy-pudding@^3.4.1, figgy-pudding@^3.5.1: version "3.5.2" @@ -4238,10 +4006,10 @@ flatted@^3.2.9: resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== -flatted@^3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" - integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== +flatted@^3.4.2: + version "3.4.4" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.4.4.tgz#aeeca2a506303f0cee61c59e6c9f2a88d2f29fc6" + integrity sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q== flush-write-stream@^1.0.0: version "1.1.1" @@ -4323,7 +4091,7 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== -fsevents@~2.3.2, fsevents@~2.3.3: +fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== @@ -4369,10 +4137,10 @@ genfun@^5.0.0: resolved "https://registry.yarnpkg.com/genfun/-/genfun-5.0.0.tgz#9dd9710a06900a5c4a5bf57aca5da4e52fe76537" integrity sha512-KGDOARWVga7+rnB3z9Sd2Letx515owfk0hSxHGuqjANb1M+x2bGZGqHLiozPsYMdM2OubeMni/Hpwmjq6qIUhA== -gensequence@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/gensequence/-/gensequence-7.0.0.tgz#bb6aedec8ff665e3a6c42f92823121e3a6ea7718" - integrity sha512-47Frx13aZh01afHJTB3zTtKIlFI6vWY+MYCN9Qpew6i52rfKjnhCF/l1YlC8UmEMvvntZZ6z4PiCcmyuedR2aQ== +gensequence@^8.0.8: + version "8.0.8" + resolved "https://registry.yarnpkg.com/gensequence/-/gensequence-8.0.8.tgz#381a46bef4b1c26f6aff2b291ce9cd417d363fb1" + integrity sha512-omMVniXEXpdx/vKxGnPRoO2394Otlze28TyxECbFVyoSpZ9H3EO7lemjcB12OpQJzRW4e5tt/dL1rOxry6aMHg== get-caller-file@^2.0.1: version "2.0.5" @@ -4440,13 +4208,6 @@ get-symbol-description@^1.1.0: es-errors "^1.3.0" get-intrinsic "^1.2.6" -get-tsconfig@^4.7.5: - version "4.10.0" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.0.tgz#403a682b373a823612475a4c2928c7326fc0f6bb" - integrity sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A== - dependencies: - resolve-pkg-maps "^1.0.0" - get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -4566,12 +4327,12 @@ glob@^7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -global-directory@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-4.0.1.tgz#4d7ac7cfd2cb73f304c53b8810891748df5e361e" - integrity sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q== +global-directory@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/global-directory/-/global-directory-5.0.0.tgz#0f66a94212acd0f81ee838d0a991e88d1c2836cf" + integrity sha512-1pgFdhK3J2LeM+dVf2Pd424yHx2ou338lC0ErNP2hPx4j8eW1Sp0XqSjNxtk6Tc4Kr5wlWtSvz8cn2yb7/SG/w== dependencies: - ini "4.1.1" + ini "6.0.0" globals@^13.19.0: version "13.24.0" @@ -4600,17 +4361,6 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -globby@^13.1.4: - version "13.2.2" - resolved "https://registry.yarnpkg.com/globby/-/globby-13.2.2.tgz#63b90b1bf68619c2135475cbd4e71e66aa090592" - integrity sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w== - dependencies: - dir-glob "^3.0.1" - fast-glob "^3.3.0" - ignore "^5.2.4" - merge2 "^1.4.1" - slash "^4.0.0" - globby@^9.2.0: version "9.2.0" resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d" @@ -4635,11 +4385,6 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6 resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -graceful-fs@^4.2.10: - version "4.2.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" - integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== - graphemer@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" @@ -4690,11 +4435,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-own-prop@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-own-prop/-/has-own-prop-2.0.0.tgz#f0f95d58f65804f5d218db32563bb85b8e0417af" - integrity sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ== - has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" @@ -4857,7 +4597,7 @@ ignore@^4.0.3: resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== -ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: +ignore@^5.2.0, ignore@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== @@ -4878,13 +4618,10 @@ import-fresh@^3.2.1: parent-module "^1.0.0" resolve-from "^4.0.0" -import-fresh@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" - integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== - dependencies: - parent-module "^1.0.0" - resolve-from "^4.0.0" +import-fresh@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-4.0.0.tgz#07057d6f3b6d9bf19b8f287c8d73b43da5f9f289" + integrity sha512-Fpi660c7VPDM3fPKYovStd9IP1CPOikf6v/dGxJJMmHPcwYQIMJ4W7kO1avBYEpMqkCh+Dx3Ln6H7VYqgztLjw== import-local@^2.0.0: version "2.0.0" @@ -4894,10 +4631,10 @@ import-local@^2.0.0: pkg-dir "^3.0.0" resolve-cwd "^2.0.0" -import-meta-resolve@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz#f9db8bead9fafa61adb811db77a2bf22c5399706" - integrity sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw== +import-meta-resolve@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz#08cb85b5bd37ecc8eb1e0f670dc2767002d43734" + integrity sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg== imurmurhash@^0.1.4: version "0.1.4" @@ -4921,11 +4658,6 @@ indent-string@^4.0.0: resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -indent-string@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-5.0.0.tgz#4fd2980fccaf8622d14c64d694f4cf33c81951a5" - integrity sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg== - infer-owner@^1.0.3, infer-owner@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" @@ -4944,10 +4676,10 @@ inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -ini@4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ini/-/ini-4.1.1.tgz#d95b3d843b1e906e56d6747d5447904ff50ce7a1" - integrity sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g== +ini@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/ini/-/ini-6.0.0.tgz#efc7642b276f6a37d22fdf56ef50889d7146bf30" + integrity sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ== ini@^1.3.2, ini@^1.3.4: version "1.3.5" @@ -5281,6 +5013,11 @@ is-regex@^1.2.1: has-tostringtag "^1.0.2" hasown "^2.0.2" +is-safe-filename@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-safe-filename/-/is-safe-filename-0.1.1.tgz#fb22eead097c614c47aa674de5d79a1648a53e66" + integrity sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g== + is-set@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" @@ -5417,15 +5154,6 @@ istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1: make-dir "^4.0.0" supports-color "^7.1.0" -istanbul-lib-source-maps@^5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.6.tgz#acaef948df7747c8eb5fbf1265cb980f6353a441" - integrity sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A== - dependencies: - "@jridgewell/trace-mapping" "^0.3.23" - debug "^4.1.1" - istanbul-lib-coverage "^3.0.0" - istanbul-reports@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93" @@ -5434,16 +5162,16 @@ istanbul-reports@^3.2.0: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +js-tokens@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-10.0.0.tgz#dffe7599b4a8bb7fe30aff8d0235234dffb79831" + integrity sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.1.tgz#2ec43964658435296f6761b34e10671c2d9527f4" - integrity sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ== - js-yaml@^3.13.1: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" @@ -5528,11 +5256,6 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -junk@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/junk/-/junk-4.0.1.tgz#7ee31f876388c05177fe36529ee714b07b50fbed" - integrity sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ== - keyv@^4.5.3: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" @@ -5596,6 +5319,80 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" +lightningcss-android-arm64@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz#9a6841f88ae50fc83502903892b41af41bc2b907" + integrity sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg== + +lightningcss-darwin-arm64@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz#c0f2c31c0bfd19fa4dd3f18e957a1f1a152097d6" + integrity sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg== + +lightningcss-darwin-x64@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz#cb0705965acb538c6683949ce6925fb3cdf7c361" + integrity sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ== + +lightningcss-freebsd-x64@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz#763538828b26bab2680dadafcc84ee78b0eb502b" + integrity sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg== + +lightningcss-linux-arm-gnueabihf@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz#6862e3176a331aedbdec1ed352b4d7d0dd0784de" + integrity sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ== + +lightningcss-linux-arm64-gnu@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz#c6a3a2ed15141daf6bdc2628930f8e39bdf473aa" + integrity sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg== + +lightningcss-linux-arm64-musl@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz#7fa1334971fc82845f9827df6ef8a0b20914bac6" + integrity sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ== + +lightningcss-linux-x64-gnu@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz#8b927862ea8c2bbc6831a46509244b50d9936e55" + integrity sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg== + +lightningcss-linux-x64-musl@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz#0c525bb077dfd94404c059cfe42dad797e96aeaf" + integrity sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw== + +lightningcss-win32-arm64-msvc@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz#850ee1103dac989cfab50e3ac22d1a69e394e63d" + integrity sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA== + +lightningcss-win32-x64-msvc@1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz#e343ae152eed3609dc6e11949d1a3bf39a1c946f" + integrity sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA== + +lightningcss@^1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.33.0.tgz#c08867d71a79385c6e190214fd72fef3e5f95f0b" + integrity sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-android-arm64 "1.33.0" + lightningcss-darwin-arm64 "1.33.0" + lightningcss-darwin-x64 "1.33.0" + lightningcss-freebsd-x64 "1.33.0" + lightningcss-linux-arm-gnueabihf "1.33.0" + lightningcss-linux-arm64-gnu "1.33.0" + lightningcss-linux-arm64-musl "1.33.0" + lightningcss-linux-x64-gnu "1.33.0" + lightningcss-linux-x64-musl "1.33.0" + lightningcss-win32-arm64-msvc "1.33.0" + lightningcss-win32-x64-msvc "1.33.0" + lines-and-columns@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" @@ -5755,13 +5552,13 @@ magic-string@^0.30.21: dependencies: "@jridgewell/sourcemap-codec" "^1.5.5" -magicast@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.5.1.tgz#518959aea78851cd35d4bb0da92f780db3f606d3" - integrity sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw== +magicast@^0.5.2: + version "0.5.4" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.5.4.tgz#bbe38dfd6037670057f33abf22b8aa79d5e99d0a" + integrity sha512-llBEhWm1SacoRwgHUoQJYtwp4PBLF4faQi5TCpIGyGs9n4y5+juI0tDgyKIfpqxckRHaHzouUEph3THklWh03w== dependencies: - "@babel/parser" "^7.28.5" - "@babel/types" "^7.28.5" + "@babel/parser" "^7.29.7" + "@babel/types" "^7.29.7" source-map-js "^1.2.1" make-dir@^1.0.0: @@ -5835,11 +5632,6 @@ math-intrinsics@^1.1.0: resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== -meow@^12.0.1: - version "12.1.1" - resolved "https://registry.yarnpkg.com/meow/-/meow-12.1.1.tgz#e558dddbab12477b69b2e9a2728c327f191bace6" - integrity sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw== - meow@^3.3.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" @@ -5912,7 +5704,7 @@ micromatch@^3.1.10: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8: +micromatch@^4.0.4: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -6102,10 +5894,10 @@ mz@^2.5.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nanoid@^3.3.11: - version "3.3.11" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" - integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== +nanoid@^3.3.17: + version "3.3.18" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.18.tgz#f66a2de1199ffde0fcf21c8a5f13106b1c081913" + integrity sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w== nanomatch@^1.2.9: version "1.2.13" @@ -6134,11 +5926,6 @@ neo-async@^2.6.0: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -nested-error-stacks@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.1.tgz#26c8a3cee6cc05fbcf1e333cd2fc3e003326c0b5" - integrity sha512-9iN1ka/9zmX1ZvLV9ewJYEk9h7RyRRtqdK0woXcqohu8EWIerfPUjYJPg0ULy0UqP7cslmdGc8xKDJcojlKiaw== - nice-try@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" @@ -6471,20 +6258,6 @@ own-keys@^1.0.1: object-keys "^1.1.1" safe-push-apply "^1.0.0" -p-event@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-5.0.1.tgz#614624ec02ae7f4f13d09a721c90586184af5b0c" - integrity sha512-dd589iCQ7m1L0bmC5NLlVYfy3TbBEsMUfWx9PyAgPeIcFZ/E2yaTZ4Rz4MiBmmJShviiftHVXOqfnfzJ6kyMrQ== - dependencies: - p-timeout "^5.0.2" - -p-filter@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-filter/-/p-filter-3.0.0.tgz#ce50e03b24b23930e11679ab8694bd09a2d7ed35" - integrity sha512-QtoWLjXAW++uTX67HZQz1dbTpqBfiidsB6VtQUC9iR85S120+s0T5sO6s+B5MLzFcZkrEd/DGMmCjR+f2Qpxwg== - dependencies: - p-map "^5.1.0" - p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" @@ -6551,18 +6324,6 @@ p-map@^2.1.0: resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== -p-map@^5.1.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-5.5.0.tgz#054ca8ca778dfa4cf3f8db6638ccb5b937266715" - integrity sha512-VFqfGDHlx87K66yZrNdI4YGtD70IRyd+zSvgks6mzHPRNkoKy+9EKP4SFC77/vTTQYmRmti7dvqC+m5jBrBAcg== - dependencies: - aggregate-error "^4.0.0" - -p-map@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-6.0.0.tgz#4d9c40d3171632f86c47601b709f4b4acd70fed4" - integrity sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw== - p-pipe@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-1.2.0.tgz#4b1a11399a11520a67790ee5a0c1d5881d6befe9" @@ -6595,11 +6356,6 @@ p-retry@^8.0.0: dependencies: is-network-error "^1.3.0" -p-timeout@^5.0.2: - version "5.1.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-5.1.0.tgz#b3c691cf4415138ce2d9cfe071dba11f0fee085b" - integrity sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew== - p-timeout@^7.0.0: version "7.0.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-7.0.1.tgz#95680a6aa693c530f14ac337b8bd32d4ec6ae4f0" @@ -6638,13 +6394,6 @@ parent-module@^1.0.0: dependencies: callsites "^3.0.0" -parent-module@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-2.0.0.tgz#fa71f88ff1a50c27e15d8ff74e0e3a9523bf8708" - integrity sha512-uo0Z9JJeWzv8BG+tRcapBKNJ0dro9cLyczGzulS6EfeyAdeC9sbojtW6XwvYxJkEne9En+J2XEl4zyglVeIwFg== - dependencies: - callsites "^3.1.0" - parse-github-repo-url@^1.3.0: version "1.4.1" resolved "https://registry.yarnpkg.com/parse-github-repo-url/-/parse-github-repo-url-1.4.1.tgz#9e7d8bb252a6cb6ba42595060b7bf6df3dbc1f50" @@ -6786,16 +6535,16 @@ picomatch@^2.3.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -picomatch@^4.0.2: - version "4.0.2" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" - integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== - picomatch@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== +picomatch@^4.0.4, picomatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.5.tgz#51ea57a17d86f605f81039595fbc40ed06a55fab" + integrity sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A== + pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" @@ -6840,12 +6589,12 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== -postcss@^8.5.6: - version "8.5.6" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" - integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== +postcss@^8.5.25: + version "8.5.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.26.tgz#6e75135780c7e10df3433bf2266c552d35c8c620" + integrity sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ== dependencies: - nanoid "^3.3.11" + nanoid "^3.3.17" picocolors "^1.1.1" source-map-js "^1.2.1" @@ -7212,11 +6961,6 @@ resolve-from@^5.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== -resolve-pkg-maps@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" - integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== - resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" @@ -7275,34 +7019,28 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rollup@^4.43.0: - version "4.48.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.48.1.tgz#acd64b7e3f8734728c5daedd5db42f4a8ea57858" - integrity sha512-jVG20NvbhTYDkGAty2/Yh7HK6/q3DGSRH4o8ALKGArmMuaauM9kLfoMZ+WliPwA5+JHr2lTn3g557FxBV87ifg== +rolldown@~1.2.1: + version "1.2.3" + resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.2.3.tgz#103bdcbbd575d51265277b8b510f080827b6eb6f" + integrity sha512-rn9wpmxplLf7NLNyCk9FyWh3FM43DbY8jOzCdEPzH7uflhTftRbCEpqi6Ly2osgoU8OwObtmavMbWLaWy4LX7A== dependencies: - "@types/estree" "1.0.8" + "@oxc-project/types" "=0.143.0" + "@rolldown/pluginutils" "^1.0.0" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.48.1" - "@rollup/rollup-android-arm64" "4.48.1" - "@rollup/rollup-darwin-arm64" "4.48.1" - "@rollup/rollup-darwin-x64" "4.48.1" - "@rollup/rollup-freebsd-arm64" "4.48.1" - "@rollup/rollup-freebsd-x64" "4.48.1" - "@rollup/rollup-linux-arm-gnueabihf" "4.48.1" - "@rollup/rollup-linux-arm-musleabihf" "4.48.1" - "@rollup/rollup-linux-arm64-gnu" "4.48.1" - "@rollup/rollup-linux-arm64-musl" "4.48.1" - "@rollup/rollup-linux-loongarch64-gnu" "4.48.1" - "@rollup/rollup-linux-ppc64-gnu" "4.48.1" - "@rollup/rollup-linux-riscv64-gnu" "4.48.1" - "@rollup/rollup-linux-riscv64-musl" "4.48.1" - "@rollup/rollup-linux-s390x-gnu" "4.48.1" - "@rollup/rollup-linux-x64-gnu" "4.48.1" - "@rollup/rollup-linux-x64-musl" "4.48.1" - "@rollup/rollup-win32-arm64-msvc" "4.48.1" - "@rollup/rollup-win32-ia32-msvc" "4.48.1" - "@rollup/rollup-win32-x64-msvc" "4.48.1" - fsevents "~2.3.2" + "@rolldown/binding-android-arm64" "1.2.3" + "@rolldown/binding-darwin-arm64" "1.2.3" + "@rolldown/binding-darwin-x64" "1.2.3" + "@rolldown/binding-freebsd-x64" "1.2.3" + "@rolldown/binding-linux-arm-gnueabihf" "1.2.3" + "@rolldown/binding-linux-arm64-gnu" "1.2.3" + "@rolldown/binding-linux-arm64-musl" "1.2.3" + "@rolldown/binding-linux-ppc64-gnu" "1.2.3" + "@rolldown/binding-linux-s390x-gnu" "1.2.3" + "@rolldown/binding-linux-x64-gnu" "1.2.3" + "@rolldown/binding-linux-x64-musl" "1.2.3" + "@rolldown/binding-openharmony-arm64" "1.2.3" + "@rolldown/binding-win32-arm64-msvc" "1.2.3" + "@rolldown/binding-win32-x64-msvc" "1.2.3" run-async@^2.2.0: version "2.4.1" @@ -7405,10 +7143,10 @@ semver@^7.6.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== -semver@^7.7.2: - version "7.7.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58" - integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA== +semver@^7.8.1, semver@^7.8.5: + version "7.8.5" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.5.tgz#39b646037dd50c14fb451e7e4cac58ed8b863f69" + integrity sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA== set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" @@ -7547,11 +7285,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slash@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" - integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== - slide@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" @@ -7562,10 +7295,10 @@ smart-buffer@^4.1.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== -smol-toml@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.4.1.tgz#f67dff9e1d4ba344242aaf9864062543536b1f72" - integrity sha512-CxdwHXyYTONGHThDbq5XdwbFsuY4wlClRGejfE2NtwUtiHYsP1QtNsHb/hnj31jKYSchztJsaA8pSQoVzkfCFg== +smol-toml@^1.6.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/smol-toml/-/smol-toml-1.7.1.tgz#ba3e28d2e4348874a824fd8e1d73fec618cb763b" + integrity sha512-PPlsspAZ4jbMBu5DMFhfUGDQLu/vrL4SyBROVS37x8ynnVmFIs1VPBz1Co8Xks3TvpIaZXmU85y4DrQ+UyVFoQ== snapdragon-node@^2.0.1: version "2.1.1" @@ -7738,10 +7471,10 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -std-env@^3.10.0: - version "3.10.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" - integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== +std-env@^4.0.0-rc.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-4.2.0.tgz#8ebe0ec60485668ab47227b312f4254cdf80c9d3" + integrity sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw== stream-each@^1.1.0: version "1.2.3" @@ -8026,14 +7759,6 @@ tinyexec@^1.0.2: resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.2.tgz#bdd2737fe2ba40bd6f918ae26642f264b99ca251" integrity sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg== -tinyglobby@^0.2.14: - version "0.2.14" - resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" - integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== - dependencies: - fdir "^6.4.4" - picomatch "^4.0.2" - tinyglobby@^0.2.15: version "0.2.15" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2" @@ -8042,10 +7767,18 @@ tinyglobby@^0.2.15: fdir "^6.5.0" picomatch "^4.0.3" -tinyrainbow@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.0.3.tgz#984a5b1c1b25854a9b6bccbe77964d0593d1ea42" - integrity sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q== +tinyglobby@^0.2.16, tinyglobby@^0.2.17: + version "0.2.17" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.17.tgz#562a9a6c9eb2b3b123d39719f9af5bb44fcd7631" + integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.4" + +tinyrainbow@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.1.1.tgz#c0168387d3d8d70b6b3c2c0936de5fee738cea20" + integrity sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw== tmp@^0.0.33: version "0.0.33" @@ -8146,13 +7879,12 @@ tslib@^2.4.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== -tsx@^4.20.3: - version "4.20.3" - resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.20.3.tgz#f913e4911d59ad177c1bcee19d1035ef8dd6e2fb" - integrity sha512-qjbnuR9Tr+FJOMBqJCW5ehvIo/buZq7vH7qD7JziU98h6l3qGy0a/yPFjwO+y0/T7GFpNgNAvEcPPVfyT8rrPQ== +tsx@^4.23.12: + version "4.23.12" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.23.12.tgz#3a4919591cd9b9e00011b75e596c8ab8db23c09c" + integrity sha512-FDf4L4sYzKtzWYhU/Xm0AQFdTjdIxNo9ElTf2mxXM6k8YMHXzYUe4yODVaXP4V9uMFbVg8c0qyBccK2OOxb45Q== dependencies: - esbuild "~0.25.0" - get-tsconfig "^4.7.5" + esbuild "~0.28.0" optionalDependencies: fsevents "~2.3.3" @@ -8285,10 +8017,10 @@ undici-types@~6.20.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== -undici-types@~6.21.0: - version "6.21.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" - integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== +undici-types@~7.18.0: + version "7.18.2" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.18.2.tgz#29357a89e7b7ca4aef3bf0fd3fd0cd73884229e9" + integrity sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w== union-value@^1.0.0: version "1.0.1" @@ -8402,44 +8134,43 @@ verror@1.10.0: core-util-is "1.0.2" extsprintf "^1.2.0" -"vite@^6.0.0 || ^7.0.0": - version "7.2.7" - resolved "https://registry.yarnpkg.com/vite/-/vite-7.2.7.tgz#0789a4c3206081699f34a9ecca2dda594a07478e" - integrity sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ== +"vite@^6.0.0 || ^7.0.0 || ^8.0.0": + version "8.2.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-8.2.1.tgz#6fc8d8bb843bd52353091fac978e194d4de5b31d" + integrity sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw== dependencies: - esbuild "^0.25.0" - fdir "^6.5.0" - picomatch "^4.0.3" - postcss "^8.5.6" - rollup "^4.43.0" - tinyglobby "^0.2.15" + lightningcss "^1.33.0" + picomatch "^4.0.5" + postcss "^8.5.25" + rolldown "~1.2.1" + tinyglobby "^0.2.17" optionalDependencies: fsevents "~2.3.3" -vitest@^4.0.15: - version "4.0.15" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.0.15.tgz#bb65e8289d49c89bc3c1dba8e1bf9c13f039c6b0" - integrity sha512-n1RxDp8UJm6N0IbJLQo+yzLZ2sQCDyl1o0LeugbPWf8+8Fttp29GghsQBjYJVmWq3gBFfe9Hs1spR44vovn2wA== - dependencies: - "@vitest/expect" "4.0.15" - "@vitest/mocker" "4.0.15" - "@vitest/pretty-format" "4.0.15" - "@vitest/runner" "4.0.15" - "@vitest/snapshot" "4.0.15" - "@vitest/spy" "4.0.15" - "@vitest/utils" "4.0.15" - es-module-lexer "^1.7.0" - expect-type "^1.2.2" +vitest@^4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.1.10.tgz#7e9285efe264b1167050b7a3a7ff34788e1b7afc" + integrity sha512-R9jUTe5S4Qb0HCd4TNqpC7oGcrMssMRGXLW80ubjWsW9VH5GF8y1Y0SFLY9AbqSk6nt0PnOx4H4WNJYZ13GUPw== + dependencies: + "@vitest/expect" "4.1.10" + "@vitest/mocker" "4.1.10" + "@vitest/pretty-format" "4.1.10" + "@vitest/runner" "4.1.10" + "@vitest/snapshot" "4.1.10" + "@vitest/spy" "4.1.10" + "@vitest/utils" "4.1.10" + es-module-lexer "^2.0.0" + expect-type "^1.3.0" magic-string "^0.30.21" obug "^2.1.1" pathe "^2.0.3" picomatch "^4.0.3" - std-env "^3.10.0" + std-env "^4.0.0-rc.1" tinybench "^2.9.0" tinyexec "^1.0.2" tinyglobby "^0.2.15" - tinyrainbow "^3.0.3" - vite "^6.0.0 || ^7.0.0" + tinyrainbow "^3.1.0" + vite "^6.0.0 || ^7.0.0 || ^8.0.0" why-is-node-running "^2.3.0" vscode-languageserver-textdocument@^1.0.12: @@ -8631,10 +8362,10 @@ write-pkg@^3.1.0: sort-keys "^2.0.0" write-json-file "^2.2.0" -ws@^8.13.0: - version "8.18.1" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" - integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w== +ws@^8.13.0, ws@^8.21.3: + version "8.21.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.21.3.tgz#660b4faddb6a3e575c86e078126919961f4de4fc" + integrity sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw== xdg-basedir@^5.1.0: version "5.1.0" @@ -8656,10 +8387,10 @@ yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== -yaml@^2.8.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.0.tgz#15f8c9866211bdc2d3781a0890e44d4fa1a5fff6" - integrity sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ== +yaml@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.9.0.tgz#78274afd93598a1dfdd6130df6a566defcbf9aa4" + integrity sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA== yargs-parser@^15.0.1: version "15.0.1" From ab739817bae0091b5d5ade5acac55c6cc1a698d3 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 18 Aug 2026 10:23:15 +0200 Subject: [PATCH 21/37] Add support for reassigning variables inside tuple assignments (#436) --- packages/cashc/src/Errors.ts | 10 + packages/cashc/src/ast/AST.ts | 6 +- packages/cashc/src/ast/AstBuilder.ts | 15 +- .../src/generation/GenerateTargetTraversal.ts | 31 +- packages/cashc/src/grammar/CashScript.g4 | 12 +- packages/cashc/src/grammar/CashScript.interp | 3 +- .../cashc/src/grammar/CashScriptParser.ts | 1242 +++++++++-------- .../cashc/src/grammar/CashScriptVisitor.ts | 7 + .../src/print/OutputSourceCodeTraversal.ts | 4 +- .../src/semantic/SymbolTableTraversal.ts | 36 +- .../cashc/src/semantic/TypeCheckTraversal.ts | 4 +- packages/cashc/test/ast/fixtures.ts | 4 +- .../tuple_reassign_constant.cash | 11 + .../declaration_then_reassignment.cash | 10 + .../duplicate_reassignment_targets.cash | 11 + .../tuple_reassign_unused.cash | 13 + .../assign_to_builtin_name.cash | 0 .../assign_to_function_name.cash | 0 .../tuple_reassign_function_name.cash | 10 + .../ParseError/single_type_destructuring.cash | 5 - .../tuple_reassign_undefined.cash | 12 + packages/cashc/test/generation/fixtures.ts | 134 ++ .../tuple_reassignment.cash | 50 + .../tuple_reassignment_after_final_read.cash | 31 + .../tuple_reassignment_branches.cash | 33 + packages/utils/src/cashproof-optimisations.ts | 2 + packages/utils/src/optimisations.ts | 3 + website/docs/compiler/grammar.md | 8 +- website/docs/language/contracts.md | 21 + website/docs/language/types.md | 4 +- website/docs/releases/release-notes.md | 2 + 31 files changed, 1130 insertions(+), 604 deletions(-) create mode 100644 packages/cashc/test/compiler/ConstantModificationError/tuple_reassign_constant.cash create mode 100644 packages/cashc/test/compiler/DuplicateTupleTargetError/declaration_then_reassignment.cash create mode 100644 packages/cashc/test/compiler/DuplicateTupleTargetError/duplicate_reassignment_targets.cash create mode 100644 packages/cashc/test/compiler/InvalidModifierError/tuple_reassign_unused.cash rename packages/cashc/test/compiler/{UndefinedReferenceError => InvalidSymbolTypeError}/assign_to_builtin_name.cash (100%) rename packages/cashc/test/compiler/{UndefinedReferenceError => InvalidSymbolTypeError}/assign_to_function_name.cash (100%) create mode 100644 packages/cashc/test/compiler/InvalidSymbolTypeError/tuple_reassign_function_name.cash delete mode 100644 packages/cashc/test/compiler/ParseError/single_type_destructuring.cash create mode 100644 packages/cashc/test/compiler/UndefinedReferenceError/tuple_reassign_undefined.cash create mode 100644 packages/cashc/test/valid-contract-files/tuple_reassignment.cash create mode 100644 packages/cashc/test/valid-contract-files/tuple_reassignment_after_final_read.cash create mode 100644 packages/cashc/test/valid-contract-files/tuple_reassignment_branches.cash diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index aca72ce5d..05ca2d22e 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -20,6 +20,7 @@ import { ContractNode, SliceNode, IntLiteralNode, + TupleAssignmentNode, } from './ast/AST.js'; import { Symbol, SymbolType } from './ast/SymbolTable.js'; import { Location } from './ast/Location.js'; @@ -283,6 +284,15 @@ export class DivisionByZeroError extends CashScriptError { } } +export class DuplicateTupleTargetError extends CashScriptError { + constructor( + node: TupleAssignmentNode, + name: string, + ) { + super(node, `Duplicate target '${name}' in tuple destructuring`); + } +} + export class ConstantModificationError extends CashScriptError { constructor(node: VariableDefinitionNode | ConstantDefinitionNode); constructor(node: Node, name: string); diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index 01f08e16c..3b787b5ea 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -155,13 +155,13 @@ export class VariableDefinitionNode extends NonControlStatementNode implements N } export interface TupleAssignmentTarget { - name: string; - type: Type; + identifier: IdentifierNode; + type?: Type; + isReassignment?: boolean; } export class TupleAssignmentNode extends NonControlStatementNode { constructor( - // TODO: Use IdentifierNodes instead of a custom type public targets: TupleAssignmentTarget[], public tuple: ExpressionNode, ) { diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index 05db951d4..53e16bce3 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -249,11 +249,16 @@ export default class AstBuilder visitTupleAssignment(ctx: TupleAssignmentContext): TupleAssignmentNode { const expression = this.visit(ctx.expression()); - const types = ctx.typeName_list(); - const targets = ctx.Identifier_list().map((name, i) => ({ - name: name.getText(), - type: parseType(types[i].getText()), - })); + const targets = ctx.tupleTarget_list().map((target) => { + const typeName = target.typeName(); + const identifier = new IdentifierNode(target.Identifier().getText()); + identifier.location = Location.fromToken(target.Identifier().symbol); + return { + identifier, + type: typeName ? parseType(typeName.getText()) : undefined, + isReassignment: !typeName, + }; + }); const tupleAssignment = new TupleAssignmentNode(targets, expression); tupleAssignment.location = Location.fromCtx(ctx); return tupleAssignment; diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index 076c9650a..ad905b8fc 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -508,8 +508,34 @@ export default class GenerateTargetTraversal extends AstTraversal { visitTupleAssignment(node: TupleAssignmentNode): Node { node.tuple = this.visit(node.tuple); - this.popFromStack(node.targets.length); - node.targets.forEach((target) => this.pushToStack(target.name)); + + // Outside of a loop/branch, a reassignment is just a rename (the old value stays on the stack) + const scopedReassign = this.scopeDepth > 0 && node.targets.some((target) => target.isReassignment); + if (!scopedReassign) { + this.popFromStack(node.targets.length); + node.targets.forEach((target) => this.pushToStack(target.identifier.name)); + return node; + } + + const locationData = { location: node.location, positionHint: PositionHint.END }; + const parkedDeclarations: string[] = []; + + const reversedTargets = [...node.targets].reverse(); + reversedTargets.forEach((target) => { + if (target.isReassignment) { + this.emitReplace(this.getStackIndex(target.identifier.name), node); + } else { + this.emit(Op.OP_TOALTSTACK, locationData); + parkedDeclarations.push(target.identifier.name); + } + this.popFromStack(); + }); + + parkedDeclarations.reverse().forEach((name) => { + this.emit(Op.OP_FROMALTSTACK, locationData); + this.pushToStack(name); + }); + return node; } @@ -1017,4 +1043,3 @@ export default class GenerateTargetTraversal extends AstTraversal { return node; } } - diff --git a/packages/cashc/src/grammar/CashScript.g4 b/packages/cashc/src/grammar/CashScript.g4 index 7800db392..5e6ed26b6 100644 --- a/packages/cashc/src/grammar/CashScript.g4 +++ b/packages/cashc/src/grammar/CashScript.g4 @@ -101,7 +101,13 @@ variableDefinition ; tupleAssignment - : typeName Identifier (',' typeName Identifier)+ '=' expression + : tupleTarget (',' tupleTarget)+ '=' expression + | '(' tupleTarget (',' tupleTarget)+ ')' '=' expression + ; + +tupleTarget + : typeName Identifier + | Identifier ; assignStatement @@ -215,8 +221,8 @@ numberLiteral ; typeName - : PrimitiveType - | BoundedBytes + : PrimitiveType + | BoundedBytes | UnboundedBytes ; diff --git a/packages/cashc/src/grammar/CashScript.interp b/packages/cashc/src/grammar/CashScript.interp index 63f11d9df..04be55783 100644 --- a/packages/cashc/src/grammar/CashScript.interp +++ b/packages/cashc/src/grammar/CashScript.interp @@ -198,6 +198,7 @@ returnStatement controlStatement variableDefinition tupleAssignment +tupleTarget assignStatement timeOpStatement requireStatement @@ -222,4 +223,4 @@ typeCast atn: -[4, 1, 85, 515, 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, 1, 0, 5, 0, 90, 8, 0, 10, 0, 12, 0, 93, 9, 0, 1, 0, 5, 0, 96, 8, 0, 10, 0, 12, 0, 99, 9, 0, 1, 0, 5, 0, 102, 8, 0, 10, 0, 12, 0, 105, 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, 118, 8, 3, 1, 4, 3, 4, 121, 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, 134, 8, 7, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 1, 8, 5, 8, 144, 8, 8, 10, 8, 12, 8, 147, 9, 8, 1, 8, 1, 8, 3, 8, 151, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 10, 1, 10, 5, 10, 167, 8, 10, 10, 10, 12, 10, 170, 9, 10, 1, 10, 1, 10, 1, 11, 1, 11, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 5, 12, 181, 8, 12, 10, 12, 12, 12, 184, 9, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 5, 13, 192, 8, 13, 10, 13, 12, 13, 195, 9, 13, 1, 13, 3, 13, 198, 8, 13, 3, 13, 200, 8, 13, 1, 13, 1, 13, 1, 14, 1, 14, 5, 14, 206, 8, 14, 10, 14, 12, 14, 209, 9, 14, 1, 14, 1, 14, 1, 15, 1, 15, 5, 15, 215, 8, 15, 10, 15, 12, 15, 218, 9, 15, 1, 15, 1, 15, 3, 15, 222, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 228, 8, 16, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 1, 17, 3, 17, 238, 8, 17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 5, 19, 246, 8, 19, 10, 19, 12, 19, 249, 9, 19, 1, 20, 1, 20, 3, 20, 253, 8, 20, 1, 21, 1, 21, 5, 21, 257, 8, 21, 10, 21, 12, 21, 260, 9, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 1, 22, 4, 22, 272, 8, 22, 11, 22, 12, 22, 273, 1, 22, 1, 22, 1, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 3, 23, 284, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 293, 8, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 302, 8, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 1, 27, 3, 27, 316, 8, 27, 1, 28, 1, 28, 1, 28, 3, 28, 321, 8, 28, 1, 29, 1, 29, 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, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 1, 32, 3, 32, 349, 8, 32, 1, 33, 1, 33, 1, 34, 1, 34, 3, 34, 355, 8, 34, 1, 35, 1, 35, 1, 35, 1, 35, 5, 35, 361, 8, 35, 10, 35, 12, 35, 364, 9, 35, 1, 35, 3, 35, 367, 8, 35, 3, 35, 369, 8, 35, 1, 35, 1, 35, 1, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 37, 5, 37, 380, 8, 37, 10, 37, 12, 37, 383, 9, 37, 1, 37, 3, 37, 386, 8, 37, 3, 37, 388, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 401, 8, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 427, 8, 38, 10, 38, 12, 38, 430, 9, 38, 1, 38, 3, 38, 433, 8, 38, 3, 38, 435, 8, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 441, 8, 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, 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, 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, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 493, 8, 38, 10, 38, 12, 38, 496, 9, 38, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 3, 40, 505, 8, 40, 1, 41, 1, 41, 3, 41, 509, 8, 41, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 0, 1, 76, 44, 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, 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, 17, 17, 65, 65, 1, 0, 72, 74, 2, 0, 72, 73, 80, 80, 546, 0, 91, 1, 0, 0, 0, 2, 108, 1, 0, 0, 0, 4, 113, 1, 0, 0, 0, 6, 115, 1, 0, 0, 0, 8, 120, 1, 0, 0, 0, 10, 124, 1, 0, 0, 0, 12, 126, 1, 0, 0, 0, 14, 133, 1, 0, 0, 0, 16, 135, 1, 0, 0, 0, 18, 154, 1, 0, 0, 0, 20, 161, 1, 0, 0, 0, 22, 173, 1, 0, 0, 0, 24, 178, 1, 0, 0, 0, 26, 187, 1, 0, 0, 0, 28, 203, 1, 0, 0, 0, 30, 221, 1, 0, 0, 0, 32, 227, 1, 0, 0, 0, 34, 237, 1, 0, 0, 0, 36, 239, 1, 0, 0, 0, 38, 241, 1, 0, 0, 0, 40, 252, 1, 0, 0, 0, 42, 254, 1, 0, 0, 0, 44, 265, 1, 0, 0, 0, 46, 283, 1, 0, 0, 0, 48, 285, 1, 0, 0, 0, 50, 296, 1, 0, 0, 0, 52, 305, 1, 0, 0, 0, 54, 308, 1, 0, 0, 0, 56, 320, 1, 0, 0, 0, 58, 322, 1, 0, 0, 0, 60, 330, 1, 0, 0, 0, 62, 336, 1, 0, 0, 0, 64, 348, 1, 0, 0, 0, 66, 350, 1, 0, 0, 0, 68, 354, 1, 0, 0, 0, 70, 356, 1, 0, 0, 0, 72, 372, 1, 0, 0, 0, 74, 375, 1, 0, 0, 0, 76, 440, 1, 0, 0, 0, 78, 497, 1, 0, 0, 0, 80, 504, 1, 0, 0, 0, 82, 506, 1, 0, 0, 0, 84, 510, 1, 0, 0, 0, 86, 512, 1, 0, 0, 0, 88, 90, 3, 2, 1, 0, 89, 88, 1, 0, 0, 0, 90, 93, 1, 0, 0, 0, 91, 89, 1, 0, 0, 0, 91, 92, 1, 0, 0, 0, 92, 97, 1, 0, 0, 0, 93, 91, 1, 0, 0, 0, 94, 96, 3, 12, 6, 0, 95, 94, 1, 0, 0, 0, 96, 99, 1, 0, 0, 0, 97, 95, 1, 0, 0, 0, 97, 98, 1, 0, 0, 0, 98, 103, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 100, 102, 3, 14, 7, 0, 101, 100, 1, 0, 0, 0, 102, 105, 1, 0, 0, 0, 103, 101, 1, 0, 0, 0, 103, 104, 1, 0, 0, 0, 104, 106, 1, 0, 0, 0, 105, 103, 1, 0, 0, 0, 106, 107, 5, 0, 0, 1, 107, 1, 1, 0, 0, 0, 108, 109, 5, 1, 0, 0, 109, 110, 3, 4, 2, 0, 110, 111, 3, 6, 3, 0, 111, 112, 5, 2, 0, 0, 112, 3, 1, 0, 0, 0, 113, 114, 5, 3, 0, 0, 114, 5, 1, 0, 0, 0, 115, 117, 3, 8, 4, 0, 116, 118, 3, 8, 4, 0, 117, 116, 1, 0, 0, 0, 117, 118, 1, 0, 0, 0, 118, 7, 1, 0, 0, 0, 119, 121, 3, 10, 5, 0, 120, 119, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 122, 1, 0, 0, 0, 122, 123, 5, 66, 0, 0, 123, 9, 1, 0, 0, 0, 124, 125, 7, 0, 0, 0, 125, 11, 1, 0, 0, 0, 126, 127, 5, 11, 0, 0, 127, 128, 5, 76, 0, 0, 128, 129, 5, 2, 0, 0, 129, 13, 1, 0, 0, 0, 130, 134, 3, 16, 8, 0, 131, 134, 3, 18, 9, 0, 132, 134, 3, 20, 10, 0, 133, 130, 1, 0, 0, 0, 133, 131, 1, 0, 0, 0, 133, 132, 1, 0, 0, 0, 134, 15, 1, 0, 0, 0, 135, 136, 5, 12, 0, 0, 136, 137, 5, 82, 0, 0, 137, 150, 3, 26, 13, 0, 138, 139, 5, 13, 0, 0, 139, 140, 5, 14, 0, 0, 140, 145, 3, 84, 42, 0, 141, 142, 5, 15, 0, 0, 142, 144, 3, 84, 42, 0, 143, 141, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 148, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 149, 5, 16, 0, 0, 149, 151, 1, 0, 0, 0, 150, 138, 1, 0, 0, 0, 150, 151, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 153, 3, 24, 12, 0, 153, 17, 1, 0, 0, 0, 154, 155, 3, 84, 42, 0, 155, 156, 5, 17, 0, 0, 156, 157, 5, 82, 0, 0, 157, 158, 5, 10, 0, 0, 158, 159, 3, 76, 38, 0, 159, 160, 5, 2, 0, 0, 160, 19, 1, 0, 0, 0, 161, 162, 5, 18, 0, 0, 162, 163, 5, 82, 0, 0, 163, 164, 3, 26, 13, 0, 164, 168, 5, 19, 0, 0, 165, 167, 3, 22, 11, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 172, 5, 20, 0, 0, 172, 21, 1, 0, 0, 0, 173, 174, 5, 12, 0, 0, 174, 175, 5, 82, 0, 0, 175, 176, 3, 26, 13, 0, 176, 177, 3, 24, 12, 0, 177, 23, 1, 0, 0, 0, 178, 182, 5, 19, 0, 0, 179, 181, 3, 32, 16, 0, 180, 179, 1, 0, 0, 0, 181, 184, 1, 0, 0, 0, 182, 180, 1, 0, 0, 0, 182, 183, 1, 0, 0, 0, 183, 185, 1, 0, 0, 0, 184, 182, 1, 0, 0, 0, 185, 186, 5, 20, 0, 0, 186, 25, 1, 0, 0, 0, 187, 199, 5, 14, 0, 0, 188, 193, 3, 28, 14, 0, 189, 190, 5, 15, 0, 0, 190, 192, 3, 28, 14, 0, 191, 189, 1, 0, 0, 0, 192, 195, 1, 0, 0, 0, 193, 191, 1, 0, 0, 0, 193, 194, 1, 0, 0, 0, 194, 197, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 196, 198, 5, 15, 0, 0, 197, 196, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 200, 1, 0, 0, 0, 199, 188, 1, 0, 0, 0, 199, 200, 1, 0, 0, 0, 200, 201, 1, 0, 0, 0, 201, 202, 5, 16, 0, 0, 202, 27, 1, 0, 0, 0, 203, 207, 3, 84, 42, 0, 204, 206, 3, 78, 39, 0, 205, 204, 1, 0, 0, 0, 206, 209, 1, 0, 0, 0, 207, 205, 1, 0, 0, 0, 207, 208, 1, 0, 0, 0, 208, 210, 1, 0, 0, 0, 209, 207, 1, 0, 0, 0, 210, 211, 5, 82, 0, 0, 211, 29, 1, 0, 0, 0, 212, 216, 5, 19, 0, 0, 213, 215, 3, 32, 16, 0, 214, 213, 1, 0, 0, 0, 215, 218, 1, 0, 0, 0, 216, 214, 1, 0, 0, 0, 216, 217, 1, 0, 0, 0, 217, 219, 1, 0, 0, 0, 218, 216, 1, 0, 0, 0, 219, 222, 5, 20, 0, 0, 220, 222, 3, 32, 16, 0, 221, 212, 1, 0, 0, 0, 221, 220, 1, 0, 0, 0, 222, 31, 1, 0, 0, 0, 223, 228, 3, 40, 20, 0, 224, 225, 3, 34, 17, 0, 225, 226, 5, 2, 0, 0, 226, 228, 1, 0, 0, 0, 227, 223, 1, 0, 0, 0, 227, 224, 1, 0, 0, 0, 228, 33, 1, 0, 0, 0, 229, 238, 3, 42, 21, 0, 230, 238, 3, 44, 22, 0, 231, 238, 3, 46, 23, 0, 232, 238, 3, 48, 24, 0, 233, 238, 3, 50, 25, 0, 234, 238, 3, 36, 18, 0, 235, 238, 3, 52, 26, 0, 236, 238, 3, 38, 19, 0, 237, 229, 1, 0, 0, 0, 237, 230, 1, 0, 0, 0, 237, 231, 1, 0, 0, 0, 237, 232, 1, 0, 0, 0, 237, 233, 1, 0, 0, 0, 237, 234, 1, 0, 0, 0, 237, 235, 1, 0, 0, 0, 237, 236, 1, 0, 0, 0, 238, 35, 1, 0, 0, 0, 239, 240, 3, 72, 36, 0, 240, 37, 1, 0, 0, 0, 241, 242, 5, 21, 0, 0, 242, 247, 3, 76, 38, 0, 243, 244, 5, 15, 0, 0, 244, 246, 3, 76, 38, 0, 245, 243, 1, 0, 0, 0, 246, 249, 1, 0, 0, 0, 247, 245, 1, 0, 0, 0, 247, 248, 1, 0, 0, 0, 248, 39, 1, 0, 0, 0, 249, 247, 1, 0, 0, 0, 250, 253, 3, 54, 27, 0, 251, 253, 3, 56, 28, 0, 252, 250, 1, 0, 0, 0, 252, 251, 1, 0, 0, 0, 253, 41, 1, 0, 0, 0, 254, 258, 3, 84, 42, 0, 255, 257, 3, 78, 39, 0, 256, 255, 1, 0, 0, 0, 257, 260, 1, 0, 0, 0, 258, 256, 1, 0, 0, 0, 258, 259, 1, 0, 0, 0, 259, 261, 1, 0, 0, 0, 260, 258, 1, 0, 0, 0, 261, 262, 5, 82, 0, 0, 262, 263, 5, 10, 0, 0, 263, 264, 3, 76, 38, 0, 264, 43, 1, 0, 0, 0, 265, 266, 3, 84, 42, 0, 266, 271, 5, 82, 0, 0, 267, 268, 5, 15, 0, 0, 268, 269, 3, 84, 42, 0, 269, 270, 5, 82, 0, 0, 270, 272, 1, 0, 0, 0, 271, 267, 1, 0, 0, 0, 272, 273, 1, 0, 0, 0, 273, 271, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 276, 5, 10, 0, 0, 276, 277, 3, 76, 38, 0, 277, 45, 1, 0, 0, 0, 278, 279, 5, 82, 0, 0, 279, 280, 7, 1, 0, 0, 280, 284, 3, 76, 38, 0, 281, 282, 5, 82, 0, 0, 282, 284, 7, 2, 0, 0, 283, 278, 1, 0, 0, 0, 283, 281, 1, 0, 0, 0, 284, 47, 1, 0, 0, 0, 285, 286, 5, 26, 0, 0, 286, 287, 5, 14, 0, 0, 287, 288, 5, 79, 0, 0, 288, 289, 5, 6, 0, 0, 289, 292, 3, 76, 38, 0, 290, 291, 5, 15, 0, 0, 291, 293, 3, 66, 33, 0, 292, 290, 1, 0, 0, 0, 292, 293, 1, 0, 0, 0, 293, 294, 1, 0, 0, 0, 294, 295, 5, 16, 0, 0, 295, 49, 1, 0, 0, 0, 296, 297, 5, 26, 0, 0, 297, 298, 5, 14, 0, 0, 298, 301, 3, 76, 38, 0, 299, 300, 5, 15, 0, 0, 300, 302, 3, 66, 33, 0, 301, 299, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 303, 1, 0, 0, 0, 303, 304, 5, 16, 0, 0, 304, 51, 1, 0, 0, 0, 305, 306, 5, 27, 0, 0, 306, 307, 3, 70, 35, 0, 307, 53, 1, 0, 0, 0, 308, 309, 5, 28, 0, 0, 309, 310, 5, 14, 0, 0, 310, 311, 3, 76, 38, 0, 311, 312, 5, 16, 0, 0, 312, 315, 3, 30, 15, 0, 313, 314, 5, 29, 0, 0, 314, 316, 3, 30, 15, 0, 315, 313, 1, 0, 0, 0, 315, 316, 1, 0, 0, 0, 316, 55, 1, 0, 0, 0, 317, 321, 3, 58, 29, 0, 318, 321, 3, 60, 30, 0, 319, 321, 3, 62, 31, 0, 320, 317, 1, 0, 0, 0, 320, 318, 1, 0, 0, 0, 320, 319, 1, 0, 0, 0, 321, 57, 1, 0, 0, 0, 322, 323, 5, 30, 0, 0, 323, 324, 3, 30, 15, 0, 324, 325, 5, 31, 0, 0, 325, 326, 5, 14, 0, 0, 326, 327, 3, 76, 38, 0, 327, 328, 5, 16, 0, 0, 328, 329, 5, 2, 0, 0, 329, 59, 1, 0, 0, 0, 330, 331, 5, 31, 0, 0, 331, 332, 5, 14, 0, 0, 332, 333, 3, 76, 38, 0, 333, 334, 5, 16, 0, 0, 334, 335, 3, 30, 15, 0, 335, 61, 1, 0, 0, 0, 336, 337, 5, 32, 0, 0, 337, 338, 5, 14, 0, 0, 338, 339, 3, 64, 32, 0, 339, 340, 5, 2, 0, 0, 340, 341, 3, 76, 38, 0, 341, 342, 5, 2, 0, 0, 342, 343, 3, 46, 23, 0, 343, 344, 5, 16, 0, 0, 344, 345, 3, 30, 15, 0, 345, 63, 1, 0, 0, 0, 346, 349, 3, 42, 21, 0, 347, 349, 3, 46, 23, 0, 348, 346, 1, 0, 0, 0, 348, 347, 1, 0, 0, 0, 349, 65, 1, 0, 0, 0, 350, 351, 5, 76, 0, 0, 351, 67, 1, 0, 0, 0, 352, 355, 5, 82, 0, 0, 353, 355, 3, 80, 40, 0, 354, 352, 1, 0, 0, 0, 354, 353, 1, 0, 0, 0, 355, 69, 1, 0, 0, 0, 356, 368, 5, 14, 0, 0, 357, 362, 3, 68, 34, 0, 358, 359, 5, 15, 0, 0, 359, 361, 3, 68, 34, 0, 360, 358, 1, 0, 0, 0, 361, 364, 1, 0, 0, 0, 362, 360, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 366, 1, 0, 0, 0, 364, 362, 1, 0, 0, 0, 365, 367, 5, 15, 0, 0, 366, 365, 1, 0, 0, 0, 366, 367, 1, 0, 0, 0, 367, 369, 1, 0, 0, 0, 368, 357, 1, 0, 0, 0, 368, 369, 1, 0, 0, 0, 369, 370, 1, 0, 0, 0, 370, 371, 5, 16, 0, 0, 371, 71, 1, 0, 0, 0, 372, 373, 5, 82, 0, 0, 373, 374, 3, 74, 37, 0, 374, 73, 1, 0, 0, 0, 375, 387, 5, 14, 0, 0, 376, 381, 3, 76, 38, 0, 377, 378, 5, 15, 0, 0, 378, 380, 3, 76, 38, 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, 15, 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, 16, 0, 0, 390, 75, 1, 0, 0, 0, 391, 392, 6, 38, -1, 0, 392, 393, 5, 14, 0, 0, 393, 394, 3, 76, 38, 0, 394, 395, 5, 16, 0, 0, 395, 441, 1, 0, 0, 0, 396, 397, 3, 86, 43, 0, 397, 398, 5, 14, 0, 0, 398, 400, 3, 76, 38, 0, 399, 401, 5, 15, 0, 0, 400, 399, 1, 0, 0, 0, 400, 401, 1, 0, 0, 0, 401, 402, 1, 0, 0, 0, 402, 403, 5, 16, 0, 0, 403, 441, 1, 0, 0, 0, 404, 441, 3, 72, 36, 0, 405, 406, 5, 33, 0, 0, 406, 407, 5, 82, 0, 0, 407, 441, 3, 74, 37, 0, 408, 409, 5, 36, 0, 0, 409, 410, 5, 34, 0, 0, 410, 411, 3, 76, 38, 0, 411, 412, 5, 35, 0, 0, 412, 413, 7, 3, 0, 0, 413, 441, 1, 0, 0, 0, 414, 415, 5, 42, 0, 0, 415, 416, 5, 34, 0, 0, 416, 417, 3, 76, 38, 0, 417, 418, 5, 35, 0, 0, 418, 419, 7, 4, 0, 0, 419, 441, 1, 0, 0, 0, 420, 421, 7, 5, 0, 0, 421, 441, 3, 76, 38, 15, 422, 434, 5, 34, 0, 0, 423, 428, 3, 76, 38, 0, 424, 425, 5, 15, 0, 0, 425, 427, 3, 76, 38, 0, 426, 424, 1, 0, 0, 0, 427, 430, 1, 0, 0, 0, 428, 426, 1, 0, 0, 0, 428, 429, 1, 0, 0, 0, 429, 432, 1, 0, 0, 0, 430, 428, 1, 0, 0, 0, 431, 433, 5, 15, 0, 0, 432, 431, 1, 0, 0, 0, 432, 433, 1, 0, 0, 0, 433, 435, 1, 0, 0, 0, 434, 423, 1, 0, 0, 0, 434, 435, 1, 0, 0, 0, 435, 436, 1, 0, 0, 0, 436, 441, 5, 35, 0, 0, 437, 441, 5, 81, 0, 0, 438, 441, 5, 82, 0, 0, 439, 441, 3, 80, 40, 0, 440, 391, 1, 0, 0, 0, 440, 396, 1, 0, 0, 0, 440, 404, 1, 0, 0, 0, 440, 405, 1, 0, 0, 0, 440, 408, 1, 0, 0, 0, 440, 414, 1, 0, 0, 0, 440, 420, 1, 0, 0, 0, 440, 422, 1, 0, 0, 0, 440, 437, 1, 0, 0, 0, 440, 438, 1, 0, 0, 0, 440, 439, 1, 0, 0, 0, 441, 494, 1, 0, 0, 0, 442, 443, 10, 14, 0, 0, 443, 444, 7, 6, 0, 0, 444, 493, 3, 76, 38, 15, 445, 446, 10, 13, 0, 0, 446, 447, 7, 7, 0, 0, 447, 493, 3, 76, 38, 14, 448, 449, 10, 12, 0, 0, 449, 450, 7, 8, 0, 0, 450, 493, 3, 76, 38, 13, 451, 452, 10, 11, 0, 0, 452, 453, 7, 9, 0, 0, 453, 493, 3, 76, 38, 12, 454, 455, 10, 10, 0, 0, 455, 456, 7, 10, 0, 0, 456, 493, 3, 76, 38, 11, 457, 458, 10, 9, 0, 0, 458, 459, 5, 61, 0, 0, 459, 493, 3, 76, 38, 10, 460, 461, 10, 8, 0, 0, 461, 462, 5, 4, 0, 0, 462, 493, 3, 76, 38, 9, 463, 464, 10, 7, 0, 0, 464, 465, 5, 62, 0, 0, 465, 493, 3, 76, 38, 8, 466, 467, 10, 6, 0, 0, 467, 468, 5, 63, 0, 0, 468, 493, 3, 76, 38, 7, 469, 470, 10, 5, 0, 0, 470, 471, 5, 64, 0, 0, 471, 493, 3, 76, 38, 6, 472, 473, 10, 21, 0, 0, 473, 474, 5, 34, 0, 0, 474, 475, 5, 69, 0, 0, 475, 493, 5, 35, 0, 0, 476, 477, 10, 18, 0, 0, 477, 493, 7, 11, 0, 0, 478, 479, 10, 17, 0, 0, 479, 480, 5, 49, 0, 0, 480, 481, 5, 14, 0, 0, 481, 482, 3, 76, 38, 0, 482, 483, 5, 16, 0, 0, 483, 493, 1, 0, 0, 0, 484, 485, 10, 16, 0, 0, 485, 486, 5, 50, 0, 0, 486, 487, 5, 14, 0, 0, 487, 488, 3, 76, 38, 0, 488, 489, 5, 15, 0, 0, 489, 490, 3, 76, 38, 0, 490, 491, 5, 16, 0, 0, 491, 493, 1, 0, 0, 0, 492, 442, 1, 0, 0, 0, 492, 445, 1, 0, 0, 0, 492, 448, 1, 0, 0, 0, 492, 451, 1, 0, 0, 0, 492, 454, 1, 0, 0, 0, 492, 457, 1, 0, 0, 0, 492, 460, 1, 0, 0, 0, 492, 463, 1, 0, 0, 0, 492, 466, 1, 0, 0, 0, 492, 469, 1, 0, 0, 0, 492, 472, 1, 0, 0, 0, 492, 476, 1, 0, 0, 0, 492, 478, 1, 0, 0, 0, 492, 484, 1, 0, 0, 0, 493, 496, 1, 0, 0, 0, 494, 492, 1, 0, 0, 0, 494, 495, 1, 0, 0, 0, 495, 77, 1, 0, 0, 0, 496, 494, 1, 0, 0, 0, 497, 498, 7, 12, 0, 0, 498, 79, 1, 0, 0, 0, 499, 505, 5, 67, 0, 0, 500, 505, 3, 82, 41, 0, 501, 505, 5, 76, 0, 0, 502, 505, 5, 77, 0, 0, 503, 505, 5, 78, 0, 0, 504, 499, 1, 0, 0, 0, 504, 500, 1, 0, 0, 0, 504, 501, 1, 0, 0, 0, 504, 502, 1, 0, 0, 0, 504, 503, 1, 0, 0, 0, 505, 81, 1, 0, 0, 0, 506, 508, 5, 69, 0, 0, 507, 509, 5, 68, 0, 0, 508, 507, 1, 0, 0, 0, 508, 509, 1, 0, 0, 0, 509, 83, 1, 0, 0, 0, 510, 511, 7, 13, 0, 0, 511, 85, 1, 0, 0, 0, 512, 513, 7, 14, 0, 0, 513, 87, 1, 0, 0, 0, 44, 91, 97, 103, 117, 120, 133, 145, 150, 168, 182, 193, 197, 199, 207, 216, 221, 227, 237, 247, 252, 258, 273, 283, 292, 301, 315, 320, 348, 354, 362, 366, 368, 381, 385, 387, 400, 428, 432, 434, 440, 492, 494, 504, 508] \ 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, 8, 5, 8, 146, 8, 8, 10, 8, 12, 8, 149, 9, 8, 1, 8, 1, 8, 3, 8, 153, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 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, 17, 17, 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, 156, 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, 16, 8, 0, 133, 136, 3, 18, 9, 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, 5, 12, 0, 0, 138, 139, 5, 82, 0, 0, 139, 152, 3, 26, 13, 0, 140, 141, 5, 13, 0, 0, 141, 142, 5, 14, 0, 0, 142, 147, 3, 86, 43, 0, 143, 144, 5, 15, 0, 0, 144, 146, 3, 86, 43, 0, 145, 143, 1, 0, 0, 0, 146, 149, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 147, 148, 1, 0, 0, 0, 148, 150, 1, 0, 0, 0, 149, 147, 1, 0, 0, 0, 150, 151, 5, 16, 0, 0, 151, 153, 1, 0, 0, 0, 152, 140, 1, 0, 0, 0, 152, 153, 1, 0, 0, 0, 153, 154, 1, 0, 0, 0, 154, 155, 3, 24, 12, 0, 155, 17, 1, 0, 0, 0, 156, 157, 3, 86, 43, 0, 157, 158, 5, 17, 0, 0, 158, 159, 5, 82, 0, 0, 159, 160, 5, 10, 0, 0, 160, 161, 3, 78, 39, 0, 161, 162, 5, 2, 0, 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, 12, 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, 14, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 15, 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, 15, 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, 16, 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, 15, 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, 15, 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, 14, 0, 0, 278, 281, 3, 46, 23, 0, 279, 280, 5, 15, 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, 16, 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, 14, 0, 0, 306, 307, 5, 79, 0, 0, 307, 308, 5, 6, 0, 0, 308, 311, 3, 78, 39, 0, 309, 310, 5, 15, 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, 16, 0, 0, 314, 51, 1, 0, 0, 0, 315, 316, 5, 26, 0, 0, 316, 317, 5, 14, 0, 0, 317, 320, 3, 78, 39, 0, 318, 319, 5, 15, 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, 16, 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, 14, 0, 0, 329, 330, 3, 78, 39, 0, 330, 331, 5, 16, 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, 14, 0, 0, 345, 346, 3, 78, 39, 0, 346, 347, 5, 16, 0, 0, 347, 348, 5, 2, 0, 0, 348, 61, 1, 0, 0, 0, 349, 350, 5, 31, 0, 0, 350, 351, 5, 14, 0, 0, 351, 352, 3, 78, 39, 0, 352, 353, 5, 16, 0, 0, 353, 354, 3, 30, 15, 0, 354, 63, 1, 0, 0, 0, 355, 356, 5, 32, 0, 0, 356, 357, 5, 14, 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, 16, 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, 14, 0, 0, 376, 381, 3, 70, 35, 0, 377, 378, 5, 15, 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, 15, 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, 16, 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, 14, 0, 0, 395, 400, 3, 78, 39, 0, 396, 397, 5, 15, 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, 15, 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, 16, 0, 0, 409, 77, 1, 0, 0, 0, 410, 411, 6, 39, -1, 0, 411, 412, 5, 14, 0, 0, 412, 413, 3, 78, 39, 0, 413, 414, 5, 16, 0, 0, 414, 460, 1, 0, 0, 0, 415, 416, 3, 88, 44, 0, 416, 417, 5, 14, 0, 0, 417, 419, 3, 78, 39, 0, 418, 420, 5, 15, 0, 0, 419, 418, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 420, 421, 1, 0, 0, 0, 421, 422, 5, 16, 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, 15, 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, 15, 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, 14, 0, 0, 500, 501, 3, 78, 39, 0, 501, 502, 5, 16, 0, 0, 502, 512, 1, 0, 0, 0, 503, 504, 10, 16, 0, 0, 504, 505, 5, 50, 0, 0, 505, 506, 5, 14, 0, 0, 506, 507, 3, 78, 39, 0, 507, 508, 5, 15, 0, 0, 508, 509, 3, 78, 39, 0, 509, 510, 5, 16, 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, 147, 152, 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/CashScriptParser.ts b/packages/cashc/src/grammar/CashScriptParser.ts index c94f6b254..d08aa12af 100644 --- a/packages/cashc/src/grammar/CashScriptParser.ts +++ b/packages/cashc/src/grammar/CashScriptParser.ts @@ -127,27 +127,28 @@ export default class CashScriptParser extends Parser { public static readonly RULE_controlStatement = 20; public static readonly RULE_variableDefinition = 21; public static readonly RULE_tupleAssignment = 22; - public static readonly RULE_assignStatement = 23; - public static readonly RULE_timeOpStatement = 24; - public static readonly RULE_requireStatement = 25; - public static readonly RULE_consoleStatement = 26; - public static readonly RULE_ifStatement = 27; - public static readonly RULE_loopStatement = 28; - public static readonly RULE_doWhileStatement = 29; - public static readonly RULE_whileStatement = 30; - public static readonly RULE_forStatement = 31; - public static readonly RULE_forInit = 32; - public static readonly RULE_requireMessage = 33; - public static readonly RULE_consoleParameter = 34; - public static readonly RULE_consoleParameterList = 35; - public static readonly RULE_functionCall = 36; - public static readonly RULE_expressionList = 37; - public static readonly RULE_expression = 38; - public static readonly RULE_modifier = 39; - public static readonly RULE_literal = 40; - public static readonly RULE_numberLiteral = 41; - public static readonly RULE_typeName = 42; - public static readonly RULE_typeCast = 43; + 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'", "'^'", "'~'", @@ -254,11 +255,11 @@ export default class CashScriptParser extends Parser { "constantDefinition", "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", + "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; } @@ -282,49 +283,49 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 91; + this.state = 93; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===1) { { { - this.state = 88; + this.state = 90; this.pragmaDirective(); } } - this.state = 93; + this.state = 95; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 97; + this.state = 99; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===11) { { { - this.state = 94; + this.state = 96; this.importDirective(); } } - this.state = 99; + this.state = 101; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 103; + this.state = 105; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===12 || _la===18 || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 7) !== 0)) { { { - this.state = 100; + this.state = 102; this.topLevelDefinition(); } } - this.state = 105; + this.state = 107; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 106; + this.state = 108; this.match(CashScriptParser.EOF); } } @@ -349,13 +350,13 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 108; + this.state = 110; this.match(CashScriptParser.T__0); - this.state = 109; + this.state = 111; this.pragmaName(); - this.state = 110; + this.state = 112; this.pragmaValue(); - this.state = 111; + this.state = 113; this.match(CashScriptParser.T__1); } } @@ -380,7 +381,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 113; + this.state = 115; this.match(CashScriptParser.T__2); } } @@ -406,14 +407,14 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 115; - this.versionConstraint(); this.state = 117; + this.versionConstraint(); + this.state = 119; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0) || _la===66) { { - this.state = 116; + this.state = 118; this.versionConstraint(); } } @@ -442,17 +443,17 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 120; + this.state = 122; this._errHandler.sync(this); _la = this._input.LA(1); if ((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0)) { { - this.state = 119; + this.state = 121; this.versionOperator(); } } - this.state = 122; + this.state = 124; this.match(CashScriptParser.VersionLiteral); } } @@ -478,7 +479,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 124; + this.state = 126; _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 2032) !== 0))) { this._errHandler.recoverInline(this); @@ -510,11 +511,11 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 126; + this.state = 128; this.match(CashScriptParser.T__10); - this.state = 127; + this.state = 129; this.match(CashScriptParser.StringLiteral); - this.state = 128; + this.state = 130; this.match(CashScriptParser.T__1); } } @@ -537,13 +538,13 @@ 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 = 133; + this.state = 135; this._errHandler.sync(this); switch (this._input.LA(1)) { case 12: this.enterOuterAlt(localctx, 1); { - this.state = 130; + this.state = 132; this.globalFunctionDefinition(); } break; @@ -552,14 +553,14 @@ export default class CashScriptParser extends Parser { case 74: this.enterOuterAlt(localctx, 2); { - this.state = 131; + this.state = 133; this.constantDefinition(); } break; case 18: this.enterOuterAlt(localctx, 3); { - this.state = 132; + this.state = 134; this.contractDefinition(); } break; @@ -589,45 +590,45 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 135; + this.state = 137; this.match(CashScriptParser.T__11); - this.state = 136; + this.state = 138; this.match(CashScriptParser.Identifier); - this.state = 137; + this.state = 139; this.parameterList(); - this.state = 150; + this.state = 152; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===13) { { - this.state = 138; + this.state = 140; this.match(CashScriptParser.T__12); - this.state = 139; + this.state = 141; this.match(CashScriptParser.T__13); - this.state = 140; + this.state = 142; this.typeName(); - this.state = 145; + this.state = 147; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===15) { { { - this.state = 141; + this.state = 143; this.match(CashScriptParser.T__14); - this.state = 142; + this.state = 144; this.typeName(); } } - this.state = 147; + this.state = 149; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 148; + this.state = 150; this.match(CashScriptParser.T__15); } } - this.state = 152; + this.state = 154; this.functionBody(); } } @@ -652,17 +653,17 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 154; + this.state = 156; this.typeName(); - this.state = 155; + this.state = 157; this.match(CashScriptParser.T__16); - this.state = 156; + this.state = 158; this.match(CashScriptParser.Identifier); - this.state = 157; + this.state = 159; this.match(CashScriptParser.T__9); - this.state = 158; + this.state = 160; this.expression(0); - this.state = 159; + this.state = 161; this.match(CashScriptParser.T__1); } } @@ -688,29 +689,29 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 161; + this.state = 163; this.match(CashScriptParser.T__17); - this.state = 162; + this.state = 164; this.match(CashScriptParser.Identifier); - this.state = 163; + this.state = 165; this.parameterList(); - this.state = 164; + this.state = 166; this.match(CashScriptParser.T__18); - this.state = 168; + this.state = 170; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===12) { { { - this.state = 165; + this.state = 167; this.contractFunctionDefinition(); } } - this.state = 170; + this.state = 172; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 171; + this.state = 173; this.match(CashScriptParser.T__19); } } @@ -735,13 +736,13 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 173; + this.state = 175; this.match(CashScriptParser.T__11); - this.state = 174; + this.state = 176; this.match(CashScriptParser.Identifier); - this.state = 175; + this.state = 177; this.parameterList(); - this.state = 176; + this.state = 178; this.functionBody(); } } @@ -767,23 +768,23 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 178; + this.state = 180; this.match(CashScriptParser.T__18); - this.state = 182; + this.state = 184; this._errHandler.sync(this); _la = this._input.LA(1); - while (((((_la - 21)) & ~0x1F) === 0 && ((1 << (_la - 21)) & 3809) !== 0) || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 1031) !== 0)) { + while (((((_la - 14)) & ~0x1F) === 0 && ((1 << (_la - 14)) & 487553) !== 0) || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 1031) !== 0)) { { { - this.state = 179; + this.state = 181; this.statement(); } } - this.state = 184; + this.state = 186; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 185; + this.state = 187; this.match(CashScriptParser.T__19); } } @@ -810,39 +811,39 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 187; + this.state = 189; this.match(CashScriptParser.T__13); - this.state = 199; + this.state = 201; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 7) !== 0)) { { - this.state = 188; + this.state = 190; this.parameter(); - this.state = 193; + this.state = 195; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 10, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 189; + this.state = 191; this.match(CashScriptParser.T__14); - this.state = 190; + this.state = 192; this.parameter(); } } } - this.state = 195; + this.state = 197; this._errHandler.sync(this); _alt = this._interp.adaptivePredict(this._input, 10, this._ctx); } - this.state = 197; + this.state = 199; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 196; + this.state = 198; this.match(CashScriptParser.T__14); } } @@ -850,7 +851,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 201; + this.state = 203; this.match(CashScriptParser.T__15); } } @@ -876,23 +877,23 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 203; + this.state = 205; this.typeName(); - this.state = 207; + this.state = 209; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===17 || _la===65) { { { - this.state = 204; + this.state = 206; this.modifier(); } } - this.state = 209; + this.state = 211; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 210; + this.state = 212; this.match(CashScriptParser.Identifier); } } @@ -916,32 +917,33 @@ export default class CashScriptParser extends Parser { this.enterRule(localctx, 30, CashScriptParser.RULE_block); let _la: number; try { - this.state = 221; + this.state = 223; this._errHandler.sync(this); switch (this._input.LA(1)) { case 19: this.enterOuterAlt(localctx, 1); { - this.state = 212; + this.state = 214; this.match(CashScriptParser.T__18); - this.state = 216; + this.state = 218; this._errHandler.sync(this); _la = this._input.LA(1); - while (((((_la - 21)) & ~0x1F) === 0 && ((1 << (_la - 21)) & 3809) !== 0) || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 1031) !== 0)) { + while (((((_la - 14)) & ~0x1F) === 0 && ((1 << (_la - 14)) & 487553) !== 0) || ((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 1031) !== 0)) { { { - this.state = 213; + this.state = 215; this.statement(); } } - this.state = 218; + this.state = 220; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 219; + this.state = 221; this.match(CashScriptParser.T__19); } break; + case 14: case 21: case 26: case 27: @@ -955,7 +957,7 @@ export default class CashScriptParser extends Parser { case 82: this.enterOuterAlt(localctx, 2); { - this.state = 220; + this.state = 222; this.statement(); } break; @@ -982,7 +984,7 @@ export default class CashScriptParser extends Parser { let localctx: StatementContext = new StatementContext(this, this._ctx, this.state); this.enterRule(localctx, 32, CashScriptParser.RULE_statement); try { - this.state = 227; + this.state = 229; this._errHandler.sync(this); switch (this._input.LA(1)) { case 28: @@ -991,10 +993,11 @@ export default class CashScriptParser extends Parser { case 32: this.enterOuterAlt(localctx, 1); { - this.state = 223; + this.state = 225; this.controlStatement(); } break; + case 14: case 21: case 26: case 27: @@ -1004,9 +1007,9 @@ export default class CashScriptParser extends Parser { case 82: this.enterOuterAlt(localctx, 2); { - this.state = 224; + this.state = 226; this.nonControlStatement(); - this.state = 225; + this.state = 227; this.match(CashScriptParser.T__1); } break; @@ -1033,62 +1036,62 @@ export default class CashScriptParser extends Parser { let localctx: NonControlStatementContext = new NonControlStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 34, CashScriptParser.RULE_nonControlStatement); try { - this.state = 237; + this.state = 239; this._errHandler.sync(this); switch ( this._interp.adaptivePredict(this._input, 17, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 229; + this.state = 231; this.variableDefinition(); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 230; + this.state = 232; this.tupleAssignment(); } break; case 3: this.enterOuterAlt(localctx, 3); { - this.state = 231; + this.state = 233; this.assignStatement(); } break; case 4: this.enterOuterAlt(localctx, 4); { - this.state = 232; + this.state = 234; this.timeOpStatement(); } break; case 5: this.enterOuterAlt(localctx, 5); { - this.state = 233; + this.state = 235; this.requireStatement(); } break; case 6: this.enterOuterAlt(localctx, 6); { - this.state = 234; + this.state = 236; this.functionCallStatement(); } break; case 7: this.enterOuterAlt(localctx, 7); { - this.state = 235; + this.state = 237; this.consoleStatement(); } break; case 8: this.enterOuterAlt(localctx, 8); { - this.state = 236; + this.state = 238; this.returnStatement(); } break; @@ -1115,7 +1118,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 239; + this.state = 241; this.functionCall(); } } @@ -1141,23 +1144,23 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 241; + this.state = 243; this.match(CashScriptParser.T__20); - this.state = 242; + this.state = 244; this.expression(0); - this.state = 247; + this.state = 249; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===15) { { { - this.state = 243; + this.state = 245; this.match(CashScriptParser.T__14); - this.state = 244; + this.state = 246; this.expression(0); } } - this.state = 249; + this.state = 251; this._errHandler.sync(this); _la = this._input.LA(1); } @@ -1182,13 +1185,13 @@ export default class CashScriptParser extends Parser { let localctx: ControlStatementContext = new ControlStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 40, CashScriptParser.RULE_controlStatement); try { - this.state = 252; + this.state = 254; this._errHandler.sync(this); switch (this._input.LA(1)) { case 28: this.enterOuterAlt(localctx, 1); { - this.state = 250; + this.state = 252; this.ifStatement(); } break; @@ -1197,7 +1200,7 @@ export default class CashScriptParser extends Parser { case 32: this.enterOuterAlt(localctx, 2); { - this.state = 251; + this.state = 253; this.loopStatement(); } break; @@ -1227,27 +1230,27 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 254; + this.state = 256; this.typeName(); - this.state = 258; + this.state = 260; this._errHandler.sync(this); _la = this._input.LA(1); while (_la===17 || _la===65) { { { - this.state = 255; + this.state = 257; this.modifier(); } } - this.state = 260; + this.state = 262; this._errHandler.sync(this); _la = this._input.LA(1); } - this.state = 261; + this.state = 263; this.match(CashScriptParser.Identifier); - this.state = 262; + this.state = 264; this.match(CashScriptParser.T__9); - this.state = 263; + this.state = 265; this.expression(0); } } @@ -1271,34 +1274,116 @@ export default class CashScriptParser extends Parser { this.enterRule(localctx, 44, CashScriptParser.RULE_tupleAssignment); let _la: number; try { - this.enterOuterAlt(localctx, 1); - { - this.state = 265; - this.typeName(); - this.state = 266; - this.match(CashScriptParser.Identifier); - this.state = 271; + this.state = 289; this._errHandler.sync(this); - _la = this._input.LA(1); - do { - { + switch (this._input.LA(1)) { + case 72: + case 73: + case 74: + case 82: + this.enterOuterAlt(localctx, 1); { this.state = 267; - this.match(CashScriptParser.T__14); - this.state = 268; + this.tupleTarget(); + this.state = 270; + this._errHandler.sync(this); + _la = this._input.LA(1); + do { + { + { + this.state = 268; + this.match(CashScriptParser.T__14); + this.state = 269; + this.tupleTarget(); + } + } + this.state = 272; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la===15); + this.state = 274; + this.match(CashScriptParser.T__9); + this.state = 275; + this.expression(0); + } + break; + case 14: + this.enterOuterAlt(localctx, 2); + { + this.state = 277; + this.match(CashScriptParser.T__13); + 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__14); + this.state = 280; + this.tupleTarget(); + } + } + this.state = 283; + this._errHandler.sync(this); + _la = this._input.LA(1); + } while (_la===15); + this.state = 285; + this.match(CashScriptParser.T__15); + 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 = 269; + this.state = 292; this.match(CashScriptParser.Identifier); } + break; + case 82: + this.enterOuterAlt(localctx, 2); + { + this.state = 294; + this.match(CashScriptParser.Identifier); } - this.state = 273; - this._errHandler.sync(this); - _la = this._input.LA(1); - } while (_la===15); - this.state = 275; - this.match(CashScriptParser.T__9); - this.state = 276; - this.expression(0); + break; + default: + throw new NoViableAltException(this); } } catch (re) { @@ -1318,18 +1403,18 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public assignStatement(): AssignStatementContext { let localctx: AssignStatementContext = new AssignStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 46, CashScriptParser.RULE_assignStatement); + this.enterRule(localctx, 48, CashScriptParser.RULE_assignStatement); let _la: number; try { - this.state = 283; + this.state = 302; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 22, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 25, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 278; + this.state = 297; this.match(CashScriptParser.Identifier); - this.state = 279; + this.state = 298; localctx._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 12583936) !== 0))) { @@ -1339,16 +1424,16 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 280; + this.state = 299; this.expression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 281; + this.state = 300; this.match(CashScriptParser.Identifier); - this.state = 282; + this.state = 301; localctx._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===24 || _la===25)) { @@ -1379,34 +1464,34 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public timeOpStatement(): TimeOpStatementContext { let localctx: TimeOpStatementContext = new TimeOpStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 48, CashScriptParser.RULE_timeOpStatement); + this.enterRule(localctx, 50, CashScriptParser.RULE_timeOpStatement); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 285; + this.state = 304; this.match(CashScriptParser.T__25); - this.state = 286; + this.state = 305; this.match(CashScriptParser.T__13); - this.state = 287; + this.state = 306; this.match(CashScriptParser.TxVar); - this.state = 288; + this.state = 307; this.match(CashScriptParser.T__5); - this.state = 289; + this.state = 308; this.expression(0); - this.state = 292; + this.state = 311; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 290; + this.state = 309; this.match(CashScriptParser.T__14); - this.state = 291; + this.state = 310; this.requireMessage(); } } - this.state = 294; + this.state = 313; this.match(CashScriptParser.T__15); } } @@ -1427,30 +1512,30 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public requireStatement(): RequireStatementContext { let localctx: RequireStatementContext = new RequireStatementContext(this, this._ctx, this.state); - this.enterRule(localctx, 50, CashScriptParser.RULE_requireStatement); + this.enterRule(localctx, 52, CashScriptParser.RULE_requireStatement); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 296; + this.state = 315; this.match(CashScriptParser.T__25); - this.state = 297; + this.state = 316; this.match(CashScriptParser.T__13); - this.state = 298; + this.state = 317; this.expression(0); - this.state = 301; + this.state = 320; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 299; + this.state = 318; this.match(CashScriptParser.T__14); - this.state = 300; + this.state = 319; this.requireMessage(); } } - this.state = 303; + this.state = 322; this.match(CashScriptParser.T__15); } } @@ -1471,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, 52, CashScriptParser.RULE_consoleStatement); + this.enterRule(localctx, 54, CashScriptParser.RULE_consoleStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 305; + this.state = 324; this.match(CashScriptParser.T__26); - this.state = 306; + this.state = 325; this.consoleParameterList(); } } @@ -1498,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, 54, CashScriptParser.RULE_ifStatement); + this.enterRule(localctx, 56, CashScriptParser.RULE_ifStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 308; + this.state = 327; this.match(CashScriptParser.T__27); - this.state = 309; + this.state = 328; this.match(CashScriptParser.T__13); - this.state = 310; + this.state = 329; this.expression(0); - this.state = 311; + this.state = 330; this.match(CashScriptParser.T__15); - this.state = 312; + this.state = 331; localctx._ifBlock = this.block(); - this.state = 315; + this.state = 334; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 25, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 28, this._ctx) ) { case 1: { - this.state = 313; + this.state = 332; this.match(CashScriptParser.T__28); - this.state = 314; + this.state = 333; localctx._elseBlock = this.block(); } break; @@ -1543,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, 56, CashScriptParser.RULE_loopStatement); + this.enterRule(localctx, 58, CashScriptParser.RULE_loopStatement); try { - this.state = 320; + this.state = 339; this._errHandler.sync(this); switch (this._input.LA(1)) { case 30: this.enterOuterAlt(localctx, 1); { - this.state = 317; + this.state = 336; this.doWhileStatement(); } break; case 31: this.enterOuterAlt(localctx, 2); { - this.state = 318; + this.state = 337; this.whileStatement(); } break; case 32: this.enterOuterAlt(localctx, 3); { - this.state = 319; + this.state = 338; this.forStatement(); } break; @@ -1590,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, 58, CashScriptParser.RULE_doWhileStatement); + this.enterRule(localctx, 60, CashScriptParser.RULE_doWhileStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 322; + this.state = 341; this.match(CashScriptParser.T__29); - this.state = 323; + this.state = 342; this.block(); - this.state = 324; + this.state = 343; this.match(CashScriptParser.T__30); - this.state = 325; + this.state = 344; this.match(CashScriptParser.T__13); - this.state = 326; + this.state = 345; this.expression(0); - this.state = 327; + this.state = 346; this.match(CashScriptParser.T__15); - this.state = 328; + this.state = 347; this.match(CashScriptParser.T__1); } } @@ -1627,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, 60, CashScriptParser.RULE_whileStatement); + this.enterRule(localctx, 62, CashScriptParser.RULE_whileStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 330; + this.state = 349; this.match(CashScriptParser.T__30); - this.state = 331; + this.state = 350; this.match(CashScriptParser.T__13); - this.state = 332; + this.state = 351; this.expression(0); - this.state = 333; + this.state = 352; this.match(CashScriptParser.T__15); - this.state = 334; + this.state = 353; this.block(); } } @@ -1660,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, 62, CashScriptParser.RULE_forStatement); + this.enterRule(localctx, 64, CashScriptParser.RULE_forStatement); try { this.enterOuterAlt(localctx, 1); { - this.state = 336; + this.state = 355; this.match(CashScriptParser.T__31); - this.state = 337; + this.state = 356; this.match(CashScriptParser.T__13); - this.state = 338; + this.state = 357; this.forInit(); - this.state = 339; + this.state = 358; this.match(CashScriptParser.T__1); - this.state = 340; + this.state = 359; this.expression(0); - this.state = 341; + this.state = 360; this.match(CashScriptParser.T__1); - this.state = 342; + this.state = 361; this.assignStatement(); - this.state = 343; + this.state = 362; this.match(CashScriptParser.T__15); - this.state = 344; + this.state = 363; this.block(); } } @@ -1701,9 +1786,9 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public forInit(): ForInitContext { let localctx: ForInitContext = new ForInitContext(this, this._ctx, this.state); - this.enterRule(localctx, 64, CashScriptParser.RULE_forInit); + this.enterRule(localctx, 66, CashScriptParser.RULE_forInit); try { - this.state = 348; + this.state = 367; this._errHandler.sync(this); switch (this._input.LA(1)) { case 72: @@ -1711,14 +1796,14 @@ export default class CashScriptParser extends Parser { case 74: this.enterOuterAlt(localctx, 1); { - this.state = 346; + this.state = 365; this.variableDefinition(); } break; case 82: this.enterOuterAlt(localctx, 2); { - this.state = 347; + this.state = 366; this.assignStatement(); } break; @@ -1743,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, 66, CashScriptParser.RULE_requireMessage); + this.enterRule(localctx, 68, CashScriptParser.RULE_requireMessage); try { this.enterOuterAlt(localctx, 1); { - this.state = 350; + this.state = 369; this.match(CashScriptParser.StringLiteral); } } @@ -1768,15 +1853,15 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public consoleParameter(): ConsoleParameterContext { let localctx: ConsoleParameterContext = new ConsoleParameterContext(this, this._ctx, this.state); - this.enterRule(localctx, 68, CashScriptParser.RULE_consoleParameter); + this.enterRule(localctx, 70, CashScriptParser.RULE_consoleParameter); try { - this.state = 354; + this.state = 373; this._errHandler.sync(this); switch (this._input.LA(1)) { case 82: this.enterOuterAlt(localctx, 1); { - this.state = 352; + this.state = 371; this.match(CashScriptParser.Identifier); } break; @@ -1787,7 +1872,7 @@ export default class CashScriptParser extends Parser { case 78: this.enterOuterAlt(localctx, 2); { - this.state = 353; + this.state = 372; this.literal(); } break; @@ -1812,45 +1897,45 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public consoleParameterList(): ConsoleParameterListContext { let localctx: ConsoleParameterListContext = new ConsoleParameterListContext(this, this._ctx, this.state); - this.enterRule(localctx, 70, CashScriptParser.RULE_consoleParameterList); + this.enterRule(localctx, 72, CashScriptParser.RULE_consoleParameterList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 356; + this.state = 375; this.match(CashScriptParser.T__13); - this.state = 368; + this.state = 387; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 36357) !== 0)) { { - this.state = 357; + this.state = 376; this.consoleParameter(); - this.state = 362; + this.state = 381; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 29, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 358; + this.state = 377; this.match(CashScriptParser.T__14); - this.state = 359; + this.state = 378; this.consoleParameter(); } } } - this.state = 364; + this.state = 383; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 29, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); } - this.state = 366; + this.state = 385; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 365; + this.state = 384; this.match(CashScriptParser.T__14); } } @@ -1858,7 +1943,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 370; + this.state = 389; this.match(CashScriptParser.T__15); } } @@ -1879,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, 72, CashScriptParser.RULE_functionCall); + this.enterRule(localctx, 74, CashScriptParser.RULE_functionCall); try { this.enterOuterAlt(localctx, 1); { - this.state = 372; + this.state = 391; this.match(CashScriptParser.Identifier); - this.state = 373; + this.state = 392; this.expressionList(); } } @@ -1906,45 +1991,45 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public expressionList(): ExpressionListContext { let localctx: ExpressionListContext = new ExpressionListContext(this, this._ctx, this.state); - this.enterRule(localctx, 74, CashScriptParser.RULE_expressionList); + this.enterRule(localctx, 76, CashScriptParser.RULE_expressionList); let _la: number; try { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 375; + this.state = 394; this.match(CashScriptParser.T__13); - this.state = 387; + this.state = 406; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===5 || _la===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 61029) !== 0)) { { - this.state = 376; + this.state = 395; this.expression(0); - this.state = 381; + this.state = 400; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 377; + this.state = 396; this.match(CashScriptParser.T__14); - this.state = 378; + this.state = 397; this.expression(0); } } } - this.state = 383; + this.state = 402; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); } - this.state = 385; + this.state = 404; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 384; + this.state = 403; this.match(CashScriptParser.T__14); } } @@ -1952,7 +2037,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 389; + this.state = 408; this.match(CashScriptParser.T__15); } } @@ -1983,27 +2068,27 @@ 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 = 76; - this.enterRecursionRule(localctx, 76, 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 = 440; + this.state = 459; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 39, 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 = 392; + this.state = 411; this.match(CashScriptParser.T__13); - this.state = 393; + this.state = 412; this.expression(0); - this.state = 394; + this.state = 413; this.match(CashScriptParser.T__15); } break; @@ -2012,23 +2097,23 @@ export default class CashScriptParser extends Parser { localctx = new CastContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 396; + this.state = 415; this.typeCast(); - this.state = 397; + this.state = 416; this.match(CashScriptParser.T__13); - this.state = 398; + this.state = 417; (localctx as CastContext)._castable = this.expression(0); - this.state = 400; + this.state = 419; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 399; + this.state = 418; this.match(CashScriptParser.T__14); } } - this.state = 402; + this.state = 421; this.match(CashScriptParser.T__15); } break; @@ -2037,7 +2122,7 @@ export default class CashScriptParser extends Parser { localctx = new FunctionCallExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 404; + this.state = 423; this.functionCall(); } break; @@ -2046,11 +2131,11 @@ export default class CashScriptParser extends Parser { localctx = new InstantiationContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 405; + this.state = 424; this.match(CashScriptParser.T__32); - this.state = 406; + this.state = 425; this.match(CashScriptParser.Identifier); - this.state = 407; + this.state = 426; this.expressionList(); } break; @@ -2059,15 +2144,15 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 408; + this.state = 427; (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__35); - this.state = 409; + this.state = 428; this.match(CashScriptParser.T__33); - this.state = 410; + this.state = 429; this.expression(0); - this.state = 411; + this.state = 430; this.match(CashScriptParser.T__34); - this.state = 412; + this.state = 431; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 37)) & ~0x1F) === 0 && ((1 << (_la - 37)) & 31) !== 0))) { @@ -2084,15 +2169,15 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 414; + this.state = 433; (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__41); - this.state = 415; + this.state = 434; this.match(CashScriptParser.T__33); - this.state = 416; + this.state = 435; this.expression(0); - this.state = 417; + this.state = 436; this.match(CashScriptParser.T__34); - this.state = 418; + this.state = 437; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 37)) & ~0x1F) === 0 && ((1 << (_la - 37)) & 991) !== 0))) { @@ -2109,7 +2194,7 @@ export default class CashScriptParser extends Parser { localctx = new UnaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 420; + this.state = 439; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===5 || _la===51 || _la===52)) { @@ -2119,7 +2204,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 421; + this.state = 440; this.expression(15); } break; @@ -2128,39 +2213,39 @@ export default class CashScriptParser extends Parser { localctx = new ArrayContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 422; + this.state = 441; this.match(CashScriptParser.T__33); - this.state = 434; + this.state = 453; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===5 || _la===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 61029) !== 0)) { { - this.state = 423; + this.state = 442; this.expression(0); - this.state = 428; + this.state = 447; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 36, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 424; + this.state = 443; this.match(CashScriptParser.T__14); - this.state = 425; + this.state = 444; this.expression(0); } } } - this.state = 430; + this.state = 449; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 36, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); } - this.state = 432; + this.state = 451; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 431; + this.state = 450; this.match(CashScriptParser.T__14); } } @@ -2168,7 +2253,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 436; + this.state = 455; this.match(CashScriptParser.T__34); } break; @@ -2177,7 +2262,7 @@ export default class CashScriptParser extends Parser { localctx = new NullaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 437; + this.state = 456; this.match(CashScriptParser.NullaryOp); } break; @@ -2186,7 +2271,7 @@ export default class CashScriptParser extends Parser { localctx = new IdentifierContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 438; + this.state = 457; this.match(CashScriptParser.Identifier); } break; @@ -2195,15 +2280,15 @@ export default class CashScriptParser extends Parser { localctx = new LiteralExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 439; + this.state = 458; this.literal(); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 494; + this.state = 513; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 41, 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) { @@ -2211,19 +2296,19 @@ export default class CashScriptParser extends Parser { } _prevctx = localctx; { - this.state = 492; + this.state = 511; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 40, 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 = 442; + this.state = 461; if (!(this.precpred(this._ctx, 14))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 14)"); } - this.state = 443; + this.state = 462; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & 7) !== 0))) { @@ -2233,7 +2318,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 444; + this.state = 463; (localctx as BinaryOpContext)._right = this.expression(15); } break; @@ -2242,11 +2327,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 = 445; + this.state = 464; if (!(this.precpred(this._ctx, 13))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 13)"); } - this.state = 446; + this.state = 465; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===52 || _la===56)) { @@ -2256,7 +2341,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 447; + this.state = 466; (localctx as BinaryOpContext)._right = this.expression(14); } break; @@ -2265,11 +2350,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 = 448; + this.state = 467; if (!(this.precpred(this._ctx, 12))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 12)"); } - this.state = 449; + this.state = 468; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===57 || _la===58)) { @@ -2279,7 +2364,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 450; + this.state = 469; (localctx as BinaryOpContext)._right = this.expression(13); } break; @@ -2288,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 = 451; + this.state = 470; if (!(this.precpred(this._ctx, 11))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 11)"); } - this.state = 452; + this.state = 471; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 960) !== 0))) { @@ -2302,7 +2387,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 453; + this.state = 472; (localctx as BinaryOpContext)._right = this.expression(12); } break; @@ -2311,11 +2396,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 = 454; + this.state = 473; if (!(this.precpred(this._ctx, 10))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 10)"); } - this.state = 455; + this.state = 474; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===59 || _la===60)) { @@ -2325,7 +2410,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 456; + this.state = 475; (localctx as BinaryOpContext)._right = this.expression(11); } break; @@ -2334,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 = 457; + this.state = 476; if (!(this.precpred(this._ctx, 9))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 9)"); } - this.state = 458; + this.state = 477; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); - this.state = 459; + this.state = 478; (localctx as BinaryOpContext)._right = this.expression(10); } break; @@ -2349,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 = 460; + this.state = 479; if (!(this.precpred(this._ctx, 8))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 8)"); } - this.state = 461; + this.state = 480; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__3); - this.state = 462; + this.state = 481; (localctx as BinaryOpContext)._right = this.expression(9); } break; @@ -2364,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 = 463; + this.state = 482; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 464; + this.state = 483; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); - this.state = 465; + this.state = 484; (localctx as BinaryOpContext)._right = this.expression(8); } break; @@ -2379,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 = 466; + this.state = 485; if (!(this.precpred(this._ctx, 6))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 6)"); } - this.state = 467; + this.state = 486; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); - this.state = 468; + this.state = 487; (localctx as BinaryOpContext)._right = this.expression(7); } break; @@ -2394,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 = 469; + this.state = 488; if (!(this.precpred(this._ctx, 5))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 5)"); } - this.state = 470; + this.state = 489; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__63); - this.state = 471; + this.state = 490; (localctx as BinaryOpContext)._right = this.expression(6); } break; @@ -2408,15 +2493,15 @@ export default class CashScriptParser extends Parser { { localctx = new TupleIndexOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 472; + this.state = 491; if (!(this.precpred(this._ctx, 21))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 21)"); } - this.state = 473; + this.state = 492; this.match(CashScriptParser.T__33); - this.state = 474; + this.state = 493; (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); - this.state = 475; + this.state = 494; this.match(CashScriptParser.T__34); } break; @@ -2424,11 +2509,11 @@ export default class CashScriptParser extends Parser { { localctx = new UnaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 476; + this.state = 495; if (!(this.precpred(this._ctx, 18))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 18)"); } - this.state = 477; + this.state = 496; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===47 || _la===48)) { @@ -2445,17 +2530,17 @@ 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 = 478; + this.state = 497; if (!(this.precpred(this._ctx, 17))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 17)"); } - this.state = 479; + this.state = 498; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__48); - this.state = 480; + this.state = 499; this.match(CashScriptParser.T__13); - this.state = 481; + this.state = 500; (localctx as BinaryOpContext)._right = this.expression(0); - this.state = 482; + this.state = 501; this.match(CashScriptParser.T__15); } break; @@ -2464,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 = 484; + this.state = 503; if (!(this.precpred(this._ctx, 16))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 16)"); } - this.state = 485; + this.state = 504; this.match(CashScriptParser.T__49); - this.state = 486; + this.state = 505; this.match(CashScriptParser.T__13); - this.state = 487; + this.state = 506; (localctx as SliceContext)._start = this.expression(0); - this.state = 488; + this.state = 507; this.match(CashScriptParser.T__14); - this.state = 489; + this.state = 508; (localctx as SliceContext)._end = this.expression(0); - this.state = 490; + this.state = 509; this.match(CashScriptParser.T__15); } break; } } } - this.state = 496; + this.state = 515; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 41, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); } } } @@ -2508,12 +2593,12 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public modifier(): ModifierContext { let localctx: ModifierContext = new ModifierContext(this, this._ctx, this.state); - this.enterRule(localctx, 78, CashScriptParser.RULE_modifier); + this.enterRule(localctx, 80, CashScriptParser.RULE_modifier); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 497; + this.state = 516; _la = this._input.LA(1); if(!(_la===17 || _la===65)) { this._errHandler.recoverInline(this); @@ -2541,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, 80, CashScriptParser.RULE_literal); + this.enterRule(localctx, 82, CashScriptParser.RULE_literal); try { - this.state = 504; + this.state = 523; this._errHandler.sync(this); switch (this._input.LA(1)) { case 67: this.enterOuterAlt(localctx, 1); { - this.state = 499; + this.state = 518; this.match(CashScriptParser.BooleanLiteral); } break; case 69: this.enterOuterAlt(localctx, 2); { - this.state = 500; + this.state = 519; this.numberLiteral(); } break; case 76: this.enterOuterAlt(localctx, 3); { - this.state = 501; + this.state = 520; this.match(CashScriptParser.StringLiteral); } break; case 77: this.enterOuterAlt(localctx, 4); { - this.state = 502; + this.state = 521; this.match(CashScriptParser.DateLiteral); } break; case 78: this.enterOuterAlt(localctx, 5); { - this.state = 503; + this.state = 522; this.match(CashScriptParser.HexLiteral); } break; @@ -2602,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, 82, CashScriptParser.RULE_numberLiteral); + this.enterRule(localctx, 84, CashScriptParser.RULE_numberLiteral); try { this.enterOuterAlt(localctx, 1); { - this.state = 506; + this.state = 525; this.match(CashScriptParser.NumberLiteral); - this.state = 508; + this.state = 527; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 43, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 46, this._ctx) ) { case 1: { - this.state = 507; + this.state = 526; this.match(CashScriptParser.NumberUnit); } break; @@ -2637,12 +2722,12 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public typeName(): TypeNameContext { let localctx: TypeNameContext = new TypeNameContext(this, this._ctx, this.state); - this.enterRule(localctx, 84, CashScriptParser.RULE_typeName); + this.enterRule(localctx, 86, CashScriptParser.RULE_typeName); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 510; + this.state = 529; _la = this._input.LA(1); if(!(((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 7) !== 0))) { this._errHandler.recoverInline(this); @@ -2670,12 +2755,12 @@ export default class CashScriptParser extends Parser { // @RuleVersion(0) public typeCast(): TypeCastContext { let localctx: TypeCastContext = new TypeCastContext(this, this._ctx, this.state); - this.enterRule(localctx, 86, CashScriptParser.RULE_typeCast); + this.enterRule(localctx, 88, CashScriptParser.RULE_typeCast); let _la: number; try { this.enterOuterAlt(localctx, 1); { - this.state = 512; + this.state = 531; _la = this._input.LA(1); if(!(((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 259) !== 0))) { this._errHandler.recoverInline(this); @@ -2703,7 +2788,7 @@ export default class CashScriptParser extends Parser { public sempred(localctx: RuleContext, ruleIndex: number, predIndex: number): boolean { switch (ruleIndex) { - case 38: + case 39: return this.expression_sempred(localctx as ExpressionContext, predIndex); } return true; @@ -2742,177 +2827,183 @@ export default class CashScriptParser extends Parser { return true; } - public static readonly _serializedATN: number[] = [4,1,85,515,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,2,43,7,43,1,0,5,0,90,8,0,10,0,12, - 0,93,9,0,1,0,5,0,96,8,0,10,0,12,0,99,9,0,1,0,5,0,102,8,0,10,0,12,0,105, - 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,118,8,3,1,4,3,4,121, - 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,134,8,7,1,8,1,8,1,8, - 1,8,1,8,1,8,1,8,1,8,5,8,144,8,8,10,8,12,8,147,9,8,1,8,1,8,3,8,151,8,8,1, - 8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,10,1,10,1,10,5,10,167,8,10, - 10,10,12,10,170,9,10,1,10,1,10,1,11,1,11,1,11,1,11,1,11,1,12,1,12,5,12, - 181,8,12,10,12,12,12,184,9,12,1,12,1,12,1,13,1,13,1,13,1,13,5,13,192,8, - 13,10,13,12,13,195,9,13,1,13,3,13,198,8,13,3,13,200,8,13,1,13,1,13,1,14, - 1,14,5,14,206,8,14,10,14,12,14,209,9,14,1,14,1,14,1,15,1,15,5,15,215,8, - 15,10,15,12,15,218,9,15,1,15,1,15,3,15,222,8,15,1,16,1,16,1,16,1,16,3,16, - 228,8,16,1,17,1,17,1,17,1,17,1,17,1,17,1,17,1,17,3,17,238,8,17,1,18,1,18, - 1,19,1,19,1,19,1,19,5,19,246,8,19,10,19,12,19,249,9,19,1,20,1,20,3,20,253, - 8,20,1,21,1,21,5,21,257,8,21,10,21,12,21,260,9,21,1,21,1,21,1,21,1,21,1, - 22,1,22,1,22,1,22,1,22,1,22,4,22,272,8,22,11,22,12,22,273,1,22,1,22,1,22, - 1,23,1,23,1,23,1,23,1,23,3,23,284,8,23,1,24,1,24,1,24,1,24,1,24,1,24,1, - 24,3,24,293,8,24,1,24,1,24,1,25,1,25,1,25,1,25,1,25,3,25,302,8,25,1,25, - 1,25,1,26,1,26,1,26,1,27,1,27,1,27,1,27,1,27,1,27,1,27,3,27,316,8,27,1, - 28,1,28,1,28,3,28,321,8,28,1,29,1,29,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,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1,31,1, - 31,1,32,1,32,3,32,349,8,32,1,33,1,33,1,34,1,34,3,34,355,8,34,1,35,1,35, - 1,35,1,35,5,35,361,8,35,10,35,12,35,364,9,35,1,35,3,35,367,8,35,3,35,369, - 8,35,1,35,1,35,1,36,1,36,1,36,1,37,1,37,1,37,1,37,5,37,380,8,37,10,37,12, - 37,383,9,37,1,37,3,37,386,8,37,3,37,388,8,37,1,37,1,37,1,38,1,38,1,38,1, - 38,1,38,1,38,1,38,1,38,1,38,3,38,401,8,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,38,1,38,1,38,1,38,1,38,1,38,1, - 38,1,38,1,38,1,38,5,38,427,8,38,10,38,12,38,430,9,38,1,38,3,38,433,8,38, - 3,38,435,8,38,1,38,1,38,1,38,1,38,3,38,441,8,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,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,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,38,1,38,1,38,1,38,1, - 38,1,38,5,38,493,8,38,10,38,12,38,496,9,38,1,39,1,39,1,40,1,40,1,40,1,40, - 1,40,3,40,505,8,40,1,41,1,41,3,41,509,8,41,1,42,1,42,1,43,1,43,1,43,0,1, - 76,44,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,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,17,17, - 65,65,1,0,72,74,2,0,72,73,80,80,546,0,91,1,0,0,0,2,108,1,0,0,0,4,113,1, - 0,0,0,6,115,1,0,0,0,8,120,1,0,0,0,10,124,1,0,0,0,12,126,1,0,0,0,14,133, - 1,0,0,0,16,135,1,0,0,0,18,154,1,0,0,0,20,161,1,0,0,0,22,173,1,0,0,0,24, - 178,1,0,0,0,26,187,1,0,0,0,28,203,1,0,0,0,30,221,1,0,0,0,32,227,1,0,0,0, - 34,237,1,0,0,0,36,239,1,0,0,0,38,241,1,0,0,0,40,252,1,0,0,0,42,254,1,0, - 0,0,44,265,1,0,0,0,46,283,1,0,0,0,48,285,1,0,0,0,50,296,1,0,0,0,52,305, - 1,0,0,0,54,308,1,0,0,0,56,320,1,0,0,0,58,322,1,0,0,0,60,330,1,0,0,0,62, - 336,1,0,0,0,64,348,1,0,0,0,66,350,1,0,0,0,68,354,1,0,0,0,70,356,1,0,0,0, - 72,372,1,0,0,0,74,375,1,0,0,0,76,440,1,0,0,0,78,497,1,0,0,0,80,504,1,0, - 0,0,82,506,1,0,0,0,84,510,1,0,0,0,86,512,1,0,0,0,88,90,3,2,1,0,89,88,1, - 0,0,0,90,93,1,0,0,0,91,89,1,0,0,0,91,92,1,0,0,0,92,97,1,0,0,0,93,91,1,0, - 0,0,94,96,3,12,6,0,95,94,1,0,0,0,96,99,1,0,0,0,97,95,1,0,0,0,97,98,1,0, - 0,0,98,103,1,0,0,0,99,97,1,0,0,0,100,102,3,14,7,0,101,100,1,0,0,0,102,105, - 1,0,0,0,103,101,1,0,0,0,103,104,1,0,0,0,104,106,1,0,0,0,105,103,1,0,0,0, - 106,107,5,0,0,1,107,1,1,0,0,0,108,109,5,1,0,0,109,110,3,4,2,0,110,111,3, - 6,3,0,111,112,5,2,0,0,112,3,1,0,0,0,113,114,5,3,0,0,114,5,1,0,0,0,115,117, - 3,8,4,0,116,118,3,8,4,0,117,116,1,0,0,0,117,118,1,0,0,0,118,7,1,0,0,0,119, - 121,3,10,5,0,120,119,1,0,0,0,120,121,1,0,0,0,121,122,1,0,0,0,122,123,5, - 66,0,0,123,9,1,0,0,0,124,125,7,0,0,0,125,11,1,0,0,0,126,127,5,11,0,0,127, - 128,5,76,0,0,128,129,5,2,0,0,129,13,1,0,0,0,130,134,3,16,8,0,131,134,3, - 18,9,0,132,134,3,20,10,0,133,130,1,0,0,0,133,131,1,0,0,0,133,132,1,0,0, - 0,134,15,1,0,0,0,135,136,5,12,0,0,136,137,5,82,0,0,137,150,3,26,13,0,138, - 139,5,13,0,0,139,140,5,14,0,0,140,145,3,84,42,0,141,142,5,15,0,0,142,144, - 3,84,42,0,143,141,1,0,0,0,144,147,1,0,0,0,145,143,1,0,0,0,145,146,1,0,0, - 0,146,148,1,0,0,0,147,145,1,0,0,0,148,149,5,16,0,0,149,151,1,0,0,0,150, - 138,1,0,0,0,150,151,1,0,0,0,151,152,1,0,0,0,152,153,3,24,12,0,153,17,1, - 0,0,0,154,155,3,84,42,0,155,156,5,17,0,0,156,157,5,82,0,0,157,158,5,10, - 0,0,158,159,3,76,38,0,159,160,5,2,0,0,160,19,1,0,0,0,161,162,5,18,0,0,162, - 163,5,82,0,0,163,164,3,26,13,0,164,168,5,19,0,0,165,167,3,22,11,0,166,165, - 1,0,0,0,167,170,1,0,0,0,168,166,1,0,0,0,168,169,1,0,0,0,169,171,1,0,0,0, - 170,168,1,0,0,0,171,172,5,20,0,0,172,21,1,0,0,0,173,174,5,12,0,0,174,175, - 5,82,0,0,175,176,3,26,13,0,176,177,3,24,12,0,177,23,1,0,0,0,178,182,5,19, - 0,0,179,181,3,32,16,0,180,179,1,0,0,0,181,184,1,0,0,0,182,180,1,0,0,0,182, - 183,1,0,0,0,183,185,1,0,0,0,184,182,1,0,0,0,185,186,5,20,0,0,186,25,1,0, - 0,0,187,199,5,14,0,0,188,193,3,28,14,0,189,190,5,15,0,0,190,192,3,28,14, - 0,191,189,1,0,0,0,192,195,1,0,0,0,193,191,1,0,0,0,193,194,1,0,0,0,194,197, - 1,0,0,0,195,193,1,0,0,0,196,198,5,15,0,0,197,196,1,0,0,0,197,198,1,0,0, - 0,198,200,1,0,0,0,199,188,1,0,0,0,199,200,1,0,0,0,200,201,1,0,0,0,201,202, - 5,16,0,0,202,27,1,0,0,0,203,207,3,84,42,0,204,206,3,78,39,0,205,204,1,0, - 0,0,206,209,1,0,0,0,207,205,1,0,0,0,207,208,1,0,0,0,208,210,1,0,0,0,209, - 207,1,0,0,0,210,211,5,82,0,0,211,29,1,0,0,0,212,216,5,19,0,0,213,215,3, - 32,16,0,214,213,1,0,0,0,215,218,1,0,0,0,216,214,1,0,0,0,216,217,1,0,0,0, - 217,219,1,0,0,0,218,216,1,0,0,0,219,222,5,20,0,0,220,222,3,32,16,0,221, - 212,1,0,0,0,221,220,1,0,0,0,222,31,1,0,0,0,223,228,3,40,20,0,224,225,3, - 34,17,0,225,226,5,2,0,0,226,228,1,0,0,0,227,223,1,0,0,0,227,224,1,0,0,0, - 228,33,1,0,0,0,229,238,3,42,21,0,230,238,3,44,22,0,231,238,3,46,23,0,232, - 238,3,48,24,0,233,238,3,50,25,0,234,238,3,36,18,0,235,238,3,52,26,0,236, - 238,3,38,19,0,237,229,1,0,0,0,237,230,1,0,0,0,237,231,1,0,0,0,237,232,1, - 0,0,0,237,233,1,0,0,0,237,234,1,0,0,0,237,235,1,0,0,0,237,236,1,0,0,0,238, - 35,1,0,0,0,239,240,3,72,36,0,240,37,1,0,0,0,241,242,5,21,0,0,242,247,3, - 76,38,0,243,244,5,15,0,0,244,246,3,76,38,0,245,243,1,0,0,0,246,249,1,0, - 0,0,247,245,1,0,0,0,247,248,1,0,0,0,248,39,1,0,0,0,249,247,1,0,0,0,250, - 253,3,54,27,0,251,253,3,56,28,0,252,250,1,0,0,0,252,251,1,0,0,0,253,41, - 1,0,0,0,254,258,3,84,42,0,255,257,3,78,39,0,256,255,1,0,0,0,257,260,1,0, - 0,0,258,256,1,0,0,0,258,259,1,0,0,0,259,261,1,0,0,0,260,258,1,0,0,0,261, - 262,5,82,0,0,262,263,5,10,0,0,263,264,3,76,38,0,264,43,1,0,0,0,265,266, - 3,84,42,0,266,271,5,82,0,0,267,268,5,15,0,0,268,269,3,84,42,0,269,270,5, - 82,0,0,270,272,1,0,0,0,271,267,1,0,0,0,272,273,1,0,0,0,273,271,1,0,0,0, - 273,274,1,0,0,0,274,275,1,0,0,0,275,276,5,10,0,0,276,277,3,76,38,0,277, - 45,1,0,0,0,278,279,5,82,0,0,279,280,7,1,0,0,280,284,3,76,38,0,281,282,5, - 82,0,0,282,284,7,2,0,0,283,278,1,0,0,0,283,281,1,0,0,0,284,47,1,0,0,0,285, - 286,5,26,0,0,286,287,5,14,0,0,287,288,5,79,0,0,288,289,5,6,0,0,289,292, - 3,76,38,0,290,291,5,15,0,0,291,293,3,66,33,0,292,290,1,0,0,0,292,293,1, - 0,0,0,293,294,1,0,0,0,294,295,5,16,0,0,295,49,1,0,0,0,296,297,5,26,0,0, - 297,298,5,14,0,0,298,301,3,76,38,0,299,300,5,15,0,0,300,302,3,66,33,0,301, - 299,1,0,0,0,301,302,1,0,0,0,302,303,1,0,0,0,303,304,5,16,0,0,304,51,1,0, - 0,0,305,306,5,27,0,0,306,307,3,70,35,0,307,53,1,0,0,0,308,309,5,28,0,0, - 309,310,5,14,0,0,310,311,3,76,38,0,311,312,5,16,0,0,312,315,3,30,15,0,313, - 314,5,29,0,0,314,316,3,30,15,0,315,313,1,0,0,0,315,316,1,0,0,0,316,55,1, - 0,0,0,317,321,3,58,29,0,318,321,3,60,30,0,319,321,3,62,31,0,320,317,1,0, - 0,0,320,318,1,0,0,0,320,319,1,0,0,0,321,57,1,0,0,0,322,323,5,30,0,0,323, - 324,3,30,15,0,324,325,5,31,0,0,325,326,5,14,0,0,326,327,3,76,38,0,327,328, - 5,16,0,0,328,329,5,2,0,0,329,59,1,0,0,0,330,331,5,31,0,0,331,332,5,14,0, - 0,332,333,3,76,38,0,333,334,5,16,0,0,334,335,3,30,15,0,335,61,1,0,0,0,336, - 337,5,32,0,0,337,338,5,14,0,0,338,339,3,64,32,0,339,340,5,2,0,0,340,341, - 3,76,38,0,341,342,5,2,0,0,342,343,3,46,23,0,343,344,5,16,0,0,344,345,3, - 30,15,0,345,63,1,0,0,0,346,349,3,42,21,0,347,349,3,46,23,0,348,346,1,0, - 0,0,348,347,1,0,0,0,349,65,1,0,0,0,350,351,5,76,0,0,351,67,1,0,0,0,352, - 355,5,82,0,0,353,355,3,80,40,0,354,352,1,0,0,0,354,353,1,0,0,0,355,69,1, - 0,0,0,356,368,5,14,0,0,357,362,3,68,34,0,358,359,5,15,0,0,359,361,3,68, - 34,0,360,358,1,0,0,0,361,364,1,0,0,0,362,360,1,0,0,0,362,363,1,0,0,0,363, - 366,1,0,0,0,364,362,1,0,0,0,365,367,5,15,0,0,366,365,1,0,0,0,366,367,1, - 0,0,0,367,369,1,0,0,0,368,357,1,0,0,0,368,369,1,0,0,0,369,370,1,0,0,0,370, - 371,5,16,0,0,371,71,1,0,0,0,372,373,5,82,0,0,373,374,3,74,37,0,374,73,1, - 0,0,0,375,387,5,14,0,0,376,381,3,76,38,0,377,378,5,15,0,0,378,380,3,76, - 38,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,15,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,16,0,0,390,75,1,0,0,0,391,392,6,38,-1,0,392,393,5,14,0,0,393,394, - 3,76,38,0,394,395,5,16,0,0,395,441,1,0,0,0,396,397,3,86,43,0,397,398,5, - 14,0,0,398,400,3,76,38,0,399,401,5,15,0,0,400,399,1,0,0,0,400,401,1,0,0, - 0,401,402,1,0,0,0,402,403,5,16,0,0,403,441,1,0,0,0,404,441,3,72,36,0,405, - 406,5,33,0,0,406,407,5,82,0,0,407,441,3,74,37,0,408,409,5,36,0,0,409,410, - 5,34,0,0,410,411,3,76,38,0,411,412,5,35,0,0,412,413,7,3,0,0,413,441,1,0, - 0,0,414,415,5,42,0,0,415,416,5,34,0,0,416,417,3,76,38,0,417,418,5,35,0, - 0,418,419,7,4,0,0,419,441,1,0,0,0,420,421,7,5,0,0,421,441,3,76,38,15,422, - 434,5,34,0,0,423,428,3,76,38,0,424,425,5,15,0,0,425,427,3,76,38,0,426,424, - 1,0,0,0,427,430,1,0,0,0,428,426,1,0,0,0,428,429,1,0,0,0,429,432,1,0,0,0, - 430,428,1,0,0,0,431,433,5,15,0,0,432,431,1,0,0,0,432,433,1,0,0,0,433,435, - 1,0,0,0,434,423,1,0,0,0,434,435,1,0,0,0,435,436,1,0,0,0,436,441,5,35,0, - 0,437,441,5,81,0,0,438,441,5,82,0,0,439,441,3,80,40,0,440,391,1,0,0,0,440, - 396,1,0,0,0,440,404,1,0,0,0,440,405,1,0,0,0,440,408,1,0,0,0,440,414,1,0, - 0,0,440,420,1,0,0,0,440,422,1,0,0,0,440,437,1,0,0,0,440,438,1,0,0,0,440, - 439,1,0,0,0,441,494,1,0,0,0,442,443,10,14,0,0,443,444,7,6,0,0,444,493,3, - 76,38,15,445,446,10,13,0,0,446,447,7,7,0,0,447,493,3,76,38,14,448,449,10, - 12,0,0,449,450,7,8,0,0,450,493,3,76,38,13,451,452,10,11,0,0,452,453,7,9, - 0,0,453,493,3,76,38,12,454,455,10,10,0,0,455,456,7,10,0,0,456,493,3,76, - 38,11,457,458,10,9,0,0,458,459,5,61,0,0,459,493,3,76,38,10,460,461,10,8, - 0,0,461,462,5,4,0,0,462,493,3,76,38,9,463,464,10,7,0,0,464,465,5,62,0,0, - 465,493,3,76,38,8,466,467,10,6,0,0,467,468,5,63,0,0,468,493,3,76,38,7,469, - 470,10,5,0,0,470,471,5,64,0,0,471,493,3,76,38,6,472,473,10,21,0,0,473,474, - 5,34,0,0,474,475,5,69,0,0,475,493,5,35,0,0,476,477,10,18,0,0,477,493,7, - 11,0,0,478,479,10,17,0,0,479,480,5,49,0,0,480,481,5,14,0,0,481,482,3,76, - 38,0,482,483,5,16,0,0,483,493,1,0,0,0,484,485,10,16,0,0,485,486,5,50,0, - 0,486,487,5,14,0,0,487,488,3,76,38,0,488,489,5,15,0,0,489,490,3,76,38,0, - 490,491,5,16,0,0,491,493,1,0,0,0,492,442,1,0,0,0,492,445,1,0,0,0,492,448, - 1,0,0,0,492,451,1,0,0,0,492,454,1,0,0,0,492,457,1,0,0,0,492,460,1,0,0,0, - 492,463,1,0,0,0,492,466,1,0,0,0,492,469,1,0,0,0,492,472,1,0,0,0,492,476, - 1,0,0,0,492,478,1,0,0,0,492,484,1,0,0,0,493,496,1,0,0,0,494,492,1,0,0,0, - 494,495,1,0,0,0,495,77,1,0,0,0,496,494,1,0,0,0,497,498,7,12,0,0,498,79, - 1,0,0,0,499,505,5,67,0,0,500,505,3,82,41,0,501,505,5,76,0,0,502,505,5,77, - 0,0,503,505,5,78,0,0,504,499,1,0,0,0,504,500,1,0,0,0,504,501,1,0,0,0,504, - 502,1,0,0,0,504,503,1,0,0,0,505,81,1,0,0,0,506,508,5,69,0,0,507,509,5,68, - 0,0,508,507,1,0,0,0,508,509,1,0,0,0,509,83,1,0,0,0,510,511,7,13,0,0,511, - 85,1,0,0,0,512,513,7,14,0,0,513,87,1,0,0,0,44,91,97,103,117,120,133,145, - 150,168,182,193,197,199,207,216,221,227,237,247,252,258,273,283,292,301, - 315,320,348,354,362,366,368,381,385,387,400,428,432,434,440,492,494,504, - 508]; + 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,8,5,8,146,8,8,10,8,12,8,149,9,8,1,8,1,8,3, + 8,153,8,8,1,8,1,8,1,9,1,9,1,9,1,9,1,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,17,17,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,156,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,16,8,0,133,136,3, + 18,9,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,5,12,0,0,138,139,5,82,0,0,139,152,3,26,13,0,140, + 141,5,13,0,0,141,142,5,14,0,0,142,147,3,86,43,0,143,144,5,15,0,0,144,146, + 3,86,43,0,145,143,1,0,0,0,146,149,1,0,0,0,147,145,1,0,0,0,147,148,1,0,0, + 0,148,150,1,0,0,0,149,147,1,0,0,0,150,151,5,16,0,0,151,153,1,0,0,0,152, + 140,1,0,0,0,152,153,1,0,0,0,153,154,1,0,0,0,154,155,3,24,12,0,155,17,1, + 0,0,0,156,157,3,86,43,0,157,158,5,17,0,0,158,159,5,82,0,0,159,160,5,10, + 0,0,160,161,3,78,39,0,161,162,5,2,0,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,12,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,14,0,0,190,195,3,28,14,0,191,192,5,15,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,15,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,16,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,15,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,15,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,14,0,0,278,281,3,46,23,0,279, + 280,5,15,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,16,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,14, + 0,0,306,307,5,79,0,0,307,308,5,6,0,0,308,311,3,78,39,0,309,310,5,15,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,16,0,0,314,51,1,0,0,0,315,316,5,26,0,0,316,317,5,14,0,0,317,320,3,78, + 39,0,318,319,5,15,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,16,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,14,0,0,329,330,3,78, + 39,0,330,331,5,16,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,14,0,0,345,346,3,78,39,0,346,347,5,16,0,0,347,348,5,2,0,0, + 348,61,1,0,0,0,349,350,5,31,0,0,350,351,5,14,0,0,351,352,3,78,39,0,352, + 353,5,16,0,0,353,354,3,30,15,0,354,63,1,0,0,0,355,356,5,32,0,0,356,357, + 5,14,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,16,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,14,0,0,376, + 381,3,70,35,0,377,378,5,15,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,15,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,16,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,14,0,0,395, + 400,3,78,39,0,396,397,5,15,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,15,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,16,0,0,409,77,1,0,0,0, + 410,411,6,39,-1,0,411,412,5,14,0,0,412,413,3,78,39,0,413,414,5,16,0,0,414, + 460,1,0,0,0,415,416,3,88,44,0,416,417,5,14,0,0,417,419,3,78,39,0,418,420, + 5,15,0,0,419,418,1,0,0,0,419,420,1,0,0,0,420,421,1,0,0,0,421,422,5,16,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,15,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,15,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,14,0,0,500,501,3,78,39,0,501,502,5,16,0,0,502, + 512,1,0,0,0,503,504,10,16,0,0,504,505,5,50,0,0,505,506,5,14,0,0,506,507, + 3,78,39,0,507,508,5,15,0,0,508,509,3,78,39,0,509,510,5,16,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,147,152,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 { @@ -3537,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 tupleTarget_list(): TupleTargetContext[] { + return this.getTypedRuleContexts(TupleTargetContext) as TupleTargetContext[]; } - public Identifier_list(): TerminalNode[] { - return this.getTokens(CashScriptParser.Identifier); - } - 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; @@ -3566,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) { diff --git a/packages/cashc/src/grammar/CashScriptVisitor.ts b/packages/cashc/src/grammar/CashScriptVisitor.ts index 187bf8c79..3c4d117bc 100644 --- a/packages/cashc/src/grammar/CashScriptVisitor.ts +++ b/packages/cashc/src/grammar/CashScriptVisitor.ts @@ -26,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"; @@ -207,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 b6921d3ba..851ae88ec 100644 --- a/packages/cashc/src/print/OutputSourceCodeTraversal.ts +++ b/packages/cashc/src/print/OutputSourceCodeTraversal.ts @@ -141,7 +141,9 @@ export default class OutputSourceCodeTraversal extends AstTraversal { } visitTupleAssignment(node: TupleAssignmentNode): Node { - const targets = node.targets.map((target) => `${target.type} ${target.name}`).join(', '); + const targets = node.targets + .map((target) => (target.isReassignment ? target.identifier.name : `${target.type} ${target.identifier.name}`)) + .join(', '); this.addOutput(`${targets} = `, true); this.visit(node.tuple); diff --git a/packages/cashc/src/semantic/SymbolTableTraversal.ts b/packages/cashc/src/semantic/SymbolTableTraversal.ts index 11c380a02..b27b2ebf9 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -29,6 +29,7 @@ import { UnusedVariableError, InvalidSymbolTypeError, ConstantModificationError, + DuplicateTupleTargetError, InvalidModifierError, } from '../Errors.js'; @@ -164,7 +165,7 @@ export default class SymbolTableTraversal extends AstTraversal { visitAssign(node: AssignNode): Node { const symbol = this.symbolTables[0].get(node.identifier.name); - if (symbol?.definition === undefined || symbol.definition instanceof FunctionDefinitionNode) { + if (!symbol) { throw new UndefinedReferenceError(node.identifier); } @@ -177,16 +178,29 @@ export default class SymbolTableTraversal extends AstTraversal { } visitTupleAssignment(node: TupleAssignmentNode): Node { - node.targets.forEach((variable) => { - const definition = createTupleVariableDefinition(node, variable); + const seenTargetNames = new Set(); + node.targets.forEach((target) => { + if (seenTargetNames.has(target.identifier.name)) { + throw new DuplicateTupleTargetError(node, target.identifier.name); + } + seenTargetNames.add(target.identifier.name); + + if (target.isReassignment) { + if (this.symbolTables[0].get(target.identifier.name)?.hasModifier(Modifier.CONSTANT)) { + throw new ConstantModificationError(node, target.identifier.name); + } + + target.identifier = this.visit(target.identifier) as IdentifierNode; + target.type = target.identifier.symbol!.type; + } else { + const definition = createTupleVariableDefinition(node, target); + + if (this.symbolTables[0].get(target.identifier.name)) { + throw new RedefinitionError(definition, target.identifier.name); + } - const { name } = variable; - if (this.symbolTables[0].get(name)) { - throw new RedefinitionError(definition, name); + this.symbolTables[0].set(Symbol.variable(definition)); } - this.symbolTables[0].set( - Symbol.variable(definition), - ); }); node.tuple = this.visit(node.tuple); @@ -273,9 +287,9 @@ function validateModifiers( function createTupleVariableDefinition( node: TupleAssignmentNode, - variable: TupleAssignmentTarget, + target: TupleAssignmentTarget, ): VariableDefinitionNode { - const definition = new VariableDefinitionNode(variable.type, [], variable.name, node.tuple); + const definition = new VariableDefinitionNode(target.type!, [], target.identifier.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 8a5af6637..b76a75db4 100644 --- a/packages/cashc/src/semantic/TypeCheckTraversal.ts +++ b/packages/cashc/src/semantic/TypeCheckTraversal.ts @@ -79,9 +79,9 @@ export default class TypeCheckTraversal extends AstTraversal { visitTupleAssignment(node: TupleAssignmentNode): Node { node.tuple = this.visit(node.tuple); - const targetsType = new TupleType(node.targets.map((target) => target.type)); + const targetsType = new TupleType(node.targets.map((target) => target.type!)); if (!implicitlyCastable(node.tuple.type, targetsType)) { - const targetNames = node.targets.map((target) => target.name).join(', '); + const targetNames = node.targets.map((target) => target.identifier.name).join(', '); const syntheticAssignment = new VariableDefinitionNode(targetsType, [], targetNames, node.tuple); syntheticAssignment.location = node.location; throw new AssignTypeError(syntheticAssignment); diff --git a/packages/cashc/test/ast/fixtures.ts b/packages/cashc/test/ast/fixtures.ts index 9cfd509a0..d3468bd9b 100644 --- a/packages/cashc/test/ast/fixtures.ts +++ b/packages/cashc/test/ast/fixtures.ts @@ -367,8 +367,8 @@ export const fixtures: Fixture[] = [ new BlockNode([ new TupleAssignmentNode( [ - { name: 'blockHeightBin', type: new BytesType(4) }, - { name: 'priceBin', type: new BytesType(4) }, + { identifier: new IdentifierNode('blockHeightBin'), type: new BytesType(4) }, + { identifier: new IdentifierNode('priceBin'), type: new BytesType(4) }, ], new BinaryOpNode( new IdentifierNode('oracleMessage'), 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 000000000..f439d5641 --- /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/DuplicateTupleTargetError/declaration_then_reassignment.cash b/packages/cashc/test/compiler/DuplicateTupleTargetError/declaration_then_reassignment.cash new file mode 100644 index 000000000..b1785eb5f --- /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 000000000..d4a721253 --- /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/tuple_reassign_unused.cash b/packages/cashc/test/compiler/InvalidModifierError/tuple_reassign_unused.cash new file mode 100644 index 000000000..37ae74cc0 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/tuple_reassign_unused.cash @@ -0,0 +1,13 @@ +function pair(int n) returns (int, int) { + return n + 1, n + 2; +} + +contract Test() { + function spend(int n, int unused pad) { + if (n > 0) { + (int q, pad) = pair(n); + require(q > 0); + } + require(n < 100); + } +} diff --git a/packages/cashc/test/compiler/UndefinedReferenceError/assign_to_builtin_name.cash b/packages/cashc/test/compiler/InvalidSymbolTypeError/assign_to_builtin_name.cash similarity index 100% rename from packages/cashc/test/compiler/UndefinedReferenceError/assign_to_builtin_name.cash rename to packages/cashc/test/compiler/InvalidSymbolTypeError/assign_to_builtin_name.cash diff --git a/packages/cashc/test/compiler/UndefinedReferenceError/assign_to_function_name.cash b/packages/cashc/test/compiler/InvalidSymbolTypeError/assign_to_function_name.cash similarity index 100% rename from packages/cashc/test/compiler/UndefinedReferenceError/assign_to_function_name.cash rename to packages/cashc/test/compiler/InvalidSymbolTypeError/assign_to_function_name.cash 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 000000000..572e098eb --- /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/ParseError/single_type_destructuring.cash b/packages/cashc/test/compiler/ParseError/single_type_destructuring.cash deleted file mode 100644 index 89afb1bfe..000000000 --- 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/UndefinedReferenceError/tuple_reassign_undefined.cash b/packages/cashc/test/compiler/UndefinedReferenceError/tuple_reassign_undefined.cash new file mode 100644 index 000000000..396dcf8ac --- /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/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts index 83301fcbf..7157acdc7 100644 --- a/packages/cashc/test/generation/fixtures.ts +++ b/packages/cashc/test/generation/fixtures.ts @@ -1876,4 +1876,138 @@ export const fixtures: Fixture[] = [ fingerprint: '4fcac7e0c885a2d3d6a344866c39c4febdffcaf9bb658ac08a87ed7dea9808b6', }, }, + { + // Tuple destructuring into existing variables inside branches. Scoped reassignment values are + // folded into the existing slots; a declaration value above a reassignment value is parked on + // the altstack while the fold runs (OP_TOALTSTACK ... OP_FROMALTSTACK in reassignmentFirst). + fn: 'tuple_reassignment_branches.cash', + artifact: { + contractName: 'TupleReassignmentBranches', + constructorInputs: [], + abi: [ + { name: 'declarationFirst', inputs: [{ name: 'a', type: 'int' }] }, + { name: 'reassignmentFirst', inputs: [{ name: 'a', type: 'int' }] }, + ], + bytecode: + // OP_DEFINE branchPair (id 0) — called from both functions, too large to inline + '7653957857979378529693768b7c52957b94 OP_0 OP_DEFINE ' + // function declarationFirst + + 'OP_DUP OP_0 OP_NUMEQUAL OP_IF ' + // int total = 0 + + 'OP_0 ' + // if (a > 10) + + 'OP_2 OP_PICK OP_10 OP_GREATERTHAN OP_IF ' + // int d, total = branchPair(a) — call, then fold total's value (top) into its slot; + // d's value stays in place (declarations-first needs no parking) + + 'OP_2 OP_PICK OP_0 OP_INVOKE OP_ROT OP_DROP OP_SWAP ' + // require(d != 0) + + 'OP_DUP OP_0 OP_NUMNOTEQUAL OP_VERIFY ' + // scope cleanup (drop d) + + 'OP_DROP OP_ENDIF ' + // require(total >= 0) + cleanup + + 'OP_0 OP_GREATERTHANOREQUAL OP_NIP OP_NIP ' + // function reassignmentFirst + + 'OP_ELSE OP_1 OP_NUMEQUALVERIFY ' + // int total = 0 + + 'OP_0 ' + // if (a > 10) + + 'OP_OVER OP_10 OP_GREATERTHAN OP_IF ' + // (total, int extra) = branchPair(a + 1) — call, park extra's value on the altstack, + // fold total's value into its slot (OP_NIP), restore extra's value + + 'OP_OVER OP_1ADD OP_0 OP_INVOKE OP_TOALTSTACK OP_NIP OP_FROMALTSTACK ' + // require(extra != 0) + + 'OP_DUP OP_0 OP_NUMNOTEQUAL OP_VERIFY ' + // scope cleanup (drop extra) + + 'OP_DROP OP_ENDIF ' + // require(total >= 0) + cleanup + + 'OP_0 OP_GREATERTHANOREQUAL OP_NIP OP_ENDIF', + debug: { + bytecode: '127653957857979378529693768b7c52957b94008976009c630052795aa0635279008a7b757c76009e69756800a2777767519d00785aa063788b008a6b776c76009e69756800a27768', + sourceMap: '7::10:1;;::::1;14:4:21:5:0;;;;15:20:15:21;16:12:16:13;;:16::18;:12:::1;:20:19:9:0;17:38:17:39;;:27::40:1;;:12::41;;;18:20:18:21:0;:25::26;:20:::1;:12::28;16:20:19:9;;20:25:20:26:0;:8::28:1;14:37:21:5;;:4;25::32::0;;26:20:26:21;27:12:27:13;:16::18;:12:::1;:20:30:9:0;28:44:28:45;:::49:1;:33::50;;:12::51;;;29:20:29:25:0;:29::30;:20:::1;:12::32;27:20:30:9;;31:25:31:26:0;:8::28:1;25:38:32:5;12:0:33:1', + logs: [], + requires: [ + { ip: 23, line: 18 }, + { ip: 28, line: 20 }, + { ip: 48, line: 29 }, + { ip: 53, line: 31 }, + ], + sourceTags: '24:24:sc;28:29:sc;49:49:sc;53:53:sc', + functions: [ + { + id: 0, + name: 'branchPair', + inputs: [{ name: 'x', type: 'int' }], + bytecode: '7653957857979378529693768b7c52957b94', + sourceMap: '8:12:8:13;:16::17;:12:::1;:21::22:0;:25::26;:21:::1;:12::27;:31::32:0;:35::36;:31:::1;:12::37;9:11:9:12:0;:::16:1;:18::19:0;:22::23;:18:::1;:26::27:0;:18:::1', + logs: [], + requires: [], + }, + ], + }, + source: fs.readFileSync(new URL('../valid-contract-files/tuple_reassignment_branches.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: 'da4982948327a26f2c708b13af6977715747aa0b5c64bc00b04e3ddbc11ca67d', + }, + }, + { + // Tuple destructuring into existing variables: top-level renames (with the small helpers + // inlined at the call sites), pure and mixed reassignment in loops, and the interleaved + // order that parks a declaration value on the altstack mid-fold. + fn: 'tuple_reassignment.cash', + artifact: { + contractName: 'TupleReassignment', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'seed', type: 'int' }] }], + bytecode: 'OP_DUP OP_1ADD OP_2DUP OP_SWAP OP_2DUP OP_SWAP OP_0 OP_BEGIN OP_DUP OP_4 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_SWAP OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_ROT OP_DROP OP_SWAP OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_0 OP_BEGIN OP_DUP OP_4 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_OVER OP_2 OP_PICK OP_MUL OP_1ADD OP_SWAP OP_ROT OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_OVER OP_2 OP_PICK OP_MUL OP_1ADD OP_SWAP OP_ROT OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_TOALTSTACK OP_ROT OP_DROP OP_SWAP OP_FROMALTSTACK OP_DUP OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_2DUP OP_ROT OP_ROT OP_ADD OP_ROT OP_ADD OP_ADD OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_2DROP OP_2DROP OP_1', + debug: { + bytecode: '768b6e7c6e7c006576549f766b637854797c557a757c6b7c6b7c6b7c6c6c6c7b757c768b77686c916675006576549f766b63785479785279958b7c7b567a757c6b7c6b7c6b7c6b7c6c6c6c6c537a757c6b7c6c7600a269788b7b7577686c916675006576529f766b63785479785279958b7c7b567a757c6b7c6b7c6b7c6b7c6c6c6c6c6b7b757c6c7600a269788b7b7577686c9166756e7b7b937b939300a2696d6d51', + sourceMap: '17:16:18:20;18:::24:1;21:22:21:26:0;:17::27:1;24:26:24:30:0;:21::31:1;27::27:22:0;:8:29:9;:24:27:25;:28::29;:24:::1;;;:42:29:9:0;28:26:28:27;:29::30;;:21::31:1;:12::32;;;;;;;;;;;;;;;;27:35:27:36:0;:::40:1;:31;:42:29:9;;:8;;;33:21:33:22:0;:8:36:9;:24:33:25;:28::29;:24:::1;;;:42:36:9:0;34:34:34:35;:37::38;;:29::39:1;;;;;;;:12::40;;;;;;;;;;;;;;;;;;;;;;;35:20:35:22:0;:26::27;:20:::1;:12::29;33:35:33:36:0;:::40:1;:31;;::36:9;:42;;:8;;;40:21:40:22:0;:8:43:9;:24:40:25;:28::29;:24:::1;;;:42:43:9:0;41:34:41:35;:37::38;;:29::39:1;;;;;;;:12::40;;;;;;;;;;;;;;;;;;;;;42:20:42:22:0;:26::27;:20:::1;:12::29;40:35:40:36:0;:::40:1;:31;;::43:9;:42;;:8;;;46:24:46:28:0;48:16:48:17;:20::21;:16:::1;:24::25:0;:16:::1;:::29;:33::34:0;:16:::1;:8::36;16:29:49:5;;', + logs: [], + requires: [ + { ip: 86, line: 35 }, + { ip: 139, line: 42 }, + { ip: 159, line: 48 }, + ], + sourceTags: '34:36:fu;37:40:lc;41:41:sc;87:91:fu;92:95:lc;96:96:sc;140:144:fu;145:148:lc;149:149:sc', + functions: [ + { + name: 'swap', + inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], + bytecode: '7c', + sourceMap: '7:14:7:15', + logs: [], + requires: [], + }, + { + name: 'step', + inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], + bytecode: '785279958b7c7b', + sourceMap: '12:11:12:12;:15::16;;:11:::1;:::20;:22::23:0;:25::26', + logs: [], + requires: [], + }, + ], + inlineRanges: '3:3:swap;5:5:swap;17:17:swap;53:59:step;108:114:step;151:151:swap', + }, + source: fs.readFileSync(new URL('../valid-contract-files/tuple_reassignment.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: '3ab69a954ec4bf9ceeb58eceb8ead206195032edf6627155eb82f528403c94dd', + }, + }, ]; 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 000000000..a1a80ffd1 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/tuple_reassignment.cash @@ -0,0 +1,50 @@ +// 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 + (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-first compiles smallest + // (the reassignment values fold straight off the top of the stack) + for (int j = 0; j < 4; j = j + 1) { + (int lo, a, b) = step(a, b); + require(lo >= 0); + } + + // interleaved order works too: the declaration value is parked on the altstack while the + // reassignment value below it folds into its slot + for (int k = 0; k < 2; k = k + 1) { + (a, int hi, b) = step(a, b); + require(hi >= 0); + } + + // reassignment before declaration, in the bare (unparenthesized) form + b, int d = swap(a, c); + + require(a + b + c + d >= 0); + } +} diff --git a/packages/cashc/test/valid-contract-files/tuple_reassignment_after_final_read.cash b/packages/cashc/test/valid-contract-files/tuple_reassignment_after_final_read.cash new file mode 100644 index 000000000..15a643f64 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/tuple_reassignment_after_final_read.cash @@ -0,0 +1,31 @@ +// Regression coverage: a scoped tuple reassignment is itself the variable's latest use, so the +// symbol pass must move the opRolls entry to it. Previously the last plain read kept the roll, +// codegen rolled the variable off the stack model at that read, and the reassignment crashed with +// a raw "Expected variable ... does not exist on the stack". + +function pair(int n) returns (int, int) { + return n * 2, n + 1; +} + +contract ReassignAfterFinalRead() { + function ifBranch(int x) { + int p = 10; + int q = 0; + require(p == 10); + if (x == 1) { + (p, q) = pair(x); + } + require(q == 0 || q == 2); + } + + function whileLoop(int x) { + int p = 10; + int q = 0; + require(p == 10); + while (x == 1) { + (p, q) = pair(x); + x = x + 1; + } + require(q == 0 || q == 2); + } +} diff --git a/packages/cashc/test/valid-contract-files/tuple_reassignment_branches.cash b/packages/cashc/test/valid-contract-files/tuple_reassignment_branches.cash new file mode 100644 index 000000000..f19f83281 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/tuple_reassignment_branches.cash @@ -0,0 +1,33 @@ +// Scoped tuple reassignment inside if-branches: the stack layout must be preserved, so +// reassignment values are folded into the existing variable slots (with altstack parking when a +// declaration value sits above a reassignment value). + +// Called from both contract functions and large enough that it is NOT inlined, so destructuring +// also covers results produced by an OP_INVOKE call (single-call functions are always inlined). +function branchPair(int x) returns (int, int) { + int t = x * 3 + (x % 7) + (x / 2); + return t + 1, t * 2 - x; +} + +contract TupleReassignmentBranches() { + // mixed declaration + reassignment inside a branch, declarations first: no parking needed + function declarationFirst(int a) { + int total = 0; + if (a > 10) { + int d, total = branchPair(a); + require(d != 0); + } + require(total >= 0); + } + + // reassignment before declaration inside a branch: the trailing declaration value is parked + // on the altstack while the reassignment value below it folds into its slot + function reassignmentFirst(int a) { + int total = 0; + if (a > 10) { + (total, int extra) = branchPair(a + 1); + require(extra != 0); + } + require(total >= 0); + } +} diff --git a/packages/utils/src/cashproof-optimisations.ts b/packages/utils/src/cashproof-optimisations.ts index 85181ce85..ddb5cf139 100644 --- a/packages/utils/src/cashproof-optimisations.ts +++ b/packages/utils/src/cashproof-optimisations.ts @@ -134,4 +134,6 @@ OP_LESSTHAN OP_NOT <=> OP_GREATERTHANOREQUAL; OP_GREATERTHAN OP_NOT <=> OP_LESSTHANOREQUAL; OP_LESSTHANOREQUAL OP_NOT <=> OP_GREATERTHAN; OP_GREATERTHANOREQUAL OP_NOT <=> OP_LESSTHAN; + +OP_TOALTSTACK OP_FROMALTSTACK <=> ; `; diff --git a/packages/utils/src/optimisations.ts b/packages/utils/src/optimisations.ts index e22e702f0..06d22f2aa 100644 --- a/packages/utils/src/optimisations.ts +++ b/packages/utils/src/optimisations.ts @@ -150,6 +150,9 @@ const unprovableOptimisations = [ ['OP_GREATERTHAN OP_NOT', 'OP_LESSTHANOREQUAL'], ['OP_LESSTHANOREQUAL OP_NOT', 'OP_GREATERTHAN'], ['OP_GREATERTHANOREQUAL OP_NOT', 'OP_LESSTHAN'], + + // This can get emitted by tuple destructuring + ['OP_TOALTSTACK OP_FROMALTSTACK', ''], ] as [string, string][]; // Note: we moved these optimisations into a single file, but kept the exact same order as before, diff --git a/website/docs/compiler/grammar.md b/website/docs/compiler/grammar.md index fa483f8bf..05a4fb8fc 100644 --- a/website/docs/compiler/grammar.md +++ b/website/docs/compiler/grammar.md @@ -103,7 +103,13 @@ variableDefinition ; tupleAssignment - : typeName Identifier ',' typeName Identifier '=' expression + : tupleTarget (',' tupleTarget)+ '=' expression + | '(' tupleTarget (',' tupleTarget)+ ')' '=' expression + ; + +tupleTarget + : typeName Identifier + | Identifier ; assignStatement diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index a60cf8ac6..4bec99458 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -133,6 +133,27 @@ contract Example() { } ``` +You can also destructure the return value into existing variables instead of declaring new ones: + +```solidity +function nextFib(int a, int b) returns (int, int) { + return b, a + b; +} + +contract Example() { + function spend(int fib5) { + int current = 0; + int next = 1; + for (int i = 0; i < 5; i = i + 1) { + (current, next) = nextFib(current, next); + } + require(current == fib5); + } +} +``` + +Declarations and reassignments can be mixed freely in a single destructuring (e.g. `(int fresh, current, next) = step(current, next);`). Inside loops and branches, listing declarations before reassignments compiles to slightly smaller bytecode. + :::info `checkSig`, `checkMultiSig` and `this.activeBytecode` cannot be used inside a user-defined function, since they would apply to the function body rather than the contract. Use them in a contract function instead (`checkDataSig` is allowed). ::: diff --git a/website/docs/language/types.md b/website/docs/language/types.md index cdcdf61fb..06c42f429 100644 --- a/website/docs/language/types.md +++ b/website/docs/language/types.md @@ -161,13 +161,15 @@ string cash = bitcoinCash.split(8)[1]; It is not supported to use a variable for the tupleIndex. Instead you can assign both sides of the tuple as shown below and use either element conditional on the value of the variable. ::: -It is also possible to assign both sides of the tuple at once with a destructuring syntax: +It is also possible to assign both sides of the tuple at once with a destructuring syntax, allowing both new variable declarations and reassignments: ```solidity string hello, string world = "Hello World".split(6); require(hello + "World" == "Hello " + world); ``` +Declarations and reassignments can be mixed freely in a single destructuring (e.g. `(bytes fresh, existing) = x.split(1);`). The target list may optionally be wrapped in parentheses. + ## Type Casting Type casting can be done both explicitly and implicitly depending on the type. `pubkey`, `sig` and `datasig` can be implicitly cast to `bytes`, meaning they can be used anywhere where you would normally use a `bytes` type. Explicit type casting can be done with a broader range of types, but is still limited. The syntax of this explicit type casting is illustrated below: diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 51d504564..92afce18e 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -13,6 +13,8 @@ title: Release Notes - :sparkles: Allow for simple arithmetic / concatenation operations in global constant definitions. - :sparkles: Add `unused` modifier for parameters or variables that are intentionally unused. - :sparkles: Add support for `import` directives to share user-defined functions across files. +- :sparkles: Resolve package imports (e.g. `import "pkg/math.cash"`) from `node_modules`, so contract libraries can be installed as npm packages. +- :sparkles: Add support for reassigning existing variables in tuple destructuring (e.g. `(a, b) = swap(a, b)`), optionally mixed with fresh declarations. - :hammer_and_wrench: Update `compileString` to take an optional `files` object for filesystem-free import resolution. - :racehorse: Inline global functions and constants when this is no larger than `OP_DEFINE`/`OP_INVOKE`. - :racehorse: Add new `OP_SWAP OP_MUL` optimisation. From 202ec4d2373c4386a81c5b82c2a006e8871daced Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 18 Aug 2026 10:50:37 +0200 Subject: [PATCH 22/37] Remove old bytecode optimisation --- .cspell.json | 1 - AGENTS.md | 2 +- DEVELOPMENT.md | 18 --- packages/cashc/src/compiler.ts | 9 -- .../cashc/test/cashproof/0.1.2=0.2.0.equiv | 111 -------------- .../cashc/test/cashproof/0.3.3=0.4.0.equiv | 32 ---- packages/cashc/test/cashproof/slice.equiv | 14 -- packages/utils/src/cashproof-optimisations.ts | 139 ------------------ packages/utils/src/optimisations.ts | 20 +-- packages/utils/src/script.ts | 52 ------- 10 files changed, 7 insertions(+), 391 deletions(-) delete mode 100644 packages/cashc/test/cashproof/0.1.2=0.2.0.equiv delete mode 100644 packages/cashc/test/cashproof/0.3.3=0.4.0.equiv delete mode 100644 packages/cashc/test/cashproof/slice.equiv delete mode 100644 packages/utils/src/cashproof-optimisations.ts diff --git a/.cspell.json b/.cspell.json index 4764b7ab6..3231913ce 100644 --- a/.cspell.json +++ b/.cspell.json @@ -36,7 +36,6 @@ "cashaddress", "cashc", "cashlibs", - "cashproof", "cashscript", "cashtokens", "castable", diff --git a/AGENTS.md b/AGENTS.md index 61233412c..3d84b4ba6 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -84,7 +84,7 @@ Shared between compiler and SDK: - `source-map.ts` — source map encoding/decoding (format: `sl:sc:el:ec:h` per opcode, `;`-separated, with field inheritance compression) - `bitauth-script.ts` — formats bytecode as human-readable BitAuth script (used in debugging) - `types.ts` — shared types including `SourceTagKind`, `SourceTagEntry` -- `optimisations.ts` / `cashproof-optimisations.ts` — peephole optimization rules +- `optimisations.ts` — peephole optimization rules ## Code Conventions diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index 95b52c5a6..a202d27ed 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -38,24 +38,6 @@ When updating the grammar file in `src/grammar/CashScript.g4`, we also need to m yarn antlr ``` -### Running `cashproof` - -Most of the bytecode optimisations that the `cashc` compiler uses can be verified for correctness using the [`cashproof` tool](https://github.com/EyeOfPython/cashproof). This tool needs to be installed separately by installing its dependencies using `pip` and cloning its repository from GitHub. - -From there, you can run `python [filenames]` to verify that the optimisations contained in these files are provably correct. - -Example: -```bash -python packages/cashc/test/cashproof/0.1.2=0.2.0.equiv -``` - -Note that if you want to run `cashproof` on the "main" CashScript optimisations file, you need to first extract the optimisations from the `cashc` compiler and save them in a separate file. This can be done using the following commands: - -```bash -cp packages/utils/src/cashproof-optimisations.ts opt.equiv && sed -i '' '/`/d' opt.equiv -python opt.equiv -``` - ## cashscript ### Running tests diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index 168c5bb99..6724d8c18 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -7,8 +7,6 @@ import { generateSourceTags, generateInlineRanges, optimiseBytecode, - optimiseBytecodeOld, - scriptToAsm, scriptToBytecode, sourceMapToLocationData, } from '@cashscript/utils'; @@ -139,7 +137,6 @@ function compileCode( ast = ast.accept(traversal) as Ast; // Bytecode optimisation - const optimisedBytecodeOld = optimiseBytecodeOld(traversal.output); const optimisationResult = optimiseBytecode( traversal.output, sourceMapToLocationData(traversal.sourceMap), @@ -150,12 +147,6 @@ 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'); - } - const debug = { bytecode: binToHex(scriptToBytecode(optimisationResult.script)), sourceMap: generateSourceMap(optimisationResult.locationData), diff --git a/packages/cashc/test/cashproof/0.1.2=0.2.0.equiv b/packages/cashc/test/cashproof/0.1.2=0.2.0.equiv deleted file mode 100644 index 99d2bf7f8..000000000 --- a/packages/cashc/test/cashproof/0.1.2=0.2.0.equiv +++ /dev/null @@ -1,111 +0,0 @@ -# This file includes several examples CashScript contracts as compiled with 0.1.2 and 0.2.0 -# to verify their equivalence. These Scripts contain the exact output as compiled by Cashc, -# except for the following changes: -# * "Default case" has been added to the 0.1.2 bytecode, as this was a vulnerability fix in 0.2.0 -# but we are only interested in the optimisation equivalence, so we simulate this fix for 0.1.2 -# * Final OP_1/0 has been changed to OP_TRUE/FALSE to play nice with CashProof type checking -# * Raw data has been prepended with 0x or changed to integer representation -# (CashScript hex-encodes numbers, CashProof expects decimal numbers, -# and assumes hex-encoded data is of the raw bytes type). - -!full_script=True; - -# P2PKH -# 12 opcount, 17 bytes -OP_1 OP_PICK OP_HASH160 OP_1 OP_PICK OP_EQUAL OP_VERIFY OP_2 OP_PICK OP_2 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_TRUE -<=> -# 4 opcount, 4 bytes -OP_OVER OP_HASH160 OP_EQUALVERIFY OP_CHECKSIG -# optimisation: opcount ~67%, bytes ~76% -; - -# TransferWithTimeout -# 31 opcount, 43 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_2 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_3 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_1 OP_PICK OP_CHECKSIG OP_VERIFY OP_2 OP_PICK OP_CHECKLOCKTIMEVERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -<=> -# 23 opcount, 31 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_4 OP_ROLL OP_ROT OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_ROLL OP_1 OP_NUMEQUAL OP_IF OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_DROP OP_TRUE OP_NIP OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -# optimisation: opcount ~26%, bytes ~28% -; - -# HodlVault -# 37 opcount, 52 bytes -OP_6 OP_PICK OP_4 OP_SPLIT OP_DROP OP_BIN2NUM OP_7 OP_PICK OP_4 OP_SPLIT OP_NIP OP_BIN2NUM OP_1 OP_PICK OP_5 OP_PICK OP_GREATERTHANOREQUAL OP_VERIFY OP_1 OP_PICK OP_CHECKLOCKTIMEVERIFY OP_DROP OP_0 OP_PICK OP_6 OP_PICK OP_GREATERTHANOREQUAL OP_VERIFY OP_7 OP_PICK OP_9 OP_PICK OP_5 OP_PICK OP_CHECKDATASIG OP_VERIFY OP_6 OP_PICK OP_3 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE -<=> -# 23 opcount, 32 bytes -OP_6 OP_PICK OP_4 OP_SPLIT OP_DROP OP_BIN2NUM OP_7 OP_PICK OP_4 OP_SPLIT OP_NIP OP_BIN2NUM OP_OVER OP_5 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_DROP OP_3 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY OP_3 OP_ROLL OP_4 OP_ROLL OP_3 OP_ROLL OP_CHECKDATASIGVERIFY OP_CHECKSIG -# optimisation: opcount ~38%, bytes ~38% -; - -# # Doesn't work yet -- CashProof doesn't fully support CMS yet -# # 2 of 3 Multisig -# # 12 opcount, 21 bytes -# OP_0 OP_3 OP_PICK OP_5 OP_PICK OP_2 OP_3 OP_PICK OP_5 OP_PICK OP_7 OP_PICK OP_3 OP_CHECKMULTISIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE -# <=> -# # 6 opcount, 12 bytes -# OP_0 OP_3 OP_ROLL OP_4 OP_ROLL OP_2 OP_3 OP_ROLL OP_2ROT OP_SWAP OP_3 OP_CHECKMULTISIG -# optimisation: opcount 50%, bytes ~43% -# ; - -# # Does prove, but this is very slow, so it's commented out -# # Zero-conf forfeits -# # 60 opcount, 83 bytes -# OP_2 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_3 OP_PICK OP_HASH160 OP_2 OP_PICK OP_EQUAL OP_VERIFY OP_4 OP_PICK OP_4 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_2 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_7 OP_PICK OP_HASH160 OP_1 OP_PICK OP_EQUAL OP_VERIFY OP_4 OP_PICK OP_7 OP_PICK OP_EQUAL OP_NOT OP_VERIFY OP_3 OP_PICK OP_SIZE OP_1 OP_SUB OP_SPLIT OP_DROP OP_5 OP_PICK OP_9 OP_PICK OP_CHECKDATASIG OP_VERIFY OP_5 OP_PICK OP_SIZE OP_1 OP_SUB OP_SPLIT OP_DROP OP_7 OP_PICK OP_9 OP_PICK OP_CHECKDATASIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -# <=> -# # 43 opcount, 52 bytes -# OP_2 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_3 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_2SWAP OP_CHECKSIG OP_NIP OP_NIP OP_ELSE OP_ROT OP_1 OP_NUMEQUAL OP_IF OP_6 OP_PICK OP_HASH160 OP_EQUALVERIFY OP_2 OP_PICK OP_5 OP_PICK OP_EQUAL OP_NOT OP_VERIFY OP_SWAP OP_SIZE OP_1SUB OP_SPLIT OP_DROP OP_ROT OP_5 OP_PICK OP_CHECKDATASIGVERIFY OP_SWAP OP_SIZE OP_1SUB OP_SPLIT OP_DROP OP_2SWAP OP_SWAP OP_CHECKDATASIG OP_NIP OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -# optimisation: opcount ~28%, bytes ~37% -# ; - -# HTLC -# 39 opcount, 53 bytes -OP_4 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_5 OP_PICK OP_SHA256 OP_4 OP_PICK OP_EQUAL OP_VERIFY OP_6 OP_PICK OP_2 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_4 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_2 OP_PICK OP_CHECKLOCKTIMEVERIFY OP_DROP OP_5 OP_PICK OP_1 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -<=> -# 28 opcount, 37 bytes -OP_4 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_5 OP_ROLL OP_SHA256 OP_4 OP_ROLL OP_EQUALVERIFY OP_4 OP_ROLL OP_ROT OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_4 OP_ROLL OP_1 OP_NUMEQUAL OP_IF OP_ROT OP_CHECKLOCKTIMEVERIFY OP_DROP OP_3 OP_ROLL OP_SWAP OP_CHECKSIG OP_NIP OP_NIP OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -# optimisation: opcount ~28%, bytes ~30% -; - -# Local.bitcoin.com -# 86 opcount, 128 bytes -OP_0 OP_8 OP_NUM2BIN OP_0 OP_8 OP_NUM2BIN OP_10 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_3 OP_PICK OP_2 OP_ROLL OP_DROP OP_SWAP OP_2 OP_PICK OP_1 OP_ROLL OP_DROP OP_ELSE OP_10 OP_PICK OP_2 OP_NUMEQUAL OP_IF OP_3 OP_PICK OP_2 OP_ROLL OP_DROP OP_SWAP OP_4 OP_PICK OP_1 OP_ROLL OP_DROP OP_ELSE OP_10 OP_PICK OP_3 OP_NUMEQUAL OP_IF OP_2 OP_PICK OP_2 OP_ROLL OP_DROP OP_SWAP OP_3 OP_PICK OP_1 OP_ROLL OP_DROP OP_ELSE OP_10 OP_PICK OP_4 OP_NUMEQUAL OP_IF OP_2 OP_PICK OP_2 OP_ROLL OP_DROP OP_SWAP OP_4 OP_PICK OP_1 OP_ROLL OP_DROP OP_ELSE OP_FALSE OP_VERIFY OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_9 OP_PICK OP_HASH160 OP_1 OP_PICK OP_EQUAL OP_VERIFY OP_7 OP_PICK OP_HASH160 OP_2 OP_PICK OP_EQUAL OP_VERIFY OP_5 OP_PICK OP_11 OP_PICK OP_8 OP_NUM2BIN OP_CAT OP_9 OP_PICK OP_1 OP_PICK OP_12 OP_PICK OP_CHECKDATASIG OP_VERIFY OP_7 OP_PICK OP_9 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE -<=> -# 60 opcount, 86 bytes -OP_0 OP_8 OP_NUM2BIN OP_0 OP_8 OP_NUM2BIN OP_10 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_2DROP OP_2DUP OP_ELSE OP_10 OP_PICK OP_2 OP_NUMEQUAL OP_IF OP_NIP OP_2 OP_PICK OP_SWAP OP_4 OP_PICK OP_NIP OP_ELSE OP_10 OP_PICK OP_3 OP_NUMEQUAL OP_IF OP_NIP OP_OVER OP_SWAP OP_3 OP_PICK OP_NIP OP_ELSE OP_10 OP_PICK OP_4 OP_NUMEQUAL OP_IF OP_NIP OP_OVER OP_SWAP OP_4 OP_PICK OP_NIP OP_ELSE OP_FALSE OP_VERIFY OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_9 OP_PICK OP_HASH160 OP_EQUALVERIFY OP_6 OP_PICK OP_HASH160 OP_EQUALVERIFY OP_3 OP_ROLL OP_8 OP_ROLL OP_8 OP_NUM2BIN OP_CAT OP_6 OP_ROLL OP_SWAP OP_7 OP_ROLL OP_CHECKDATASIGVERIFY OP_3 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG OP_NIP OP_NIP OP_NIP -# optimisation: opcount ~33%, bytes ~33% -; - -# Last Will -# 139 opcount, 207 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_SHA256 OP_RIPEMD160 OP_1 OP_PICK OP_EQUAL OP_VERIFY OP_5 OP_PICK OP_5 OP_PICK OP_CHECKSIG OP_VERIFY OP_6 OP_PICK OP_8 OP_PICK OP_CAT OP_9 OP_PICK OP_CAT OP_10 OP_PICK OP_CAT OP_11 OP_PICK OP_CAT OP_12 OP_PICK OP_CAT OP_13 OP_PICK OP_CAT OP_6 OP_PICK OP_SIZE OP_1 OP_SUB OP_SPLIT OP_DROP OP_1 OP_PICK OP_SHA256 OP_7 OP_PICK OP_CHECKDATASIG OP_VERIFY 1000 OP_11 OP_PICK OP_BIN2NUM OP_1 OP_PICK OP_SUB OP_8 OP_NUM2BIN 0x87 0xa9 0x14 0x17 OP_15 OP_PICK OP_1 OP_SPLIT OP_NIP 436800 OP_CHECKSEQUENCEVERIFY OP_DROP OP_14 OP_PICK OP_BIN2NUM OP_2 OP_GREATERTHANOREQUAL OP_VERIFY OP_5 OP_PICK OP_2 OP_PICK OP_CAT OP_4 OP_PICK OP_CAT OP_3 OP_PICK OP_CAT OP_1 OP_PICK OP_HASH160 OP_CAT OP_5 OP_PICK OP_CAT OP_HASH256 20 OP_PICK OP_EQUAL OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_3 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_HASH160 OP_2 OP_PICK OP_EQUAL OP_VERIFY OP_5 OP_PICK OP_5 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_3 OP_PICK OP_2 OP_NUMEQUAL OP_IF 15552000 OP_CHECKSEQUENCEVERIFY OP_DROP OP_4 OP_PICK OP_HASH160 OP_3 OP_PICK OP_EQUAL OP_VERIFY OP_5 OP_PICK OP_5 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF OP_ENDIF -<=> -# 102 opcount, 155 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_HASH160 OP_EQUALVERIFY OP_4 OP_PICK OP_4 OP_PICK OP_CHECKSIGVERIFY OP_5 OP_PICK OP_7 OP_ROLL OP_CAT OP_7 OP_PICK OP_CAT OP_8 OP_PICK OP_CAT OP_9 OP_ROLL OP_CAT OP_9 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_5 OP_ROLL OP_SIZE OP_1SUB OP_SPLIT OP_DROP OP_SWAP OP_SHA256 OP_5 OP_ROLL OP_CHECKDATASIGVERIFY 1000 OP_6 OP_ROLL OP_BIN2NUM OP_SWAP OP_SUB OP_8 OP_NUM2BIN 0x87 0xa9 0x14 0x17 OP_9 OP_ROLL OP_1 OP_SPLIT OP_NIP 436800 OP_CHECKSEQUENCEVERIFY OP_DROP OP_9 OP_ROLL OP_BIN2NUM OP_2 OP_GREATERTHANOREQUAL OP_VERIFY OP_5 OP_ROLL OP_ROT OP_CAT OP_3 OP_ROLL OP_CAT OP_ROT OP_CAT OP_SWAP OP_HASH160 OP_CAT OP_SWAP OP_CAT OP_HASH256 OP_4 OP_ROLL OP_EQUAL OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_4 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_ROLL OP_2 OP_NUMEQUAL OP_IF 15552000 OP_CHECKSEQUENCEVERIFY OP_DROP OP_3 OP_PICK OP_HASH160 OP_3 OP_ROLL OP_EQUALVERIFY OP_2SWAP OP_CHECKSIG OP_NIP OP_NIP OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF OP_ENDIF -# optimisation: opcount ~27%, bytes ~25% -; - -# Mecenas -# 177 opcount, 260 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_6 OP_PICK OP_SIZE OP_NIP OP_4 OP_NUMEQUAL OP_VERIFY OP_7 OP_PICK OP_SIZE OP_NIP 100 OP_NUMEQUAL OP_VERIFY OP_9 OP_PICK OP_SIZE OP_NIP OP_8 OP_NUMEQUAL OP_VERIFY OP_10 OP_PICK OP_SIZE OP_NIP OP_4 OP_NUMEQUAL OP_VERIFY OP_10 OP_PICK OP_SIZE OP_NIP 32 OP_NUMEQUAL OP_VERIFY OP_12 OP_PICK OP_SIZE OP_NIP OP_8 OP_NUMEQUAL OP_VERIFY OP_5 OP_PICK OP_5 OP_PICK OP_CHECKSIG OP_VERIFY OP_6 OP_PICK OP_8 OP_PICK OP_CAT OP_9 OP_PICK OP_CAT OP_10 OP_PICK OP_CAT OP_11 OP_PICK OP_CAT OP_12 OP_PICK OP_CAT OP_13 OP_PICK OP_CAT OP_6 OP_PICK OP_SIZE OP_1 OP_SUB OP_SPLIT OP_DROP OP_1 OP_PICK OP_SHA256 OP_7 OP_PICK OP_CHECKDATASIG OP_VERIFY 1000 OP_4 OP_PICK OP_8 OP_NUM2BIN OP_12 OP_PICK OP_BIN2NUM OP_6 OP_PICK OP_SUB OP_2 OP_PICK OP_SUB OP_8 OP_NUM2BIN 0x76 0x87 0xa9 0x14 0x17 0x19 0x88 0xac 20 OP_PICK OP_3 OP_SPLIT OP_NIP 2700000 OP_CHECKSEQUENCEVERIFY OP_DROP 19 OP_PICK OP_BIN2NUM OP_2 OP_GREATERTHANOREQUAL OP_VERIFY OP_9 OP_PICK OP_5 OP_PICK OP_CAT OP_7 OP_PICK OP_CAT OP_6 OP_PICK OP_CAT OP_1 OP_PICK OP_HASH160 OP_CAT OP_8 OP_PICK OP_CAT OP_11 OP_PICK OP_5 OP_PICK OP_CAT OP_10 OP_PICK OP_CAT OP_8 OP_PICK OP_CAT OP_7 OP_PICK OP_CAT OP_15 OP_PICK OP_CAT OP_4 OP_PICK OP_CAT OP_3 OP_PICK OP_CAT OP_1 OP_PICK OP_1 OP_PICK OP_CAT OP_HASH256 27 OP_PICK OP_SHA256 OP_EQUAL OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_3 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_HASH160 OP_2 OP_PICK OP_EQUAL OP_VERIFY OP_5 OP_PICK OP_5 OP_PICK OP_CHECKSIG OP_VERIFY OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_DROP OP_TRUE OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -<=> -# 131 opcount, 207 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_6 OP_PICK OP_SIZE OP_NIP OP_4 OP_NUMEQUALVERIFY OP_7 OP_PICK OP_SIZE OP_NIP 100 OP_NUMEQUALVERIFY OP_9 OP_PICK OP_SIZE OP_NIP OP_8 OP_NUMEQUALVERIFY OP_10 OP_PICK OP_SIZE OP_NIP OP_4 OP_NUMEQUALVERIFY OP_10 OP_PICK OP_SIZE OP_NIP 32 OP_NUMEQUALVERIFY OP_12 OP_PICK OP_SIZE OP_NIP OP_8 OP_NUMEQUALVERIFY OP_5 OP_PICK OP_5 OP_PICK OP_CHECKSIGVERIFY OP_6 OP_PICK OP_8 OP_ROLL OP_CAT OP_8 OP_PICK OP_CAT OP_9 OP_PICK OP_CAT OP_10 OP_ROLL OP_CAT OP_10 OP_PICK OP_CAT OP_11 OP_ROLL OP_CAT OP_6 OP_ROLL OP_SIZE OP_1SUB OP_SPLIT OP_DROP OP_SWAP OP_SHA256 OP_6 OP_ROLL OP_CHECKDATASIGVERIFY 1000 OP_3 OP_PICK OP_8 OP_NUM2BIN OP_8 OP_ROLL OP_BIN2NUM OP_5 OP_ROLL OP_SUB OP_ROT OP_SUB OP_8 OP_NUM2BIN 0x76 0x87 0xa9 0x14 0x17 0x19 0x88 0xac OP_14 OP_ROLL OP_3 OP_SPLIT OP_NIP 2700000 OP_CHECKSEQUENCEVERIFY OP_DROP OP_14 OP_ROLL OP_BIN2NUM OP_2 OP_GREATERTHANOREQUAL OP_VERIFY OP_9 OP_ROLL OP_5 OP_ROLL OP_CAT OP_6 OP_PICK OP_CAT OP_5 OP_PICK OP_CAT OP_SWAP OP_HASH160 OP_CAT OP_6 OP_ROLL OP_CAT OP_7 OP_ROLL OP_4 OP_ROLL OP_CAT OP_6 OP_ROLL OP_CAT OP_5 OP_ROLL OP_CAT OP_4 OP_ROLL OP_CAT OP_4 OP_ROLL OP_CAT OP_3 OP_ROLL OP_CAT OP_ROT OP_CAT OP_CAT OP_HASH256 OP_3 OP_ROLL OP_SHA256 OP_EQUAL OP_NIP OP_NIP OP_ELSE OP_3 OP_ROLL OP_1 OP_NUMEQUAL OP_IF OP_3 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_2SWAP OP_CHECKSIG OP_NIP OP_NIP OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -# optimisation: opcount ~26%, bytes ~20% -; - -# Avg unoptimised opcount: 593 / 9 ≈ 65.89 -# Avg unoptimised bytes: 864 / 9 = 96 - -# Avg optimised opcount: 420 / 9 ≈ 46.67 -# Avg optimised bytes: 616 / 9 ≈ 68.44 - -# Avg opcount optimisation: (56.75 - 39.75) / 56.75 ≈ 29% -# Avg bytes optimisation: (96 - 68.44) / 96 ≈ 29% - -# Min optimisation (Mecenas): -# opcount: 177 -> 131 (~26%) -# bytes: 250 -> 207 (~20%) - -# Max optimisation (P2PKH): -# opcount: 12 -> 4 (~67%) -# bytes: 17 -> 4 (~76%) diff --git a/packages/cashc/test/cashproof/0.3.3=0.4.0.equiv b/packages/cashc/test/cashproof/0.3.3=0.4.0.equiv deleted file mode 100644 index a6569563d..000000000 --- a/packages/cashc/test/cashproof/0.3.3=0.4.0.equiv +++ /dev/null @@ -1,32 +0,0 @@ -!full_script=True; - - -# THIS CASHPROOF FAILS DUE TO THE NUMEQUALVERIFY OPTIMISATION MAKING THE IF-STATEMENTS -# NOT EQUIVALENT. I'M STILL COMMITTING THIS FILE FOR REFERENCE. - -# TransferWithTimeout -# 22 opcount, 31 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_4 OP_ROLL OP_ROT OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_ROLL OP_1 OP_NUMEQUAL OP_IF OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_2DROP OP_TRUE OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -<=> -# 19 opcount, 26 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_4 OP_ROLL OP_ROT OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_2DROP OP_TRUE OP_ENDIF -# optimisation: opcount ~14%, bytes ~16% -; - -# HTLC -# 28 opcount, 37 bytes -OP_4 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_5 OP_ROLL OP_SHA256 OP_4 OP_ROLL OP_EQUALVERIFY OP_4 OP_ROLL OP_ROT OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_4 OP_ROLL OP_1 OP_NUMEQUAL OP_IF OP_ROT OP_CHECKLOCKTIMEVERIFY OP_DROP OP_3 OP_ROLL OP_SWAP OP_CHECKSIG OP_NIP OP_NIP OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF -<=> -# 25 opcount, 33 bytes -OP_4 OP_PICK OP_0 OP_NUMEQUAL OP_IF OP_5 OP_ROLL OP_SHA256 OP_4 OP_ROLL OP_EQUALVERIFY OP_4 OP_ROLL OP_ROT OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_4 OP_ROLL OP_1 OP_NUMEQUALVERIFY OP_ROT OP_CHECKLOCKTIMEVERIFY OP_DROP OP_3 OP_ROLL OP_SWAP OP_CHECKSIG OP_NIP OP_NIP OP_ENDIF -# optimisation: opcount ~11%, bytes ~11% -; - -# Last Will -# 87 opcount, 131 bytes -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF 15552000 OP_CHECKSEQUENCEVERIFY OP_DROP OP_4 OP_PICK OP_HASH160 OP_3 OP_ROLL OP_EQUALVERIFY OP_4 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_4 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_ROLL OP_2 OP_NUMEQUAL OP_IF OP_3 OP_PICK 105 OP_SPLIT OP_NIP OP_SIZE 52 OP_SUB OP_SPLIT OP_8 OP_SPLIT OP_4 OP_SPLIT OP_NIP 32 OP_SPLIT OP_DROP OP_7 OP_PICK OP_HASH160 OP_4 OP_ROLL OP_EQUALVERIFY OP_7 OP_ROLL OP_7 OP_ROLL OP_2DUP OP_SWAP OP_SIZE OP_1SUB OP_SPLIT OP_DROP OP_9 OP_ROLL OP_SHA256 OP_ROT OP_CHECKDATASIGVERIFY OP_CHECKSIGVERIFY 1000 OP_ROT OP_BIN2NUM OP_SWAP OP_SUB OP_8 OP_NUM2BIN 0x17a914 OP_CAT OP_ROT OP_HASH160 OP_CAT 0x87 OP_CAT OP_HASH256 OP_EQUAL OP_NIP OP_NIP OP_ELSE OP_FALSE OP_ENDIF OP_ENDIF OP_ENDIF -<=> -# 83 opcount, 124 -OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF 15552000 OP_CHECKSEQUENCEVERIFY OP_DROP OP_4 OP_PICK OP_HASH160 OP_3 OP_ROLL OP_EQUALVERIFY OP_4 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_PICK OP_1 OP_NUMEQUAL OP_IF OP_4 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY OP_4 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_ROLL OP_2 OP_NUMEQUALVERIFY OP_3 OP_PICK 105 OP_SPLIT OP_NIP OP_SIZE 52 OP_SUB OP_SPLIT OP_8 OP_SPLIT OP_4 OP_SPLIT OP_NIP 32 OP_SPLIT OP_DROP OP_7 OP_PICK OP_HASH160 OP_4 OP_ROLL OP_EQUALVERIFY OP_7 OP_ROLL OP_7 OP_ROLL OP_2DUP OP_SWAP OP_SIZE OP_1SUB OP_SPLIT OP_DROP OP_9 OP_ROLL OP_SHA256 OP_ROT OP_CHECKDATASIGVERIFY OP_CHECKSIGVERIFY 1000 OP_ROT OP_BIN2NUM OP_SWAP OP_SUB OP_8 OP_NUM2BIN 0x17a914 OP_CAT OP_ROT OP_HASH160 OP_CAT 0x87 OP_CAT OP_HASH256 OP_EQUAL OP_NIP OP_NIP OP_ENDIF OP_ENDIF -# optimisation: opcount ~5%, bytes ~5% -; diff --git a/packages/cashc/test/cashproof/slice.equiv b/packages/cashc/test/cashproof/slice.equiv deleted file mode 100644 index e16364cb0..000000000 --- a/packages/cashc/test/cashproof/slice.equiv +++ /dev/null @@ -1,14 +0,0 @@ -!full_script=True; - -# We are unable to run cashproof any more due to Python ecosystem issues, but we're including this file for reference. - -# x.slice(10, 25) & x.split(25)[0].split(10)[1] -25 OP_SPLIT OP_DROP OP_10 OP_SPLIT OP_NIP -<=> -# x.split(10)[1].split(15)[0] -OP_10 OP_SPLIT OP_NIP OP_15 OP_SPLIT OP_DROP -; - -# Slice optimisation -OP_0 OP_SPLIT OP_NIP <=> ; -OP_SIZE OP_SPLIT OP_DROP <=> ; diff --git a/packages/utils/src/cashproof-optimisations.ts b/packages/utils/src/cashproof-optimisations.ts deleted file mode 100644 index ddb5cf139..000000000 --- a/packages/utils/src/cashproof-optimisations.ts +++ /dev/null @@ -1,139 +0,0 @@ -export default ` -# This file can be run with CashProof to prove that the optimisations preserve exact functionality -# This includes most of CashScript's bytecode optimisations, although some are incompatible with CashProof - -# Hardcoded arithmetic -# OP_NOT OP_IF <=> OP_NOTIF; -OP_1 OP_ADD <=> OP_1ADD; -OP_1 OP_SUB <=> OP_1SUB; -OP_1 OP_NEGATE <=> OP_1NEGATE; -OP_0 OP_NUMEQUAL OP_NOT <=> OP_0NOTEQUAL; -OP_NUMEQUAL OP_NOT <=> OP_NUMNOTEQUAL; -OP_SHA256 OP_SHA256 <=> OP_HASH256; -OP_SHA256 OP_RIPEMD160 <=> OP_HASH160; - -# Hardcoded stack ops -OP_2 OP_PICK OP_1 OP_PICK OP_3 OP_PICK <=> OP_3DUP OP_SWAP; -OP_2 OP_PICK OP_2 OP_PICK OP_2 OP_PICK <=> OP_3DUP; - -OP_0 OP_PICK OP_2 OP_PICK <=> OP_2DUP OP_SWAP; -OP_2 OP_PICK OP_4 OP_PICK <=> OP_2OVER OP_SWAP; -OP_3 OP_PICK OP_3 OP_PICK <=> OP_2OVER; - -OP_2 OP_ROLL OP_3 OP_ROLL <=> OP_2SWAP OP_SWAP; -OP_3 OP_ROLL OP_3 OP_ROLL <=> OP_2SWAP; -OP_4 OP_ROLL OP_5 OP_ROLL <=> OP_2ROT OP_SWAP; -OP_5 OP_ROLL OP_5 OP_ROLL <=> OP_2ROT; - -OP_0 OP_PICK <=> OP_DUP; -OP_1 OP_PICK <=> OP_OVER; -OP_0 OP_ROLL <=> ; -OP_1 OP_ROLL <=> OP_SWAP; -OP_2 OP_ROLL <=> OP_ROT; -OP_DROP OP_DROP <=> OP_2DROP; - -# Secondary effects -OP_DUP OP_SWAP <=> OP_DUP; -OP_SWAP OP_SWAP <=> ; -OP_2SWAP OP_2SWAP <=> ; -OP_ROT OP_ROT OP_ROT <=> ; -OP_2ROT OP_2ROT OP_2ROT <=> ; -OP_OVER OP_OVER <=> OP_2DUP; -OP_DUP OP_DROP <=> ; -OP_DUP OP_NIP <=> ; - -# Enabling secondary effects -OP_DUP OP_OVER <=> OP_DUP OP_DUP; - -# Merge OP_VERIFY -OP_EQUAL OP_VERIFY <=> OP_EQUALVERIFY; -OP_NUMEQUAL OP_VERIFY <=> OP_NUMEQUALVERIFY; -OP_CHECKSIG OP_VERIFY <=> OP_CHECKSIGVERIFY; -# OP_CHECKMULTISIG OP_VERIFY <=> OP_CHECKMULTISIGVERIFY; -OP_CHECKDATASIG OP_VERIFY <=> OP_CHECKDATASIGVERIFY; - -# Remove/replace extraneous OP_SWAP -# OP_SWAP OP_AND <=> OP_AND; -# OP_SWAP OP_OR <=> OP_OR; -# OP_SWAP OP_XOR <=> OP_XOR; -OP_SWAP OP_ADD <=> OP_ADD; -OP_SWAP OP_MUL <=> OP_MUL; -OP_SWAP OP_EQUAL <=> OP_EQUAL; -OP_SWAP OP_NUMEQUAL <=> OP_NUMEQUAL; -OP_SWAP OP_NUMNOTEQUAL <=> OP_NUMNOTEQUAL; -OP_SWAP OP_GREATERTHANOREQUAL <=> OP_LESSTHANOREQUAL; -OP_SWAP OP_LESSTHANOREQUAL <=> OP_GREATERTHANOREQUAL; -OP_SWAP OP_GREATERTHAN <=> OP_LESSTHAN; -OP_SWAP OP_LESSTHAN <=> OP_GREATERTHAN; -OP_SWAP OP_DROP <=> OP_NIP; -OP_SWAP OP_NIP <=> OP_DROP; - -# Remove/replace extraneous OP_DUP -# OP_DUP OP_AND <=> ; -# OP_DUP OP_OR <=> ; -OP_DUP OP_DROP <=> ; -OP_DUP OP_NIP <=> ; - -# Random optimisations (don't know what I'm targeting with this) -OP_2DUP OP_DROP <=> OP_OVER; -OP_2DUP OP_NIP <=> OP_DUP; -OP_CAT OP_DROP <=> OP_2DROP; -OP_NIP OP_DROP <=> OP_2DROP; - -# Far-fetched stuff -OP_DUP OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_OVER OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_2 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_3 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_4 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_5 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_6 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_7 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_8 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_9 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_10 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_11 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_12 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_13 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_14 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_15 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; -OP_16 OP_PICK OP_ROT OP_SWAP OP_DROP <=> OP_SWAP; - -OP_DUP OP_ROT OP_DROP <=> OP_NIP OP_DUP; -OP_OVER OP_ROT OP_DROP <=> OP_SWAP; -OP_2 OP_PICK OP_ROT OP_DROP <=> OP_NIP OP_OVER; - -OP_0 OP_NIP <=> OP_DROP OP_0; -OP_1 OP_NIP <=> OP_DROP OP_1; -OP_2 OP_NIP <=> OP_DROP OP_2; -OP_3 OP_NIP <=> OP_DROP OP_3; -OP_4 OP_NIP <=> OP_DROP OP_4; -OP_5 OP_NIP <=> OP_DROP OP_5; -OP_6 OP_NIP <=> OP_DROP OP_6; -OP_7 OP_NIP <=> OP_DROP OP_7; -OP_8 OP_NIP <=> OP_DROP OP_8; -OP_9 OP_NIP <=> OP_DROP OP_9; -OP_10 OP_NIP <=> OP_DROP OP_10; -OP_11 OP_NIP <=> OP_DROP OP_11; -OP_12 OP_NIP <=> OP_DROP OP_12; -OP_13 OP_NIP <=> OP_DROP OP_13; -OP_14 OP_NIP <=> OP_DROP OP_14; -OP_15 OP_NIP <=> OP_DROP OP_15; -OP_16 OP_NIP <=> OP_DROP OP_16; - -OP_2 OP_PICK OP_SWAP OP_2 OP_PICK OP_NIP <=> OP_DROP OP_2DUP; - -# .slice(0, x) optimisation & .slice(x, y.length) optimisation -OP_0 OP_SPLIT OP_NIP <=> ; -OP_SIZE OP_SPLIT OP_DROP <=> ; - -# These are new optimisations that we cannot prove since CashProof doesn't work any more -# ////////////////////////////////////////////////////////////////////////////////////// - -OP_LESSTHAN OP_NOT <=> OP_GREATERTHANOREQUAL; -OP_GREATERTHAN OP_NOT <=> OP_LESSTHANOREQUAL; -OP_LESSTHANOREQUAL OP_NOT <=> OP_GREATERTHAN; -OP_GREATERTHANOREQUAL OP_NOT <=> OP_LESSTHAN; - -OP_TOALTSTACK OP_FROMALTSTACK <=> ; -`; diff --git a/packages/utils/src/optimisations.ts b/packages/utils/src/optimisations.ts index 06d22f2aa..22d399256 100644 --- a/packages/utils/src/optimisations.ts +++ b/packages/utils/src/optimisations.ts @@ -1,4 +1,6 @@ -const provableOptimisations = [ +// Note: the order in which these optimisations are applied can impact the output, so entries should +// not be reordered without carefully verifying the compiled bytecode of existing contracts. +export const optimisationReplacements = [ // Hardcoded arithmetic ['OP_1 OP_ADD', 'OP_1ADD'], ['OP_1 OP_SUB', 'OP_1SUB'], @@ -119,33 +121,27 @@ const provableOptimisations = [ // .slice(0, x) optimisation & .slice(x, y.length) optimisation ['OP_0 OP_SPLIT OP_NIP', ''], ['OP_SIZE OP_SPLIT OP_DROP', ''], -] as [string, string][]; -const unprovableOptimisations = [ // Hardcoded arithmetic - // CashProof can't prove OP_IF without parameters ['OP_NOT OP_IF', 'OP_NOTIF'], + // Merge OP_VERIFY - // CashProof can't prove OP_CHECKMULTISIG without specifying N ['OP_CHECKMULTISIG OP_VERIFY', 'OP_CHECKMULTISIGVERIFY'], + // Remove/replace extraneous OP_SWAP - // CashProof can't prove bitwise operators ['OP_SWAP OP_AND', 'OP_AND'], ['OP_SWAP OP_OR', 'OP_OR'], ['OP_SWAP OP_XOR', 'OP_XOR'], // Remove/replace extraneous OP_DUP - // CashProof can't prove bitwise operators ['OP_DUP OP_AND', ''], ['OP_DUP OP_OR', ''], - // These are new optimisations that we cannot prove since CashProof doesn't work any more - // ////////////////////////////////////////////////////////////////////////////////////// - // TODO: Enable this optimisation when we overhaul the type system // (right now bool(4) == true => false, but !!bool(4) == true => true) so can't replace OP_NOT OP_NOT with '' // ['OP_NOT OP_NOT', ''] + // Invert comparison operators instead of negating them ['OP_LESSTHAN OP_NOT', 'OP_GREATERTHANOREQUAL'], ['OP_GREATERTHAN OP_NOT', 'OP_LESSTHANOREQUAL'], ['OP_LESSTHANOREQUAL OP_NOT', 'OP_GREATERTHAN'], @@ -154,7 +150,3 @@ const unprovableOptimisations = [ // This can get emitted by tuple destructuring ['OP_TOALTSTACK OP_FROMALTSTACK', ''], ] as [string, string][]; - -// Note: we moved these optimisations into a single file, but kept the exact same order as before, -// because the order in which optimisations are applied can impact the output. -export const optimisationReplacements = [...provableOptimisations, ...unprovableOptimisations]; diff --git a/packages/utils/src/script.ts b/packages/utils/src/script.ts index 4d114a5ee..e82a8b184 100644 --- a/packages/utils/src/script.ts +++ b/packages/utils/src/script.ts @@ -8,7 +8,6 @@ import { OpcodesBch, AuthenticationInstruction, } from '@bitauth/libauth'; -import OptimisationsEquivFile from './cashproof-optimisations.js'; import { optimisationReplacements } from './optimisations.js'; import { range } from './data.js'; import { FullLocationData, PositionHint, SingleLocationData, SourceTagEntry, SourceTagKind } from './types.js'; @@ -222,57 +221,6 @@ function reconcileScopeCleanupTags(script: Script, sourceTags: SourceTagEntry[]) }); } -export function optimiseBytecodeOld(script: Script, runs: number = 1000): Script { - const optimisations = OptimisationsEquivFile - // Split by line and filter all line comments (#) - .split('\n') - .map((equiv) => equiv.trim()) - .filter((equiv) => !equiv.startsWith('#')) - // Join back the lines, and split on semicolon - .join('') - .split(';') - // Parse all optimisations in .equiv file - .map((equiv) => equiv.trim()) - .map((equiv) => equiv.split('<=>').map((part) => part.trim())) - .filter((equiv) => equiv.length === 2); - - for (let i = 0; i < runs; i += 1) { - const oldScript = script; - script = replaceOpsOld(script, optimisations); - - // Break on fixed point - if (scriptToAsm(oldScript) === scriptToAsm(script)) break; - } - - return script; -} - -function replaceOpsOld(script: Script, optimisations: string[][]): Script { - let asm = scriptToAsm(script); - - // Apply all optimisations in the cashproof file - optimisations.forEach(([pattern, replacement]) => { - asm = asm.replace(new RegExp(pattern, 'g'), replacement); - }); - - // Add optimisations that are not compatible with CashProof - // CashProof can't prove OP_IF without parameters - asm = asm.replace(/OP_NOT OP_IF/g, 'OP_NOTIF'); - // CashProof can't prove OP_CHECKMULTISIG without specifying N - asm = asm.replace(/OP_CHECKMULTISIG OP_VERIFY/g, 'OP_CHECKMULTISIGVERIFY'); - // CashProof can't prove bitwise operators - asm = asm.replace(/OP_SWAP OP_AND/g, 'OP_AND'); - asm = asm.replace(/OP_SWAP OP_OR/g, 'OP_OR'); - asm = asm.replace(/OP_SWAP OP_XOR/g, 'OP_XOR'); - asm = asm.replace(/OP_DUP OP_AND/g, ''); - asm = asm.replace(/OP_DUP OP_OR/g, ''); - - // Remove any double spaces as a result of opcode removal - asm = asm.replace(/\s+/g, ' ').trim(); - - return asmToScript(asm); -} - interface ReplaceOpsResult { script: Script; locationData: FullLocationData; From 0a48bbc9879856cc1422dc52bf61af05a3718cfa Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 18 Aug 2026 11:07:35 +0200 Subject: [PATCH 23/37] Add safe OP_NOT OP_NOT optimisations --- packages/utils/src/optimisations.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/utils/src/optimisations.ts b/packages/utils/src/optimisations.ts index 22d399256..fb52c677c 100644 --- a/packages/utils/src/optimisations.ts +++ b/packages/utils/src/optimisations.ts @@ -137,10 +137,6 @@ export const optimisationReplacements = [ ['OP_DUP OP_AND', ''], ['OP_DUP OP_OR', ''], - // TODO: Enable this optimisation when we overhaul the type system - // (right now bool(4) == true => false, but !!bool(4) == true => true) so can't replace OP_NOT OP_NOT with '' - // ['OP_NOT OP_NOT', ''] - // Invert comparison operators instead of negating them ['OP_LESSTHAN OP_NOT', 'OP_GREATERTHANOREQUAL'], ['OP_GREATERTHAN OP_NOT', 'OP_LESSTHANOREQUAL'], @@ -149,4 +145,12 @@ export const optimisationReplacements = [ // This can get emitted by tuple destructuring ['OP_TOALTSTACK OP_FROMALTSTACK', ''], + + // unsafe_bool(4) == true => false, but !!unsafe_bool(4) == true => true) so we can't replace OP_NOT OP_NOT with '' + // in the general case, but when it is followed by a consuming instruction that does not differentiate between + // true and truthy values (e.g. OP_IF, OP_UNTIL, OP_VERIFY), we can replace OP_NOT OP_NOT with '' + // Note that technically OP_NOT OP_NOT would also do a VM-number check, which gets removed by this optimisation + ['OP_NOT OP_NOT OP_UNTIL', 'OP_UNTIL'], + ['OP_NOT OP_NOTIF', 'OP_IF'], + ['OP_NOT OP_NOT OP_VERIFY', 'OP_VERIFY'], ] as [string, string][]; From 45b3fbce756db129c4c6caca24c4cfeba527cb38 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 18 Aug 2026 11:18:57 +0200 Subject: [PATCH 24/37] Add fixture for double negation optimisation --- packages/cashc/test/generation/fixtures.ts | 49 +++++++++++++++++++ .../valid-contract-files/double_negation.cash | 22 +++++++++ 2 files changed, 71 insertions(+) create mode 100644 packages/cashc/test/valid-contract-files/double_negation.cash diff --git a/packages/cashc/test/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts index 7157acdc7..219eeb70a 100644 --- a/packages/cashc/test/generation/fixtures.ts +++ b/packages/cashc/test/generation/fixtures.ts @@ -2010,4 +2010,53 @@ export const fixtures: Fixture[] = [ fingerprint: '3ab69a954ec4bf9ceeb58eceb8ead206195032edf6627155eb82f528403c94dd', }, }, + { + fn: 'double_negation.cash', + artifact: { + contractName: 'DoubleNegation', + constructorInputs: [{ name: 'flag', type: 'bool' }], + abi: [{ name: 'spend', inputs: [{ name: 'target', type: 'int' }] }], + bytecode: + // require(!!flag) - OP_NOT OP_NOT OP_VERIFY is optimised to OP_VERIFY + 'OP_DUP OP_VERIFY ' + // int i = 0; bool done = false; + + 'OP_0 OP_0 ' + // do { i = i + 1; + + 'OP_BEGIN OP_OVER OP_1ADD OP_ROT OP_DROP OP_SWAP ' + // done = i >= target; + + 'OP_OVER OP_4 OP_PICK OP_GREATERTHANOREQUAL OP_NIP ' + // } while (!done) - OP_NOT OP_NOT OP_UNTIL is optimised to OP_UNTIL + + 'OP_DUP OP_UNTIL ' + // if (!!flag) - OP_NOT OP_NOT OP_IF becomes OP_NOT OP_NOTIF, which is optimised to OP_IF + + 'OP_ROT OP_IF ' + // require(i == target); } + + 'OP_OVER OP_3 OP_PICK OP_NUMEQUALVERIFY OP_ENDIF ' + // require(i > 0) + + 'OP_SWAP OP_0 OP_GREATERTHAN ' + // clean up i and done + + 'OP_NIP OP_NIP', + debug: { + bytecode: '7669000065788b7b757c785479a27776667b637853799d687c00a07777', + sourceMap: '4:18:4:22;:8::24:1;6:16:6:17:0;7:20:7:25;9:8:13:24;10:16:10:17;:::21:1;:12::22;;;11:19:11:20:0;:24::30;;:19:::1;:12::31;13:18:13:22:0;9:8::24:1;16:14:16:18:0;:12:18:9;17:20:17:21;:25::31;;:12::33:1;16:20:18:9;20:16:20:17:0;:20::21;:8::23:1;2:31:21:5;', + logs: [], + requires: [ + { ip: 2, line: 4 }, + { ip: 23, line: 17 }, + { ip: 28, line: 20 }, + ], + sourceTags: '27:28:sc', + }, + source: fs.readFileSync(new URL('../valid-contract-files/double_negation.cash', import.meta.url), { encoding: 'utf-8' }), + compiler: { + name: 'cashc', + version, + options: { + enforceFunctionParameterTypes: true, + enforceLocktimeGuard: true, + }, + }, + updatedAt: '', + fingerprint: 'ed0b5bc35f0130fa04d1fce813fbd7c183bb5346006d10c0808f0d9872712ded', + }, + }, ]; diff --git a/packages/cashc/test/valid-contract-files/double_negation.cash b/packages/cashc/test/valid-contract-files/double_negation.cash new file mode 100644 index 000000000..55bcfb785 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/double_negation.cash @@ -0,0 +1,22 @@ +contract DoubleNegation(bool flag) { + function spend(int target) { + // OP_NOT OP_NOT OP_VERIFY => OP_VERIFY + require(!!flag); + + int i = 0; + bool done = false; + + do { + i = i + 1; + done = i >= target; + // OP_NOT OP_NOT OP_UNTIL => OP_UNTIL + } while (!done); + + // OP_NOT OP_NOT OP_IF => OP_NOT OP_NOTIF => OP_IF + if (!!flag) { + require(i == target); + } + + require(i > 0); + } +} From 981eb07f197cf2197260ffdbaf7a052f5aa2a530 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 18 Aug 2026 11:51:25 +0200 Subject: [PATCH 25/37] Breaking changes to SignatureTemplate (#440) - Rename HashType to SighashType - Change SignatureTemplate getters to simple properties - Update docs, release notes & migration notes --- .cspell.json | 1 - packages/cashscript/src/Contract.ts | 2 +- packages/cashscript/src/SignatureTemplate.ts | 65 ++++++------------- packages/cashscript/src/interfaces.ts | 2 +- .../cashscript/src/libauth-template/utils.ts | 38 +++++------ packages/cashscript/src/utils.ts | 11 +++- .../cashscript/test/SignatureTemplate.test.ts | 18 ++--- .../cashscript/test/e2e/HodlVault.test.ts | 6 +- .../test/fixture/libauth-template/fixtures.ts | 12 ++-- website/docs/releases/migration-notes.md | 42 ++++++++++++ website/docs/releases/release-notes.md | 3 + website/docs/sdk/signature-templates.md | 61 ++++++++++------- 12 files changed, 148 insertions(+), 113 deletions(-) diff --git a/.cspell.json b/.cspell.json index 3231913ce..a14829167 100644 --- a/.cspell.json +++ b/.cspell.json @@ -86,7 +86,6 @@ "hashprevouts", "hashsequence", "hashtype", - "hashtypes", "hodl", "hodling", "htlc", diff --git a/packages/cashscript/src/Contract.ts b/packages/cashscript/src/Contract.ts index bdf097d63..ff784aeee 100644 --- a/packages/cashscript/src/Contract.ts +++ b/packages/cashscript/src/Contract.ts @@ -195,7 +195,7 @@ class ContractInternal< if (!(arg instanceof SignatureTemplate)) return arg; // Generate transaction signature from SignatureTemplate - const preimage = createSighashPreimage(transaction, sourceOutputs, inputIndex, bytecode, arg.getHashType()); + const preimage = createSighashPreimage(transaction, sourceOutputs, inputIndex, bytecode, arg.sighashType); const sighash = hash256(preimage); return arg.generateSignature(sighash); }); diff --git a/packages/cashscript/src/SignatureTemplate.ts b/packages/cashscript/src/SignatureTemplate.ts index d8a3f9e7e..eae5d5fad 100644 --- a/packages/cashscript/src/SignatureTemplate.ts +++ b/packages/cashscript/src/SignatureTemplate.ts @@ -1,35 +1,40 @@ -import { decodePrivateKeyWif, hexToBin, isHex, secp256k1, SigningSerializationFlag } from '@bitauth/libauth'; +import { decodePrivateKeyWif, hexToBin, isHex, secp256k1 } from '@bitauth/libauth'; import { hash256, scriptToBytecode } from '@cashscript/utils'; import { GenerateUnlockingBytecodeOptions, - HashType, + SighashType, SignatureAlgorithm, P2PKHUnlocker, } from './interfaces.js'; -import { createSighashPreimage, publicKeyToP2PKHLockingBytecode } from './utils.js'; +import { createSighashPreimage, publicKeyToP2PKHLockingBytecode, toSigningSerializationType } from './utils.js'; /** * A signature template used to sign CashScript transactions. Wraps a private key together with - * the desired `HashType` and `SignatureAlgorithm`, and is consumed by the `TransactionBuilder` + * the desired `SighashType` and `SignatureAlgorithm`, and is consumed by the `TransactionBuilder` * whenever a `sig` argument is required or when unlocking a P2PKH input. */ export default class SignatureTemplate { /** The raw private key bytes used for signing. */ public privateKey: Uint8Array; + /** The 33-byte compressed public key that corresponds to the template's private key. */ + get publicKey(): Uint8Array { + return secp256k1.derivePublicKeyCompressed(this.privateKey) as Uint8Array; + } + /** * Create a new SignatureTemplate. * * @param signer - A 32-byte private key (Uint8Array), a WIF or hex-encoded private key string, * or any object exposing a `toWIF()` method (e.g. bitcore-lib or bitcoincashjs `ECPair`). - * @param hashtype - Sighash flags to use when signing. Defaults to `SIGHASH_ALL | SIGHASH_UTXOS`. + * @param sighashType - Sighash flags to use when signing. Defaults to `SIGHASH_ALL | SIGHASH_UTXOS`. * @param signatureAlgorithm - The signature algorithm to use. Defaults to * `SignatureAlgorithm.SCHNORR`. */ constructor( signer: Keypair | Uint8Array | string, - private hashtype: HashType = HashType.SIGHASH_ALL | HashType.SIGHASH_UTXOS, - private signatureAlgorithm: SignatureAlgorithm = SignatureAlgorithm.SCHNORR, + public readonly sighashType: SighashType = SighashType.SIGHASH_ALL | SighashType.SIGHASH_UTXOS, + public readonly signatureAlgorithm: SignatureAlgorithm = SignatureAlgorithm.SCHNORR, ) { if (isKeypair(signer)) { const wif = signer.toWIF(); @@ -47,24 +52,22 @@ export default class SignatureTemplate { } /** - * Sign the provided sighash payload and return the signature concatenated with the hashtype + * Sign the provided sighash payload and return the signature concatenated with the sighash type * byte, ready to be used as a transaction signature. * * @param payload - The 32-byte sighash to sign. - * @param bchForkId - Whether to include the BCH fork id flag in the appended hashtype byte. - * Defaults to `true`. - * @returns The signature bytes followed by the hashtype byte. + * @returns The signature bytes followed by the sighash type byte. */ - generateSignature(payload: Uint8Array, bchForkId?: boolean): Uint8Array { + generateSignature(payload: Uint8Array): Uint8Array { const signature = this.signMessageHash(payload); - return Uint8Array.from([...signature, this.getHashType(bchForkId)]); + return Uint8Array.from([...signature, toSigningSerializationType(this.sighashType)]); } /** * Sign a raw 32-byte message hash using the template's private key and signature algorithm. * * @param payload - The 32-byte hash to sign. - * @returns The raw signature bytes (without an appended hashtype byte). + * @returns The raw signature bytes (without an appended sighash type byte). */ signMessageHash(payload: Uint8Array): Uint8Array { const signature = this.signatureAlgorithm === SignatureAlgorithm.SCHNORR @@ -74,32 +77,6 @@ export default class SignatureTemplate { return signature; } - /** - * Get the sighash flags used by this template. - * - * @param bchForkId - Whether to OR in the BCH fork id flag. Defaults to `true`. - * @returns The combined hashtype byte. - */ - getHashType(bchForkId: boolean = true): number { - return bchForkId ? (this.hashtype | SigningSerializationFlag.forkId) : this.hashtype; - } - - /** - * @returns The signature algorithm (ECDSA or Schnorr) used by this template. - */ - getSignatureAlgorithm(): SignatureAlgorithm { - return this.signatureAlgorithm; - } - - /** - * Derive the compressed public key that corresponds to the template's private key. - * - * @returns The 33-byte compressed public key. - */ - getPublicKey(): Uint8Array { - return secp256k1.derivePublicKeyCompressed(this.privateKey) as Uint8Array; - } - /** * Build a P2PKH `Unlocker` for the address derived from this template's private key. The * returned unlocker can be passed directly to `TransactionBuilder.addInput`. @@ -107,17 +84,15 @@ export default class SignatureTemplate { * @returns An unlocker that signs the corresponding P2PKH UTXO. */ unlockP2PKH(): P2PKHUnlocker { - const publicKey = this.getPublicKey(); - const prevOutScript = publicKeyToP2PKHLockingBytecode(publicKey); - const hashtype = this.getHashType(); + const prevOutScript = publicKeyToP2PKHLockingBytecode(this.publicKey); return { generateLockingBytecode: () => prevOutScript, generateUnlockingBytecode: ({ transaction, sourceOutputs, inputIndex }: GenerateUnlockingBytecodeOptions) => { - const preimage = createSighashPreimage(transaction, sourceOutputs, inputIndex, prevOutScript, hashtype); + const preimage = createSighashPreimage(transaction, sourceOutputs, inputIndex, prevOutScript, this.sighashType); const sighash = hash256(preimage); const signature = this.generateSignature(sighash); - const unlockingBytecode = scriptToBytecode([signature, publicKey]); + const unlockingBytecode = scriptToBytecode([signature, this.publicKey]); return unlockingBytecode; }, template: this, diff --git a/packages/cashscript/src/interfaces.ts b/packages/cashscript/src/interfaces.ts index 5841ac9f2..009b672eb 100644 --- a/packages/cashscript/src/interfaces.ts +++ b/packages/cashscript/src/interfaces.ts @@ -133,7 +133,7 @@ export enum SignatureAlgorithm { SCHNORR = 0x01, } -export enum HashType { +export enum SighashType { SIGHASH_ALL = 0x01, SIGHASH_NONE = 0x02, SIGHASH_SINGLE = 0x03, diff --git a/packages/cashscript/src/libauth-template/utils.ts b/packages/cashscript/src/libauth-template/utils.ts index a987e61d8..8c4d0a5c7 100644 --- a/packages/cashscript/src/libauth-template/utils.ts +++ b/packages/cashscript/src/libauth-template/utils.ts @@ -1,5 +1,5 @@ import { AbiFunction, AbiInput, Artifact, formatBitAuthScript, sha256 } from '@cashscript/utils'; -import { HashType, LibauthTokenDetails, SignatureAlgorithm, TokenDetails, VmTarget } from '../interfaces.js'; +import { LibauthTokenDetails, SighashType, SignatureAlgorithm, TokenDetails, VmTarget } from '../interfaces.js'; import { hexToBin, binToHex, isHex, decodeCashAddress, Input, assertSuccess, decodeAuthenticationInstructions, AuthenticationInstructionPush } from '@bitauth/libauth'; import { EncodedFunctionArgument } from '../Argument.js'; import { zip } from '../utils.js'; @@ -32,23 +32,23 @@ export const getSignatureAlgorithmName = (signatureAlgorithm: SignatureAlgorithm return signatureAlgorithmNames[signatureAlgorithm]; }; -export const getHashTypeName = (hashType: HashType): string => { - const hashtypeNames = { - [HashType.SIGHASH_ALL]: 'all_outputs', - [HashType.SIGHASH_ALL | HashType.SIGHASH_ANYONECANPAY]: 'all_outputs_single_input', - [HashType.SIGHASH_ALL | HashType.SIGHASH_UTXOS]: 'all_outputs_all_utxos', - [HashType.SIGHASH_ALL | HashType.SIGHASH_ANYONECANPAY | HashType.SIGHASH_UTXOS]: 'all_outputs_single_input_INVALID_all_utxos', - [HashType.SIGHASH_SINGLE]: 'corresponding_output', - [HashType.SIGHASH_SINGLE | HashType.SIGHASH_ANYONECANPAY]: 'corresponding_output_single_input', - [HashType.SIGHASH_SINGLE | HashType.SIGHASH_UTXOS]: 'corresponding_output_all_utxos', - [HashType.SIGHASH_SINGLE | HashType.SIGHASH_ANYONECANPAY | HashType.SIGHASH_UTXOS]: 'corresponding_output_single_input_INVALID_all_utxos', - [HashType.SIGHASH_NONE]: 'no_outputs', - [HashType.SIGHASH_NONE | HashType.SIGHASH_ANYONECANPAY]: 'no_outputs_single_input', - [HashType.SIGHASH_NONE | HashType.SIGHASH_UTXOS]: 'no_outputs_all_utxos', - [HashType.SIGHASH_NONE | HashType.SIGHASH_ANYONECANPAY | HashType.SIGHASH_UTXOS]: 'no_outputs_single_input_INVALID_all_utxos', +export const getSighashTypeName = (sighashType: SighashType): string => { + const sighashTypeNames = { + [SighashType.SIGHASH_ALL]: 'all_outputs', + [SighashType.SIGHASH_ALL | SighashType.SIGHASH_ANYONECANPAY]: 'all_outputs_single_input', + [SighashType.SIGHASH_ALL | SighashType.SIGHASH_UTXOS]: 'all_outputs_all_utxos', + [SighashType.SIGHASH_ALL | SighashType.SIGHASH_ANYONECANPAY | SighashType.SIGHASH_UTXOS]: 'all_outputs_single_input_INVALID_all_utxos', + [SighashType.SIGHASH_SINGLE]: 'corresponding_output', + [SighashType.SIGHASH_SINGLE | SighashType.SIGHASH_ANYONECANPAY]: 'corresponding_output_single_input', + [SighashType.SIGHASH_SINGLE | SighashType.SIGHASH_UTXOS]: 'corresponding_output_all_utxos', + [SighashType.SIGHASH_SINGLE | SighashType.SIGHASH_ANYONECANPAY | SighashType.SIGHASH_UTXOS]: 'corresponding_output_single_input_INVALID_all_utxos', + [SighashType.SIGHASH_NONE]: 'no_outputs', + [SighashType.SIGHASH_NONE | SighashType.SIGHASH_ANYONECANPAY]: 'no_outputs_single_input', + [SighashType.SIGHASH_NONE | SighashType.SIGHASH_UTXOS]: 'no_outputs_all_utxos', + [SighashType.SIGHASH_NONE | SighashType.SIGHASH_ANYONECANPAY | SighashType.SIGHASH_UTXOS]: 'no_outputs_single_input_INVALID_all_utxos', }; - return hashtypeNames[hashType]; + return sighashTypeNames[sighashType]; }; export const addHexPrefixExceptEmpty = (value: string): string => { @@ -63,9 +63,9 @@ export const formatParametersForDebugging = (types: readonly AbiInput[], args: E return typesAndArguments.map(([input, arg]) => { if (arg instanceof SignatureTemplate) { - const signatureAlgorithmName = getSignatureAlgorithmName(arg.getSignatureAlgorithm()); - const hashtypeName = getHashTypeName(arg.getHashType(false)); - return `<${input.name}.${signatureAlgorithmName}.${hashtypeName}> // ${input.type}`; + const signatureAlgorithmName = getSignatureAlgorithmName(arg.signatureAlgorithm); + const sighashTypeName = getSighashTypeName(arg.sighashType); + return `<${input.name}.${signatureAlgorithmName}.${sighashTypeName}> // ${input.type}`; } const typeStr = input.type === 'bytes' ? `bytes${arg.length}` : input.type; diff --git a/packages/cashscript/src/utils.ts b/packages/cashscript/src/utils.ts index 743678938..d13b96cff 100644 --- a/packages/cashscript/src/utils.ts +++ b/packages/cashscript/src/utils.ts @@ -14,6 +14,7 @@ import { bigIntToCompactUint, NonFungibleTokenCapability, bigIntToVmNumber, + SigningSerializationFlag, } from '@bitauth/libauth'; import { encodeInt, @@ -35,6 +36,7 @@ import { UnlockableUtxo, LibauthTokenDetails, ContractType, + SighashType, } from './interfaces.js'; import { VERSION_SIZE, LOCKTIME_SIZE } from './constants.js'; import { @@ -265,15 +267,20 @@ function toBin(output: string): Uint8Array { return encode(data); } +// BCH consensus requires the fork id flag on every signing serialization +export function toSigningSerializationType(sighashType: SighashType): number { + return sighashType | SigningSerializationFlag.forkId; +} + export function createSighashPreimage( transaction: Transaction, sourceOutputs: LibauthOutput[], inputIndex: number, coveredBytecode: Uint8Array, - hashtype: number, + sighashType: SighashType, ): Uint8Array { const context = { inputIndex, sourceOutputs, transaction }; - const signingSerializationType = new Uint8Array([hashtype]); + const signingSerializationType = new Uint8Array([toSigningSerializationType(sighashType)]); const sighashPreimage = generateSigningSerializationBch(context, { coveredBytecode, signingSerializationType }); diff --git a/packages/cashscript/test/SignatureTemplate.test.ts b/packages/cashscript/test/SignatureTemplate.test.ts index 138d45118..c21f9588f 100644 --- a/packages/cashscript/test/SignatureTemplate.test.ts +++ b/packages/cashscript/test/SignatureTemplate.test.ts @@ -1,5 +1,5 @@ import { generateLibauthSourceOutputs } from 'cashscript/dist/utils.js'; -import { HashType, MockNetworkProvider, SignatureAlgorithm, SignatureTemplate, TransactionBuilder } from '../src/index.js'; +import { MockNetworkProvider, SighashType, SignatureAlgorithm, SignatureTemplate, TransactionBuilder } from '../src/index.js'; import { aliceAddress, alicePriv, alicePub, aliceWif } from './fixture/vars.js'; import { binToHex, decodeTransactionUnsafe, hexToBin } from '@bitauth/libauth'; @@ -33,17 +33,11 @@ describe('SignatureTemplate', () => { expect(signature).toEqual(hexToBin('3045022100fa1d6a159a124e99479f78152422d55ff3c16f7fac5ae47fa291907f8f47613f02200d6c906f667b3712860b6f5a1f296ecb7dcd44da83c6a1eb45869b61c6b8dadb61')); }); - it('should append the correct hash type when fork ID is true', () => { - const signatureTemplate = new SignatureTemplate(alicePriv, HashType.SIGHASH_SINGLE); - const signature = signatureTemplate.generateSignature(hexToBin('0000000000000000000000'), true); + it('should append the configured sighash type, always including the BCH fork ID', () => { + const signatureTemplate = new SignatureTemplate(alicePriv, SighashType.SIGHASH_SINGLE); + const signature = signatureTemplate.generateSignature(hexToBin('0000000000000000000000')); expect(signature).toEqual(hexToBin('bcac180e17de108003cce026708bd2af54b860dad2626cee157f4ed5abd993b9085d615015f905978adc51e8878226280ddd27d899f086519c0978e53332d79943')); }); - - it('should append the correct hash type when fork ID is false', () => { - const signatureTemplate = new SignatureTemplate(alicePriv, HashType.SIGHASH_SINGLE); - const signature = signatureTemplate.generateSignature(hexToBin('0000000000000000000000'), false); - expect(signature).toEqual(hexToBin('bcac180e17de108003cce026708bd2af54b860dad2626cee157f4ed5abd993b9085d615015f905978adc51e8878226280ddd27d899f086519c0978e53332d79903')); - }); }); describe('signMessageHash', () => { @@ -62,10 +56,10 @@ describe('SignatureTemplate', () => { }); }); - describe('getPublicKey', () => { + describe('publicKey', () => { it('should generate a correct public key', () => { const signatureTemplate = new SignatureTemplate(alicePriv); - expect(signatureTemplate.getPublicKey()).toEqual(alicePub); + expect(signatureTemplate.publicKey).toEqual(alicePub); }); }); diff --git a/packages/cashscript/test/e2e/HodlVault.test.ts b/packages/cashscript/test/e2e/HodlVault.test.ts index d3b0f81e6..7c42c5888 100644 --- a/packages/cashscript/test/e2e/HodlVault.test.ts +++ b/packages/cashscript/test/e2e/HodlVault.test.ts @@ -6,7 +6,7 @@ import { Network, TransactionBuilder, SignatureAlgorithm, - HashType, + SighashType, } from '../../src/index.js'; import { alicePriv, @@ -108,7 +108,7 @@ describe('HodlVault', () => { const amount = 10000n; const { utxos, changeAmount } = gatherUtxos(await hodlVault.getUtxos(), { amount, fee: 2000n }); - const signatureTemplate = new SignatureTemplate(alicePriv, HashType.SIGHASH_ALL, SignatureAlgorithm.ECDSA); + const signatureTemplate = new SignatureTemplate(alicePriv, SighashType.SIGHASH_ALL, SignatureAlgorithm.ECDSA); // when const tx = await new TransactionBuilder({ provider }) @@ -185,7 +185,7 @@ describe('HodlVault', () => { .send()).rejects.toThrow('HodlVault.cash:31 Require statement failed at input 0 in contract HodlVault.cash at line 31'); // datasig: unlocker should throw when given an improper length - const signatureTemplate = new SignatureTemplate(alicePriv, HashType.SIGHASH_ALL, SignatureAlgorithm.ECDSA); + const signatureTemplate = new SignatureTemplate(alicePriv, SighashType.SIGHASH_ALL, SignatureAlgorithm.ECDSA); expect(() => hodlVault.unlock.spend(signatureTemplate, placeholder(100), message)).toThrow("Found type 'bytes100' where type 'datasig' was expected"); // datasig: unlocker should not throw when given a proper length, but transaction should fail on invalid sig diff --git a/packages/cashscript/test/fixture/libauth-template/fixtures.ts b/packages/cashscript/test/fixture/libauth-template/fixtures.ts index 3facdf713..0a145f3b2 100644 --- a/packages/cashscript/test/fixture/libauth-template/fixtures.ts +++ b/packages/cashscript/test/fixture/libauth-template/fixtures.ts @@ -1,4 +1,4 @@ -import { Contract, HashType, MockNetworkProvider, SignatureAlgorithm, SignatureTemplate, TransactionBuilder, randomNFT, randomToken, randomUtxo } from '../../../src/index.js'; +import { Contract, MockNetworkProvider, SighashType, SignatureAlgorithm, SignatureTemplate, TransactionBuilder, randomNFT, randomToken, randomUtxo } from '../../../src/index.js'; import TransferWithTimeout from '../transfer_with_timeout.artifact.js'; import Mecenas from '../mecenas.artifact.js'; import P2PKH from '../p2pkh.artifact.js'; @@ -1262,7 +1262,7 @@ export const fixtures: Fixture[] = [ }, }, }, - // TODO: Make it work with different hashtypes and signature algorithms + // TODO: Make it work with different sighash types and signature algorithms // { // name: 'P2PKH (sending NFTs)', // transaction: (() => { @@ -1272,11 +1272,11 @@ export const fixtures: Fixture[] = [ // const to = contract.address; // const amount = 1000n; - // const hashtype = HashType.SIGHASH_SINGLE | HashType.SIGHASH_ANYONECANPAY; + // const sighashType = SighashType.SIGHASH_SINGLE | SighashType.SIGHASH_ANYONECANPAY; // const signatureAlgorithm = SignatureAlgorithm.ECDSA; // const tx = contract.functions - // .spend(alicePub, new SignatureTemplate(alicePriv, hashtype, signatureAlgorithm)) + // .spend(alicePub, new SignatureTemplate(alicePriv, sighashType, signatureAlgorithm)) // .to(to, amount); // return tx; @@ -1295,8 +1295,8 @@ export const fixtures: Fixture[] = [ const amount = 1000n; const aliceDefaultTemplate = new SignatureTemplate(alicePriv); - const aliceCustomTemplate = new SignatureTemplate(alicePriv, HashType.SIGHASH_NONE, SignatureAlgorithm.ECDSA); - const bobCustomTemplate = new SignatureTemplate(bobPriv, HashType.SIGHASH_ALL, SignatureAlgorithm.ECDSA); + const aliceCustomTemplate = new SignatureTemplate(alicePriv, SighashType.SIGHASH_NONE, SignatureAlgorithm.ECDSA); + const bobCustomTemplate = new SignatureTemplate(bobPriv, SighashType.SIGHASH_ALL, SignatureAlgorithm.ECDSA); const tx = new TransactionBuilder({ provider }) .addInput(p2pkhUtxo, aliceDefaultTemplate.unlockP2PKH()) diff --git a/website/docs/releases/migration-notes.md b/website/docs/releases/migration-notes.md index 8c2864e9b..d981afe46 100644 --- a/website/docs/releases/migration-notes.md +++ b/website/docs/releases/migration-notes.md @@ -2,6 +2,48 @@ title: Migration Notes --- +## v0.13 to v0.14 + +### CashScript SDK + +#### SignatureTemplate + +The `getHashType()`, `getPublicKey()` and `getSignatureAlgorithm()` are now simple `sighashType`, `publicKey` and `signatureAlgorithm` properties. + +```ts +// before +const hashType = signatureTemplate.getHashType(); +const publicKey = signatureTemplate.getPublicKey(); +const signatureAlgorithm = signatureTemplate.getSignatureAlgorithm(); + +// after +const sighashType = signatureTemplate.sighashType; +const publicKey = signatureTemplate.publicKey; +const signatureAlgorithm = signatureTemplate.signatureAlgorithm; +``` + +Note that `getHashType()` returned the sighash type with the BCH fork ID flag applied, while the `sighashType` property returns the configured sighash type as it was passed to the constructor. + +The `bchForkId` parameter has been removed from `generateSignature()`. A signature without the BCH fork ID flag is invalid under BCH consensus rules, so the flag is now always applied when signing. + +```ts +// before +const signature = signatureTemplate.generateSignature(sighash, bchForkId); + +// after +const signature = signatureTemplate.generateSignature(sighash); +``` + +The `HashType` enum has been renamed to `SighashType`. + +```ts +// before +const signatureTemplate = new SignatureTemplate(wif, HashType.SIGHASH_ALL | HashType.SIGHASH_UTXOS); + +// after +const signatureTemplate = new SignatureTemplate(wif, SighashType.SIGHASH_ALL | SighashType.SIGHASH_UTXOS); +``` + ## v0.12 to v0.13 ### cashc compiler diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 92afce18e..faac8f294 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -22,6 +22,9 @@ title: Release Notes #### CashScript SDK - :sparkles: Add support for debugging user-defined functions. - :sparkles: Add stack trace when debugging failed requires inside nested functions. +- :hammer_and_wrench: **BREAKING**: Replace the `SignatureTemplate`'s `getHashType()`, `getPublicKey()` and `getSignatureAlgorithm()` methods with the `sighashType`, `publicKey` and `signatureAlgorithm` properties. +- :hammer_and_wrench: **BREAKING**: Remove the `bchForkId` parameter from `SignatureTemplate`'s `generateSignature()` method, since BCH consensus rules always require the fork ID flag. +- :hammer_and_wrench: **BREAKING**: Rename the `HashType` enum to `SighashType`. ## v0.13.2 diff --git a/website/docs/sdk/signature-templates.md b/website/docs/sdk/signature-templates.md index 9f9889663..b9e51b029 100644 --- a/website/docs/sdk/signature-templates.md +++ b/website/docs/sdk/signature-templates.md @@ -16,7 +16,7 @@ In place of a signature, a `SignatureTemplate` can be passed, which will generat ```ts new SignatureTemplate( signer: Keypair | Uint8Array | string, - hashtype?: HashType, + sighashType?: SighashType, signatureAlgorithm?: SignatureAlgorithm ) ``` @@ -37,39 +37,54 @@ const transferDetails = await new TransactionBuilder({ provider }) .send(); ``` -The `hashtype` and `signatureAlgorithm` options are covered under ['Advanced Usage'](/docs/sdk/signature-templates#advanced-usage). +The `sighashType` and `signatureAlgorithm` options are covered under ['Advanced Usage'](/docs/sdk/signature-templates#advanced-usage). -## SignatureTemplate Methods +## SignatureTemplate Properties -### unlockP2PKH() +### privateKey -Importantly the `SignatureTemplate` can also be used to generate the `Unlocker` for a P2PKH UTXO in the following way: +The `SignatureTemplate` exposes the private key it signs with as a property. Whichever format the `signer` was passed in (WIF, hex string, `Uint8Array` or a `Keypair` object), it is decoded to raw private key bytes. ```ts -signatureTemplate.unlockP2PKH(): Unlocker +signatureTemplate.privateKey: Uint8Array ``` -#### Example +### publicKey + +The `SignatureTemplate` exposes the matching public key as a property: + ```ts -import { aliceTemplate, aliceAddress, transactionBuilder } from './somewhere.js'; +signatureTemplate.publicKey: Uint8Array +``` -const aliceUtxos = await provider.getUtxos(aliceAddress); -transactionBuilder.addInput(aliceUtxos[0], aliceTemplate.unlockP2PKH()); +### sighashType + +The configured sighash type is exposed as a property. Note that the BCH fork ID flag is always applied on top of this value when signing, since it is required by BCH consensus. Its possible values are covered under ['Advanced Usage'](/docs/sdk/signature-templates#sighashtype). + +### signatureAlgorithm + +The configured signature algorithm is exposed as a property. Its possible values are covered under ['Advanced Usage'](/docs/sdk/signature-templates#signaturealgorithm). + +```ts +signatureTemplate.signatureAlgorithm: SignatureAlgorithm ``` -### getPublicKey() +## SignatureTemplate Methods + +### unlockP2PKH() -The `SignatureTemplate` also has a helper method to get the matching PublicKey in the following way: +Importantly the `SignatureTemplate` can also be used to generate the `Unlocker` for a P2PKH UTXO in the following way: ```ts -signatureTemplate.getPublicKey(): Uint8Array +signatureTemplate.unlockP2PKH(): Unlocker ``` #### Example ```ts -import { aliceTemplate } from './somewhere.js'; +import { aliceTemplate, aliceAddress, transactionBuilder } from './somewhere.js'; -const alicePublicKey = aliceTemplate.getPublicKey() +const aliceUtxos = await provider.getUtxos(aliceAddress); +transactionBuilder.addInput(aliceUtxos[0], aliceTemplate.unlockP2PKH()); ``` ### signMessageHash() @@ -91,12 +106,12 @@ const signature = aliceTemplate.signMessageHash(sha256(hexToBin('000000000000000 ## Advanced Usage -### HashType +### SighashType -The default `hashtype` is `HashType.SIGHASH_ALL | HashType.SIGHASH_UTXOS` because this is the most secure option for smart contract use cases. +The default `sighashType` is `SighashType.SIGHASH_ALL | SighashType.SIGHASH_UTXOS` because this is the most secure option for smart contract use cases. ```ts -export enum HashType { +export enum SighashType { SIGHASH_ALL = 0x01, SIGHASH_NONE = 0x02, SIGHASH_SINGLE = 0x03, @@ -110,10 +125,10 @@ export enum HashType { const wif = 'L4vmKsStbQaCvaKPnCzdRArZgdAxTqVx8vjMGLW5nHtWdRguiRi1'; const signatureTemplate = new SignatureTemplate( - wif, HashType.SIGHASH_ALL | HashType.SIGHASH_UTXOS + wif, SighashType.SIGHASH_ALL | SighashType.SIGHASH_UTXOS ); -const configuredHashType = signatureTemplate.getHashType() +const configuredSighashType = signatureTemplate.sighashType ``` ### SignatureAlgorithm @@ -131,11 +146,11 @@ export enum SignatureAlgorithm { ```ts const wif = 'L4vmKsStbQaCvaKPnCzdRArZgdAxTqVx8vjMGLW5nHtWdRguiRi1'; -const hashType = HashType.SIGHASH_ALL | HashType.SIGHASH_UTXOS +const sighashType = SighashType.SIGHASH_ALL | SighashType.SIGHASH_UTXOS const signatureAlgorithm = SignatureAlgorithm.SCHNORR -const signatureTemplate = new SignatureTemplate(wif, hashType,signatureAlgorithm); +const signatureTemplate = new SignatureTemplate(wif, sighashType,signatureAlgorithm); -const configuredSignatureAlgorithm = signatureTemplate.getSignatureAlgorithm() +const configuredSignatureAlgorithm = signatureTemplate.signatureAlgorithm ``` [wif]: https://en.bitcoin.it/wiki/Wallet_import_format From 61a4b6a108d41d0ee79ac6652e406bb18ba65252 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 20 Aug 2026 10:13:19 +0200 Subject: [PATCH 26/37] Bump version to 0.14.0-next.4 & update release notes --- examples/package.json | 6 +++--- examples/testing-suite/package.json | 6 +++--- packages/cashc/package.json | 4 ++-- packages/cashc/src/index.ts | 2 +- packages/cashscript/package.json | 4 ++-- packages/utils/package.json | 2 +- website/docs/releases/release-notes.md | 4 ++-- 7 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/package.json b/examples/package.json index 9ab91215b..215f3cc89 100644 --- a/examples/package.json +++ b/examples/package.json @@ -1,7 +1,7 @@ { "name": "cashscript-examples", "private": true, - "version": "0.14.0-next.3", + "version": "0.14.0-next.4", "description": "Usage examples of the CashScript SDK", "main": "p2pkh.js", "type": "module", @@ -13,8 +13,8 @@ "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", "@types/node": "^24.13.3", - "cashc": "^0.14.0-next.3", - "cashscript": "^0.14.0-next.3", + "cashc": "^0.14.0-next.4", + "cashscript": "^0.14.0-next.4", "eslint": "^8.56.0", "typescript": "^5.9.2" } diff --git a/examples/testing-suite/package.json b/examples/testing-suite/package.json index 91cfb45a2..6564205f3 100644 --- a/examples/testing-suite/package.json +++ b/examples/testing-suite/package.json @@ -1,6 +1,6 @@ { "name": "testing-suite", - "version": "0.14.0-next.3", + "version": "0.14.0-next.4", "description": "Example project to develop and test CashScript contracts", "main": "index.js", "type": "module", @@ -18,8 +18,8 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "cashc": "^0.14.0-next.3", - "cashscript": "^0.14.0-next.3" + "cashc": "^0.14.0-next.4", + "cashscript": "^0.14.0-next.4" }, "devDependencies": { "tsx": "^4.23.12", diff --git a/packages/cashc/package.json b/packages/cashc/package.json index d75e19c61..06569be7b 100644 --- a/packages/cashc/package.json +++ b/packages/cashc/package.json @@ -1,6 +1,6 @@ { "name": "cashc", - "version": "0.14.0-next.3", + "version": "0.14.0-next.4", "description": "Compile Bitcoin Cash contracts to Bitcoin Cash Script or artifacts", "keywords": [ "bitcoin", @@ -48,7 +48,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.3", + "@cashscript/utils": "^0.14.0-next.4", "antlr4": "^4.13.2", "commander": "^14.0.0", "semver": "^7.8.5" diff --git a/packages/cashc/src/index.ts b/packages/cashc/src/index.ts index f647e3413..85f011e49 100644 --- a/packages/cashc/src/index.ts +++ b/packages/cashc/src/index.ts @@ -6,4 +6,4 @@ export { export * from './ast/Location.js'; export * from './ast/error-listeners.js'; -export const version = '0.14.0-next.3'; +export const version = '0.14.0-next.4'; diff --git a/packages/cashscript/package.json b/packages/cashscript/package.json index d6fe9cc95..37b7e8865 100644 --- a/packages/cashscript/package.json +++ b/packages/cashscript/package.json @@ -1,6 +1,6 @@ { "name": "cashscript", - "version": "0.14.0-next.3", + "version": "0.14.0-next.4", "description": "Easily write and interact with Bitcoin Cash contracts", "keywords": [ "bitcoin cash", @@ -42,7 +42,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.3", + "@cashscript/utils": "^0.14.0-next.4", "@electrum-cash/network": "^4.2.2", "fflate": "^0.8.3", "semver": "^7.8.5" diff --git a/packages/utils/package.json b/packages/utils/package.json index c0954e593..33b4616f0 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@cashscript/utils", - "version": "0.14.0-next.3", + "version": "0.14.0-next.4", "description": "CashScript utilities and types", "keywords": [ "bitcoin cash", diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index faac8f294..5f8cf21da 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -2,7 +2,7 @@ title: Release Notes --- -## v0.14.0-next.3 +## v0.14.0-next.4 ⚠️ Note that this is a pre-release version and is not yet stable. There will likely be breaking changes to the APIs and compiler output in subsequent pre-releases. @@ -17,7 +17,7 @@ title: Release Notes - :sparkles: Add support for reassigning existing variables in tuple destructuring (e.g. `(a, b) = swap(a, b)`), optionally mixed with fresh declarations. - :hammer_and_wrench: Update `compileString` to take an optional `files` object for filesystem-free import resolution. - :racehorse: Inline global functions and constants when this is no larger than `OP_DEFINE`/`OP_INVOKE`. -- :racehorse: Add new `OP_SWAP OP_MUL` optimisation. +- :racehorse: Add new `OP_SWAP OP_MUL` and `OP_NOT OP_NOT` optimisations. #### CashScript SDK - :sparkles: Add support for debugging user-defined functions. From 498b9ea20965a4b5403c06547f17fc45d7a5f094 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 1 Sep 2026 10:20:20 +0200 Subject: [PATCH 27/37] Improve compiler optimisation speed (#441) --- packages/utils/src/script.ts | 104 ++++++++++++----------------------- 1 file changed, 36 insertions(+), 68 deletions(-) diff --git a/packages/utils/src/script.ts b/packages/utils/src/script.ts index e82a8b184..180bf9f45 100644 --- a/packages/utils/src/script.ts +++ b/packages/utils/src/script.ts @@ -173,27 +173,14 @@ export function optimiseBytecode( runs: number = 1000, ): OptimiseBytecodeResult { for (let i = 0; i < runs; i += 1) { - const oldScript = script; - const { - script: newScript, - locationData: newLocationData, - logs: newLogs, - requires: newRequires, - sourceTags: newSourceTags, - inlineRanges: newInlineRanges, - } = replaceOps( + const result = replaceOps( script, locationData, logs, requires, sourceTags, inlineRanges, constructorParamLength, optimisationReplacements, ); // Break on fixed point - if (scriptToAsm(oldScript) === scriptToAsm(newScript)) break; - - script = newScript; - locationData = newLocationData; - logs = newLogs; - requires = newRequires; - sourceTags = newSourceTags; - inlineRanges = newInlineRanges; + if (!result.changed) break; + + ({ script, locationData, logs, requires, sourceTags, inlineRanges } = result); } return { @@ -221,13 +208,8 @@ function reconcileScopeCleanupTags(script: Script, sourceTags: SourceTagEntry[]) }); } -interface ReplaceOpsResult { - script: Script; - locationData: FullLocationData; - logs: LogEntry[]; - requires: RequireStatement[]; - sourceTags: SourceTagEntry[]; - inlineRanges: InlineRange[]; +interface ReplaceOpsResult extends OptimiseBytecodeResult { + changed: boolean; } function replaceOps( @@ -238,33 +220,40 @@ function replaceOps( sourceTags: SourceTagEntry[], inlineRanges: InlineRange[], constructorParamLength: number, - optimisations: string[][], + optimisations: [string, string][], ): ReplaceOpsResult { - let asm = scriptToAsm(script); - let newLocationData = [...locationData]; + const originalAsm = scriptToAsm(script); + let asm = originalAsm; + const newLocationData = [...locationData]; let newLogs = [...logs]; let newRequires = [...requires]; let newSourceTags = [...sourceTags]; let newInlineRanges = [...inlineRanges]; 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)); - - // 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; + const patternTokens = pattern.split(/\s+/); + const patternLength = patternTokens.length; + const replacementLength = replacement === '' ? 0 : replacement.split(/\s+/).length; + const lengthDiff = patternLength - replacementLength; + + // (?=\s|$) requires the pattern to end at a token boundary (no partial matches) withoutconsuming the separator + const regex = new RegExp(`${pattern}(?=\\s|$)`, 'g'); + + // Most rules match nothing on any given script, and must leave the ASM untouched. + const matches = [...asm.matchAll(regex)]; + if (matches.length === 0) return; + + // Make a mapping *once* that maps the character offset of every opcode/token to its script index + const scriptIndexAtCharacterOffset = new Map(); + asm.split(' ').reduce((characterOffset, token, scriptIndex) => { + scriptIndexAtCharacterOffset.set(characterOffset, scriptIndex); + return characterOffset + token.length + 1; + }, 0); + + // Process the matches right to left: replacing a pattern only shifts the metadata positions + // that come after it, so the indices of the remaining (earlier) matches stay valid as-is. + for (const match of matches.reverse()) { + const scriptIndex = scriptIndexAtCharacterOffset.get(match.index)!; // We get the locationData entries for every opcode in the pattern const patternLocations = newLocationData.slice(scriptIndex, scriptIndex + patternLength); @@ -295,8 +284,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; @@ -330,7 +317,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 { @@ -356,27 +343,14 @@ function replaceOps( endIp: adjustPosition(inlineRange.endIp, scriptIp), })); - // 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); } - // 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; + asm = asm.replace(regex, replacement).replace(/\s+/g, ' ').trim(); }); return { script: asmToScript(asm), + changed: asm !== originalAsm, locationData: newLocationData, logs: newLogs, requires: newRequires, @@ -416,9 +390,3 @@ const getLowestStartLocation = (locations: SingleLocationData[]): SingleLocation return lowest; }, 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(); -}; From ab46c49059d1890290e9a2d52a5146805bb37b31 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 1 Sep 2026 10:21:42 +0200 Subject: [PATCH 28/37] Refactor compiler fixtures so every fixture is its own file --- packages/cashc/src/internal.ts | 2 +- packages/cashc/test/compiler/compiler.test.ts | 15 - .../cashc/test/generation/fixture-utils.ts | 30 + packages/cashc/test/generation/fixtures.ts | 2062 ----------------- .../fixtures/import-fixtures/diamond.ts | 123 + .../valid-contract-files/2_of_3_multisig.ts | 21 + .../valid-contract-files/announcement.ts | 48 + .../fixtures/valid-contract-files/bigint.ts | 25 + .../fixtures/valid-contract-files/bitshift.ts | 22 + .../fixtures/valid-contract-files/bitwise.ts | 16 + .../valid-contract-files/bounded_bytes.ts | 24 + .../bytes1_equals_byte.ts | 26 + .../bytes_type_narrowing.ts | 152 ++ .../cast_hash_checksig.ts | 26 + .../checkdatasig_in_function.ts | 41 + .../fixtures/valid-contract-files/comments.ts | 39 + .../valid-contract-files/complex_loop.ts | 25 + .../valid-contract-files/compound_assign.ts | 32 + .../valid-contract-files/correct_pragma.ts | 37 + .../fixtures/valid-contract-files/covenant.ts | 31 + .../covenant_all_fields.ts | 88 + .../valid-contract-files/date_literal.ts | 23 + .../valid-contract-files/debug_messages.ts | 24 + .../valid-contract-files/deep_replace.ts | 30 + .../deeply_nested-logs.ts | 79 + .../valid-contract-files/deeply_nested.ts | 63 + .../valid-contract-files/do_while_loop.ts | 29 + .../do_while_loop_no_introspection.ts | 23 + .../do_while_loop_require_inside_loop.ts | 31 + .../valid-contract-files/double_negation.ts | 42 + .../valid-contract-files/double_split.ts | 24 + .../valid-contract-files/everything.ts | 68 + .../valid-contract-files/for_loop_basic.ts | 22 + .../for_loop_stack_items.ts | 24 + .../valid-contract-files/for_while_nested.ts | 35 + .../force_cast_smaller_bytes.ts | 23 + .../global_constant_arithmetic.ts | 110 + .../global_constant_inlined.ts | 40 + .../global_constant_literals.ts | 110 + .../global_constant_shared.ts | 40 + .../global_function_altstack_cleanup.ts | 36 + .../global_function_in_control_flow.ts | 57 + .../global_function_inlined.ts | 48 + .../global_function_multi_param.ts | 67 + .../global_function_multi_return.ts | 72 + .../global_function_multi_return_three.ts | 38 + .../global_function_nested.ts | 41 + .../global_function_simple.ts | 66 + .../global_function_void.ts | 68 + .../valid-contract-files/hodl_vault.ts | 58 + .../valid-contract-files/if_statement.ts | 45 + .../if_statement_number_units-logs.ts | 39 + .../if_statement_number_units.ts | 33 + .../increment_decrement.ts | 32 + .../valid-contract-files/int_to_byte.ts | 26 + .../integer_formatting.ts | 21 + .../fixtures/valid-contract-files/invert.ts | 25 + .../log_intermediate_results.ts | 38 + .../fixtures/valid-contract-files/mecenas.ts | 76 + .../valid-contract-files/multifunction.ts | 39 + .../multifunction_if_statements.ts | 71 + .../multiline_array_multisig.ts | 31 + .../multiline_statements.ts | 23 + .../valid-contract-files/multiplication.ts | 25 + .../fixtures/valid-contract-files/num2bin.ts | 23 + .../valid-contract-files/num2bin_variable.ts | 21 + .../valid-contract-files/p2palindrome.ts | 21 + .../valid-contract-files/p2pkh-logs.ts | 33 + .../fixtures/valid-contract-files/p2pkh.ts | 26 + .../p2pkh_with_assignment.ts | 25 + .../valid-contract-files/p2pkh_with_cast.ts | 26 + .../valid-contract-files/reassignment.ts | 39 + .../valid-contract-files/simple_cast.ts | 36 + .../simple_checkdatasig.ts | 21 + .../valid-contract-files/simple_constant.ts | 23 + .../valid-contract-files/simple_covenant.ts | 21 + .../valid-contract-files/simple_functions.ts | 37 + .../simple_if_statement.ts | 33 + .../valid-contract-files/simple_multisig.ts | 21 + .../valid-contract-files/simple_splice.ts | 25 + .../valid-contract-files/simple_variables.ts | 36 + .../valid-contract-files/simulating_state.ts | 87 + .../fixtures/valid-contract-files/slice.ts | 25 + .../valid-contract-files/slice_optimised.ts | 25 + .../slice_variable_parameter.ts | 25 + .../split_or_slice_signature.ts | 27 + .../valid-contract-files/split_size.ts | 28 + .../valid-contract-files/split_typed.ts | 23 + .../string_concatenation.ts | 21 + .../string_with_escaped_characters.ts | 31 + .../valid-contract-files/sum_input_amount.ts | 36 + .../token_category_comparison.ts | 21 + .../valid-contract-files/trailing_comma.ts | 50 + .../tuple_reassignment.ts | 46 + .../tuple_reassignment_after_final_read.ts | 76 + .../tuple_reassignment_branches.ts | 74 + .../valid-contract-files/tuple_unpacking.ts | 27 + .../tuple_unpacking_parameter.ts | 26 + .../tuple_unpacking_single_side_type.ts | 23 + .../valid-contract-files/type_enforcement.ts | 86 + .../valid-contract-files/unsafe_bool_cast.ts | 14 + .../valid-contract-files/unsafe_int_cast.ts | 24 + .../valid-contract-files/unused_modifier.ts | 93 + .../valid-contract-files/while_loop.ts | 24 + .../valid-contract-files/while_loop_basic.ts | 22 + .../valid-contract-files/while_loop_nested.ts | 46 + .../cashc/test/generation/generation.test.ts | 51 +- .../cashc/test/global-definitions.test.ts | 2 +- packages/utils/src/script.ts | 2 +- 109 files changed, 4211 insertions(+), 2091 deletions(-) create mode 100644 packages/cashc/test/generation/fixture-utils.ts delete mode 100644 packages/cashc/test/generation/fixtures.ts create mode 100644 packages/cashc/test/generation/fixtures/import-fixtures/diamond.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/2_of_3_multisig.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/announcement.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/bigint.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/bitshift.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/bitwise.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/bounded_bytes.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/bytes1_equals_byte.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/bytes_type_narrowing.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/cast_hash_checksig.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/checkdatasig_in_function.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/comments.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/complex_loop.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/compound_assign.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/correct_pragma.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/covenant.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/covenant_all_fields.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/date_literal.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/debug_messages.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/deep_replace.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/deeply_nested-logs.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/deeply_nested.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop_no_introspection.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop_require_inside_loop.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/double_negation.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/double_split.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/everything.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/for_loop_basic.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/for_loop_stack_items.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/for_while_nested.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/force_cast_smaller_bytes.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_arithmetic.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_inlined.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_literals.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_shared.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_altstack_cleanup.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_in_control_flow.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_inlined.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_param.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_return.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_return_three.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_nested.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_simple.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/global_function_void.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/hodl_vault.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/if_statement.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/if_statement_number_units-logs.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/if_statement_number_units.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/increment_decrement.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/int_to_byte.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/integer_formatting.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/invert.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/log_intermediate_results.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/mecenas.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/multifunction.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/multifunction_if_statements.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/multiline_array_multisig.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/multiline_statements.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/multiplication.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/num2bin.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/num2bin_variable.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/p2palindrome.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh-logs.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh_with_assignment.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh_with_cast.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/reassignment.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_cast.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_checkdatasig.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_constant.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_covenant.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_functions.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_if_statement.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_multisig.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_splice.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simple_variables.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/simulating_state.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/slice.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/slice_optimised.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/slice_variable_parameter.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/split_or_slice_signature.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/split_size.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/split_typed.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/string_concatenation.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/string_with_escaped_characters.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/sum_input_amount.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/token_category_comparison.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/trailing_comma.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment_after_final_read.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment_branches.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking_parameter.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking_single_side_type.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/type_enforcement.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/unsafe_bool_cast.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/unsafe_int_cast.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/unused_modifier.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/while_loop.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/while_loop_basic.ts create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/while_loop_nested.ts diff --git a/packages/cashc/src/internal.ts b/packages/cashc/src/internal.ts index 4d5d7a98b..583874697 100644 --- a/packages/cashc/src/internal.ts +++ b/packages/cashc/src/internal.ts @@ -4,5 +4,5 @@ * from the package's public API. This module is not re-exported from the package index and * carries no stability guarantees. */ -export { compileFileInternal as compileFile, compileStringInternal as compileString } from './compiler.js'; +export { compileFileInternal as compileFile, compileStringInternal as compileString, DEFAULT_COMPILER_OPTIONS } from './compiler.js'; export type { InternalCompilerOptions } from './compiler.js'; diff --git a/packages/cashc/test/compiler/compiler.test.ts b/packages/cashc/test/compiler/compiler.test.ts index f121476ca..19fef16ce 100644 --- a/packages/cashc/test/compiler/compiler.test.ts +++ b/packages/cashc/test/compiler/compiler.test.ts @@ -1,10 +1,3 @@ -/* Compiler.test.ts - * - * - This file is used to test the overall functioning of the compiler. - * - It tests successful compilation using fixture .cash files in ../valid-contract-files. - * - It tests compile errors using fixture .cash files in respective Error directories. - */ - import { URL } from 'url'; import { getSubdirectories, readCashFiles } from '../test-utils.js'; import * as Errors from '../../src/Errors.js'; @@ -21,14 +14,6 @@ contract Test() { const INVALID_SOURCE = 'contract Test() { function unlock() { require(true) } }'; describe('Compiler', () => { - describe('Successful compilation', () => { - readCashFiles(new URL('../valid-contract-files', import.meta.url)).forEach((file) => { - it(`${file.fn} should succeed`, () => { - expect(() => compileString(file.contents)).not.toThrow(); - }); - }); - }); - describe('Compilation errors', () => { const errorTypes = getSubdirectories(new URL('.', import.meta.url)); diff --git a/packages/cashc/test/generation/fixture-utils.ts b/packages/cashc/test/generation/fixture-utils.ts new file mode 100644 index 000000000..5946ffd7c --- /dev/null +++ b/packages/cashc/test/generation/fixture-utils.ts @@ -0,0 +1,30 @@ +import fs from 'fs'; +import { URL } from 'url'; +import { Artifact } from '@cashscript/utils'; +import { InternalCompilerOptions } from '../../src/internal.js'; + +export interface Fixture { + compilerOptions?: InternalCompilerOptions; + artifact: Omit; +} + +export interface FixtureModule { + cashFile: string; + fixtures: Fixture[]; +} + +export async function loadFixtureModules(): Promise { + const modulePaths = fs.readdirSync(new URL('fixtures/', import.meta.url), { recursive: true, encoding: 'utf-8' }) + .map((entry) => entry.replaceAll('\\', '/')) + .filter((entry) => entry.endsWith('.ts')); + + return Promise.all(modulePaths.map(async (modulePath) => { + const imported = await import(`./fixtures/${modulePath.replace(/\.ts$/, '.js')}`); + + if (!Array.isArray(imported.fixtures)) { + throw new Error(`Fixture module fixtures/${modulePath} must export a 'fixtures' array`); + } + + return { cashFile: modulePath.replace(/\.ts$/, '.cash'), fixtures: imported.fixtures }; + })); +} diff --git a/packages/cashc/test/generation/fixtures.ts b/packages/cashc/test/generation/fixtures.ts deleted file mode 100644 index 219eeb70a..000000000 --- a/packages/cashc/test/generation/fixtures.ts +++ /dev/null @@ -1,2062 +0,0 @@ -import { Artifact } from '@cashscript/utils'; -import { InternalCompilerOptions } from '../../src/internal.js'; -import fs from 'fs'; -import { URL } from 'url'; -import { version } from '../../src/index.js'; - -interface Fixture { - fn: string, - artifact: Artifact, - compilerOptions?: InternalCompilerOptions, -} - -export const fixtures: Fixture[] = [ - { - fn: 'p2pkh.cash', - artifact: { - contractName: 'P2PKH', - constructorInputs: [{ name: 'pkh', type: 'bytes20' }], - abi: [{ name: 'spend', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }], - bytecode: - // require(hash160(pk) == pkh) - 'OP_OVER OP_HASH160 OP_EQUALVERIFY ' - // require(checkSig(s, pk)) - + 'OP_CHECKSIG', - debug: { - bytecode: '78a988ac', - logs: [], - requires: [ - { ip: 3, line: 3 }, - { ip: 5, line: 4 }, - ], - sourceMap: '3:24:3:26;:16::27:1;:8::36;4::4:33', - }, - source: fs.readFileSync(new URL('../valid-contract-files/p2pkh.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '07f5c2c2cf10439f063f3b92b9420b110614fb57b5c5015120bfca2688fedcc7', - }, - }, - { - fn: 'reassignment.cash', - artifact: { - contractName: 'Reassignment', - constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'string' }], - abi: [{ name: 'hello', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }], - bytecode: - // int myVariable = 10 - 4 - 'OP_10 OP_4 OP_SUB ' - // int myOtherVariable = 20 + myVariable % 2 - + '14 OP_SWAP OP_2 OP_MOD OP_ADD ' - // require(myOtherVariable > x) - + 'OP_LESSTHAN OP_VERIFY ' - // string hw = "Hello World" - + '48656c6c6f20576f726c64 ' - // hw = hw + y - + 'OP_DUP OP_ROT OP_CAT ' - // require(ripemd160(pk) == ripemd160(hw)) - + 'OP_2 OP_PICK OP_RIPEMD160 OP_SWAP OP_RIPEMD160 OP_EQUALVERIFY ' - // require(checkSig(s, pk)) - + 'OP_ROT OP_ROT OP_CHECKSIG ' - + 'OP_NIP', - debug: { - bytecode: '5a549401147c5297939f690b48656c6c6f20576f726c64767b7e5279a67ca6887b7bac77', - logs: [], - requires: [ - { ip: 11, line: 5 }, - { ip: 21, line: 10 }, - { ip: 25, line: 11 }, - ], - sourceMap: '3:25:3:27;:30::31;:25:::1;4:30:4:32:0;:35::45;:48::49;:35:::1;:30;5:16:5:35;:8::37;7:20:7:33:0;8:13:8:15;:18::19;:13:::1;10:26:10:28:0;;:16::29:1;:43::45:0;:33::46:1;:8::48;11:25:11:26:0;:28::30;:8::33:1;2:37:12:5', - sourceTags: '23:23:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/reassignment.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '7dfcd01f0ecb5e1dec3d2fb363b5af79eb84a15395e1b57fe9c383cb3861d634', - }, - }, - { - fn: 'if_statement.cash', - artifact: { - contractName: 'IfStatement', - constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], - abi: [{ name: 'hello', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }] }], - bytecode: - // int d = a + b - 'OP_2OVER OP_ADD ' - // d = d - a - + 'OP_DUP OP_4 OP_PICK OP_SUB ' - // if (d == x - 2) { - + 'OP_DUP OP_3 OP_ROLL OP_2 OP_SUB OP_NUMEQUAL OP_IF ' - // int c = d + b - + 'OP_DUP OP_5 OP_PICK OP_ADD ' - // d = a + c - + 'OP_4 OP_PICK OP_OVER OP_ADD OP_ROT OP_DROP OP_SWAP ' - // require(c > d) - + 'OP_2DUP OP_LESSTHAN OP_VERIFY ' - // } else { - + 'OP_DROP OP_ELSE ' - // require(d == a) } - + 'OP_DUP OP_4 OP_PICK OP_NUMEQUALVERIFY OP_ENDIF ' - // d = d + a - + 'OP_DUP OP_4 OP_ROLL OP_ADD ' - // require(d == y) - + 'OP_3 OP_ROLL OP_NUMEQUAL ' - + 'OP_NIP OP_NIP OP_NIP', - debug: { - bytecode: '70937654799476537a52949c6376557993547978937b757c6e9f6975677654799d6876547a93537a9c777777', - logs: [], - requires: [ - { ip: 28, line: 8 }, - { ip: 34, line: 10 }, - { ip: 43, line: 13 }, - ], - sourceMap: '3:16:3:21;::::1;4:12:4:13:0;:16::17;;:12:::1;5::5:13:0;:17::18;;:21::22;:17:::1;:12;:24:9:9:0;6:20:6:21;:24::25;;:20:::1;7:16:7:17:0;;:20::21;:16:::1;:12::22;;;8:20:8:25:0;::::1;:12::27;5:24:9:9;9:15:11::0;10:20:10:21;:25::26;;:12::28:1;9:15:11:9;12:12:12:13:0;:16::17;;:12:::1;13:21:13:22:0;;:8::24:1;2:33:14:5;;', - sourceTags: '27:27:sc;41:43:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/if_statement.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'b5f6c8b6bd5a7e4bfa2a596b5639fac59338e9cbf93673abc8c32fd4565f2846', - }, - }, - { - fn: 'multifunction.cash', - artifact: { - contractName: 'MultiFunction', - constructorInputs: [{ name: 'sender', type: 'pubkey' }, { name: 'recipient', type: 'pubkey' }, { name: 'timeout', type: 'int' }], - abi: [ - { name: 'transfer', inputs: [{ name: 'recipientSig', type: 'sig' }] }, - { name: 'timeout', inputs: [{ name: 'senderSig', type: 'sig' }] }, - ], - bytecode: - // function transfer - 'OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' - // require(checkSig(recipientSig, recipient)) - + 'OP_4 OP_ROLL OP_ROT OP_CHECKSIG ' - + 'OP_NIP OP_NIP OP_NIP OP_ELSE ' - // function timeout - + 'OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY ' - // require(checkSig(senderSig, sender)) - + 'OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY ' - // require(tx.time >= timeout) - + 'OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_2DROP OP_1 ' - + 'OP_ENDIF', - debug: { - bytecode: '5379009c63547a7bac77777767537a519d537a7cad7cb16d5168', - logs: [], - requires: [ - { ip: 12, line: 7 }, - { ip: 23, line: 11 }, - { ip: 25, line: 12 }, - ], - sourceMap: '6:4:8:5;;;;;7:25:7:37;;:39::48;:8::51:1;6:40:8:5;;;:4;10::13::0;;;;11:25:11:34;;:36::42;:8::45:1;12:27:12:34:0;:8::36:1;10:36:13:5;;1:0:14:1', - sourceTags: '9:11:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/multifunction.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '4367893ec13aecfe4624b6d5b12681b9782de30dd657d1313eed269faba937e4', - }, - }, - { - fn: 'multifunction_if_statements.cash', - artifact: { - contractName: 'MultiFunctionIfStatements', - constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], - abi: [ - { name: 'transfer', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }] }, - { name: 'timeout', inputs: [{ name: 'b', type: 'int' }] }, - ], - bytecode: - // function transfer - 'OP_2 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' - // int d = a + b - + 'OP_3 OP_PICK OP_5 OP_PICK OP_ADD ' - // d = d - a - + 'OP_DUP OP_5 OP_PICK OP_SUB ' - // if (d == x && bool(x)) { - + 'OP_DUP OP_3 OP_PICK OP_NUMEQUAL OP_3 OP_ROLL OP_0NOTEQUAL OP_BOOLAND OP_IF ' - // int c = d + b - + 'OP_DUP OP_6 OP_PICK OP_ADD ' - // d = a + c - + 'OP_5 OP_PICK OP_OVER OP_ADD OP_ROT OP_DROP OP_SWAP ' - // require(c > d) - + 'OP_2DUP OP_LESSTHAN OP_VERIFY ' - // } else { - + 'OP_DROP OP_ELSE ' - // d = a } - + 'OP_4 OP_PICK OP_NIP OP_ENDIF ' - // d = d + a - + 'OP_DUP OP_5 OP_ROLL OP_ADD ' - // require(d == y) - + 'OP_3 OP_ROLL OP_NUMEQUALVERIFY ' - + 'OP_2DROP OP_2DROP OP_1 OP_ELSE ' - // function timeout - + 'OP_ROT OP_1 OP_NUMEQUALVERIFY ' - // int d = b - + 'OP_2 OP_PICK ' - // d = d + 2 - + 'OP_DUP OP_2 OP_ADD ' - // if (d == x) { - + 'OP_DUP OP_3 OP_ROLL OP_NUMEQUAL OP_IF ' - // int c = d + b - + 'OP_DUP OP_4 OP_PICK OP_ADD ' - // d = c + d - + 'OP_2DUP OP_ADD OP_ROT OP_DROP OP_SWAP ' - // require(c > d) } - + 'OP_2DUP OP_LESSTHAN OP_VERIFY ' - + 'OP_DROP OP_ENDIF ' - // d = b - + '' - // require(d == y) - + 'OP_2SWAP OP_NUMEQUAL ' - + 'OP_NIP OP_NIP OP_ENDIF', - debug: { - bytecode: '5279009c635379557993765579947653799c537a929a6376567993557978937b757c6e9f6975675479776876557a93537a9d6d6d51677b519d527976529376537a9c63765479936e937b757c6e9f697568729c777768', - logs: [], - requires: [ - { ip: 38, line: 8 }, - { ip: 51, line: 13 }, - { ip: 80, line: 22 }, - { ip: 85, line: 25 }, - ], - sourceMap: '2:4:14:5;;;;;3:16:3:17;;:20::21;;:16:::1;4:12:4:13:0;:16::17;;:12:::1;5::5:13:0;:17::18;;:12:::1;:27::28:0;;:22::29:1;:12;:31:9:9:0;6:20:6:21;:24::25;;:20:::1;7:16:7:17:0;;:20::21;:16:::1;:12::22;;;8:20:8:25:0;::::1;:12::27;5:31:9:9;9:15:11::0;10:16:10:17;;:12::18:1;9:15:11:9;12:12:12:13:0;:16::17;;:12:::1;13:21:13:22:0;;:8::24:1;2:36:14:5;;;:4;16::26::0;;;17:16:17:17;;18:12:18:13;:16::17;:12:::1;19::19:13:0;:17::18;;:12:::1;:20:23:9:0;20::20:21;:24::25;;:20:::1;21:16:21:21:0;::::1;:12::22;;;22:20:22:25:0;::::1;:12::27;19:20:23:9;;24:12:25:22:0;25:8::24:1;16:28:26:5;;1:0:27:1', - sourceTags: '37:37:sc;79:79:sc;83:84:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/multifunction_if_statements.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'f57b39c9be272a31d1aedd678087b7dd327095fde647570149d237fb34401469', - }, - }, - { - fn: '2_of_3_multisig.cash', - artifact: { - contractName: 'MultiSig', - constructorInputs: [{ name: 'pk1', type: 'pubkey' }, { name: 'pk2', type: 'pubkey' }, { name: 'pk3', type: 'pubkey' }], - abi: [{ name: 'spend', inputs: [{ name: 's1', type: 'sig' }, { name: 's2', type: 'sig' }] }], - bytecode: - // require(checkMultiSig([s1, s2], [pk1, pk2, pk3])) - 'OP_0 OP_2ROT OP_SWAP OP_2 OP_2ROT OP_SWAP OP_6 OP_ROLL OP_3 OP_CHECKMULTISIG', - debug: { - bytecode: '00717c52717c567a53ae', - logs: [], - requires: [{ ip: 13, line: 3 }], - sourceMap: '3:12:3:52;:27::33;;:26::34:1;:37::45:0;;:47::50;;:36::51:1;:4::54', - }, - source: fs.readFileSync(new URL('../valid-contract-files/2_of_3_multisig.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'd06a42627510906395fa927195c1aa420b9adf7da407d71b793fc5d550b57a39', - }, - }, - { - fn: 'split_size.cash', - artifact: { - contractName: 'SplitSize', - constructorInputs: [{ name: 'b', type: 'bytes' }], - abi: [{ name: 'spend', inputs: [] }], - bytecode: - // bytes x = b.split(b.length / 2)[1] - 'OP_DUP OP_DUP OP_SIZE OP_NIP OP_2 OP_DIV OP_SPLIT OP_NIP ' - // require(x != b) - + 'OP_2DUP OP_EQUAL OP_NOT OP_VERIFY ' - // bytes x = b.split(b.length / 2)[1] - + 'OP_SWAP OP_4 OP_SPLIT OP_DROP OP_EQUAL OP_NOT', - debug: { - bytecode: '7676827752967f776e8791697c547f758791', - logs: [], - requires: [ - { ip: 12, line: 4 }, - { ip: 19, line: 5 }, - ], - sourceMap: '3:18:3:27;;:26::34:1;;:37::38:0;:26:::1;:18::39;:::42;4:16:4:22:0;::::1;;:8::24;5:16:5:17:0;:24::25;:16::26:1;:::29;:::34;:8::36', - }, - source: fs.readFileSync(new URL('../valid-contract-files/split_size.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '49d50376d8aa76534f29c049b987238d577ce332202a2f0da0cb74d94a027b79', - }, - }, - { - fn: 'cast_hash_checksig.cash', - artifact: { - contractName: 'CastHashChecksig', - constructorInputs: [], - abi: [{ name: 'hello', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }], - bytecode: - // require((ripemd160(bytes(pk)) == hash160(0x0) == !true)); - 'OP_DUP OP_RIPEMD160 OP_0 OP_HASH160 OP_EQUAL OP_1 OP_NOT OP_NUMEQUALVERIFY ' - // require(checkSig(s, pk)); - + 'OP_CHECKSIG', - debug: { - bytecode: '76a600a98751919dac', - logs: [], - requires: [ - { ip: 7, line: 3 }, - { ip: 9, line: 4 }, - ], - sourceMap: '3:33:3:35;:17::37:1;:49::51:0;:41::52:1;:17;:57::61:0;:56:::1;:8::64;4::4:33', - }, - source: fs.readFileSync(new URL('../valid-contract-files/cast_hash_checksig.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'bbf25f5a4cfbc9380707afca6d1f14a29c7971f589949d284859225508f4bad6', - }, - }, - { - fn: 'hodl_vault.cash', - artifact: { - contractName: 'HodlVault', - constructorInputs: [ - { name: 'ownerPk', type: 'pubkey' }, - { name: 'oraclePk', type: 'pubkey' }, - { name: 'minBlock', type: 'int' }, - { name: 'priceTarget', type: 'int' }, - ], - abi: [ - { - name: 'spend', - inputs: [ - { name: 'ownerSig', type: 'sig' }, - { name: 'oracleSig', type: 'datasig' }, - { name: 'oracleMessage', type: 'bytes8' }, - ], - }, - ], - bytecode: - // Implicit type enforcement for oracleMessage: require(oracleMessage.length == 8) - 'OP_6 OP_ROLL OP_SIZE OP_8 OP_EQUALVERIFY ' - // bytes4 blockHeightBin, bytes4 priceBin = oracleMessage.split(4); - + 'OP_DUP OP_4 OP_SPLIT ' - // int blockHeight = int(blockHeightBin); - + 'OP_SWAP OP_BIN2NUM ' - // int price = int(priceBin); - + 'OP_SWAP OP_BIN2NUM ' - // require(blockHeight >= minBlock); - + 'OP_OVER OP_6 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY ' - // require(tx.time >= blockHeight); - + 'OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_DROP ' - // require(price >= priceTarget); - + 'OP_4 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY ' - // require(checkDataSig(oracleSig, oracleMessage, oraclePk)); - + 'OP_4 OP_ROLL OP_SWAP OP_3 OP_ROLL OP_CHECKDATASIGVERIFY ' - // require(checkSig(ownerSig, ownerPk)); - + 'OP_CHECKSIG', - debug: { - bytecode: '567a82588876547f7c817c8178567aa2697cb175547aa269547a7c537abbac', - logs: [], - requires: [ - { ip: 20, line: 23 }, - { ip: 22, line: 24 }, - { ip: 27, line: 27 }, - { ip: 33, line: 30 }, - { ip: 35, line: 35 }, - ], - sourceMap: '15:8:15:28;;;;;18:49:18:62;:69::70;:49::71:1;19:30:19:44:0;:26::45:1;20:24:20:32:0;:20::33:1;23:16:23:27:0;:31::39;;:16:::1;:8::41;24:27:24:38:0;:8::40:1;;27:25:27:36:0;;:16:::1;:8::38;31:12:31:21:0;;32::32:25;33::33:20;;30:8:34:11:1;35::35:45', - sourceTags: '0:4:pv', - }, - source: fs.readFileSync(new URL('../valid-contract-files/hodl_vault.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'd87449bc71344f12ed3c9ce3f69f844cd1699df29553ec3884c1fcc92a2cfccf', - }, - }, - { - fn: 'deep_replace.cash', - artifact: { - contractName: 'DeepReplace', - constructorInputs: [], - abi: [{ name: 'hello', inputs: [] }], - bytecode: - // int a = 1; int b = 2; int c = 3; int d = 4; int e = 5; int f = 6; - 'OP_1 OP_2 OP_3 OP_4 OP_5 OP_6 ' - // if (a < 3) { - + 'OP_5 OP_PICK OP_3 OP_LESSTHAN OP_IF ' - // a = 3 } - + 'OP_3 OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP ' - + 'OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK ' - + 'OP_FROMALTSTACK OP_FROMALTSTACK OP_ENDIF ' - // require(a > b + c + d + e + f); - + 'OP_2ROT OP_5 OP_ROLL OP_ADD OP_4 OP_ROLL OP_ADD ' - + 'OP_3 OP_ROLL OP_ADD OP_ROT OP_ADD OP_GREATERTHAN', - debug: { - bytecode: '5152535455565579539f6353567a757c6b7c6b7c6b7c6b7c6c6c6c6c6871557a93547a93537a937b93a0', - logs: [], - requires: [{ ip: 42, line: 14 }], - sourceMap: '3:16:3:17;4::4;5::5;6::6;7::7;8::8;10:12:10:13;;:16::17;:12:::1;:19:12:9:0;11:16:11:17;:12::18:1;;;;;;;;;;;;;;;;10:19:12:9;14:16:14:21:0;:24::25;;:20:::1;:28::29:0;;:20:::1;:32::33:0;;:20:::1;:36::37:0;:20:::1;:8::39', - }, - source: fs.readFileSync(new URL('../valid-contract-files/deep_replace.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '5ec5f2a100dc5c29c95f58ed51e4da469b74e5932b070e38f3c30c3405f40005', - }, - }, - { - fn: 'bounded_bytes.cash', - artifact: { - contractName: 'BoundedBytes', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [{ name: 'b', type: 'bytes4' }, { name: 'i', type: 'int' }] }], - bytecode: - // Implicit type enforcement for b: require(b.length == 4) - 'OP_SIZE OP_4 OP_EQUALVERIFY ' - // require(b == toPaddedBytes(i, 4)) - + 'OP_SWAP OP_4 OP_NUM2BIN OP_EQUAL', - debug: { - bytecode: '8254887c548087', - logs: [], - requires: [{ ip: 7, line: 3 }], - sourceMap: '2:19:2:27;;;3:35:3:36;:38::39;:21::40:1;:8::42', - sourceTags: '0:2:pv', - }, - source: fs.readFileSync(new URL('../valid-contract-files/bounded_bytes.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'b6381ead9be56fd0f9aa43b986ae8c3ba6aae2276596cdbd8268628397391064', - }, - }, - { - fn: 'covenant.cash', - artifact: { - contractName: 'Covenant', - constructorInputs: [ - { - name: 'requiredVersion', - type: 'int', - }, - ], - abi: [{ name: 'spend', inputs: [] }], - bytecode: - // require(tx.version == requiredVersion) - 'OP_TXVERSION OP_NUMEQUALVERIFY ' - // require(tx.bytecode == 0x00) - + 'OP_ACTIVEBYTECODE 00 OP_EQUAL', - debug: { - bytecode: 'c29dc1010087', - logs: [], - requires: [ - { ip: 2, line: 3 }, - { ip: 6, line: 4 }, - ], - sourceMap: '3:16:3:26;:8::47:1;4:16:4:35:0;:39::43;:8::45:1', - }, - source: fs.readFileSync(new URL('../valid-contract-files/covenant.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '1fd180f7d78e9670d7b2ae95e7af1f7cc533fc42c3cfdc7872619ec5810487d2', - }, - }, - { - fn: 'covenant_all_fields.cash', - artifact: { - contractName: 'Covenant', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [] }], - bytecode: - // injected by InjectLocktimeGuardTraversal because tx.locktime is used - 'OP_TXLOCKTIME OP_CHECKLOCKTIMEVERIFY OP_DROP ' - // require(tx.version == 2) - + 'OP_TXVERSION OP_2 OP_NUMEQUALVERIFY ' - // require(tx.locktime == 0) - + 'OP_TXLOCKTIME OP_0 OP_NUMEQUALVERIFY ' - // require(tx.inputs.length == 1) - + 'OP_TXINPUTCOUNT OP_1 OP_NUMEQUALVERIFY ' - // require(tx.outputs.length == 1) - + 'OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUALVERIFY ' - // require(this.activeInputIndex == 0) - + 'OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY ' - // require(this.activeBytecode.length == 300) - + 'OP_ACTIVEBYTECODE OP_SIZE OP_NIP 2c01 OP_NUMEQUALVERIFY ' - // require(tx.inputs[0].value == 10000) - + 'OP_0 OP_UTXOVALUE 1027 OP_NUMEQUALVERIFY ' - // require(tx.inputs[0].lockingBytecode.length == 10000) - + 'OP_0 OP_UTXOBYTECODE OP_SIZE OP_NIP 1027 OP_NUMEQUALVERIFY ' - // require(tx.inputs[0].outpointTransactionHash == 0x00...00) - + 'OP_0 OP_OUTPOINTTXHASH 0000000000000000000000000000000000000000000000000000000000000000 OP_EQUALVERIFY ' - // require(tx.inputs[0].outpointIndex == 0) - + 'OP_0 OP_OUTPOINTINDEX OP_0 OP_NUMEQUALVERIFY ' - // require(tx.inputs[0].unlockingBytecode.length == 100) - + 'OP_0 OP_INPUTBYTECODE OP_SIZE OP_NIP 64 OP_NUMEQUALVERIFY ' - // require(tx.inputs[0].sequenceNumber == 0) - + 'OP_0 OP_INPUTSEQUENCENUMBER OP_0 OP_NUMEQUALVERIFY ' - // require(tx.outputs[0].value == 10000) - + 'OP_0 OP_OUTPUTVALUE 1027 OP_NUMEQUALVERIFY ' - // require(tx.outputs[0].lockingBytecode.length == 100) - + 'OP_0 OP_OUTPUTBYTECODE OP_SIZE OP_NIP 64 OP_NUMEQUALVERIFY ' - // require(tx.inputs[0].tokenCategory == 0x000000000000000000000000000000000000000000000000000000000000000) - + 'OP_0 OP_UTXOTOKENCATEGORY 0000000000000000000000000000000000000000000000000000000000000000 OP_EQUALVERIFY ' - // require(tx.inputs[0].nftCommitment == 0x00); - + 'OP_0 OP_UTXOTOKENCOMMITMENT 00 OP_EQUALVERIFY ' - // require(tx.inputs[0].tokenAmount == 100); - + 'OP_0 OP_UTXOTOKENAMOUNT 64 OP_NUMEQUALVERIFY ' - // require(tx.outputs[0].tokenCategory == 0x000000000000000000000000000000000000000000000000000000000000000) - + 'OP_0 OP_OUTPUTTOKENCATEGORY 0000000000000000000000000000000000000000000000000000000000000000 OP_EQUALVERIFY ' - // require(tx.outputs[0].nftCommitment == 0x00); - + 'OP_0 OP_OUTPUTTOKENCOMMITMENT 00 OP_EQUALVERIFY ' - // require(tx.outputs[0].tokenAmount == 100); - + 'OP_0 OP_OUTPUTTOKENAMOUNT 64 OP_NUMEQUAL', - debug: { - bytecode: 'c5b175c2529dc5009dc3519dc4519dc0009dc18277022c019d00c60210279d00c782770210279d00c82000000000000000000000000000000000000000000000000000000000000000008800c9009d00ca827701649d00cb009d00cc0210279d00cd827701649d00ce2000000000000000000000000000000000000000000000000000000000000000008800cf01008800d001649d00d12000000000000000000000000000000000000000000000000000000000000000008800d201008800d301649c', - logs: [], - requires: [ - { - ip: 1, - line: 2, - message: 'Using tx.locktime requires a non-final sequence number on the spending input', - }, - { ip: 5, line: 3 }, - { ip: 8, line: 4 }, - { ip: 11, line: 5 }, - { ip: 14, line: 6 }, - { ip: 17, line: 7 }, - { ip: 22, line: 8 }, - { ip: 26, line: 9 }, - { ip: 32, line: 10 }, - { ip: 36, line: 11 }, - { ip: 40, line: 12 }, - { ip: 46, line: 13 }, - { ip: 50, line: 14 }, - { ip: 54, line: 15 }, - { ip: 60, line: 16 }, - { ip: 64, line: 17 }, - { ip: 68, line: 18 }, - { ip: 72, line: 19 }, - { ip: 76, line: 20 }, - { ip: 80, line: 21 }, - { ip: 85, line: 22 }, - ], - sourceMap: '2:21:2:21;::::1;;3:16:3:26:0;:30::31;:8::33:1;4:16:4:27:0;:31::32;:8::34:1;5:16:5:32:0;:36::37;:8::39:1;6:16:6:33:0;:37::38;:8::40:1;7:16:7:37:0;:41::42;:8::44:1;8:16:8:35:0;:::42:1;;:46::49:0;:8::51:1;9:26:9:27:0;:16::34:1;:38::43:0;:8::45:1;10:26:10:27:0;:16::44:1;:::51;;:55::60:0;:8::62:1;11:26:11:27:0;:16::52:1;:56::121:0;:8::123:1;12:26:12:27:0;:16::42:1;:46::47:0;:8::49:1;13:26:13:27:0;:16::46:1;:::53;;:57::60:0;:8::62:1;14:26:14:27:0;:16::43:1;:47::48:0;:8::50:1;15:27:15:28:0;:16::35:1;:39::44:0;:8::46:1;16:27:16:28:0;:16::45:1;:::52;;:56::59:0;:8::61:1;17:26:17:27:0;:16::42:1;:46::111:0;:8::113:1;18:26:18:27:0;:16::42:1;:46::50:0;:8::52:1;19:26:19:27:0;:16::40:1;:44::47:0;:8::49:1;20:27:20:28:0;:16::43:1;:47::112:0;:8::114:1;21:27:21:28:0;:16::43:1;:47::51:0;:8::53:1;22:27:22:28:0;:16::41:1;:45::48:0;:8::50:1', - sourceTags: '0:2:lg', - }, - source: fs.readFileSync(new URL('../valid-contract-files/covenant_all_fields.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '371d30dbd28672395a164baee67b27ad86454fa53daccdb7a770a7916902f607', - }, - }, - { - fn: 'mecenas.cash', - artifact: { - contractName: 'Mecenas', - constructorInputs: [ - { name: 'recipient', type: 'bytes20' }, - { name: 'funder', type: 'bytes20' }, - { name: 'pledge', type: 'int' }, - { name: 'period', type: 'int' }, - ], - abi: [ - { name: 'receive', inputs: [] }, - { name: 'reclaim', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }, - ], - bytecode: - // function receive - 'OP_4 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' - // require(this.age >= period) - + 'OP_3 OP_ROLL OP_CHECKSEQUENCEVERIFY OP_DROP ' - // require(tx.inputs.length == 1) - + 'OP_TXINPUTCOUNT OP_1 OP_NUMEQUALVERIFY ' - // require(tx.outputs[0].lockingBytecode == new LockingBytecodeP2PKH(recipient)) - + 'OP_0 OP_OUTPUTBYTECODE 76a914 OP_ROT OP_CAT 88ac OP_CAT OP_EQUALVERIFY ' - // int minerFee = 1000 - + 'e803 ' - // int currentValue = tx.inputs[this.activeInputIndex].value - + 'OP_INPUTINDEX OP_UTXOVALUE ' - // int changeValue = currentValue - pledge - minerFee - + 'OP_DUP OP_4 OP_PICK OP_SUB OP_2 OP_PICK OP_SUB ' - // if (changeValue <= pledge + minerFee) { - + 'OP_DUP OP_5 OP_PICK OP_4 OP_PICK OP_ADD OP_LESSTHANOREQUAL OP_IF ' - // require(tx.outputs[0].value == currentValue - minerFee) - + 'OP_0 OP_OUTPUTVALUE OP_2OVER OP_SWAP OP_SUB OP_NUMEQUALVERIFY ' - // } else { - + 'OP_ELSE ' - // require(tx.outputs[0].value == pledge) - + 'OP_0 OP_OUTPUTVALUE OP_5 OP_PICK OP_NUMEQUALVERIFY ' - // require( - // tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode - // ) - + 'OP_1 OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUALVERIFY ' - // require(tx.outputs[1].value == changeValue) } - + 'OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY ' - // Cleanup - + 'OP_ENDIF OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE ' - // function reclaim - + 'OP_4 OP_ROLL OP_1 OP_NUMEQUALVERIFY ' - // require(hash160(pk) == funder) - + 'OP_4 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY ' - // require(checkSig(s, pk)) - + 'OP_4 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG ' - // Cleanup - + 'OP_NIP OP_NIP OP_NIP OP_ENDIF', - debug: { - bytecode: '5479009c63537ab275c3519d00cd0376a9147b7e0288ac7e8802e803c0c676547994527994765579547993a16300cc707c949d6700cc55799d51cdc0c78851cc789d686d6d6d5167547a519d5479a97b88547a547aac77777768', - logs: [], - requires: [ - { ip: 11, line: 3 }, - { ip: 15, line: 7 }, - { ip: 23, line: 10 }, - { ip: 47, line: 19 }, - { ip: 53, line: 21 }, - { ip: 58, line: 22 }, - { ip: 62, line: 23 }, - { ip: 77, line: 28 }, - { ip: 83, line: 29 }, - ], - sourceMap: '2:4:25:5;;;;;3:28:3:34;;:8::36:1;;7:16:7:32:0;:36::37;:8::39:1;10:27:10:28:0;:16::45:1;:49::84:0;:74::83;:49::84:1;;;:8::86;12:23:12:27:0;13:37:13:58;:27::65:1;14:26:14:38:0;:41::47;;:26:::1;:50::58:0;;:26:::1;18:12:18:23:0;:27::33;;:36::44;;:27:::1;:12;:46:20:9:0;19:31:19:32;:20::39:1;:43::66:0;;::::1;:12::68;20:15:24:9:0;21:31:21:32;:20::39:1;:43::49:0;;:12::51:1;22:31:22:32:0;:20::49:1;:63::84:0;:53::101:1;:12::103;23:31:23:32:0;:20::39:1;:43::54:0;:12::56:1;20:15:24:9;2:23:25:5;;;;:4;27::30::0;;;;28:24:28:26;;:16::27:1;:31::37:0;:8::39:1;29:25:29:26:0;;:28::30;;:8::33:1;27:39:30:5;;;1:0:31:1', - sourceTags: '79:81:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/mecenas.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '82af4e70abe6257185f9fa2b9b65377949794a7f3f862a65eb3c61ec6bbff28a', - }, - }, - { - fn: 'announcement.cash', - artifact: { - contractName: 'Announcement', - constructorInputs: [], - abi: [{ name: 'announce', inputs: [] }], - bytecode: - // bytes announcement = new LockingBytecodeNullData(...) - '6a 6d02 OP_SIZE OP_SWAP OP_CAT OP_CAT ' - + '4120636f6e7472616374206d6179206e6f7420696e6a75726520612068756d616e20626' - + '5696e67206f722c207468726f75676820696e616374696f6e2c20616c6c6f77206120687' - + '56d616e206265696e6720746f20636f6d6520746f206861726d2e ' - + 'OP_SIZE OP_DUP 4b OP_GREATERTHAN OP_IF 4c OP_SWAP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_CAT ' - // require(tx.outputs[0].value == 0) - + 'OP_0 OP_OUTPUTVALUE OP_0 OP_NUMEQUALVERIFY ' - // require(tx.outputs[0].lockingBytecode == announcement) - + 'OP_0 OP_OUTPUTBYTECODE OP_EQUALVERIFY ' - // int minerFee = 1000 - + 'e803 ' - // int changeAmount = tx.inputs[this.activeInputIndex].value - minerFee - + 'OP_INPUTINDEX OP_UTXOVALUE OP_OVER OP_SUB ' - // if (changeAmount >= minerFee) - + 'OP_DUP OP_ROT OP_GREATERTHANOREQUAL OP_IF ' - // require( - // tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode - // ) - + 'OP_1 OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUALVERIFY ' - // require(tx.outputs[1].value == changeAmount) } - + 'OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY OP_ENDIF ' - // Stack clean-up - + 'OP_DROP OP_1', - debug: { - bytecode: '016a026d02827c7e7e4c624120636f6e7472616374206d6179206e6f7420696e6a75726520612068756d616e206265696e67206f722c207468726f75676820696e616374696f6e2c20616c6c6f7720612068756d616e206265696e6720746f20636f6d6520746f206861726d2e8276014ba063014c7c7e687c7e7e00cc009d00cd8802e803c0c67894767ba26351cdc0c78851cc789d687551', - logs: [], - requires: [ - { ip: 22, line: 16 }, - { ip: 25, line: 17 }, - { ip: 39, line: 24 }, - { ip: 43, line: 25 }, - ], - sourceMap: '10:29:13:10;11:12:11:18;::::1;;;;12:18:12:118:0;:12::119:1;;;;;;;;;;;;16:27:16:28:0;:16::35:1;:39::40:0;:8::42:1;17:27:17:28:0;:16::45:1;:8::63;21:23:21:27:0;22:37:22:58;:27::65:1;:68::76:0;:27:::1;23:12:23:24:0;:28::36;:12:::1;:38:26:9:0;24:31:24:32;:20::49:1;:63::84:0;:53::101:1;:12::103;25:31:25:32:0;:20::39:1;:43::55:0;:12::57:1;23:38:26:9;8:24:27:5;', - }, - source: fs.readFileSync(new URL('../valid-contract-files/announcement.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '542596767034cea0f3a5933a1efa49bb9aa569ec70c5f0261afd36ea845fa746', - }, - }, - { - fn: 'p2palindrome.cash', - artifact: { - contractName: 'P2Palindrome', - constructorInputs: [], - abi: [ - { name: 'spend', inputs: [{ name: 'palindrome', type: 'string' }] }, - ], - bytecode: 'OP_DUP OP_REVERSEBYTES OP_EQUAL', - debug: { - bytecode: '76bc87', - logs: [], - requires: [{ ip: 3, line: 3 }], - sourceMap: '3:16:3:26;:::36:1;:8::52', - }, - source: fs.readFileSync(new URL('../valid-contract-files/p2palindrome.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '4e9480ee14cf131a78be8da27e585e3d62c0e9cfa75d8338f2d51a67d84df0c7', - }, - }, - { - fn: 'num2bin_variable.cash', - artifact: { - contractName: 'Num2Bin', - constructorInputs: [], - abi: [ - { name: 'spend', inputs: [{ name: 'size', type: 'int' }] }, - ], - bytecode: 'OP_10 OP_SWAP OP_NUM2BIN OP_BIN2NUM OP_10 OP_NUMEQUAL', - debug: { - bytecode: '5a7c80815a9c', - logs: [], - requires: [{ ip: 6, line: 4 }], - sourceMap: '3:36:3:38;:40::44;:22::45:1;4:16:4:26;:30::32:0;:8::34:1', - }, - source: fs.readFileSync(new URL('../valid-contract-files/num2bin_variable.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '7ebb008689b080dce1061a508173a617c58b68202899cfd17a32f1a5decd4bb6', - }, - }, - { - fn: 'debug_messages.cash', - artifact: { - contractName: 'DebugMessages', - constructorInputs: [], - abi: [ - { name: 'spend', inputs: [{ name: 'value', type: 'int' }] }, - ], - bytecode: 'OP_DUP OP_1 OP_NUMEQUALVERIFY OP_1ADD OP_2 OP_NUMEQUAL', - debug: { - bytecode: '76519d8b529c', - logs: [ - { data: [{ stackIndex: 0, type: 'int', ip: 3 }, 'test'], ip: 3, line: 4 }, - { data: [{ stackIndex: 0, type: 'int', ip: 3 }, 'test2'], ip: 3, line: 5 }, - ], - requires: [{ ip: 2, line: 3, message: 'Wrong value passed' }, { ip: 6, line: 6, message: 'Sum doesn\'t work' }], - sourceMap: '3:12:3:17;:21::22;:4::46:1;6:12:6:21;:25::26:0;:4::48:1', - }, - source: fs.readFileSync(new URL('../valid-contract-files/debug_messages.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '2a4f5039ce0a481742e5b1712388a879ec8c5b617c4d4a8d676cc28d029c604f', - }, - }, - { - fn: 'integer_formatting.cash', - artifact: { - contractName: 'IntegerFormatting', - constructorInputs: [], - abi: [ - { name: 'test', inputs: [] }, - ], - bytecode: '0010a5d4e800 0010a5d4e800 0010a5d4e800 0010a5d4e800 0010a5d4e800 OP_4 OP_ROLL OP_OVER OP_NUMEQUALVERIFY OP_3 OP_ROLL OP_OVER OP_NUMEQUALVERIFY OP_ROT OP_OVER OP_NUMEQUALVERIFY OP_NUMEQUAL', - debug: { - bytecode: '060010a5d4e800060010a5d4e800060010a5d4e800060010a5d4e800060010a5d4e800547a789d537a789d7b789d9c', - logs: [], - requires: [{ ip: 8, line: 10 }, { ip: 12, line: 11 }, { ip: 15, line: 12 }, { ip: 17, line: 13 }], - sourceMap: '3:26:3:30;4::4;5::5:43;6:23:6:30;8:22:8:35;10:16:10:27;;:31::38;:8::40:1;11:16:11:27:0;;:31::38;:8::40:1;12:16:12:27:0;:31::38;:8::40:1;13::13:37', - }, - source: fs.readFileSync(new URL('../valid-contract-files/integer_formatting.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '0b4ca541ca3bfd698bda9798bc6ce5565513848fe325360248ec00266d84c874', - }, - }, - { - fn: 'multiline_statements.cash', - artifact: { - contractName: 'MultilineStatements', - constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'string' }], - abi: [{ name: 'spend', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'string' }] }], - bytecode: 'OP_ROT OP_SWAP OP_2 OP_SUB OP_NUMEQUAL OP_2 OP_PICK OP_2 OP_PICK OP_EQUAL OP_BOOLAND OP_IF OP_0 OP_VERIFY OP_ELSE OP_OVER 48656c6c6f20 OP_2 OP_PICK OP_CAT OP_EQUAL OP_IF OP_DUP 576f726c64 OP_EQUALVERIFY OP_ELSE OP_1 OP_0 OP_NOT OP_NOT OP_NOT OP_NUMEQUALVERIFY OP_ENDIF OP_ENDIF OP_2DROP OP_1', - debug: { - bytecode: '7b7c52949c52795279879a63006967780648656c6c6f2052797e87637605576f726c64886751009191919d68686d51', - logs: [], - requires: [ - { ip: 15, line: 11 }, - { ip: 26, line: 14 }, - { ip: 33, line: 18 }, - ], - sourceMap: '9:12:9:13;:17::18;:21::22;:17:::1;:12;10::10:13:0;;:17::18;;:12:::1;9;10:20:12:9:0;11::11:25;:12::27:1;12:15:19:9:0;:19:12:20;:24::32;13:10:13:11;;12:24:::1;:19;13:13:17:9:0;15:16:15:17;:21::28;14:12:16:14:1;17:15:19:9:0;18:20:18:24;:31::36;:30:::1;:29;:28;:12::38;17:15:19:9;12;8:6:20:5;', - }, - source: fs.readFileSync(new URL('../valid-contract-files/multiline_statements.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'd2aa37425c07883d3c7df823103f88a6a061d3efca1e6317b9e72e0ad4bd3611', - }, - }, - { - fn: 'log_intermediate_results.cash', - artifact: { - contractName: 'LogIntermediateResults', - constructorInputs: [{ name: 'owner', type: 'pubkey' }], - abi: [{ name: 'test_log_intermediate_result', inputs: [] }], - bytecode: 'OP_HASH256 OP_SIZE OP_NIP 20 OP_NUMEQUAL', - debug: { - bytecode: 'aa827701209c', - sourceMap: '3:29:5:47:1;6:16:6:33;;:37::39:0;:8::74:1', - logs: [ - { - ip: 1, - line: 4, - data: [ - { - stackIndex: 0, - type: 'bytes32', - ip: 1, - transformations: 'OP_SHA256', - }, - ], - }, - ], - requires: [ - { - ip: 6, - line: 6, - message: 'doubleHash should be 32 bytes', - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/log_intermediate_results.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '47bb8f4ee4f62d7ecefc7f43fd7b61d2da71767df35d3dfd90149719287a0860', - }, - }, - { - fn: 'double_split.cash', - artifact: { - contractName: 'DoubleSplit', - constructorInputs: [{ name: 'pkh', type: 'bytes20' }], - abi: [{ name: 'spend', inputs: [] }], - bytecode: 'OP_INPUTINDEX OP_UTXOBYTECODE 17 OP_SPLIT OP_DROP OP_3 OP_SPLIT OP_NIP OP_EQUAL', - debug: { - bytecode: 'c0c701177f75537f7787', - sourceMap: '3:36:3:57;:26::74:1;:81::83:0;:26::84:1;:::87;:94::95:0;:26::96:1;:::99;4:8:4:34', - logs: [], - requires: [ - { - ip: 10, - line: 4, - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/double_split.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'd8574d80ab674df33841526cf2767c09a9dc02d2faea91746465e22e3b81ae3a', - }, - }, - { - fn: 'slice.cash', - artifact: { - contractName: 'Slice', - constructorInputs: [{ name: 'pkh', type: 'bytes20' }], - abi: [{ name: 'spend', inputs: [] }], - bytecode: 'OP_INPUTINDEX OP_UTXOBYTECODE 17 OP_SPLIT OP_DROP OP_3 OP_SPLIT OP_NIP OP_EQUAL', - debug: { - bytecode: 'c0c701177f75537f7787', - sourceMap: '3:36:3:57;:26::74:1;:84::86:0;:26::87:1;;:81::82:0;:26::87:1;;4:8:4:34', - logs: [], - requires: [ - { - ip: 10, - line: 4, - message: undefined, - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/slice.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'd8574d80ab674df33841526cf2767c09a9dc02d2faea91746465e22e3b81ae3a', - }, - }, - { - fn: 'slice_optimised.cash', - artifact: { - contractName: 'Slice', - constructorInputs: [{ name: 'data', type: 'bytes32' }], - abi: [{ name: 'spend', inputs: [] }], - bytecode: '14 OP_SPLIT OP_DROP OP_0 14 OP_NUM2BIN OP_EQUAL', - debug: { - bytecode: '01147f750001148087', - sourceMap: '3:36:3:38;:22::39:1;;4:37:4:38:0;:40::42;:23::43:1;:8::45', - logs: [], - requires: [ - { - ip: 8, - line: 4, - message: undefined, - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/slice_optimised.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '779b8278e2831727686ad5c96b85bb01bab5f2692edd34d703b9d437da77ac03', - }, - }, - { - fn: 'while_loop_basic.cash', - artifact: { - contractName: 'WhileLoopBasic', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [] }], - bytecode: 'OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_3 OP_NUMEQUAL', - debug: { - bytecode: '006576539f766b63768b77686c9166539c', - sourceMap: '3:16:3:17;5:8:7:9;:15:5:16;:19::20;:15:::1;;;:22:7:9:0;6:16:6:17;:::21:1;:12::22;5:22:7:9;;:8;;9:21:9:22:0;:8::24:1', - logs: [], - requires: [ - { ip: 17, line: 9 }, - ], - sourceTags: '11:14:lc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/while_loop_basic.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '5a456e72142ae6beb6f64a3af7edfe9e14295b17724c4dfec0d84940c545d457', - }, - }, - { - fn: 'for_loop_basic.cash', - artifact: { - contractName: 'ForLoopBasic', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [] }], - bytecode: 'OP_0 OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_2DUP OP_ADD OP_ROT OP_DROP OP_SWAP OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_3 OP_NUMEQUAL', - debug: { - bytecode: '00006576539f766b636e937b757c768b77686c916675539c', - sourceMap: '3:18:3:19;5:21:5:22;:8:7:9;:24:5:25;:28::29;:24:::1;;;:36:7:9:0;6:18:6:25;::::1;:12::26;;;5:31:5:32:0;:::34:1;;:36:7:9;;:8;;;9:23:9:24:0;:8::26:1', - logs: [], - requires: [ - { ip: 24, line: 9 }, - ], - sourceTags: '14:16:fu;17:20:lc;21:21:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/for_loop_basic.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '9e52dba656b0743057d4eda76f051c8a1f4460a2becf8f372c690b1901512b4e', - }, - }, - { - fn: 'for_loop_stack_items.cash', - artifact: { - contractName: 'ForLoopBasic', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [] }], - bytecode: 'OP_0 OP_1 OP_1 OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_3 OP_PICK OP_OVER OP_ADD OP_4 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_ROT OP_3 OP_NUMEQUALVERIFY OP_SWAP OP_1 OP_NUMEQUALVERIFY OP_1 OP_NUMEQUAL', - debug: { - bytecode: '005151006576539f766b6353797893547a757c6b7c6b7c6c6c768b77686c9166757b539d7c519d519c', - sourceMap: '3:18:3:19;4:16:4:17;5::5;7:21:7:22;:8:9:9;:24:7:25;:28::29;:24:::1;;;:39:9:9:0;8:18:8:21;;:24::25;:18:::1;:12::26;;;;;;;;;;7:31:7:32:0;:::37:1;;:39:9:9;;:8;;;11:16:11:19:0;:23::24;:8::26:1;12:16:12:17:0;:21::22;:8::24:1;13:21:13:22:0;:8::24:1', - logs: [], - requires: [ - { ip: 35, line: 11 }, - { ip: 38, line: 12 }, - { ip: 41, line: 13 }, - ], - sourceTags: '25:27:fu;28:31:lc;32:32:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/for_loop_stack_items.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '05430d75d110ff5d4525f7e34bbf2c86b8d22f4e5758f2e109180b801b21b8ec', - }, - }, - { - fn: 'for_while_nested.cash', - artifact: { - contractName: 'ForWhileNested', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [] }], - bytecode: 'OP_0 OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_2 OP_PICK OP_2 OP_PICK OP_ADD OP_OVER OP_ADD OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_4 OP_NUMEQUAL', - debug: { - bytecode: '00006576529f766b63006576529f766b6352795279937893537a757c6b7c6c768b77686c9166788b7b7577686c916675549c', - sourceMap: '3:18:3:19;5:21:5:22;:8:13:9;:24:5:25;:28::29;:24:::1;;;:42:13:9:0;6:20:6:21;8:12:12:13;:19:8:20;:23::24;:19:::1;;;:26:12:13:0;9:22:9:25;;:28::29;;:22:::1;:32::33:0;:22:::1;:16::34;;;;;;;10:20:10:21:0;:::25:1;:16::26;8:26:12:13;;:12;;5:35:5:36:0;:::40:1;:31;;::13:9;:42;;:8;;;15:23:15:24:0;:8::26:1', - logs: [ - { - ip: 34, - line: 11, - data: [ - 'sum:', - { stackIndex: 2, type: 'int', ip: 34 }, - 'i:', - { stackIndex: 1, type: 'int', ip: 34 }, - 'j:', - { stackIndex: 0, type: 'int', ip: 34 }, - ], - }, - ], - requires: [ - { ip: 50, line: 15 }, - ], - sourceTags: '34:37:lc;38:42:fu;43:46:lc;47:47:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/for_while_nested.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '9eb2ec48e103cb2b0d75a326b533756d8f5edb49b2ea43a5578f5ceebde8c2ce', - }, - }, - { - fn: 'while_loop.cash', - artifact: { - contractName: 'Loopy', - constructorInputs: [], - abi: [{ name: 'doLoop', inputs: [] }], - bytecode: 'OP_0 OP_BEGIN OP_DUP OP_TXINPUTCOUNT OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_2 OP_GREATERTHAN', - debug: { - bytecode: '006576c39f766b63768b77686c916652a0', - sourceMap: '3:16:3:17;5:8:7:9;:15:5:16;:19::35;:15:::1;;;:37:7:9:0;6:16:6:17;:::21:1;:12::22;5:37:7:9;;:8;;10:20:10:21:0;:8::23:1', - logs: [ - { ip: 15, line: 9, data: [{ stackIndex: 0, type: 'int', ip: 15 }] }, - ], - requires: [ - { ip: 17, line: 10 }, - ], - sourceTags: '11:14:lc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/while_loop.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '00fc9253e439b8a2f39ba60d1d173ff4d19f557802b40b750eb6df5f92b1001e', - }, - }, - { - fn: 'complex_loop.cash', - artifact: { - contractName: 'Loopy', - constructorInputs: [], - abi: [{ name: 'doLoop', inputs: [] }], - bytecode: 'OP_0 OP_0 OP_0 OP_0 OP_BEGIN OP_DUP OP_UTXOVALUE OP_4 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_1ADD OP_NIP OP_TXOUTPUTCOUNT OP_2DUP OP_LESSTHAN OP_DUP OP_IF OP_2 OP_PICK OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUAL OP_NOT OP_NIP OP_DUP OP_IF OP_4 OP_PICK OP_3 OP_PICK OP_OUTPUTVALUE OP_ADD OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_ELSE OP_3 OP_PICK OP_1ADD OP_4 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_ENDIF OP_ENDIF OP_2DROP OP_DUP OP_TXINPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL OP_2SWAP OP_GREATERTHAN OP_VERIFY OP_SWAP OP_0 OP_GREATERTHAN OP_NIP', - debug: { - bytecode: '000000006576c6547a757c6b7c6b7c6c6c768b77c46e9f76635279d100879177766354795379cc93557a757c6b7c6b7c6b7c6c6c6c6753798b547a757c6b7c6b7c6c6c68686d76c3a26672a0697c00a077', - sourceMap: '3:23:3:24;4:24:4:25;5:25:5:26;6:16:6:17;8:8:26:39;9:33:9:34;:23::41:1;:12::42;;;;;;;;;;10:16:10:17:0;:::21:1;:12::22;12:20:12:37:0;13:21:13:26;::::1;15:16:15:17:0;:19:25:13;16:31:16:32;;:20::47:1;:51::53:0;:20:::1;;:16::54;18:20:18:21:0;:23:20:17;19:32:19:41;;:55::56;;:44::63:1;:32;:20::64;;;;;;;;;;;;;20:23:22:17:0;21:33:21:43;;:::47:1;:20::48;;;;;;;;;;20:23:22:17;15:19:25:13;8:11:26:9;26:17::18:0;:21::37;8:8::39:1;;28:16:28:36:0;::::1;:8::38;29:16:29:26:0;:29::30;:8::32:1;2:22:30:5', - logs: [ - { ip: 68, line: 24, data: [{ stackIndex: 3, type: 'int', ip: 68 }] }, - ], - requires: [ - { ip: 76, line: 28 }, - { ip: 80, line: 29 }, - ], - sourceTags: '69:69:sc;80:80:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/complex_loop.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'fa36d9b24d49525e027ba3cf3accd349e9f84d0c1bbd1141e98d6894173a1a2a', - }, - }, - { - fn: 'do_while_loop_no_introspection.cash', - artifact: { - contractName: 'Loopy', - constructorInputs: [], - abi: [{ name: 'doLoop', inputs: [] }], - bytecode: 'OP_0 OP_2 OP_BEGIN OP_OVER OP_1ADD OP_ROT OP_DROP OP_SWAP OP_2DUP OP_ADD OP_10 OP_LESSTHAN OP_VERIFY OP_OVER OP_10 OP_GREATERTHANOREQUAL OP_UNTIL OP_2DROP OP_1', - debug: { - bytecode: '005265788b7b757c6e935a9f69785aa2666d51', - sourceMap: '3:16:3:17;4::4;6:8:10:25;7:16:7:17;:::21:1;:12::22;;;9:20:9:25:0;::::1;:28::30:0;:20:::1;:12::32;10:17:10:18:0;:21::23;6:8::25:1;;2:22:11:5;', - logs: [ - { ip: 8, line: 8, data: [{ stackIndex: 1, type: 'int', ip: 8 }] }, - ], - requires: [ - { ip: 12, line: 9 }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/do_while_loop_no_introspection.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '39b67bb19440620390b83e3bc1e638ea6827998f4a14c2d6e29c2afa9815b2fd', - }, - }, - { - fn: 'bitshift.cash', - artifact: { - contractName: 'Bitshift', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [] }], - bytecode: '1122334455667788 OP_4 OP_LSHIFTBIN OP_4 OP_RSHIFTBIN 0000000055667788 OP_EQUALVERIFY OP_8 OP_2 OP_RSHIFTNUM OP_1 OP_LSHIFTNUM OP_4 OP_NUMEQUAL', - debug: { - bytecode: '081122334455667788549854990800000000556677888858528e518d549c', - sourceMap: '3:19:3:37;4:24:4:25;:19:::1;:29::30:0;:19:::1;6:21:6:39:0;:8::41:1;8:16:8:17:0;9:21:9:22;:16:::1;:26::27:0;:16:::1;11:22:11:23:0;:8::25:1', - logs: [], - requires: [ - { ip: 6, line: 6 }, - { ip: 14, line: 11 }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/bitshift.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '2c9d2ddcd53c6f4e28320acf336260ece7958753802381a2528ddfa1840eb88a', - }, - }, - { - fn: 'type_enforcement.cash', - artifact: { - contractName: 'TypeEnforcement', - constructorInputs: [], - abi: [{ - name: 'spend', inputs: [ - { name: 'nonEnforcedInt', type: 'int' }, - { name: 'enforcedBool', type: 'bool' }, - { name: 'enforcedBytes', type: 'bytes4' }, - { name: 'nonEnforcedBytes', type: 'bytes' }, - ], - }], - bytecode: - // Implicit type enforcement for enforcedBool: enforcedBool = bool(enforcedBool) - 'OP_SWAP OP_0NOTEQUAL ' - // Implicit type enforcement for enforcedBytes: require(enforcedBytes.length == 4) - + 'OP_ROT OP_SIZE OP_4 OP_EQUALVERIFY ' - // if(enforcedBool == true) ) - + 'OP_OVER OP_1 OP_NUMEQUAL OP_IF ' - // require(nonEnforcedInt > 6) - + 'OP_2 OP_PICK OP_6 OP_GREATERTHAN OP_VERIFY ' - // Cleanup - + 'OP_ENDIF ' - // if(enforcedBool == false) { - + 'OP_SWAP OP_0 OP_NUMEQUAL OP_IF ' - // require(enforcedBytes == nonEnforcedBytes) - + 'OP_DUP OP_3 OP_PICK OP_EQUALVERIFY ' - // Cleanup - + 'OP_ENDIF OP_2DROP OP_DROP OP_1', - debug: { - bytecode: '7c927b82548878519c63527956a069687c009c6376537988686d7551', - sourceMap: '4:8:4:25;;5::5:28;;;;8:12:8:24;:28::32;:12:::1;:34:10:9:0;9:20:9:34;;:37::38;:20:::1;:12::40;8:34:10:9;12:12:12:24:0;:28::33;:12:::1;:35:14:9:0;13:20:13:33;:37::53;;:12::55:1;12:35:14:9;7:6:15:5;;', - sourceTags: '0:1:pv;2:5:pv', - logs: [], - requires: [ - { ip: 14, line: 9 }, - { ip: 23, line: 13 }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/type_enforcement.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'afc9b61abaaef4b60d435309b83b2cbd5750e2c1755ca903cfd3f438f7dc6126', - }, - }, - { - // Same as the fixture above, but with enforceFunctionParameterTypes disabled - fn: 'type_enforcement.cash', - compilerOptions: { - enforceFunctionParameterTypes: false, - }, - artifact: { - contractName: 'TypeEnforcement', - constructorInputs: [], - abi: [{ - name: 'spend', inputs: [ - { name: 'nonEnforcedInt', type: 'int' }, - { name: 'enforcedBool', type: 'bool' }, - { name: 'enforcedBytes', type: 'bytes4' }, - { name: 'nonEnforcedBytes', type: 'bytes' }, - ], - }], - bytecode: - // if(enforcedBool == true) - 'OP_OVER OP_1 OP_NUMEQUAL OP_IF ' - // require(nonEnforcedInt > 6) - + 'OP_DUP OP_6 OP_GREATERTHAN OP_VERIFY ' - // Cleanup - + 'OP_ENDIF ' - // if(enforcedBool == false) { - + 'OP_SWAP OP_0 OP_NUMEQUAL OP_IF ' - // require(enforcedBytes == nonEnforcedBytes) - + 'OP_OVER OP_3 OP_PICK OP_EQUALVERIFY ' - // Cleanup - + 'OP_ENDIF OP_2DROP OP_DROP OP_1', - debug: { - bytecode: '78519c637656a069687c009c6378537988686d7551', - sourceMap: '8:12:8:24;:28::32;:12:::1;:34:10:9:0;9:20:9:34;:37::38;:20:::1;:12::40;8:34:10:9;12:12:12:24:0;:28::33;:12:::1;:35:14:9:0;13:20:13:33;:37::53;;:12::55:1;12:35:14:9;7:6:15:5;;', - logs: [], - requires: [ - { ip: 7, line: 9 }, - { ip: 16, line: 13 }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/type_enforcement.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: false, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '606e540c38f161868964b683aeb0ddf93094dc36607397ef9b9f507f9028bc37', - }, - }, - { - // A single global function — the basic OP_DEFINE / OP_INVOKE calling convention. - fn: 'global_function_simple.cash', - compilerOptions: { disableInlining: true }, - artifact: { - contractName: 'GlobalFunctionSimple', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], - bytecode: - // OP_DEFINE double (id 0): return a * 2 - '5295 OP_0 OP_DEFINE ' - // require(double(x) == 6) - + 'OP_0 OP_INVOKE OP_6 OP_NUMEQUAL', - debug: { - bytecode: '0252950089008a569c', - logs: [], - requires: [ - { ip: 7, line: 7 }, - ], - sourceMap: '1::3:1;;::::1;7:16:7:25;;:29::30:0;:8::32:1', - functions: [ - { - id: 0, - name: 'double', - inputs: [{ name: 'a', type: 'int' }], - bytecode: '5295', - sourceMap: '2:15:2:16;:11:::1', - logs: [], - requires: [], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/global_function_simple.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'ef6dd7819e66a430286fe16f3d6dad7e026cf1970eda6bc620be7e7a3bdd2a4d', - }, - }, - { - // 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', - debug: { - bytecode: '019400897c008a579c', - logs: [], - requires: [ - { ip: 8, line: 7 }, - ], - sourceMap: '1::3:1;;::::1;7:23:7:24:0;:16::25:1;;: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', - logs: [], - requires: [], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/global_function_multi_param.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '8fc72a3f89ee3238266d6dd9ad3919f7238c8d6a31296cc8925968a31c78c7dc', - }, - }, - { - // 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: [], - abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], - bytecode: - // OP_DEFINE requirePositive (id 0): require(a > 0) - '00a069 OP_0 OP_DEFINE ' - // requirePositive(x); require(x < 100) - + 'OP_DUP OP_0 OP_INVOKE 64 OP_LESSTHAN', - debug: { - bytecode: '0300a069008976008a01649f', - logs: [], - requires: [ - { ip: 8, line: 8 }, - ], - sourceMap: '1::3:1;;::::1;7:24:7:25:0;:8::26:1;;8:20:8:23:0;:8::25:1', - functions: [ - { - id: 0, - name: 'requirePositive', - inputs: [{ name: 'a', type: 'int' }], - bytecode: '00a069', - sourceMap: '2:16:2:17;:12:::1;:4::19', - logs: [], - requires: [{ ip: 2, line: 2 }], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/global_function_void.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '4d5e07b068e501eb26e61aab0d53214aa42590858253b1106d6074d494fde557', - }, - }, - { - // 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: [], - abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], - bytecode: - // Functions are defined in callee-first order (leaf before its callers), so leaf is id 0, - // m1 id 1, m2 id 2. - // OP_DEFINE leaf (id 0): return a + 1 - '8b OP_0 OP_DEFINE ' - // OP_DEFINE m1 (id 1): return leaf(a) * 2 - + '008a5295 OP_1 OP_DEFINE ' - // OP_DEFINE m2 (id 2): return leaf(a) + 3 - + '008a5393 OP_2 OP_DEFINE ' - // require(m1(x) + m2(x) == 18) - + 'OP_DUP OP_1 OP_INVOKE OP_SWAP OP_2 OP_INVOKE OP_ADD 12 OP_NUMEQUAL', - debug: { - bytecode: '018b008904008a5295518904008a5393528976518a7c528a9301129c', - logs: [], - requires: [ - { ip: 18, line: 6 }, - ], - sourceMap: '1::3:1;;::::1;2::4::0;;::::1;::::0;;::::1;6:19:6:20:0;:16::21:1;;:27::28:0;:24::29:1;;:16;:33::35:0;:8::37:1', - functions: [ - { - id: 0, - name: 'leaf', - inputs: [{ name: 'a', type: 'int' }], - bytecode: '8b', - sourceMap: '2:11:2:16:1', - logs: [], - requires: [], - source: fs.readFileSync(new URL('../import-fixtures/leaf.cash', import.meta.url), { encoding: 'utf-8' }), - sourceFile: 'leaf.cash', - }, - { - id: 1, - name: 'm1', - inputs: [{ name: 'a', type: 'int' }], - bytecode: '008a5295', - sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', - logs: [], - requires: [], - source: fs.readFileSync(new URL('../import-fixtures/mid1.cash', import.meta.url), { encoding: 'utf-8' }), - sourceFile: 'mid1.cash', - }, - { - id: 2, - name: 'm2', - inputs: [{ name: 'a', type: 'int' }], - bytecode: '008a5393', - sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', - logs: [], - requires: [], - source: fs.readFileSync(new URL('../import-fixtures/mid2.cash', import.meta.url), { encoding: 'utf-8' }), - sourceFile: 'mid2.cash', - }, - ], - }, - source: fs.readFileSync(new URL('../import-fixtures/diamond.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '316a3305152ec0695bf80303736c79dd1f9cc2f1dbccf57d9965094401363307', - }, - }, - { - // A small global constant used repeatedly — inlined as a plain literal at each use site (no - // OP_DEFINE), with source locations mapping to the use sites rather than the declaration. - fn: 'global_constant_inlined.cash', - artifact: { - contractName: 'GlobalConstantInlined', - constructorInputs: [{ name: 'value', type: 'int' }], - abi: [{ name: 'spend', inputs: [] }], - bytecode: - // require(value + ONE + ONE == 3) - 'OP_1ADD OP_1ADD OP_3 OP_NUMEQUAL', - debug: { - bytecode: '8b8b539c', - logs: [], - requires: [ - { ip: 5, line: 5 }, - ], - sourceMap: '5:16:5:27:1;:::33;:37::38:0;:8::40:1', - // Both literal pushes were fused into the OP_1ADDs during optimisation; the ranges track them - inlineRanges: '1:1:ONE;2:2:ONE', - functions: [ - { - // The inlined constant is documented as an id-less frame; both of its literal pushes - // were emitted at the use sites and fused into the OP_1ADDs during optimisation - name: 'ONE', - kind: 'constant', - inputs: [], - bytecode: '51', - sourceMap: '1:19:1:20', - logs: [], - requires: [], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/global_constant_inlined.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '0d639aa764e1dc4045e25efe7dc27bd247b3cd45dd6c3a878a83bc3015e38a59', - }, - }, - { - // A global constant used repeatedly — lowered to a zero-argument VM function definition with a - // kind: 'constant' debug frame; each use compiles to an OP_INVOKE. - fn: 'global_constant_shared.cash', - artifact: { - contractName: 'GlobalConstantShared', - constructorInputs: [{ name: 'first', type: 'bytes32' }, { name: 'second', type: 'bytes32' }], - abi: [{ name: 'spend', inputs: [] }], - bytecode: - // OP_DEFINE HASH (id 0): the 32-byte literal - '203333333333333333333333333333333333333333333333333333333333333333 OP_0 OP_DEFINE ' - // require(first == HASH); require(second == HASH) - + 'OP_0 OP_INVOKE OP_EQUALVERIFY OP_0 OP_INVOKE OP_EQUAL', - debug: { - bytecode: '212033333333333333333333333333333333333333333333333333333333333333330089008a88008a87', - logs: [], - requires: [ - { ip: 7, line: 5 }, - { ip: 11, line: 6 }, - ], - sourceMap: '1::1:91;;::::1;5:25:5:29;;:8::31;6:26:6:30;;:8::32', - functions: [ - { - id: 0, - name: 'HASH', - kind: 'constant', - inputs: [], - bytecode: '203333333333333333333333333333333333333333333333333333333333333333', - sourceMap: '1:24:1:90', - logs: [], - requires: [], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/global_constant_shared.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '6a5509a2ece64c7e47b4e1185da2f8b92fc0e1f75cc818be86b783c7bf134c5e', - }, - }, - { - // A single-use global function — inlined at the call site, splicing its console.log and require - // metadata into the contract's debug info (same-file bodies keep their own source lines). - fn: 'global_function_inlined.cash', - artifact: { - contractName: 'GlobalFunctionInlined', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [{ name: 'n', type: 'int' }] }], - bytecode: - // require(checked(n) == n), with checked(x) spliced in: - // console.log ... require(x > 0, "positive") ... return x - 'OP_DUP OP_DUP OP_0 OP_GREATERTHAN OP_VERIFY OP_NUMEQUAL', - debug: { - bytecode: '767600a0699c', - logs: [ - { ip: 1, line: 9, data: ['checking', { stackIndex: 0, type: 'int', ip: 1 }] }, - ], - requires: [ - { ip: 4, line: 9, message: 'positive' }, - { ip: 6, line: 9 }, - ], - // The emitted body ops (ips 1-4) and the merged require/log entries above all map to the - // call site; the function's own lines live on its frame below, tied together by the range - sourceMap: '9:24:9:25;:16::26:1;;;;:8::33', - inlineRanges: '1:4:checked', - functions: [ - { - // The inlined function is documented as an id-less frame carrying its compiled body - // and frame-local debug info (ips from 0) - name: 'checked', - inputs: [{ name: 'x', type: 'int' }], - bytecode: '7600a069', - sourceMap: '3:12:3:13;:16::17;:12:::1;:4::31', - logs: [ - { ip: 0, line: 2, data: ['checking', { stackIndex: 0, type: 'int', ip: 0 }] }, - ], - requires: [ - { ip: 3, line: 3, message: 'positive' }, - ], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/global_function_inlined.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'a19e54aee90995fe784da8e5501a95020d91aa1ccf17ac1f3c7a3e7be0813a73', - }, - }, - { - // A multi-return function — locks in the calling convention: return values are left on the stack - // in declared order (last value on top) and bound by an N-ary tuple destructuring at the call site. - fn: 'global_function_multi_return.cash', - compilerOptions: { disableInlining: true }, - artifact: { - contractName: 'GlobalFunctionMultiReturn', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], - bytecode: - // OP_DEFINE divmod (id 0): return a / b, a % b — leaves [quotient, remainder], remainder on top - '6e967b7b97 OP_0 OP_DEFINE ' - // int q, int r = divmod(x, 3); require(q == 4); require(r == 1) - + 'OP_3 OP_0 OP_INVOKE OP_SWAP OP_4 OP_NUMEQUALVERIFY OP_1 OP_NUMEQUAL', - debug: { - bytecode: '056e967b7b97008953008a7c549d519c', - logs: [], - requires: [ - { ip: 8, line: 8 }, - { ip: 11, line: 9 }, - ], - sourceMap: '1::3:1;;::::1;7:33:7:34:0;:23::35:1;;8:16:8:17:0;:21::22;:8::24:1;9:21:9:22:0;:8::24:1', - functions: [ - { - id: 0, - name: 'divmod', - inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }], - bytecode: '6e967b7b97', - sourceMap: '2:11:2:16;::::1;:18::19:0;:22::23;:18:::1', - logs: [], - requires: [], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/global_function_multi_return.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'f747468c9408ec52949a22dc2f271a944ee5793eabaa913c9c2b1b4c3fbd0a56', - }, - }, - { - // The `unused` modifier — unused parameters keep their slot in constructorInputs / abi / frame - // inputs, but are dropped from the stack: constructor and contract function parameters in the - // contract prologue (rolled up first if buried), locals right after their initialiser, and - // global-function parameters in the function-body prologue. - fn: 'unused_modifier.cash', - compilerOptions: { disableInlining: true }, - artifact: { - contractName: 'UnusedModifier', - constructorInputs: [{ name: 'salt', type: 'int' }], - abi: [{ - name: 'spend', - inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }, { name: 'zeroPadding', type: 'bytes' }], - }], - bytecode: - // OP_DEFINE pad (id 0): drop unused param `padding`, leaving `value` as the return value - '75 OP_0 OP_DEFINE ' - // drop unused constructor param `salt` (top of stack) - + 'OP_DROP ' - // roll up and drop unused function param `zeroPadding` - + 'OP_ROT OP_DROP ' - // int unused scratch = a + b — initialiser is evaluated, then dropped - + 'OP_2DUP OP_ADD OP_DROP ' - // int constant unused magic = 42 — dropped as well - + '2a OP_DROP ' - // require(pad(a, 100) + b == 5) - + '64 OP_0 OP_INVOKE OP_ADD OP_5 OP_NUMEQUAL', - debug: { - bytecode: '01750089757b756e9375012a750164008a93559c', - logs: [], - requires: [ - { ip: 18, line: 9 }, - ], - sourceMap: '1::3:1;;::::1;5:24:5:39:0;6:33:6:57;;7:29:7:34;::::1;:8::35;8:36:8:38:0;:8::39:1;9:23:9:26:0;:16::27:1;;:::31;:35::36:0;:8::38:1', - functions: [ - { - id: 0, - name: 'pad', - inputs: [{ name: 'value', type: 'int' }, { name: 'padding', type: 'int' }], - bytecode: '75', - sourceMap: '1:24:1:42', - logs: [], - requires: [], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/unused_modifier.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '4fcac7e0c885a2d3d6a344866c39c4febdffcaf9bb658ac08a87ed7dea9808b6', - }, - }, - { - // Tuple destructuring into existing variables inside branches. Scoped reassignment values are - // folded into the existing slots; a declaration value above a reassignment value is parked on - // the altstack while the fold runs (OP_TOALTSTACK ... OP_FROMALTSTACK in reassignmentFirst). - fn: 'tuple_reassignment_branches.cash', - artifact: { - contractName: 'TupleReassignmentBranches', - constructorInputs: [], - abi: [ - { name: 'declarationFirst', inputs: [{ name: 'a', type: 'int' }] }, - { name: 'reassignmentFirst', inputs: [{ name: 'a', type: 'int' }] }, - ], - bytecode: - // OP_DEFINE branchPair (id 0) — called from both functions, too large to inline - '7653957857979378529693768b7c52957b94 OP_0 OP_DEFINE ' - // function declarationFirst - + 'OP_DUP OP_0 OP_NUMEQUAL OP_IF ' - // int total = 0 - + 'OP_0 ' - // if (a > 10) - + 'OP_2 OP_PICK OP_10 OP_GREATERTHAN OP_IF ' - // int d, total = branchPair(a) — call, then fold total's value (top) into its slot; - // d's value stays in place (declarations-first needs no parking) - + 'OP_2 OP_PICK OP_0 OP_INVOKE OP_ROT OP_DROP OP_SWAP ' - // require(d != 0) - + 'OP_DUP OP_0 OP_NUMNOTEQUAL OP_VERIFY ' - // scope cleanup (drop d) - + 'OP_DROP OP_ENDIF ' - // require(total >= 0) + cleanup - + 'OP_0 OP_GREATERTHANOREQUAL OP_NIP OP_NIP ' - // function reassignmentFirst - + 'OP_ELSE OP_1 OP_NUMEQUALVERIFY ' - // int total = 0 - + 'OP_0 ' - // if (a > 10) - + 'OP_OVER OP_10 OP_GREATERTHAN OP_IF ' - // (total, int extra) = branchPair(a + 1) — call, park extra's value on the altstack, - // fold total's value into its slot (OP_NIP), restore extra's value - + 'OP_OVER OP_1ADD OP_0 OP_INVOKE OP_TOALTSTACK OP_NIP OP_FROMALTSTACK ' - // require(extra != 0) - + 'OP_DUP OP_0 OP_NUMNOTEQUAL OP_VERIFY ' - // scope cleanup (drop extra) - + 'OP_DROP OP_ENDIF ' - // require(total >= 0) + cleanup - + 'OP_0 OP_GREATERTHANOREQUAL OP_NIP OP_ENDIF', - debug: { - bytecode: '127653957857979378529693768b7c52957b94008976009c630052795aa0635279008a7b757c76009e69756800a2777767519d00785aa063788b008a6b776c76009e69756800a27768', - sourceMap: '7::10:1;;::::1;14:4:21:5:0;;;;15:20:15:21;16:12:16:13;;:16::18;:12:::1;:20:19:9:0;17:38:17:39;;:27::40:1;;:12::41;;;18:20:18:21:0;:25::26;:20:::1;:12::28;16:20:19:9;;20:25:20:26:0;:8::28:1;14:37:21:5;;:4;25::32::0;;26:20:26:21;27:12:27:13;:16::18;:12:::1;:20:30:9:0;28:44:28:45;:::49:1;:33::50;;:12::51;;;29:20:29:25:0;:29::30;:20:::1;:12::32;27:20:30:9;;31:25:31:26:0;:8::28:1;25:38:32:5;12:0:33:1', - logs: [], - requires: [ - { ip: 23, line: 18 }, - { ip: 28, line: 20 }, - { ip: 48, line: 29 }, - { ip: 53, line: 31 }, - ], - sourceTags: '24:24:sc;28:29:sc;49:49:sc;53:53:sc', - functions: [ - { - id: 0, - name: 'branchPair', - inputs: [{ name: 'x', type: 'int' }], - bytecode: '7653957857979378529693768b7c52957b94', - sourceMap: '8:12:8:13;:16::17;:12:::1;:21::22:0;:25::26;:21:::1;:12::27;:31::32:0;:35::36;:31:::1;:12::37;9:11:9:12:0;:::16:1;:18::19:0;:22::23;:18:::1;:26::27:0;:18:::1', - logs: [], - requires: [], - }, - ], - }, - source: fs.readFileSync(new URL('../valid-contract-files/tuple_reassignment_branches.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'da4982948327a26f2c708b13af6977715747aa0b5c64bc00b04e3ddbc11ca67d', - }, - }, - { - // Tuple destructuring into existing variables: top-level renames (with the small helpers - // inlined at the call sites), pure and mixed reassignment in loops, and the interleaved - // order that parks a declaration value on the altstack mid-fold. - fn: 'tuple_reassignment.cash', - artifact: { - contractName: 'TupleReassignment', - constructorInputs: [], - abi: [{ name: 'spend', inputs: [{ name: 'seed', type: 'int' }] }], - bytecode: 'OP_DUP OP_1ADD OP_2DUP OP_SWAP OP_2DUP OP_SWAP OP_0 OP_BEGIN OP_DUP OP_4 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_SWAP OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_ROT OP_DROP OP_SWAP OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_0 OP_BEGIN OP_DUP OP_4 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_OVER OP_2 OP_PICK OP_MUL OP_1ADD OP_SWAP OP_ROT OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_OVER OP_2 OP_PICK OP_MUL OP_1ADD OP_SWAP OP_ROT OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_TOALTSTACK OP_ROT OP_DROP OP_SWAP OP_FROMALTSTACK OP_DUP OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_2DUP OP_ROT OP_ROT OP_ADD OP_ROT OP_ADD OP_ADD OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_2DROP OP_2DROP OP_1', - debug: { - bytecode: '768b6e7c6e7c006576549f766b637854797c557a757c6b7c6b7c6b7c6c6c6c7b757c768b77686c916675006576549f766b63785479785279958b7c7b567a757c6b7c6b7c6b7c6b7c6c6c6c6c537a757c6b7c6c7600a269788b7b7577686c916675006576529f766b63785479785279958b7c7b567a757c6b7c6b7c6b7c6b7c6c6c6c6c6b7b757c6c7600a269788b7b7577686c9166756e7b7b937b939300a2696d6d51', - sourceMap: '17:16:18:20;18:::24:1;21:22:21:26:0;:17::27:1;24:26:24:30:0;:21::31:1;27::27:22:0;:8:29:9;:24:27:25;:28::29;:24:::1;;;:42:29:9:0;28:26:28:27;:29::30;;:21::31:1;:12::32;;;;;;;;;;;;;;;;27:35:27:36:0;:::40:1;:31;:42:29:9;;:8;;;33:21:33:22:0;:8:36:9;:24:33:25;:28::29;:24:::1;;;:42:36:9:0;34:34:34:35;:37::38;;:29::39:1;;;;;;;:12::40;;;;;;;;;;;;;;;;;;;;;;;35:20:35:22:0;:26::27;:20:::1;:12::29;33:35:33:36:0;:::40:1;:31;;::36:9;:42;;:8;;;40:21:40:22:0;:8:43:9;:24:40:25;:28::29;:24:::1;;;:42:43:9:0;41:34:41:35;:37::38;;:29::39:1;;;;;;;:12::40;;;;;;;;;;;;;;;;;;;;;42:20:42:22:0;:26::27;:20:::1;:12::29;40:35:40:36:0;:::40:1;:31;;::43:9;:42;;:8;;;46:24:46:28:0;48:16:48:17;:20::21;:16:::1;:24::25:0;:16:::1;:::29;:33::34:0;:16:::1;:8::36;16:29:49:5;;', - logs: [], - requires: [ - { ip: 86, line: 35 }, - { ip: 139, line: 42 }, - { ip: 159, line: 48 }, - ], - sourceTags: '34:36:fu;37:40:lc;41:41:sc;87:91:fu;92:95:lc;96:96:sc;140:144:fu;145:148:lc;149:149:sc', - functions: [ - { - name: 'swap', - inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], - bytecode: '7c', - sourceMap: '7:14:7:15', - logs: [], - requires: [], - }, - { - name: 'step', - inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], - bytecode: '785279958b7c7b', - sourceMap: '12:11:12:12;:15::16;;:11:::1;:::20;:22::23:0;:25::26', - logs: [], - requires: [], - }, - ], - inlineRanges: '3:3:swap;5:5:swap;17:17:swap;53:59:step;108:114:step;151:151:swap', - }, - source: fs.readFileSync(new URL('../valid-contract-files/tuple_reassignment.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: '3ab69a954ec4bf9ceeb58eceb8ead206195032edf6627155eb82f528403c94dd', - }, - }, - { - fn: 'double_negation.cash', - artifact: { - contractName: 'DoubleNegation', - constructorInputs: [{ name: 'flag', type: 'bool' }], - abi: [{ name: 'spend', inputs: [{ name: 'target', type: 'int' }] }], - bytecode: - // require(!!flag) - OP_NOT OP_NOT OP_VERIFY is optimised to OP_VERIFY - 'OP_DUP OP_VERIFY ' - // int i = 0; bool done = false; - + 'OP_0 OP_0 ' - // do { i = i + 1; - + 'OP_BEGIN OP_OVER OP_1ADD OP_ROT OP_DROP OP_SWAP ' - // done = i >= target; - + 'OP_OVER OP_4 OP_PICK OP_GREATERTHANOREQUAL OP_NIP ' - // } while (!done) - OP_NOT OP_NOT OP_UNTIL is optimised to OP_UNTIL - + 'OP_DUP OP_UNTIL ' - // if (!!flag) - OP_NOT OP_NOT OP_IF becomes OP_NOT OP_NOTIF, which is optimised to OP_IF - + 'OP_ROT OP_IF ' - // require(i == target); } - + 'OP_OVER OP_3 OP_PICK OP_NUMEQUALVERIFY OP_ENDIF ' - // require(i > 0) - + 'OP_SWAP OP_0 OP_GREATERTHAN ' - // clean up i and done - + 'OP_NIP OP_NIP', - debug: { - bytecode: '7669000065788b7b757c785479a27776667b637853799d687c00a07777', - sourceMap: '4:18:4:22;:8::24:1;6:16:6:17:0;7:20:7:25;9:8:13:24;10:16:10:17;:::21:1;:12::22;;;11:19:11:20:0;:24::30;;:19:::1;:12::31;13:18:13:22:0;9:8::24:1;16:14:16:18:0;:12:18:9;17:20:17:21;:25::31;;:12::33:1;16:20:18:9;20:16:20:17:0;:20::21;:8::23:1;2:31:21:5;', - logs: [], - requires: [ - { ip: 2, line: 4 }, - { ip: 23, line: 17 }, - { ip: 28, line: 20 }, - ], - sourceTags: '27:28:sc', - }, - source: fs.readFileSync(new URL('../valid-contract-files/double_negation.cash', import.meta.url), { encoding: 'utf-8' }), - compiler: { - name: 'cashc', - version, - options: { - enforceFunctionParameterTypes: true, - enforceLocktimeGuard: true, - }, - }, - updatedAt: '', - fingerprint: 'ed0b5bc35f0130fa04d1fce813fbd7c183bb5346006d10c0808f0d9872712ded', - }, - }, -]; diff --git a/packages/cashc/test/generation/fixtures/import-fixtures/diamond.ts b/packages/cashc/test/generation/fixtures/import-fixtures/diamond.ts new file mode 100644 index 000000000..12d7dc67d --- /dev/null +++ b/packages/cashc/test/generation/fixtures/import-fixtures/diamond.ts @@ -0,0 +1,123 @@ +import fs from 'fs'; +import { URL } from 'url'; +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Diamond', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // require(m1(x) + m2(x) == 18); + 'OP_DUP OP_1ADD OP_2 OP_MUL OP_SWAP OP_1ADD OP_3 OP_ADD OP_ADD 12 OP_NUMEQUAL', + fingerprint: '0467d6dd3d6e156739eece6d6d2111816622b43d31469b7fe7cbbcc59272759b', + debug: { + bytecode: '768b52957c8b53939301129c', + sourceMap: '6:19:6:20;:16::21:1;;;:27::28:0;:24::29:1;;;:16;:33::35:0;:8::37:1', + logs: [], + requires: [{ ip: 11, line: 6 }], + functions: [ + { + name: 'leaf', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '8b', + sourceMap: '2:11:2:16:1', + source: fs.readFileSync(new URL('../../../import-fixtures/leaf.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'leaf.cash', + logs: [], + requires: [], + }, + { + name: 'm1', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '8b5295', + sourceMap: '3:11:3:18:1;:21::22:0;:11:::1', + source: fs.readFileSync(new URL('../../../import-fixtures/mid1.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'mid1.cash', + logs: [], + requires: [], + inlineRanges: '0:0:leaf', + }, + { + name: 'm2', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '8b5393', + sourceMap: '3:11:3:18:1;:21::22:0;:11:::1', + source: fs.readFileSync(new URL('../../../import-fixtures/mid2.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'mid2.cash', + logs: [], + requires: [], + inlineRanges: '0:0:leaf', + }, + ], + inlineRanges: '1:3:m1;5:7:m2', + }, + }, + }, + { + // Imports resolved across a diamond (mid1 and mid2 both import leaf): leaf is defined once, and + // m1/m2 invoke it transitively. + compilerOptions: { disableInlining: true }, + artifact: { + contractName: 'Diamond', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // Functions are defined in callee-first order (leaf before its callers), so leaf is id 0, + // m1 id 1, m2 id 2. + // OP_DEFINE leaf (id 0): return a + 1 + '8b OP_0 OP_DEFINE ' + // OP_DEFINE m1 (id 1): return leaf(a) * 2 + + '008a5295 OP_1 OP_DEFINE ' + // OP_DEFINE m2 (id 2): return leaf(a) + 3 + + '008a5393 OP_2 OP_DEFINE ' + // require(m1(x) + m2(x) == 18) + + 'OP_DUP OP_1 OP_INVOKE OP_SWAP OP_2 OP_INVOKE OP_ADD 12 OP_NUMEQUAL', + debug: { + bytecode: '018b008904008a5295518904008a5393528976518a7c528a9301129c', + logs: [], + requires: [ + { ip: 18, line: 6 }, + ], + sourceMap: '1::3:1;;::::1;2::4::0;;::::1;::::0;;::::1;6:19:6:20:0;:16::21:1;;:27::28:0;:24::29:1;;:16;:33::35:0;:8::37:1', + functions: [ + { + id: 0, + name: 'leaf', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '8b', + sourceMap: '2:11:2:16:1', + logs: [], + requires: [], + source: fs.readFileSync(new URL('../../../import-fixtures/leaf.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'leaf.cash', + }, + { + id: 1, + name: 'm1', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '008a5295', + sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', + logs: [], + requires: [], + source: fs.readFileSync(new URL('../../../import-fixtures/mid1.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'mid1.cash', + }, + { + id: 2, + name: 'm2', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '008a5393', + sourceMap: '3:11:3:18:1;;:21::22:0;:11:::1', + logs: [], + requires: [], + source: fs.readFileSync(new URL('../../../import-fixtures/mid2.cash', import.meta.url), { encoding: 'utf-8' }), + sourceFile: 'mid2.cash', + }, + ], + }, + fingerprint: '316a3305152ec0695bf80303736c79dd1f9cc2f1dbccf57d9965094401363307', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/2_of_3_multisig.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/2_of_3_multisig.ts new file mode 100644 index 000000000..762f5e1cb --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/2_of_3_multisig.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'MultiSig', + constructorInputs: [{ name: 'pk1', type: 'pubkey' }, { name: 'pk2', type: 'pubkey' }, { name: 'pk3', type: 'pubkey' }], + abi: [{ name: 'spend', inputs: [{ name: 's1', type: 'sig' }, { name: 's2', type: 'sig' }] }], + bytecode: + // require(checkMultiSig([s1, s2], [pk1, pk2, pk3])) + 'OP_0 OP_2ROT OP_SWAP OP_2 OP_2ROT OP_SWAP OP_6 OP_ROLL OP_3 OP_CHECKMULTISIG', + debug: { + bytecode: '00717c52717c567a53ae', + logs: [], + requires: [{ ip: 13, line: 3 }], + sourceMap: '3:12:3:52;:27::33;;:26::34:1;:37::45:0;;:47::50;;:36::51:1;:4::54', + }, + fingerprint: 'd06a42627510906395fa927195c1aa420b9adf7da407d71b793fc5d550b57a39', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/announcement.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/announcement.ts new file mode 100644 index 000000000..07ff49c81 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/announcement.ts @@ -0,0 +1,48 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Announcement', + constructorInputs: [], + abi: [{ name: 'announce', inputs: [] }], + bytecode: + // bytes announcement = new LockingBytecodeNullData(...) + '6a 6d02 OP_SIZE OP_SWAP OP_CAT OP_CAT ' + + '4120636f6e7472616374206d6179206e6f7420696e6a75726520612068756d616e20626' + + '5696e67206f722c207468726f75676820696e616374696f6e2c20616c6c6f77206120687' + + '56d616e206265696e6720746f20636f6d6520746f206861726d2e ' + + 'OP_SIZE OP_DUP 4b OP_GREATERTHAN OP_IF 4c OP_SWAP OP_CAT OP_ENDIF OP_SWAP OP_CAT OP_CAT ' + // require(tx.outputs[0].value == 0) + + 'OP_0 OP_OUTPUTVALUE OP_0 OP_NUMEQUALVERIFY ' + // require(tx.outputs[0].lockingBytecode == announcement) + + 'OP_0 OP_OUTPUTBYTECODE OP_EQUALVERIFY ' + // int minerFee = 1000 + + 'e803 ' + // int changeAmount = tx.inputs[this.activeInputIndex].value - minerFee + + 'OP_INPUTINDEX OP_UTXOVALUE OP_OVER OP_SUB ' + // if (changeAmount >= minerFee) + + 'OP_DUP OP_ROT OP_GREATERTHANOREQUAL OP_IF ' + // require( + // tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode + // ) + + 'OP_1 OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUALVERIFY ' + // require(tx.outputs[1].value == changeAmount) } + + 'OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY OP_ENDIF ' + // Stack clean-up + + 'OP_DROP OP_1', + debug: { + bytecode: '016a026d02827c7e7e4c624120636f6e7472616374206d6179206e6f7420696e6a75726520612068756d616e206265696e67206f722c207468726f75676820696e616374696f6e2c20616c6c6f7720612068756d616e206265696e6720746f20636f6d6520746f206861726d2e8276014ba063014c7c7e687c7e7e00cc009d00cd8802e803c0c67894767ba26351cdc0c78851cc789d687551', + logs: [], + requires: [ + { ip: 22, line: 16 }, + { ip: 25, line: 17 }, + { ip: 39, line: 24 }, + { ip: 43, line: 25 }, + ], + sourceMap: '10:29:13:10;11:12:11:18;::::1;;;;12:18:12:118:0;:12::119:1;;;;;;;;;;;;16:27:16:28:0;:16::35:1;:39::40:0;:8::42:1;17:27:17:28:0;:16::45:1;:8::63;21:23:21:27:0;22:37:22:58;:27::65:1;:68::76:0;:27:::1;23:12:23:24:0;:28::36;:12:::1;:38:26:9:0;24:31:24:32;:20::49:1;:63::84:0;:53::101:1;:12::103;25:31:25:32:0;:20::39:1;:43::55:0;:12::57:1;23:38:26:9;8:24:27:5;', + }, + fingerprint: '542596767034cea0f3a5933a1efa49bb9aa569ec70c5f0261afd36ea845fa746', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/bigint.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/bigint.ts new file mode 100644 index 000000000..9c102c926 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/bigint.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'BigInt', + constructorInputs: [], + abi: [{ name: 'proofOfBigInt', inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }] }], + bytecode: + // int maxInt32PlusOne = 2147483648; + '0000008000 ' + // require(x >= maxInt32PlusOne); + + 'OP_2DUP OP_GREATERTHANOREQUAL OP_VERIFY ' + // require(x * y >= maxInt32PlusOne); + + 'OP_SWAP OP_ROT OP_MUL OP_LESSTHANOREQUAL', + fingerprint: 'f14ce38215a2c251b9851e2e8d60b1faf88093ace31621cca1d7cacbe38442a7', + debug: { + bytecode: '0500000080006ea2697c7b95a1', + sourceMap: '3:30:3:40;4:16:4:36;::::1;:8::38;5:16:5:17:0;:20::21;:16:::1;:8::42', + logs: [], + requires: [{ ip: 3, line: 4 }, { ip: 8, line: 5 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/bitshift.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/bitshift.ts new file mode 100644 index 000000000..fa6ac60e4 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/bitshift.ts @@ -0,0 +1,22 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Bitshift', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: '1122334455667788 OP_4 OP_LSHIFTBIN OP_4 OP_RSHIFTBIN 0000000055667788 OP_EQUALVERIFY OP_8 OP_2 OP_RSHIFTNUM OP_1 OP_LSHIFTNUM OP_4 OP_NUMEQUAL', + debug: { + bytecode: '081122334455667788549854990800000000556677888858528e518d549c', + sourceMap: '3:19:3:37;4:24:4:25;:19:::1;:29::30:0;:19:::1;6:21:6:39:0;:8::41:1;8:16:8:17:0;9:21:9:22;:16:::1;:26::27:0;:16:::1;11:22:11:23:0;:8::25:1', + logs: [], + requires: [ + { ip: 6, line: 6 }, + { ip: 14, line: 11 }, + ], + }, + fingerprint: '2c9d2ddcd53c6f4e28320acf336260ece7958753802381a2528ddfa1840eb88a', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/bitwise.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/bitwise.ts new file mode 100644 index 000000000..086d8fb0c --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/bitwise.ts @@ -0,0 +1,16 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'bytes8' }, { name: 'y', type: 'bytes8' }], + abi: [{ name: 'hello', inputs: [] }], + bytecode: + // require((x | y) == y); + 'OP_OVER OP_OR OP_EQUAL', + fingerprint: '323eed626e96a40e7bad6fe48fe17304f30b8ca11760d9c10fdf8dfcffc819cc', + debug: { bytecode: '788587', sourceMap: '3:21:3:22;:17:::1;:8::30', logs: [], requires: [{ ip: 5, line: 3 }] }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/bounded_bytes.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/bounded_bytes.ts new file mode 100644 index 000000000..42bf3645d --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/bounded_bytes.ts @@ -0,0 +1,24 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'BoundedBytes', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'b', type: 'bytes4' }, { name: 'i', type: 'int' }] }], + bytecode: + // Implicit type enforcement for b: require(b.length == 4) + 'OP_SIZE OP_4 OP_EQUALVERIFY ' + // require(b == toPaddedBytes(i, 4)) + + 'OP_SWAP OP_4 OP_NUM2BIN OP_EQUAL', + debug: { + bytecode: '8254887c548087', + logs: [], + requires: [{ ip: 7, line: 3 }], + sourceMap: '2:19:2:27;;;3:35:3:36;:38::39;:21::40:1;:8::42', + sourceTags: '0:2:pv', + }, + fingerprint: 'b6381ead9be56fd0f9aa43b986ae8c3ba6aae2276596cdbd8268628397391064', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/bytes1_equals_byte.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/bytes1_equals_byte.ts new file mode 100644 index 000000000..b339802b5 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/bytes1_equals_byte.ts @@ -0,0 +1,26 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Bytes1EqualsByte', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'bytes1' }] }], + bytecode: + // Implicit parameter type enforcement + 'OP_SWAP OP_SIZE OP_1 OP_EQUALVERIFY ' + // bytes1 c = toPaddedBytes(a, 1); + + 'OP_SWAP OP_1 OP_NUM2BIN ' + // require(b == c); + + 'OP_EQUAL', + fingerprint: 'cbccef08f54b0452cabaf643501a4903dab79b0d676896399771131fea3a0ad1', + debug: { + bytecode: '7c8251887c518087', + sourceMap: '2:26:2:32;;;;3:33:3:34;:36::37;:19::38:1;4:8:4:24', + logs: [], + requires: [{ ip: 8, line: 4 }], + sourceTags: '0:3:pv', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/bytes_type_narrowing.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/bytes_type_narrowing.ts new file mode 100644 index 000000000..6d54d128a --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/bytes_type_narrowing.ts @@ -0,0 +1,152 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'BytesTypeNarrowing', + constructorInputs: [], + abi: [ + { name: 'requireNarrowing', inputs: [{ name: 'data', type: 'bytes' }] }, + { name: 'ifNarrowing', inputs: [{ name: 'data', type: 'bytes' }, { name: 'x', type: 'int' }] }, + { name: 'reversedComparison', inputs: [{ name: 'data', type: 'bytes' }] }, + { name: 'ifNarrowingAnd', inputs: [{ name: 'data', type: 'bytes' }, { name: 'x', type: 'int' }] }, + { + name: 'requireNarrowingMultiple', + inputs: [{ name: 'data1', type: 'bytes' }, { name: 'data2', type: 'bytes' }], + }, + { + name: 'ifNarrowingMultiple', + inputs: [{ name: 'data1', type: 'bytes' }, { name: 'data2', type: 'bytes' }, { name: 'x', type: 'int' }], + }, + ], + bytecode: + // function requireNarrowing(bytes data) { + 'OP_DUP OP_0 OP_NUMEQUAL OP_IF ' + // require(data.length == 20); + + 'OP_OVER OP_SIZE OP_NIP 14 OP_NUMEQUALVERIFY ' + // bytes20 narrowed = data; + + 'OP_OVER ' + // require(narrowed == data); + + 'OP_2 OP_PICK OP_EQUALVERIFY ' + // require(new LockingBytecodeP2SH20(data).length > 20); + + 'a914 OP_ROT OP_CAT 87 OP_CAT OP_SIZE OP_NIP 14 OP_GREATERTHAN ' + // Cleanup + + 'OP_NIP ' + // } + + 'OP_ELSE ' + // function ifNarrowing(bytes data, int x) { + + 'OP_DUP OP_1 OP_NUMEQUAL OP_IF ' + // if (data.length == 20) { + + 'OP_OVER OP_SIZE OP_NIP 14 OP_NUMEQUAL OP_IF ' + // bytes20 narrowed = data; + + 'OP_OVER ' + // require(narrowed == data); + + 'OP_DUP OP_3 OP_PICK OP_EQUALVERIFY ' + // Cleanup + + 'OP_DROP ' + // } + + 'OP_ENDIF ' + // require(x > 0); + + 'OP_ROT OP_0 OP_GREATERTHAN ' + // Cleanup + + 'OP_NIP OP_NIP ' + // } + + 'OP_ELSE ' + // function reversedComparison(bytes data) { + + 'OP_DUP OP_2 OP_NUMEQUAL OP_IF ' + // require(20 == data.length); + + '14 OP_2 OP_PICK OP_SIZE OP_NIP OP_NUMEQUALVERIFY ' + // bytes20 narrowed = data; + + 'OP_OVER ' + // require(narrowed == data); + + 'OP_ROT OP_EQUAL ' + // Cleanup + + 'OP_NIP ' + // } + + 'OP_ELSE ' + // function ifNarrowingAnd(bytes data, int x) { + + 'OP_DUP OP_3 OP_NUMEQUAL OP_IF ' + // if (data.length == 20 && x > 0) { + + 'OP_OVER OP_SIZE OP_NIP 14 OP_NUMEQUAL OP_3 OP_PICK OP_0 OP_GREATERTHAN OP_BOOLAND OP_IF ' + // bytes20 narrowed = data; + + 'OP_OVER ' + // require(narrowed == data); + + 'OP_DUP OP_3 OP_PICK OP_EQUALVERIFY ' + // Cleanup + + 'OP_DROP ' + // } + + 'OP_ENDIF ' + // require(x > 0); + + 'OP_ROT OP_0 OP_GREATERTHAN ' + // Cleanup + + 'OP_NIP OP_NIP ' + // } + + 'OP_ELSE ' + // function requireNarrowingMultiple(bytes data1, bytes data2) { + + 'OP_DUP OP_4 OP_NUMEQUAL OP_IF ' + // require(data1.length == 20 && data2.length == 10); + + 'OP_OVER OP_SIZE OP_NIP 14 OP_NUMEQUAL OP_3 OP_PICK OP_SIZE OP_NIP OP_10 OP_NUMEQUAL OP_BOOLAND OP_VERIFY ' + // bytes20 narrowed1 = data1; + + 'OP_OVER ' + // bytes10 narrowed2 = data2; + + 'OP_3 OP_PICK ' + // require(narrowed1 == data1); + + 'OP_SWAP OP_3 OP_PICK OP_EQUALVERIFY ' + // require(narrowed2 == data2); + + 'OP_3 OP_ROLL OP_EQUALVERIFY ' + // require(new LockingBytecodeP2SH20(data1).length > 20); + + 'a914 OP_ROT OP_CAT 87 OP_CAT OP_SIZE OP_NIP 14 OP_GREATERTHAN ' + // Cleanup + + 'OP_NIP ' + // } + + 'OP_ELSE ' + // function ifNarrowingMultiple(bytes data1, bytes data2, int x) { + + 'OP_5 OP_NUMEQUALVERIFY ' + // if (data1.length == 20 && data2.length == 10) { + + 'OP_DUP OP_SIZE OP_NIP 14 OP_NUMEQUAL OP_2 OP_PICK OP_SIZE OP_NIP OP_10 OP_NUMEQUAL OP_BOOLAND OP_IF ' + // bytes20 narrowed1 = data1; + + 'OP_DUP ' + // bytes10 narrowed2 = data2; + + 'OP_3DUP ' + // require(narrowed1 == data1); + + 'OP_EQUALVERIFY ' + // require(narrowed2 == data2); + + 'OP_DUP OP_4 OP_PICK OP_EQUALVERIFY ' + // Cleanup + + 'OP_2DROP ' + // } + + 'OP_ENDIF ' + // require(x > 0); + + 'OP_ROT OP_0 OP_GREATERTHAN ' + // Cleanup + + 'OP_NIP OP_NIP ' + // } + + 'OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF OP_ENDIF', + fingerprint: '6ce346c2b481330bafc5f23000655b8f033cd71635e01987a431885433b9de30', + debug: { + bytecode: '76009c6378827701149d7852798802a9147b7e01877e82770114a0776776519c6378827701149c63787653798875687b00a077776776529c630114527982779d787b87776776539c6378827701149c537900a09a63787653798875687b00a077776776549c6378827701149c537982775a9c9a697853797c537988537a8802a9147b7e01877e82770114a07767559d76827701149c527982775a9c9a63766f88765479886d687b00a077776868686868', + sourceMap: '2:4:7:5;;;;3:16:3:20;:::27:1;;:31::33:0;:8::35:1;4:27:4:31:0;5:28:5:32;;:8::34:1;6:16:6:47:0;:42::46;:16::47:1;;;:::54;;:57::59:0;:8::61:1;2:42:7:5;:4;9::15::0;;;;10:12:10:16;:::23:1;;:27::29:0;:12:::1;:31:13:9:0;11::11:35;12:20:12:28;:32::36;;:12::38:1;10:31:13:9;;14:16:14:17:0;:20::21;:8::23:1;9:44:15:5;;:4;17::21::0;;;;18:16:18:18;:22::26;;:::33:1;;:8::35;19:27:19:31:0;20:28:20:32;:8::34:1;17:44:21:5;:4;23::29::0;;;;24:12:24:16;:::23:1;;:27::29:0;:12:::1;:33::34:0;;:37::38;:33:::1;:12;:40:27:9:0;25:31:25:35;26:20:26:28;:32::36;;:12::38:1;24:40:27:9;;28:16:28:17:0;:20::21;:8::23:1;23:47:29:5;;:4;31::38::0;;;;32:16:32:21;:::28:1;;:32::34:0;:16:::1;:38::43:0;;:::50:1;;:54::56:0;:38:::1;:16;:8::58;33:28:33:33:0;34::34;;35:16:35:25;:29::34;;:8::36:1;36:29:36:34:0;;:8::36:1;37:16:37:48:0;:42::47;:16::48:1;;;:::55;;:58::60:0;:8::62:1;31:64:38:5;:4;40::48::0;;41:12:41:17;:::24:1;;:28::30:0;:12:::1;:34::39:0;;:::46:1;;:50::52:0;:34:::1;:12;:54:46:9:0;42:32:42:37;43::44:38;:::40:1;45:20:45:29:0;:33::38;;:12::40:1;41:54:46:9;;47:16:47:17:0;:20::21;:8::23:1;40:66:48:5;;1:0:49:1;;;;', + logs: [], + requires: [ + { ip: 8, line: 3 }, + { ip: 12, line: 5 }, + { ip: 22, line: 6 }, + { ip: 38, line: 12 }, + { ip: 44, line: 14 }, + { ip: 56, line: 18 }, + { ip: 60, line: 20 }, + { ip: 81, line: 26 }, + { ip: 87, line: 28 }, + { ip: 106, line: 32 }, + { ip: 113, line: 35 }, + { ip: 116, line: 36 }, + { ip: 126, line: 37 }, + { ip: 145, line: 44 }, + { ip: 149, line: 45 }, + { ip: 155, line: 47 }, + ], + sourceTags: '22:22:sc;39:39:sc;44:45:sc;60:60:sc;82:82:sc;87:88:sc;126:126:sc;150:150:sc;155:156:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/cast_hash_checksig.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/cast_hash_checksig.ts new file mode 100644 index 000000000..6f5419a6d --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/cast_hash_checksig.ts @@ -0,0 +1,26 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'CastHashChecksig', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }], + bytecode: + // require((ripemd160(bytes(pk)) == hash160(0x0) == !true)); + 'OP_DUP OP_RIPEMD160 OP_0 OP_HASH160 OP_EQUAL OP_1 OP_NOT OP_NUMEQUALVERIFY ' + // require(checkSig(s, pk)); + + 'OP_CHECKSIG', + debug: { + bytecode: '76a600a98751919dac', + logs: [], + requires: [ + { ip: 7, line: 3 }, + { ip: 9, line: 4 }, + ], + sourceMap: '3:33:3:35;:17::37:1;:49::51:0;:41::52:1;:17;:57::61:0;:56:::1;:8::64;4::4:33', + }, + fingerprint: 'bbf25f5a4cfbc9380707afca6d1f14a29c7971f589949d284859225508f4bad6', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/checkdatasig_in_function.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/checkdatasig_in_function.ts new file mode 100644 index 000000000..e7fd8a8d7 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/checkdatasig_in_function.ts @@ -0,0 +1,41 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [ + { + name: 'spend', + inputs: [{ name: 's', type: 'datasig' }, { name: 'message', type: 'bytes' }, { name: 'pk', type: 'pubkey' }], + }, + ], + bytecode: + // require(verifyData(s, message, pk)); + 'OP_SWAP OP_ROT OP_CHECKDATASIG', + fingerprint: '1a1dd563b4b81503ce471252e609976731a2946d4466485eac35594ff2cc47f8', + debug: { + bytecode: '7c7bba', + sourceMap: '7:30:7:37;:39::41;:8::44:1', + logs: [], + requires: [{ ip: 3, line: 7 }], + functions: [ + { + name: 'verifyData', + inputs: [ + { name: 's', type: 'datasig' }, + { name: 'message', type: 'bytes' }, + { name: 'pk', type: 'pubkey' }, + ], + bytecode: 'ba', + sourceMap: '2:11:2:39:1', + logs: [], + requires: [], + }, + ], + inlineRanges: '2:2:verifyData', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/comments.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/comments.ts new file mode 100644 index 000000000..135d2a764 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/comments.ts @@ -0,0 +1,39 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'int' }], + abi: [{ name: 'hello', inputs: [{ name: 's', type: 'sig' }, { name: 'pk', type: 'pubkey' }] }], + bytecode: + // int i = 400 + x; + '9001 OP_OVER OP_ADD ' + // bytes b = 0x07364897987fe87 + bytes(x); + + '07364897987fe807 OP_2 OP_PICK OP_CAT ' + // int myVariable = 10 - 4; // they can go at the end of the line + + 'OP_10 OP_4 OP_SUB ' + // int myOtherVariable = i + myVariable % 2; + + 'OP_2 OP_PICK OP_SWAP OP_2 OP_MOD OP_ADD ' + // require(myOtherVariable /* And comments can be included within lines */ > i); + + 'OP_2 OP_PICK OP_GREATERTHAN OP_VERIFY ' + // if (x > 10) { + + 'OP_ROT OP_10 OP_GREATERTHAN OP_IF ' + // require(i < 20); + + 'OP_OVER 14 OP_LESSTHAN OP_VERIFY ' + // require(checkSig(s, pk)); + + 'OP_2OVER OP_SWAP OP_CHECKSIGVERIFY ' + // require(b == 0x01); + + 'OP_ELSE OP_DUP OP_1 OP_EQUALVERIFY OP_ENDIF ' + // } + + 'OP_2DROP OP_2DROP OP_1', + fingerprint: '63ee25992293cf9dd8752923c17b8a78840ecea53d75e814643cbb2ac914c751', + debug: { + bytecode: '02900178930807364897987fe80752797e5a549452797c5297935279a0697b5aa0637801149f69707cad67765188686d6d51', + sourceMap: '9:16:9:19;:22::23;:16:::1;10:18:10:35:0;:44::45;;:18::46:1;12:25:12:27:0;:30::31;:25:::1;13:30:13::0;;:34::44;:47::48;:34:::1;:30;14:82:14:83:0;;:16:::1;:8::85;16:12:16:13:0;:16::18;:12:::1;:20:19:9:0;17::17:21;:24::26;:20:::1;:12::28;18:29:18:34:0;;:12::37:1;20::20:31:0;:20::21;:25::29;:12::31:1;;8:37:21:5;;', + logs: [], + requires: [{ ip: 20, line: 14 }, { ip: 28, line: 17 }, { ip: 31, line: 18 }, { ip: 35, line: 20 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/complex_loop.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/complex_loop.ts new file mode 100644 index 000000000..f362178e9 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/complex_loop.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Loopy', + constructorInputs: [], + abi: [{ name: 'doLoop', inputs: [] }], + bytecode: 'OP_0 OP_0 OP_0 OP_0 OP_BEGIN OP_DUP OP_UTXOVALUE OP_4 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_1ADD OP_NIP OP_TXOUTPUTCOUNT OP_2DUP OP_LESSTHAN OP_DUP OP_IF OP_2 OP_PICK OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUAL OP_NOT OP_NIP OP_DUP OP_IF OP_4 OP_PICK OP_3 OP_PICK OP_OUTPUTVALUE OP_ADD OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_ELSE OP_3 OP_PICK OP_1ADD OP_4 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_ENDIF OP_ENDIF OP_2DROP OP_DUP OP_TXINPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL OP_2SWAP OP_GREATERTHAN OP_VERIFY OP_SWAP OP_0 OP_GREATERTHAN OP_NIP', + debug: { + bytecode: '000000006576c6547a757c6b7c6b7c6c6c768b77c46e9f76635279d100879177766354795379cc93557a757c6b7c6b7c6b7c6c6c6c6753798b547a757c6b7c6b7c6c6c68686d76c3a26672a0697c00a077', + sourceMap: '3:23:3:24;4:24:4:25;5:25:5:26;6:16:6:17;8:8:26:39;9:33:9:34;:23::41:1;:12::42;;;;;;;;;;10:16:10:17:0;:::21:1;:12::22;12:20:12:37:0;13:21:13:26;::::1;15:16:15:17:0;:19:25:13;16:31:16:32;;:20::47:1;:51::53:0;:20:::1;;:16::54;18:20:18:21:0;:23:20:17;19:32:19:41;;:55::56;;:44::63:1;:32;:20::64;;;;;;;;;;;;;20:23:22:17:0;21:33:21:43;;:::47:1;:20::48;;;;;;;;;;20:23:22:17;15:19:25:13;8:11:26:9;26:17::18:0;:21::37;8:8::39:1;;28:16:28:36:0;::::1;:8::38;29:16:29:26:0;:29::30;:8::32:1;2:22:30:5', + logs: [ + { ip: 68, line: 24, data: [{ stackIndex: 3, type: 'int', ip: 68 }] }, + ], + requires: [ + { ip: 76, line: 28 }, + { ip: 80, line: 29 }, + ], + sourceTags: '69:69:sc;80:80:sc', + }, + fingerprint: 'fa36d9b24d49525e027ba3cf3accd349e9f84d0c1bbd1141e98d6894173a1a2a', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/compound_assign.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/compound_assign.ts new file mode 100644 index 000000000..d48952c3b --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/compound_assign.ts @@ -0,0 +1,32 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'CompoundAssign', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // int x = 10; + 'OP_10 ' + // x += 5; + + 'OP_DUP OP_5 OP_ADD ' + // require(x == 15); + + 'OP_DUP OP_15 OP_NUMEQUALVERIFY ' + // x -= 3; + + 'OP_DUP OP_3 OP_SUB ' + // require(x == 12); + + 'OP_12 OP_NUMEQUAL ' + // Cleanup + + 'OP_NIP OP_NIP', + fingerprint: '3e67ebf63dbbf278589d0fffe8dd94663758334a8bf7858ea9c3613cd472b190', + debug: { + bytecode: '5a765593765f9d7653945c9c7777', + sourceMap: '3:16:3:18;4:8:4:9;:13::14;:8:::1;5:16:5:17:0;:21::23;:8::25:1;7::7:9:0;:13::14;:8:::1;8:21:8:23:0;:8::25:1;2:21:9:5;', + logs: [], + requires: [{ ip: 6, line: 5 }, { ip: 12, line: 8 }], + sourceTags: '12:13:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/correct_pragma.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/correct_pragma.ts new file mode 100644 index 000000000..6120ac887 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/correct_pragma.ts @@ -0,0 +1,37 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [ + { name: 'hello', inputs: [{ name: 's', type: 'sig' }, { name: 'pk', type: 'pubkey' }] }, + { name: 'world', inputs: [{ name: 'a', type: 'int' }] }, + ], + bytecode: + // function hello(sig s, pubkey pk) { + 'OP_DUP OP_0 OP_NUMEQUAL OP_IF ' + // require(checkSig(s, pk)); + + 'OP_SWAP OP_ROT OP_CHECKSIG ' + // Cleanup + + 'OP_NIP ' + // } + + 'OP_ELSE ' + // function world(int a) { + + 'OP_1 OP_NUMEQUALVERIFY ' + // require(a + 5 == 10); + + 'OP_5 OP_ADD OP_10 OP_NUMEQUAL ' + // } + + 'OP_ENDIF', + fingerprint: '88a901256f34c8c655657f1efad4389dc3465a1980090f817f5d1a7df7ffd701', + debug: { + bytecode: '76009c637c7bac7767519d55935a9c68', + sourceMap: '4:4:6:5;;;;5:25:5:26;:28::30;:8::33:1;4:37:6:5;:4;8::10::0;;9:20:9:21;:16:::1;:25::27:0;:8::29:1;3:0:11:1', + logs: [], + requires: [{ ip: 7, line: 5 }, { ip: 15, line: 9 }], + sourceTags: '7:7:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/covenant.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/covenant.ts new file mode 100644 index 000000000..a47946740 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/covenant.ts @@ -0,0 +1,31 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Covenant', + constructorInputs: [ + { + name: 'requiredVersion', + type: 'int', + }, + ], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // require(tx.version == requiredVersion) + 'OP_TXVERSION OP_NUMEQUALVERIFY ' + // require(tx.bytecode == 0x00) + + 'OP_ACTIVEBYTECODE 00 OP_EQUAL', + debug: { + bytecode: 'c29dc1010087', + logs: [], + requires: [ + { ip: 2, line: 3 }, + { ip: 6, line: 4 }, + ], + sourceMap: '3:16:3:26;:8::47:1;4:16:4:35:0;:39::43;:8::45:1', + }, + fingerprint: '1fd180f7d78e9670d7b2ae95e7af1f7cc533fc42c3cfdc7872619ec5810487d2', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/covenant_all_fields.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/covenant_all_fields.ts new file mode 100644 index 000000000..6b920f1da --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/covenant_all_fields.ts @@ -0,0 +1,88 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Covenant', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // injected by InjectLocktimeGuardTraversal because tx.locktime is used + 'OP_TXLOCKTIME OP_CHECKLOCKTIMEVERIFY OP_DROP ' + // require(tx.version == 2) + + 'OP_TXVERSION OP_2 OP_NUMEQUALVERIFY ' + // require(tx.locktime == 0) + + 'OP_TXLOCKTIME OP_0 OP_NUMEQUALVERIFY ' + // require(tx.inputs.length == 1) + + 'OP_TXINPUTCOUNT OP_1 OP_NUMEQUALVERIFY ' + // require(tx.outputs.length == 1) + + 'OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUALVERIFY ' + // require(this.activeInputIndex == 0) + + 'OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY ' + // require(this.activeBytecode.length == 300) + + 'OP_ACTIVEBYTECODE OP_SIZE OP_NIP 2c01 OP_NUMEQUALVERIFY ' + // require(tx.inputs[0].value == 10000) + + 'OP_0 OP_UTXOVALUE 1027 OP_NUMEQUALVERIFY ' + // require(tx.inputs[0].lockingBytecode.length == 10000) + + 'OP_0 OP_UTXOBYTECODE OP_SIZE OP_NIP 1027 OP_NUMEQUALVERIFY ' + // require(tx.inputs[0].outpointTransactionHash == 0x00...00) + + 'OP_0 OP_OUTPOINTTXHASH 0000000000000000000000000000000000000000000000000000000000000000 OP_EQUALVERIFY ' + // require(tx.inputs[0].outpointIndex == 0) + + 'OP_0 OP_OUTPOINTINDEX OP_0 OP_NUMEQUALVERIFY ' + // require(tx.inputs[0].unlockingBytecode.length == 100) + + 'OP_0 OP_INPUTBYTECODE OP_SIZE OP_NIP 64 OP_NUMEQUALVERIFY ' + // require(tx.inputs[0].sequenceNumber == 0) + + 'OP_0 OP_INPUTSEQUENCENUMBER OP_0 OP_NUMEQUALVERIFY ' + // require(tx.outputs[0].value == 10000) + + 'OP_0 OP_OUTPUTVALUE 1027 OP_NUMEQUALVERIFY ' + // require(tx.outputs[0].lockingBytecode.length == 100) + + 'OP_0 OP_OUTPUTBYTECODE OP_SIZE OP_NIP 64 OP_NUMEQUALVERIFY ' + // require(tx.inputs[0].tokenCategory == 0x000000000000000000000000000000000000000000000000000000000000000) + + 'OP_0 OP_UTXOTOKENCATEGORY 0000000000000000000000000000000000000000000000000000000000000000 OP_EQUALVERIFY ' + // require(tx.inputs[0].nftCommitment == 0x00); + + 'OP_0 OP_UTXOTOKENCOMMITMENT 00 OP_EQUALVERIFY ' + // require(tx.inputs[0].tokenAmount == 100); + + 'OP_0 OP_UTXOTOKENAMOUNT 64 OP_NUMEQUALVERIFY ' + // require(tx.outputs[0].tokenCategory == 0x000000000000000000000000000000000000000000000000000000000000000) + + 'OP_0 OP_OUTPUTTOKENCATEGORY 0000000000000000000000000000000000000000000000000000000000000000 OP_EQUALVERIFY ' + // require(tx.outputs[0].nftCommitment == 0x00); + + 'OP_0 OP_OUTPUTTOKENCOMMITMENT 00 OP_EQUALVERIFY ' + // require(tx.outputs[0].tokenAmount == 100); + + 'OP_0 OP_OUTPUTTOKENAMOUNT 64 OP_NUMEQUAL', + debug: { + bytecode: 'c5b175c2529dc5009dc3519dc4519dc0009dc18277022c019d00c60210279d00c782770210279d00c82000000000000000000000000000000000000000000000000000000000000000008800c9009d00ca827701649d00cb009d00cc0210279d00cd827701649d00ce2000000000000000000000000000000000000000000000000000000000000000008800cf01008800d001649d00d12000000000000000000000000000000000000000000000000000000000000000008800d201008800d301649c', + logs: [], + requires: [ + { + ip: 1, + line: 2, + message: 'Using tx.locktime requires a non-final sequence number on the spending input', + }, + { ip: 5, line: 3 }, + { ip: 8, line: 4 }, + { ip: 11, line: 5 }, + { ip: 14, line: 6 }, + { ip: 17, line: 7 }, + { ip: 22, line: 8 }, + { ip: 26, line: 9 }, + { ip: 32, line: 10 }, + { ip: 36, line: 11 }, + { ip: 40, line: 12 }, + { ip: 46, line: 13 }, + { ip: 50, line: 14 }, + { ip: 54, line: 15 }, + { ip: 60, line: 16 }, + { ip: 64, line: 17 }, + { ip: 68, line: 18 }, + { ip: 72, line: 19 }, + { ip: 76, line: 20 }, + { ip: 80, line: 21 }, + { ip: 85, line: 22 }, + ], + sourceMap: '2:21:2:21;::::1;;3:16:3:26:0;:30::31;:8::33:1;4:16:4:27:0;:31::32;:8::34:1;5:16:5:32:0;:36::37;:8::39:1;6:16:6:33:0;:37::38;:8::40:1;7:16:7:37:0;:41::42;:8::44:1;8:16:8:35:0;:::42:1;;:46::49:0;:8::51:1;9:26:9:27:0;:16::34:1;:38::43:0;:8::45:1;10:26:10:27:0;:16::44:1;:::51;;:55::60:0;:8::62:1;11:26:11:27:0;:16::52:1;:56::121:0;:8::123:1;12:26:12:27:0;:16::42:1;:46::47:0;:8::49:1;13:26:13:27:0;:16::46:1;:::53;;:57::60:0;:8::62:1;14:26:14:27:0;:16::43:1;:47::48:0;:8::50:1;15:27:15:28:0;:16::35:1;:39::44:0;:8::46:1;16:27:16:28:0;:16::45:1;:::52;;:56::59:0;:8::61:1;17:26:17:27:0;:16::42:1;:46::111:0;:8::113:1;18:26:18:27:0;:16::42:1;:46::50:0;:8::52:1;19:26:19:27:0;:16::40:1;:44::47:0;:8::49:1;20:27:20:28:0;:16::43:1;:47::112:0;:8::114:1;21:27:21:28:0;:16::43:1;:47::51:0;:8::53:1;22:27:22:28:0;:16::41:1;:45::48:0;:8::50:1', + sourceTags: '0:2:lg', + }, + fingerprint: '371d30dbd28672395a164baee67b27ad86454fa53daccdb7a770a7916902f607', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/date_literal.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/date_literal.ts new file mode 100644 index 000000000..59321bcff --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/date_literal.ts @@ -0,0 +1,23 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'test', inputs: [] }], + bytecode: + // int d = date("2021-02-17T01:30:00"); //YYYY-MM-DDThh:mm:ss + '88632c60 ' + // require(d == 0); + + 'OP_0 OP_NUMEQUAL', + fingerprint: '3584793ef9b31561ca87330a348b586c6352c8fa413985079b7d8ca3aca5bdf0', + debug: { + bytecode: '0488632c60009c', + sourceMap: '5:16:5:43;6:21:6:22;:8::24:1', + logs: [], + requires: [{ ip: 3, line: 6 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/debug_messages.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/debug_messages.ts new file mode 100644 index 000000000..d86000b10 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/debug_messages.ts @@ -0,0 +1,24 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'DebugMessages', + constructorInputs: [], + abi: [ + { name: 'spend', inputs: [{ name: 'value', type: 'int' }] }, + ], + bytecode: 'OP_DUP OP_1 OP_NUMEQUALVERIFY OP_1ADD OP_2 OP_NUMEQUAL', + debug: { + bytecode: '76519d8b529c', + logs: [ + { data: [{ stackIndex: 0, type: 'int', ip: 3 }, 'test'], ip: 3, line: 4 }, + { data: [{ stackIndex: 0, type: 'int', ip: 3 }, 'test2'], ip: 3, line: 5 }, + ], + requires: [{ ip: 2, line: 3, message: 'Wrong value passed' }, { ip: 6, line: 6, message: 'Sum doesn\'t work' }], + sourceMap: '3:12:3:17;:21::22;:4::46:1;6:12:6:21;:25::26:0;:4::48:1', + }, + fingerprint: '2a4f5039ce0a481742e5b1712388a879ec8c5b617c4d4a8d676cc28d029c604f', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/deep_replace.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/deep_replace.ts new file mode 100644 index 000000000..ef8985c15 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/deep_replace.ts @@ -0,0 +1,30 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'DeepReplace', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [] }], + bytecode: + // int a = 1; int b = 2; int c = 3; int d = 4; int e = 5; int f = 6; + 'OP_1 OP_2 OP_3 OP_4 OP_5 OP_6 ' + // if (a < 3) { + + 'OP_5 OP_PICK OP_3 OP_LESSTHAN OP_IF ' + // a = 3 } + + 'OP_3 OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP ' + + 'OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK ' + + 'OP_FROMALTSTACK OP_FROMALTSTACK OP_ENDIF ' + // require(a > b + c + d + e + f); + + 'OP_2ROT OP_5 OP_ROLL OP_ADD OP_4 OP_ROLL OP_ADD ' + + 'OP_3 OP_ROLL OP_ADD OP_ROT OP_ADD OP_GREATERTHAN', + debug: { + bytecode: '5152535455565579539f6353567a757c6b7c6b7c6b7c6b7c6c6c6c6c6871557a93547a93537a937b93a0', + logs: [], + requires: [{ ip: 42, line: 14 }], + sourceMap: '3:16:3:17;4::4;5::5;6::6;7::7;8::8;10:12:10:13;;:16::17;:12:::1;:19:12:9:0;11:16:11:17;:12::18:1;;;;;;;;;;;;;;;;10:19:12:9;14:16:14:21:0;:24::25;;:20:::1;:28::29:0;;:20:::1;:32::33:0;;:20:::1;:36::37:0;:20:::1;:8::39', + }, + fingerprint: '5ec5f2a100dc5c29c95f58ed51e4da469b74e5932b070e38f3c30c3405f40005', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/deeply_nested-logs.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/deeply_nested-logs.ts new file mode 100644 index 000000000..2c099e5fd --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/deeply_nested-logs.ts @@ -0,0 +1,79 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'TransferWithTimeout', + constructorInputs: [ + { name: 'sender', type: 'pubkey' }, + { name: 'recipient', type: 'pubkey' }, + { name: 'timeout', type: 'int' }, + ], + abi: [ + { name: 'transfer', inputs: [{ name: 'recipientSig', type: 'sig' }] }, + { name: 'timeout', inputs: [{ name: 'senderSig', type: 'sig' }] }, + ], + bytecode: + // function transfer(sig recipientSig) { + 'OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' + // require(checkSig(recipientSig, recipient)); + + 'OP_4 OP_ROLL OP_ROT OP_CHECKSIG ' + // Cleanup + + 'OP_NIP OP_NIP OP_NIP ' + // } + + 'OP_ELSE ' + // function timeout(sig senderSig) { + + 'OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY ' + // require(checkSig(senderSig, sender)); + + 'OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY ' + // if (timeout > 0) { + + 'OP_OVER OP_0 OP_GREATERTHAN OP_IF ' + // if (timeout < 10) { + + 'OP_OVER OP_10 OP_LESSTHAN OP_IF ' + // require(timeout == 5); + + 'OP_OVER OP_5 OP_NUMEQUALVERIFY ' + // } else { + + 'OP_ELSE ' + // require(timeout == 15); + + 'OP_OVER OP_15 OP_NUMEQUALVERIFY ' + // } + + 'OP_ENDIF ' + // } else { + + 'OP_ELSE ' + // require(timeout == 0); + + 'OP_OVER OP_0 OP_NUMEQUALVERIFY ' + // } + + 'OP_ENDIF OP_2DROP OP_1 OP_ENDIF', + fingerprint: '8c0754826497834b06b82f8e040f49613e1bc193b8b1bb8ab171f8538ddfb47e', + debug: { + bytecode: '5379009c63547a7bac77777767537a519d537a7cad7800a063785a9f6378559d67785f9d686778009d686d5168', + sourceMap: '9:4:12:5;;;;;10:25:10:37;;:39::48;:8::51:1;9:40:12:5;;;:4;15::32::0;;;;16:25:16:34;;:36::42;:8::45:1;17:12:17:19:0;:22::23;:12:::1;:25:26:9:0;18:16:18:23;:26::28;:16:::1;:30:22:13:0;19:24:19:31;:35::36;:16::38:1;22:19:25:13:0;24:24:24:31;:35::37;:16::39:1;22:19:25:13;26:15:29:9:0;27:20:27:27;:31::32;:12::34:1;26:15:29:9;15:36:32:5;;3:0:33:1', + logs: [ + { ip: 12, line: 11, data: ['recipientSig is', { type: 'sig', stackIndex: 4, ip: 8 }] }, + { ip: 35, line: 20, data: ['timeout is', { stackIndex: 1, type: 'int', ip: 35 }] }, + { ip: 35, line: 21, data: ['senderSig is', { type: 'sig', stackIndex: 3, ip: 20 }] }, + { ip: 36, line: 23, data: ['timeout is', { stackIndex: 1, type: 'int', ip: 36 }] }, + { ip: 44, line: 28, data: ['timeout is', { stackIndex: 1, type: 'int', ip: 44 }] }, + { + ip: 45, + line: 31, + data: [ + 'timeout is', + { stackIndex: 1, type: 'int', ip: 45 }, + 'and senderSig is', + { type: 'sig', stackIndex: 3, ip: 20 }, + ], + }, + ], + requires: [ + { ip: 12, line: 10 }, + { ip: 23, line: 16 }, + { ip: 34, line: 19 }, + { ip: 38, line: 24 }, + { ip: 43, line: 27 }, + ], + sourceTags: '9:11:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/deeply_nested.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/deeply_nested.ts new file mode 100644 index 000000000..592826315 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/deeply_nested.ts @@ -0,0 +1,63 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'TransferWithTimeout', + constructorInputs: [ + { name: 'sender', type: 'pubkey' }, + { name: 'recipient', type: 'pubkey' }, + { name: 'timeout', type: 'int' }, + ], + abi: [ + { name: 'transfer', inputs: [{ name: 'recipientSig', type: 'sig' }] }, + { name: 'timeout', inputs: [{ name: 'senderSig', type: 'sig' }] }, + ], + bytecode: + // function transfer(sig recipientSig) { + 'OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' + // require(checkSig(recipientSig, recipient)); + + 'OP_4 OP_ROLL OP_ROT OP_CHECKSIG ' + // Cleanup + + 'OP_NIP OP_NIP OP_NIP ' + // } + + 'OP_ELSE ' + // function timeout(sig senderSig) { + + 'OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY ' + // require(checkSig(senderSig, sender)); + + 'OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY ' + // if (timeout > 0) { + + 'OP_OVER OP_0 OP_GREATERTHAN OP_IF ' + // if (timeout < 10) { + + 'OP_OVER OP_10 OP_LESSTHAN OP_IF ' + // require(timeout == 5); + + 'OP_OVER OP_5 OP_NUMEQUALVERIFY ' + // } else { + + 'OP_ELSE ' + // require(timeout == 15); + + 'OP_OVER OP_15 OP_NUMEQUALVERIFY ' + // } + + 'OP_ENDIF ' + // } else { + + 'OP_ELSE ' + // require(timeout == 0); + + 'OP_OVER OP_0 OP_NUMEQUALVERIFY ' + // } + + 'OP_ENDIF OP_2DROP OP_1 OP_ENDIF', + fingerprint: '8c0754826497834b06b82f8e040f49613e1bc193b8b1bb8ab171f8538ddfb47e', + debug: { + bytecode: '5379009c63547a7bac77777767537a519d537a7cad7800a063785a9f6378559d67785f9d686778009d686d5168', + sourceMap: '9:4:11:5;;;;;10:25:10:37;;:39::48;:8::51:1;9:40:11:5;;;:4;14::25::0;;;;15:25:15:34;;:36::42;:8::45:1;16:12:16:19:0;:22::23;:12:::1;:25:22:9:0;17:16:17:23;:26::28;:16:::1;:30:19:13:0;18:24:18:31;:35::36;:16::38:1;19:19:21:13:0;20:24:20:31;:35::37;:16::39:1;19:19:21:13;22:15:24:9:0;23:20:23:27;:31::32;:12::34:1;22:15:24:9;14:36:25:5;;3:0:26:1', + logs: [], + requires: [ + { ip: 12, line: 10 }, + { ip: 23, line: 15 }, + { ip: 34, line: 18 }, + { ip: 38, line: 20 }, + { ip: 43, line: 23 }, + ], + sourceTags: '9:11:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop.ts new file mode 100644 index 000000000..7e03e275a --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop.ts @@ -0,0 +1,29 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Loopy', + constructorInputs: [], + abi: [{ name: 'doLoop', inputs: [] }], + bytecode: + // int i = 0; + 'OP_0 ' + // do { + + 'OP_BEGIN ' + // i = i + 1; + + 'OP_DUP OP_1ADD OP_NIP ' + // } while (i < tx.inputs.length); + + 'OP_DUP OP_TXINPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL ' + // require(i > 2); + + 'OP_2 OP_GREATERTHAN', + fingerprint: '45d5cf43034d482df71ca54496793bff3f932d37dd77e95367edeb22a98a9154', + debug: { + bytecode: '0065768b7776c3a26652a0', + sourceMap: '3:16:3:17;5:8:7:39;6:16:6:17;:::21:1;:12::22;7:17:7:18:0;:21::37;5:8::39:1;;10:20:10:21:0;:8::23:1', + logs: [{ ip: 9, line: 9, data: [{ stackIndex: 0, type: 'int', ip: 9 }] }], + requires: [{ ip: 11, line: 10 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop_no_introspection.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop_no_introspection.ts new file mode 100644 index 000000000..485a6a804 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop_no_introspection.ts @@ -0,0 +1,23 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Loopy', + constructorInputs: [], + abi: [{ name: 'doLoop', inputs: [] }], + bytecode: 'OP_0 OP_2 OP_BEGIN OP_OVER OP_1ADD OP_ROT OP_DROP OP_SWAP OP_2DUP OP_ADD OP_10 OP_LESSTHAN OP_VERIFY OP_OVER OP_10 OP_GREATERTHANOREQUAL OP_UNTIL OP_2DROP OP_1', + debug: { + bytecode: '005265788b7b757c6e935a9f69785aa2666d51', + sourceMap: '3:16:3:17;4::4;6:8:10:25;7:16:7:17;:::21:1;:12::22;;;9:20:9:25:0;::::1;:28::30:0;:20:::1;:12::32;10:17:10:18:0;:21::23;6:8::25:1;;2:22:11:5;', + logs: [ + { ip: 8, line: 8, data: [{ stackIndex: 1, type: 'int', ip: 8 }] }, + ], + requires: [ + { ip: 12, line: 9 }, + ], + }, + fingerprint: '39b67bb19440620390b83e3bc1e638ea6827998f4a14c2d6e29c2afa9815b2fd', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop_require_inside_loop.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop_require_inside_loop.ts new file mode 100644 index 000000000..807a47786 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/do_while_loop_require_inside_loop.ts @@ -0,0 +1,31 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Loopy', + constructorInputs: [], + abi: [{ name: 'doLoop', inputs: [] }], + bytecode: + // int i = 0; + 'OP_0 ' + // do { + + 'OP_BEGIN ' + // i = i + 1; + + 'OP_DUP OP_1ADD OP_NIP ' + // require(i < 10); + + 'OP_DUP OP_10 OP_LESSTHAN OP_VERIFY ' + // } while (i < tx.inputs.length); + + 'OP_DUP OP_TXINPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL ' + // } + + 'OP_DROP OP_1', + fingerprint: 'ce6d7a3b336f2b8c85a25c362635f801df5ebc31a54f6940c02df6966d7dd484', + debug: { + bytecode: '0065768b77765a9f6976c3a2667551', + sourceMap: '3:16:3:17;5:8:8:39;6:16:6:17;:::21:1;:12::22;7:20:7:21:0;:24::26;:20:::1;:12::28;8:17:8:18:0;:21::37;5:8::39:1;;2:22:9:5;', + logs: [], + requires: [{ ip: 8, line: 7 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/double_negation.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/double_negation.ts new file mode 100644 index 000000000..eb39fbb22 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/double_negation.ts @@ -0,0 +1,42 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'DoubleNegation', + constructorInputs: [{ name: 'flag', type: 'bool' }], + abi: [{ name: 'spend', inputs: [{ name: 'target', type: 'int' }] }], + bytecode: + // require(!!flag) - OP_NOT OP_NOT OP_VERIFY is optimised to OP_VERIFY + 'OP_DUP OP_VERIFY ' + // int i = 0; bool done = false; + + 'OP_0 OP_0 ' + // do { i = i + 1; + + 'OP_BEGIN OP_OVER OP_1ADD OP_ROT OP_DROP OP_SWAP ' + // done = i >= target; + + 'OP_OVER OP_4 OP_PICK OP_GREATERTHANOREQUAL OP_NIP ' + // } while (!done) - OP_NOT OP_NOT OP_UNTIL is optimised to OP_UNTIL + + 'OP_DUP OP_UNTIL ' + // if (!!flag) - OP_NOT OP_NOT OP_IF becomes OP_NOT OP_NOTIF, which is optimised to OP_IF + + 'OP_ROT OP_IF ' + // require(i == target); } + + 'OP_OVER OP_3 OP_PICK OP_NUMEQUALVERIFY OP_ENDIF ' + // require(i > 0) + + 'OP_SWAP OP_0 OP_GREATERTHAN ' + // clean up i and done + + 'OP_NIP OP_NIP', + debug: { + bytecode: '7669000065788b7b757c785479a27776667b637853799d687c00a07777', + sourceMap: '4:18:4:22;:8::24:1;6:16:6:17:0;7:20:7:25;9:8:13:24;10:16:10:17;:::21:1;:12::22;;;11:19:11:20:0;:24::30;;:19:::1;:12::31;13:18:13:22:0;9:8::24:1;16:14:16:18:0;:12:18:9;17:20:17:21;:25::31;;:12::33:1;16:20:18:9;20:16:20:17:0;:20::21;:8::23:1;2:31:21:5;', + logs: [], + requires: [ + { ip: 2, line: 4 }, + { ip: 23, line: 17 }, + { ip: 28, line: 20 }, + ], + sourceTags: '27:28:sc', + }, + fingerprint: 'ed0b5bc35f0130fa04d1fce813fbd7c183bb5346006d10c0808f0d9872712ded', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/double_split.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/double_split.ts new file mode 100644 index 000000000..c0987be84 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/double_split.ts @@ -0,0 +1,24 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'DoubleSplit', + constructorInputs: [{ name: 'pkh', type: 'bytes20' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: 'OP_INPUTINDEX OP_UTXOBYTECODE 17 OP_SPLIT OP_DROP OP_3 OP_SPLIT OP_NIP OP_EQUAL', + debug: { + bytecode: 'c0c701177f75537f7787', + sourceMap: '3:36:3:57;:26::74:1;:81::83:0;:26::84:1;:::87;:94::95:0;:26::96:1;:::99;4:8:4:34', + logs: [], + requires: [ + { + ip: 10, + line: 4, + }, + ], + }, + fingerprint: 'd8574d80ab674df33841526cf2767c09a9dc02d2faea91746465e22e3b81ae3a', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/everything.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/everything.ts new file mode 100644 index 000000000..84c710c8b --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/everything.ts @@ -0,0 +1,68 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'string' }], + abi: [{ name: 'hello', inputs: [{ name: 's', type: 'sig' }, { name: 'pk', type: 'pubkey' }] }], + bytecode: + // int i = 400 + x; + '9001 OP_OVER OP_ADD ' + // bytes b = 0x07364897987fe87 + bytes(y); + + '07364897987fe807 OP_3 OP_PICK OP_CAT ' + // int myVariable = 10 - int(false); // they can go at the end of the line + + 'OP_10 OP_0 OP_SUB ' + // int myOtherVariable = (i + myVariable) % 2; + + 'OP_2 OP_PICK OP_OVER OP_ADD OP_2 OP_MOD ' + // require(myOtherVariable /* And comments can be included within lines */ > i); + + 'OP_DUP OP_4 OP_PICK OP_GREATERTHAN OP_VERIFY ' + // myOtherVariable = i; + + 'OP_3 OP_PICK ' + // myVariable = 10; + + 'OP_10 ' + // require(ripemd160(b) == ripemd160(bytes(myVariable))); + + 'OP_4 OP_ROLL OP_RIPEMD160 OP_OVER OP_RIPEMD160 OP_EQUALVERIFY ' + // require(this.age >= 500); + + 'f401 OP_CHECKSEQUENCEVERIFY OP_DROP ' + // require(y.length < -10); + + 'OP_6 OP_ROLL OP_SIZE OP_NIP 8a OP_LESSTHAN OP_VERIFY ' + // if (i > 400) { + + 'OP_4 OP_PICK 9001 OP_GREATERTHAN OP_IF ' + // i = 400; + + '9001 OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK ' + // } + + 'OP_ENDIF ' + // if (x > 10) { + + 'OP_5 OP_PICK OP_10 OP_GREATERTHAN OP_IF ' + // require(i < 20); + + 'OP_4 OP_PICK 14 OP_LESSTHAN OP_VERIFY ' + // require(checkSig(s, pk)); + + 'OP_6 OP_PICK OP_8 OP_PICK OP_CHECKSIGVERIFY ' + // } else if (x < 5) { + + 'OP_ELSE OP_5 OP_PICK OP_5 OP_LESSTHAN OP_IF ' + // require(false); + + 'OP_0 OP_VERIFY ' + // require(myVariable == 1); + + 'OP_ELSE OP_DUP OP_1 OP_NUMEQUALVERIFY OP_ENDIF OP_ENDIF ' + // } + + 'OP_2DROP OP_2DROP OP_2DROP OP_2DROP OP_1', + fingerprint: '5c83820f08cc787eb0078463cbf16b3b8c605a21bf42464bf9d4f9f31f254569', + debug: { + bytecode: '02900178930807364897987fe80753797e5a0094527978935297765479a06953795a547aa678a68802f401b275567a8277018a9f695479029001a063029001557a757c6b7c6b7c6b7c6c6c6c6855795aa063547901149f6956795879ad675579559f6300696776519d68686d6d6d6d51', + sourceMap: '9:16:9:19;:22::23;:16:::1;10:18:10:35:0;:44::45;;:18::46:1;12:25:12:27:0;:34::39;:25::40:1;13:31:13:32:0;;:35::45;:31:::1;:49::50:0;:30:::1;14:16:14:31:0;:82::83;;:16:::1;:8::85;16:26:16:27:0;;17:21:17:23;19:26:19:27;;:16::28:1;:48::58:0;:32::60:1;:8::62;20:28:20:31:0;:8::33:1;;21:16:21:17:0;;:::24:1;;:27::30:0;:16:::1;:8::32;23:12:23:13:0;;:16::19;:12:::1;:21:25:9:0;24:16:24:19;:12::20:1;;;;;;;;;;;;;23:21:25:9;27:12:27:13:0;;:16::18;:12:::1;:20:30:9:0;28::28:21;;:24::26;:20:::1;:12::28;29:29:29:30:0;;:32::34;;:12::37:1;30:15:33::0;:19:30:20;;:23::24;:19:::1;:26:32:9:0;31:20:31:25;:12::27:1;33::33:37:0;:20::30;:34::35;:12::37:1;;30:15;8:37:34:5;;;;', + logs: [], + requires: [ + { ip: 22, line: 14 }, + { ip: 31, line: 19 }, + { ip: 33, line: 20 }, + { ip: 41, line: 21 }, + { ip: 71, line: 28 }, + { ip: 76, line: 29 }, + { ip: 84, line: 31 }, + { ip: 88, line: 33 }, + ], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/for_loop_basic.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/for_loop_basic.ts new file mode 100644 index 000000000..cf31a691f --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/for_loop_basic.ts @@ -0,0 +1,22 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'ForLoopBasic', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: 'OP_0 OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_2DUP OP_ADD OP_ROT OP_DROP OP_SWAP OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_3 OP_NUMEQUAL', + debug: { + bytecode: '00006576539f766b636e937b757c768b77686c916675539c', + sourceMap: '3:18:3:19;5:21:5:22;:8:7:9;:24:5:25;:28::29;:24:::1;;;:36:7:9:0;6:18:6:25;::::1;:12::26;;;5:31:5:32:0;:::34:1;;:36:7:9;;:8;;;9:23:9:24:0;:8::26:1', + logs: [], + requires: [ + { ip: 24, line: 9 }, + ], + sourceTags: '14:16:fu;17:20:lc;21:21:sc', + }, + fingerprint: '9e52dba656b0743057d4eda76f051c8a1f4460a2becf8f372c690b1901512b4e', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/for_loop_stack_items.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/for_loop_stack_items.ts new file mode 100644 index 000000000..063af7457 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/for_loop_stack_items.ts @@ -0,0 +1,24 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'ForLoopBasic', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: 'OP_0 OP_1 OP_1 OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_3 OP_PICK OP_OVER OP_ADD OP_4 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_ROT OP_3 OP_NUMEQUALVERIFY OP_SWAP OP_1 OP_NUMEQUALVERIFY OP_1 OP_NUMEQUAL', + debug: { + bytecode: '005151006576539f766b6353797893547a757c6b7c6b7c6c6c768b77686c9166757b539d7c519d519c', + sourceMap: '3:18:3:19;4:16:4:17;5::5;7:21:7:22;:8:9:9;:24:7:25;:28::29;:24:::1;;;:39:9:9:0;8:18:8:21;;:24::25;:18:::1;:12::26;;;;;;;;;;7:31:7:32:0;:::37:1;;:39:9:9;;:8;;;11:16:11:19:0;:23::24;:8::26:1;12:16:12:17:0;:21::22;:8::24:1;13:21:13:22:0;:8::24:1', + logs: [], + requires: [ + { ip: 35, line: 11 }, + { ip: 38, line: 12 }, + { ip: 41, line: 13 }, + ], + sourceTags: '25:27:fu;28:31:lc;32:32:sc', + }, + fingerprint: '05430d75d110ff5d4525f7e34bbf2c86b8d22f4e5758f2e109180b801b21b8ec', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/for_while_nested.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/for_while_nested.ts new file mode 100644 index 000000000..3d00a2526 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/for_while_nested.ts @@ -0,0 +1,35 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'ForWhileNested', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: 'OP_0 OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_2 OP_PICK OP_2 OP_PICK OP_ADD OP_OVER OP_ADD OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_4 OP_NUMEQUAL', + debug: { + bytecode: '00006576529f766b63006576529f766b6352795279937893537a757c6b7c6c768b77686c9166788b7b7577686c916675549c', + sourceMap: '3:18:3:19;5:21:5:22;:8:13:9;:24:5:25;:28::29;:24:::1;;;:42:13:9:0;6:20:6:21;8:12:12:13;:19:8:20;:23::24;:19:::1;;;:26:12:13:0;9:22:9:25;;:28::29;;:22:::1;:32::33:0;:22:::1;:16::34;;;;;;;10:20:10:21:0;:::25:1;:16::26;8:26:12:13;;:12;;5:35:5:36:0;:::40:1;:31;;::13:9;:42;;:8;;;15:23:15:24:0;:8::26:1', + logs: [ + { + ip: 34, + line: 11, + data: [ + 'sum:', + { stackIndex: 2, type: 'int', ip: 34 }, + 'i:', + { stackIndex: 1, type: 'int', ip: 34 }, + 'j:', + { stackIndex: 0, type: 'int', ip: 34 }, + ], + }, + ], + requires: [ + { ip: 50, line: 15 }, + ], + sourceTags: '34:37:lc;38:42:fu;43:46:lc;47:47:sc', + }, + fingerprint: '9eb2ec48e103cb2b0d75a326b533756d8f5edb49b2ea43a5578f5ceebde8c2ce', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/force_cast_smaller_bytes.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/force_cast_smaller_bytes.ts new file mode 100644 index 000000000..1fc969f5e --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/force_cast_smaller_bytes.ts @@ -0,0 +1,23 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [] }], + bytecode: + // bytes3 byte_ = unsafe_bytes3(bytes(0x1234)); + '1234 ' + // require(byte_.length == 1); + + 'OP_SIZE OP_NIP OP_1 OP_NUMEQUAL', + fingerprint: '07359fa5600dcaa0a9c582b428cdad5a3a9c63ac13f44b3503eaf31b540edc8e', + debug: { + bytecode: '0212348277519c', + sourceMap: '4:43:4:49;5:16:5:28:1;;:32::33:0;:8::35:1', + logs: [], + requires: [{ ip: 5, line: 5 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_arithmetic.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_arithmetic.ts new file mode 100644 index 000000000..b11a004dc --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_arithmetic.ts @@ -0,0 +1,110 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalConstantArithmetic', + constructorInputs: [], + abi: [ + { + name: 'spend', + inputs: [ + { name: 'base', type: 'int' }, + { name: 'derived', type: 'int' }, + { name: 'negated', type: 'int' }, + { name: 'complex', type: 'int' }, + { name: 'greeting', type: 'string' }, + { name: 'magic', type: 'bytes4' }, + ], + }, + ], + bytecode: + // Implicit parameter type enforcement + 'OP_5 OP_ROLL OP_SIZE OP_4 OP_EQUALVERIFY ' + // require(base == BASE); + + 'OP_SWAP 14 OP_NUMEQUALVERIFY ' + // require(derived == DERIVED); + + 'OP_SWAP OP_15 OP_NUMEQUALVERIFY ' + // require(negated == NEGATED); + + 'OP_SWAP 9e OP_NUMEQUALVERIFY ' + // require(complex == COMPLEX); + + 'OP_SWAP 0002 OP_NUMEQUALVERIFY ' + // require(greeting == GREETING); + + 'OP_SWAP 68656c6c6f20776f726c64 OP_EQUALVERIFY ' + // require(magic == MAGIC); + + '01020304 OP_EQUAL', + fingerprint: '29ddac97c055a2c032d2164877831a3ba0506b19bf20e0e3511da9dc874a21dc', + debug: { + bytecode: '557a8254887c01149d7c5f9d7c019e9d7c0200029d7c0b68656c6c6f20776f726c6488040102030487', + sourceMap: '9:85:9:97;;;;;10:16:10:20;:24::28:1;:8::30;11:16:11:23:0;:27::34:1;:8::36;12:16:12:23:0;:27::34:1;:8::36;13:16:13:23:0;:27::34:1;:8::36;14:16:14:24:0;:28::36:1;:8::38;15:25:15:30;:8::32', + logs: [], + requires: [ + { ip: 7, line: 10 }, + { ip: 10, line: 11 }, + { ip: 13, line: 12 }, + { ip: 16, line: 13 }, + { ip: 19, line: 14 }, + { ip: 22, line: 15 }, + ], + sourceTags: '0:4:pv', + functions: [ + { + name: 'BASE', + kind: 'constant', + inputs: [], + bytecode: '0114', + sourceMap: '1:20:1:27', + logs: [], + requires: [], + }, + { + name: 'DERIVED', + kind: 'constant', + inputs: [], + bytecode: '5f', + sourceMap: '2:23:2:31', + logs: [], + requires: [], + }, + { + name: 'NEGATED', + kind: 'constant', + inputs: [], + bytecode: '019e', + sourceMap: '3:23:3:35', + logs: [], + requires: [], + }, + { + name: 'COMPLEX', + kind: 'constant', + inputs: [], + bytecode: '020002', + sourceMap: '4:23:4:51', + logs: [], + requires: [], + }, + { + name: 'GREETING', + kind: 'constant', + inputs: [], + bytecode: '0b68656c6c6f20776f726c64', + sourceMap: '5:27:5:50', + logs: [], + requires: [], + }, + { + name: 'MAGIC', + kind: 'constant', + inputs: [], + bytecode: '0401020304', + sourceMap: '6:24:6:39', + logs: [], + requires: [], + }, + ], + inlineRanges: '6:6:BASE;9:9:DERIVED;12:12:NEGATED;15:15:COMPLEX;18:18:GREETING;20:20:MAGIC', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_inlined.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_inlined.ts new file mode 100644 index 000000000..9e2088d5f --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_inlined.ts @@ -0,0 +1,40 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + // A small global constant used repeatedly — inlined as a plain literal at each use site (no + // OP_DEFINE), with source locations mapping to the use sites rather than the declaration. + artifact: { + contractName: 'GlobalConstantInlined', + constructorInputs: [{ name: 'value', type: 'int' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // require(value + ONE + ONE == 3) + 'OP_1ADD OP_1ADD OP_3 OP_NUMEQUAL', + debug: { + bytecode: '8b8b539c', + logs: [], + requires: [ + { ip: 5, line: 5 }, + ], + sourceMap: '5:16:5:27:1;:::33;:37::38:0;:8::40:1', + // Both literal pushes were fused into the OP_1ADDs during optimisation; the ranges track them + inlineRanges: '1:1:ONE;2:2:ONE', + functions: [ + { + // The inlined constant is documented as an id-less frame; both of its literal pushes + // were emitted at the use sites and fused into the OP_1ADDs during optimisation + name: 'ONE', + kind: 'constant', + inputs: [], + bytecode: '51', + sourceMap: '1:19:1:20', + logs: [], + requires: [], + }, + ], + }, + fingerprint: '0d639aa764e1dc4045e25efe7dc27bd247b3cd45dd6c3a878a83bc3015e38a59', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_literals.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_literals.ts new file mode 100644 index 000000000..e1aebed30 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_literals.ts @@ -0,0 +1,110 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalConstantLiterals', + constructorInputs: [], + abi: [ + { + name: 'spend', + inputs: [ + { name: 'enabled', type: 'bool' }, + { name: 'negative', type: 'int' }, + { name: 'interval', type: 'int' }, + { name: 'deadline', type: 'int' }, + { name: 'greeting', type: 'string' }, + { name: 'magic', type: 'bytes4' }, + ], + }, + ], + bytecode: + // Implicit parameter type enforcement + 'OP_0NOTEQUAL OP_5 OP_ROLL OP_SIZE OP_4 OP_EQUALVERIFY ' + // require(enabled == ENABLED); + + 'OP_SWAP OP_1 OP_NUMEQUALVERIFY ' + // require(negative == NEGATIVE); + + 'OP_SWAP 87 OP_NUMEQUALVERIFY ' + // require(interval == INTERVAL); + + 'OP_SWAP 201c OP_NUMEQUALVERIFY ' + // require(deadline == DEADLINE); + + 'OP_SWAP 88632c60 OP_NUMEQUALVERIFY ' + // require(greeting == GREETING); + + 'OP_SWAP 68656c6c6f OP_EQUALVERIFY ' + // require(magic == MAGIC); + + '01020304 OP_EQUAL', + fingerprint: '74578f6eb254c7cb367434c6754d27e684bd1b3c7362fac7a0024397c9f73331', + debug: { + bytecode: '92557a8254887c519d7c01879d7c02201c9d7c0488632c609d7c0568656c6c6f88040102030487', + sourceMap: '9:19:9:31;:92::104;;;;;10:16:10:23;:27::34:1;:8::36;11:16:11:24:0;:28::36:1;:8::38;12:16:12:24:0;:28::36:1;:8::38;13:16:13:24:0;:28::36:1;:8::38;14:16:14:24:0;:28::36:1;:8::38;15:25:15:30;:8::32', + logs: [], + requires: [ + { ip: 8, line: 10 }, + { ip: 11, line: 11 }, + { ip: 14, line: 12 }, + { ip: 17, line: 13 }, + { ip: 20, line: 14 }, + { ip: 23, line: 15 }, + ], + sourceTags: '0:0:pv;1:5:pv', + functions: [ + { + name: 'ENABLED', + kind: 'constant', + inputs: [], + bytecode: '51', + sourceMap: '1:24:1:28', + logs: [], + requires: [], + }, + { + name: 'NEGATIVE', + kind: 'constant', + inputs: [], + bytecode: '0187', + sourceMap: '2:24:2:26', + logs: [], + requires: [], + }, + { + name: 'INTERVAL', + kind: 'constant', + inputs: [], + bytecode: '02201c', + sourceMap: '3:24:3:31', + logs: [], + requires: [], + }, + { + name: 'DEADLINE', + kind: 'constant', + inputs: [], + bytecode: '0488632c60', + sourceMap: '4:24:4:51', + logs: [], + requires: [], + }, + { + name: 'GREETING', + kind: 'constant', + inputs: [], + bytecode: '0568656c6c6f', + sourceMap: '5:27:5:34', + logs: [], + requires: [], + }, + { + name: 'MAGIC', + kind: 'constant', + inputs: [], + bytecode: '0401020304', + sourceMap: '6:24:6:34', + logs: [], + requires: [], + }, + ], + inlineRanges: '7:7:ENABLED;10:10:NEGATIVE;13:13:INTERVAL;16:16:DEADLINE;19:19:GREETING;21:21:MAGIC', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_shared.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_shared.ts new file mode 100644 index 000000000..0bc9674b6 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_shared.ts @@ -0,0 +1,40 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + // A global constant used repeatedly — lowered to a zero-argument VM function definition with a + // kind: 'constant' debug frame; each use compiles to an OP_INVOKE. + artifact: { + contractName: 'GlobalConstantShared', + constructorInputs: [{ name: 'first', type: 'bytes32' }, { name: 'second', type: 'bytes32' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // OP_DEFINE HASH (id 0): the 32-byte literal + '203333333333333333333333333333333333333333333333333333333333333333 OP_0 OP_DEFINE ' + // require(first == HASH); require(second == HASH) + + 'OP_0 OP_INVOKE OP_EQUALVERIFY OP_0 OP_INVOKE OP_EQUAL', + debug: { + bytecode: '212033333333333333333333333333333333333333333333333333333333333333330089008a88008a87', + logs: [], + requires: [ + { ip: 7, line: 5 }, + { ip: 11, line: 6 }, + ], + sourceMap: '1::1:91;;::::1;5:25:5:29;;:8::31;6:26:6:30;;:8::32', + functions: [ + { + id: 0, + name: 'HASH', + kind: 'constant', + inputs: [], + bytecode: '203333333333333333333333333333333333333333333333333333333333333333', + sourceMap: '1:24:1:90', + logs: [], + requires: [], + }, + ], + }, + fingerprint: '6a5509a2ece64c7e47b4e1185da2f8b92fc0e1f75cc818be86b783c7bf134c5e', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_altstack_cleanup.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_altstack_cleanup.ts new file mode 100644 index 000000000..89579712f --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_altstack_cleanup.ts @@ -0,0 +1,36 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalFunctionAltStackCleanup', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // int lo, int hi = orderedPair(1, 2, x); + 'OP_1 OP_2 OP_ROT OP_0 OP_0 OP_ROT OP_0 OP_GREATERTHAN OP_IF OP_3 OP_PICK OP_ROT OP_DROP OP_SWAP OP_2 OP_PICK OP_NIP OP_ELSE OP_NIP OP_OVER OP_SWAP OP_3 OP_PICK OP_NIP OP_ENDIF OP_ROT OP_DROP OP_ROT OP_DROP ' + // require(lo == 1, "lo should be 1"); + + 'OP_SWAP OP_1 OP_NUMEQUALVERIFY ' + // require(hi == 2, "hi should be 2"); + + 'OP_2 OP_NUMEQUAL', + fingerprint: '641437fc5e376f92f1da865a9a0e8a1cc1a48fe845b38ea10afa9ba4ce4e5908', + debug: { + bytecode: '51527b00007b00a06353797b757c5279776777787c537977687b757b757c519d529c', + sourceMap: '16:37:16:38;:40::41;:43::44;:25::45:1;;;;;;;;;;;;;;;;;;;;;;;;;;17:16:17:18:0;:22::23;:8::43:1;18:22:18:23:0;:8::43:1', + logs: [], + requires: [{ ip: 31, line: 17, message: 'lo should be 1' }, { ip: 34, line: 18, message: 'hi should be 2' }], + functions: [ + { + name: 'orderedPair', + inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }, { name: 'c', type: 'int' }], + bytecode: '00007b00a06353797b757c5279776777787c537977687b757b75', + sourceMap: '2:13:2:14;3::3;4:8:4:9;:12::13;:8:::1;:15:7:5:0;5:13:5:14;;:8::15:1;;;6:13:6:14:0;;:8::15:1;7:11:10:5:0;8:8:8:15:1;;;9:13:9:14:0;;:8::15:1;7:11:10:5;1:61:12:1;;;', + logs: [], + requires: [], + }, + ], + inlineRanges: '3:28:orderedPair', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_in_control_flow.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_in_control_flow.ts new file mode 100644 index 000000000..b6573cedb --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_in_control_flow.ts @@ -0,0 +1,57 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalFunctionInControlFlow', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }, { name: 'useLoop', type: 'bool' }] }], + bytecode: + // Implicit parameter type enforcement + 'OP_SWAP OP_0NOTEQUAL ' + // int total = 0; + + 'OP_0 ' + // if (useLoop) { + + 'OP_SWAP OP_IF ' + // for (int i = 0; i < 3; i = i + 1) { + + 'OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF ' + // total = total + triple(x); + + 'OP_OVER OP_3 OP_PICK OP_3 OP_MUL OP_ADD OP_ROT OP_DROP OP_SWAP ' + // For loop update + + 'OP_DUP OP_1ADD OP_NIP ' + // Loop condition + + 'OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL ' + // Cleanup + + 'OP_DROP ' + // } else { + + 'OP_ELSE ' + // total = triple(x); + + 'OP_OVER OP_3 OP_MUL OP_NIP ' + // } + + 'OP_ENDIF ' + // require(total == 9); + + 'OP_9 OP_NUMEQUAL ' + // Cleanup + + 'OP_NIP', + fingerprint: '55b4a10e6ce60560acbb358c02189f85620385e0fcfd5013fe236339e8b238bb', + debug: { + bytecode: '7c92007c63006576539f766b637853795395937b757c768b77686c916675677853957768599c77', + sourceMap: '6:26:6:38;;7:20:7:21;8:12:8:19;:21:12:9;9:25:9:26;:12:11:13;:28:9:29;:32::33;:28:::1;;;:46:11:13:0;10:24:10:29;:39::40;;:32::41:1;;:24;:16::42;;;9:39:9:40:0;:::44:1;:35;:46:11:13;;:12;;;12:15:14:9:0;13:27:13:28;:20::29:1;;:12::30;12:15:14:9;15:25:15:26:0;:8::28:1;6:40:16:5', + logs: [], + requires: [{ ip: 38, line: 15 }], + sourceTags: '0:1:pv;22:24:fu;25:28:lc;29:29:sc;38:38:sc', + functions: [ + { + name: 'triple', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '5395', + sourceMap: '2:15:2:16;:11:::1', + logs: [], + requires: [], + }, + ], + inlineRanges: '16:17:triple;32:33:triple', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_inlined.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_inlined.ts new file mode 100644 index 000000000..be0fdc3d4 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_inlined.ts @@ -0,0 +1,48 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + // A single-use global function — inlined at the call site, splicing its console.log and require + // metadata into the contract's debug info (same-file bodies keep their own source lines). + artifact: { + contractName: 'GlobalFunctionInlined', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'n', type: 'int' }] }], + bytecode: + // require(checked(n) == n), with checked(x) spliced in: + // console.log ... require(x > 0, "positive") ... return x + 'OP_DUP OP_DUP OP_0 OP_GREATERTHAN OP_VERIFY OP_NUMEQUAL', + debug: { + bytecode: '767600a0699c', + logs: [ + { ip: 1, line: 9, data: ['checking', { stackIndex: 0, type: 'int', ip: 1 }] }, + ], + requires: [ + { ip: 4, line: 9, message: 'positive' }, + { ip: 6, line: 9 }, + ], + // The emitted body ops (ips 1-4) and the merged require/log entries above all map to the + // call site; the function's own lines live on its frame below, tied together by the range + sourceMap: '9:24:9:25;:16::26:1;;;;:8::33', + inlineRanges: '1:4:checked', + functions: [ + { + // The inlined function is documented as an id-less frame carrying its compiled body + // and frame-local debug info (ips from 0) + name: 'checked', + inputs: [{ name: 'x', type: 'int' }], + bytecode: '7600a069', + sourceMap: '3:12:3:13;:16::17;:12:::1;:4::31', + logs: [ + { ip: 0, line: 2, data: ['checking', { stackIndex: 0, type: 'int', ip: 0 }] }, + ], + requires: [ + { ip: 3, line: 3, message: 'positive' }, + ], + }, + ], + }, + fingerprint: 'a19e54aee90995fe784da8e5501a95020d91aa1ccf17ac1f3c7a3e7be0813a73', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_param.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_param.ts new file mode 100644 index 000000000..b0d4a1762 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_param.ts @@ -0,0 +1,67 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalFunctionMultiParam', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }] }], + bytecode: + // require(sub(x, y) == 7); + 'OP_SWAP OP_SUB OP_7 OP_NUMEQUAL', + fingerprint: 'e2fc400768dc40234ade786da44ad2a623d43f73ee5b70af21da0647616b162f', + debug: { + bytecode: '7c94579c', + sourceMap: '7:23:7:24;:16::25:1;:29::30:0;:8::32:1', + logs: [], + requires: [{ ip: 4, line: 7 }], + functions: [ + { + name: 'sub', + inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }], + bytecode: '94', + sourceMap: '2:11:2:16:1', + logs: [], + requires: [], + }, + ], + inlineRanges: '1:1:sub', + }, + }, + }, + { + // 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). + 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', + debug: { + bytecode: '019400897c008a579c', + logs: [], + requires: [ + { ip: 8, line: 7 }, + ], + sourceMap: '1::3:1;;::::1;7:23:7:24:0;:16::25:1;;: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', + logs: [], + requires: [], + }, + ], + }, + fingerprint: '8fc72a3f89ee3238266d6dd9ad3919f7238c8d6a31296cc8925968a31c78c7dc', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_return.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_return.ts new file mode 100644 index 000000000..3b8a955a7 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_return.ts @@ -0,0 +1,72 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalFunctionMultiReturn', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // int q, int r = divmod(x, 3); + 'OP_3 OP_2DUP OP_DIV OP_ROT OP_ROT OP_MOD ' + // require(q == 4); + + 'OP_SWAP OP_4 OP_NUMEQUALVERIFY ' + // require(r == 1); + + 'OP_1 OP_NUMEQUAL', + fingerprint: '04958e32271966d1b4d4365481f1d3210fde12595fa9261b454f430bf8afe521', + debug: { + bytecode: '536e967b7b977c549d519c', + sourceMap: '7:33:7:34;:23::35:1;;;;;8:16:8:17:0;:21::22;:8::24:1;9:21:9:22:0;:8::24:1', + logs: [], + requires: [{ ip: 8, line: 8 }, { ip: 11, line: 9 }], + functions: [ + { + name: 'divmod', + inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }], + bytecode: '6e967b7b97', + sourceMap: '2:11:2:16;::::1;:18::19:0;:22::23;:18:::1', + logs: [], + requires: [], + }, + ], + inlineRanges: '1:5:divmod', + }, + }, + }, + { + // A multi-return function — locks in the calling convention: return values are left on the stack + // in declared order (last value on top) and bound by an N-ary tuple destructuring at the call site. + compilerOptions: { disableInlining: true }, + artifact: { + contractName: 'GlobalFunctionMultiReturn', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // OP_DEFINE divmod (id 0): return a / b, a % b — leaves [quotient, remainder], remainder on top + '6e967b7b97 OP_0 OP_DEFINE ' + // int q, int r = divmod(x, 3); require(q == 4); require(r == 1) + + 'OP_3 OP_0 OP_INVOKE OP_SWAP OP_4 OP_NUMEQUALVERIFY OP_1 OP_NUMEQUAL', + debug: { + bytecode: '056e967b7b97008953008a7c549d519c', + logs: [], + requires: [ + { ip: 8, line: 8 }, + { ip: 11, line: 9 }, + ], + sourceMap: '1::3:1;;::::1;7:33:7:34:0;:23::35:1;;8:16:8:17:0;:21::22;:8::24:1;9:21:9:22:0;:8::24:1', + functions: [ + { + id: 0, + name: 'divmod', + inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }], + bytecode: '6e967b7b97', + sourceMap: '2:11:2:16;::::1;:18::19:0;:22::23;:18:::1', + logs: [], + requires: [], + }, + ], + }, + fingerprint: 'f747468c9408ec52949a22dc2f271a944ee5793eabaa913c9c2b1b4c3fbd0a56', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_return_three.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_return_three.ts new file mode 100644 index 000000000..7a9731dfb --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_multi_return_three.ts @@ -0,0 +1,38 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalFunctionMultiReturnThree', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // int p, int q, int r = spread(x); + 'OP_DUP OP_DUP OP_1ADD OP_ROT OP_2 OP_ADD ' + // require(p == 5); + + 'OP_ROT OP_5 OP_NUMEQUALVERIFY ' + // require(q == 6); + + 'OP_SWAP OP_6 OP_NUMEQUALVERIFY ' + // require(r == 7); + + 'OP_7 OP_NUMEQUAL', + fingerprint: 'aa5e498180e729156632201aff442d09e0c613298bf26169ff93956605eb2cfb', + debug: { + bytecode: '76768b7b52937b559d7c569d579c', + sourceMap: '7:30:7:39:1;;;;;;8:16:8:17:0;:21::22;:8::24:1;9:16:9:17:0;:21::22;:8::24:1;10:21:10:22:0;:8::24:1', + logs: [], + requires: [{ ip: 8, line: 8 }, { ip: 11, line: 9 }, { ip: 14, line: 10 }], + functions: [ + { + name: 'spread', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '76768b7b5293', + sourceMap: '2:11:2:15;;:14::19:1;:21::22:0;:25::26;:21:::1', + logs: [], + requires: [], + }, + ], + inlineRanges: '0:5:spread', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_nested.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_nested.ts new file mode 100644 index 000000000..4b03c133d --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_nested.ts @@ -0,0 +1,41 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalFunctionNested', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // require(doubleIncremented(x) == 8); + 'OP_1ADD OP_2 OP_MUL OP_8 OP_NUMEQUAL', + fingerprint: '01c59dd1621703390bdc5e526ab56f2a37ed8cef6d3a61ff6218a80d51831703', + debug: { + bytecode: '8b5295589c', + sourceMap: '11:16:11:36:1;;;:40::41:0;:8::43:1', + logs: [], + requires: [{ ip: 5, line: 11 }], + functions: [ + { + name: 'addOne', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '8b', + sourceMap: '2:11:2:16:1', + logs: [], + requires: [], + }, + { + name: 'doubleIncremented', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '8b5295', + sourceMap: '6:11:6:20:1;:23::24:0;:11:::1', + logs: [], + requires: [], + inlineRanges: '0:0:addOne', + }, + ], + inlineRanges: '0:2:doubleIncremented', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_simple.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_simple.ts new file mode 100644 index 000000000..c275e05c7 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_simple.ts @@ -0,0 +1,66 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalFunctionSimple', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // require(double(x) == 6); + 'OP_2 OP_MUL OP_6 OP_NUMEQUAL', + fingerprint: '36698e75d5530f81a95354d9c1c11e7de7c8867595b28ca69cad14e24647ccf3', + debug: { + bytecode: '5295569c', + sourceMap: '7:16:7:25:1;;:29::30:0;:8::32:1', + logs: [], + requires: [{ ip: 4, line: 7 }], + functions: [ + { + name: 'double', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '5295', + sourceMap: '2:15:2:16;:11:::1', + logs: [], + requires: [], + }, + ], + inlineRanges: '0:1:double', + }, + }, + }, + { + // A single global function — the basic OP_DEFINE / OP_INVOKE calling convention. + compilerOptions: { disableInlining: true }, + artifact: { + contractName: 'GlobalFunctionSimple', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // OP_DEFINE double (id 0): return a * 2 + '5295 OP_0 OP_DEFINE ' + // require(double(x) == 6) + + 'OP_0 OP_INVOKE OP_6 OP_NUMEQUAL', + debug: { + bytecode: '0252950089008a569c', + logs: [], + requires: [ + { ip: 7, line: 7 }, + ], + sourceMap: '1::3:1;;::::1;7:16:7:25;;:29::30:0;:8::32:1', + functions: [ + { + id: 0, + name: 'double', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '5295', + sourceMap: '2:15:2:16;:11:::1', + logs: [], + requires: [], + }, + ], + }, + fingerprint: 'ef6dd7819e66a430286fe16f3d6dad7e026cf1970eda6bc620be7e7a3bdd2a4d', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_void.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_void.ts new file mode 100644 index 000000000..cbab13fed --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_function_void.ts @@ -0,0 +1,68 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'GlobalFunctionVoid', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // requirePositive(x); + 'OP_DUP OP_0 OP_GREATERTHAN OP_VERIFY ' + // require(x < 100); + + '64 OP_LESSTHAN', + fingerprint: '0c69be9a969ec46cf4dbb0c1b6581f833ff8f2117e03eaae0548312df8b74d99', + debug: { + bytecode: '7600a06901649f', + sourceMap: '7:24:7:25;:8::26:1;;;8:20:8:23:0;:8::25:1', + logs: [], + requires: [{ ip: 3, line: 7 }, { ip: 6, line: 8 }], + functions: [ + { + name: 'requirePositive', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '00a069', + sourceMap: '2:16:2:17;:12:::1;:4::19', + logs: [], + requires: [{ ip: 2, line: 2 }], + }, + ], + inlineRanges: '1:3:requirePositive', + }, + }, + }, + { + // A void global function called as a statement — no return value, and the void stack-cleanup path. + compilerOptions: { disableInlining: true }, + artifact: { + contractName: 'GlobalFunctionVoid', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'x', type: 'int' }] }], + bytecode: + // OP_DEFINE requirePositive (id 0): require(a > 0) + '00a069 OP_0 OP_DEFINE ' + // requirePositive(x); require(x < 100) + + 'OP_DUP OP_0 OP_INVOKE 64 OP_LESSTHAN', + debug: { + bytecode: '0300a069008976008a01649f', + logs: [], + requires: [ + { ip: 8, line: 8 }, + ], + sourceMap: '1::3:1;;::::1;7:24:7:25:0;:8::26:1;;8:20:8:23:0;:8::25:1', + functions: [ + { + id: 0, + name: 'requirePositive', + inputs: [{ name: 'a', type: 'int' }], + bytecode: '00a069', + sourceMap: '2:16:2:17;:12:::1;:4::19', + logs: [], + requires: [{ ip: 2, line: 2 }], + }, + ], + }, + fingerprint: '4d5e07b068e501eb26e61aab0d53214aa42590858253b1106d6074d494fde557', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/hodl_vault.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/hodl_vault.ts new file mode 100644 index 000000000..943f563e5 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/hodl_vault.ts @@ -0,0 +1,58 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'HodlVault', + constructorInputs: [ + { name: 'ownerPk', type: 'pubkey' }, + { name: 'oraclePk', type: 'pubkey' }, + { name: 'minBlock', type: 'int' }, + { name: 'priceTarget', type: 'int' }, + ], + abi: [ + { + name: 'spend', + inputs: [ + { name: 'ownerSig', type: 'sig' }, + { name: 'oracleSig', type: 'datasig' }, + { name: 'oracleMessage', type: 'bytes8' }, + ], + }, + ], + bytecode: + // Implicit type enforcement for oracleMessage: require(oracleMessage.length == 8) + 'OP_6 OP_ROLL OP_SIZE OP_8 OP_EQUALVERIFY ' + // bytes4 blockHeightBin, bytes4 priceBin = oracleMessage.split(4); + + 'OP_DUP OP_4 OP_SPLIT ' + // int blockHeight = int(blockHeightBin); + + 'OP_SWAP OP_BIN2NUM ' + // int price = int(priceBin); + + 'OP_SWAP OP_BIN2NUM ' + // require(blockHeight >= minBlock); + + 'OP_OVER OP_6 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY ' + // require(tx.time >= blockHeight); + + 'OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_DROP ' + // require(price >= priceTarget); + + 'OP_4 OP_ROLL OP_GREATERTHANOREQUAL OP_VERIFY ' + // require(checkDataSig(oracleSig, oracleMessage, oraclePk)); + + 'OP_4 OP_ROLL OP_SWAP OP_3 OP_ROLL OP_CHECKDATASIGVERIFY ' + // require(checkSig(ownerSig, ownerPk)); + + 'OP_CHECKSIG', + debug: { + bytecode: '567a82588876547f7c817c8178567aa2697cb175547aa269547a7c537abbac', + logs: [], + requires: [ + { ip: 20, line: 23 }, + { ip: 22, line: 24 }, + { ip: 27, line: 27 }, + { ip: 33, line: 30 }, + { ip: 35, line: 35 }, + ], + sourceMap: '15:8:15:28;;;;;18:49:18:62;:69::70;:49::71:1;19:30:19:44:0;:26::45:1;20:24:20:32:0;:20::33:1;23:16:23:27:0;:31::39;;:16:::1;:8::41;24:27:24:38:0;:8::40:1;;27:25:27:36:0;;:16:::1;:8::38;31:12:31:21:0;;32::32:25;33::33:20;;30:8:34:11:1;35::35:45', + sourceTags: '0:4:pv', + }, + fingerprint: 'd87449bc71344f12ed3c9ce3f69f844cd1699df29553ec3884c1fcc92a2cfccf', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement.ts new file mode 100644 index 000000000..db677aea7 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement.ts @@ -0,0 +1,45 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'IfStatement', + constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], + abi: [{ name: 'hello', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }] }], + bytecode: + // int d = a + b + 'OP_2OVER OP_ADD ' + // d = d - a + + 'OP_DUP OP_4 OP_PICK OP_SUB ' + // if (d == x - 2) { + + 'OP_DUP OP_3 OP_ROLL OP_2 OP_SUB OP_NUMEQUAL OP_IF ' + // int c = d + b + + 'OP_DUP OP_5 OP_PICK OP_ADD ' + // d = a + c + + 'OP_4 OP_PICK OP_OVER OP_ADD OP_ROT OP_DROP OP_SWAP ' + // require(c > d) + + 'OP_2DUP OP_LESSTHAN OP_VERIFY ' + // } else { + + 'OP_DROP OP_ELSE ' + // require(d == a) } + + 'OP_DUP OP_4 OP_PICK OP_NUMEQUALVERIFY OP_ENDIF ' + // d = d + a + + 'OP_DUP OP_4 OP_ROLL OP_ADD ' + // require(d == y) + + 'OP_3 OP_ROLL OP_NUMEQUAL ' + + 'OP_NIP OP_NIP OP_NIP', + debug: { + bytecode: '70937654799476537a52949c6376557993547978937b757c6e9f6975677654799d6876547a93537a9c777777', + logs: [], + requires: [ + { ip: 28, line: 8 }, + { ip: 34, line: 10 }, + { ip: 43, line: 13 }, + ], + sourceMap: '3:16:3:21;::::1;4:12:4:13:0;:16::17;;:12:::1;5::5:13:0;:17::18;;:21::22;:17:::1;:12;:24:9:9:0;6:20:6:21;:24::25;;:20:::1;7:16:7:17:0;;:20::21;:16:::1;:12::22;;;8:20:8:25:0;::::1;:12::27;5:24:9:9;9:15:11::0;10:20:10:21;:25::26;;:12::28:1;9:15:11:9;12:12:12:13:0;:16::17;;:12:::1;13:21:13:22:0;;:8::24:1;2:33:14:5;;', + sourceTags: '27:27:sc;41:43:sc', + }, + fingerprint: 'b5f6c8b6bd5a7e4bfa2a596b5639fac59338e9cbf93673abc8c32fd4565f2846', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement_number_units-logs.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement_number_units-logs.ts new file mode 100644 index 000000000..e87c0baaf --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement_number_units-logs.ts @@ -0,0 +1,39 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }] }], + bytecode: + // if (a == b - 2 minutes) { + 'OP_2DUP OP_SWAP 78 OP_SUB OP_NUMEQUAL OP_IF ' + // require(false); + + 'OP_0 OP_VERIFY ' + // } else if (b == 2 weeks) + + 'OP_ELSE OP_OVER 007512 OP_NUMEQUAL ' + // require(a == 20 seconds); + + 'OP_IF OP_DUP 14 OP_NUMEQUALVERIFY ' + // else { + + 'OP_ELSE ' + // require(true == !!!false); + + 'OP_1 OP_0 OP_NOT OP_NOT OP_NOT OP_NUMEQUALVERIFY ' + // } + + 'OP_ENDIF OP_ENDIF OP_2DROP OP_1', + fingerprint: '3e2c04970e538e423ce77e999ec3d3fe25e286141f4a57aa6ce77c0d1719ccc9', + debug: { + bytecode: '6e7c0178949c6300696778030075129c637601149d6751009191919d68686d51', + sourceMap: '3:12:3:18;;:21::30;:17:::1;:12;:32:5:9:0;4:20:4:25;:12::27:1;5:15:9:9:0;:19:5:20;:24::31;:19:::1;6:12:6:37:0;:20::21;:25::35;:12::37:1;7:13:9:9:0;8:20:8:24;:31::36;:30:::1;:29;:28;:12::38;7:13:9:9;5:15;2:33:12:5;', + logs: [ + { + ip: 25, + line: 11, + data: [{ stackIndex: 0, type: 'int', ip: 25 }, { stackIndex: 1, type: 'int', ip: 25 }], + }, + ], + requires: [{ ip: 7, line: 4 }, { ip: 15, line: 6 }, { ip: 22, line: 8 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement_number_units.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement_number_units.ts new file mode 100644 index 000000000..8cd822a99 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/if_statement_number_units.ts @@ -0,0 +1,33 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }] }], + bytecode: + // if (a == b - 2 minutes) { + 'OP_2DUP OP_SWAP 78 OP_SUB OP_NUMEQUAL OP_IF ' + // require(false); + + 'OP_0 OP_VERIFY ' + // } else if (b == 2 weeks) + + 'OP_ELSE OP_OVER 007512 OP_NUMEQUAL ' + // require(a == 20 seconds); + + 'OP_IF OP_DUP 14 OP_NUMEQUALVERIFY ' + // else { + + 'OP_ELSE ' + // require(true == !!!false); + + 'OP_1 OP_0 OP_NOT OP_NOT OP_NOT OP_NUMEQUALVERIFY ' + // } + + 'OP_ENDIF OP_ENDIF OP_2DROP OP_1', + fingerprint: '3e2c04970e538e423ce77e999ec3d3fe25e286141f4a57aa6ce77c0d1719ccc9', + debug: { + bytecode: '6e7c0178949c6300696778030075129c637601149d6751009191919d68686d51', + sourceMap: '3:12:3:18;;:21::30;:17:::1;:12;:32:5:9:0;4:20:4:25;:12::27:1;5:15:9:9:0;:19:5:20;:24::31;:19:::1;6:12:6:37:0;:20::21;:25::35;:12::37:1;7:13:9:9:0;8:20:8:24;:31::36;:30:::1;:29;:28;:12::38;7:13:9:9;5:15;2:33:10:5;', + logs: [], + requires: [{ ip: 7, line: 4 }, { ip: 15, line: 6 }, { ip: 22, line: 8 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/increment_decrement.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/increment_decrement.ts new file mode 100644 index 000000000..59d1b4593 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/increment_decrement.ts @@ -0,0 +1,32 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'IncrementDecrement', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // int x = 5; + 'OP_5 ' + // x++; + + 'OP_DUP OP_1ADD ' + // require(x == 6); + + 'OP_DUP OP_6 OP_NUMEQUALVERIFY ' + // x--; + + 'OP_DUP OP_1SUB ' + // require(x == 5); + + 'OP_5 OP_NUMEQUAL ' + // Cleanup + + 'OP_NIP OP_NIP', + fingerprint: '5ccf48b6901709f59aaa5fab621021cf8598fb6fdd591f7f714902070c84bb85', + debug: { + bytecode: '55768b76569d768c559c7777', + sourceMap: '3:16:3:17;4:8:4:9;:::11:1;5:16:5:17:0;:21::22;:8::24:1;7::7:9:0;:::11:1;8:21:8:22:0;:8::24:1;2:21:9:5;', + logs: [], + requires: [{ ip: 5, line: 5 }, { ip: 10, line: 8 }], + sourceTags: '10:11:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/int_to_byte.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/int_to_byte.ts new file mode 100644 index 000000000..ba8bda48f --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/int_to_byte.ts @@ -0,0 +1,26 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'IntToByte', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'bytes1' }] }], + bytecode: + // Implicit parameter type enforcement + 'OP_SWAP OP_SIZE OP_1 OP_EQUALVERIFY ' + // byte c = toPaddedBytes(a, 1); + + 'OP_SWAP OP_1 OP_NUM2BIN ' + // require(b == c); + + 'OP_EQUAL', + fingerprint: 'cbccef08f54b0452cabaf643501a4903dab79b0d676896399771131fea3a0ad1', + debug: { + bytecode: '7c8251887c518087', + sourceMap: '2:26:2:32;;;;3:31:3;:34::35;:17::36:1;4:8:4:24', + logs: [], + requires: [{ ip: 8, line: 4 }], + sourceTags: '0:3:pv', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/integer_formatting.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/integer_formatting.ts new file mode 100644 index 000000000..0425e700d --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/integer_formatting.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'IntegerFormatting', + constructorInputs: [], + abi: [ + { name: 'test', inputs: [] }, + ], + bytecode: '0010a5d4e800 0010a5d4e800 0010a5d4e800 0010a5d4e800 0010a5d4e800 OP_4 OP_ROLL OP_OVER OP_NUMEQUALVERIFY OP_3 OP_ROLL OP_OVER OP_NUMEQUALVERIFY OP_ROT OP_OVER OP_NUMEQUALVERIFY OP_NUMEQUAL', + debug: { + bytecode: '060010a5d4e800060010a5d4e800060010a5d4e800060010a5d4e800060010a5d4e800547a789d537a789d7b789d9c', + logs: [], + requires: [{ ip: 8, line: 10 }, { ip: 12, line: 11 }, { ip: 15, line: 12 }, { ip: 17, line: 13 }], + sourceMap: '3:26:3:30;4::4;5::5:43;6:23:6:30;8:22:8:35;10:16:10:27;;:31::38;:8::40:1;11:16:11:27:0;;:31::38;:8::40:1;12:16:12:27:0;:31::38;:8::40:1;13::13:37', + }, + fingerprint: '0b4ca541ca3bfd698bda9798bc6ce5565513848fe325360248ec00266d84c874', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/invert.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/invert.ts new file mode 100644 index 000000000..e70fcaa6a --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/invert.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // bytes4 x = 0x00000000; + '00000000 ' + // bytes4 y = ~x; + + 'OP_INVERT ' + // require(y == 0xffffffff); + + 'ffffffff OP_EQUAL', + fingerprint: '75fe92c7557ba121b07d4d7bf705fdcdb925d98a7ccd669e499eadeacba041a9', + debug: { + bytecode: '04000000008304ffffffff87', + sourceMap: '3:19:3:29;4::4:21:1;6:21:6:31:0;:8::33:1', + logs: [], + requires: [{ ip: 4, line: 6 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/log_intermediate_results.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/log_intermediate_results.ts new file mode 100644 index 000000000..16084574d --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/log_intermediate_results.ts @@ -0,0 +1,38 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'LogIntermediateResults', + constructorInputs: [{ name: 'owner', type: 'pubkey' }], + abi: [{ name: 'test_log_intermediate_result', inputs: [] }], + bytecode: 'OP_HASH256 OP_SIZE OP_NIP 20 OP_NUMEQUAL', + debug: { + bytecode: 'aa827701209c', + sourceMap: '3:29:5:47:1;6:16:6:33;;:37::39:0;:8::74:1', + logs: [ + { + ip: 1, + line: 4, + data: [ + { + stackIndex: 0, + type: 'bytes32', + ip: 1, + transformations: 'OP_SHA256', + }, + ], + }, + ], + requires: [ + { + ip: 6, + line: 6, + message: 'doubleHash should be 32 bytes', + }, + ], + }, + fingerprint: '47bb8f4ee4f62d7ecefc7f43fd7b61d2da71767df35d3dfd90149719287a0860', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/mecenas.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/mecenas.ts new file mode 100644 index 000000000..4a9c8e095 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/mecenas.ts @@ -0,0 +1,76 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Mecenas', + constructorInputs: [ + { name: 'recipient', type: 'bytes20' }, + { name: 'funder', type: 'bytes20' }, + { name: 'pledge', type: 'int' }, + { name: 'period', type: 'int' }, + ], + abi: [ + { name: 'receive', inputs: [] }, + { name: 'reclaim', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }, + ], + bytecode: + // function receive + 'OP_4 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' + // require(this.age >= period) + + 'OP_3 OP_ROLL OP_CHECKSEQUENCEVERIFY OP_DROP ' + // require(tx.inputs.length == 1) + + 'OP_TXINPUTCOUNT OP_1 OP_NUMEQUALVERIFY ' + // require(tx.outputs[0].lockingBytecode == new LockingBytecodeP2PKH(recipient)) + + 'OP_0 OP_OUTPUTBYTECODE 76a914 OP_ROT OP_CAT 88ac OP_CAT OP_EQUALVERIFY ' + // int minerFee = 1000 + + 'e803 ' + // int currentValue = tx.inputs[this.activeInputIndex].value + + 'OP_INPUTINDEX OP_UTXOVALUE ' + // int changeValue = currentValue - pledge - minerFee + + 'OP_DUP OP_4 OP_PICK OP_SUB OP_2 OP_PICK OP_SUB ' + // if (changeValue <= pledge + minerFee) { + + 'OP_DUP OP_5 OP_PICK OP_4 OP_PICK OP_ADD OP_LESSTHANOREQUAL OP_IF ' + // require(tx.outputs[0].value == currentValue - minerFee) + + 'OP_0 OP_OUTPUTVALUE OP_2OVER OP_SWAP OP_SUB OP_NUMEQUALVERIFY ' + // } else { + + 'OP_ELSE ' + // require(tx.outputs[0].value == pledge) + + 'OP_0 OP_OUTPUTVALUE OP_5 OP_PICK OP_NUMEQUALVERIFY ' + // require( + // tx.outputs[1].lockingBytecode == tx.inputs[this.activeInputIndex].lockingBytecode + // ) + + 'OP_1 OP_OUTPUTBYTECODE OP_INPUTINDEX OP_UTXOBYTECODE OP_EQUALVERIFY ' + // require(tx.outputs[1].value == changeValue) } + + 'OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY ' + // Cleanup + + 'OP_ENDIF OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE ' + // function reclaim + + 'OP_4 OP_ROLL OP_1 OP_NUMEQUALVERIFY ' + // require(hash160(pk) == funder) + + 'OP_4 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY ' + // require(checkSig(s, pk)) + + 'OP_4 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG ' + // Cleanup + + 'OP_NIP OP_NIP OP_NIP OP_ENDIF', + debug: { + bytecode: '5479009c63537ab275c3519d00cd0376a9147b7e0288ac7e8802e803c0c676547994527994765579547993a16300cc707c949d6700cc55799d51cdc0c78851cc789d686d6d6d5167547a519d5479a97b88547a547aac77777768', + logs: [], + requires: [ + { ip: 11, line: 3 }, + { ip: 15, line: 7 }, + { ip: 23, line: 10 }, + { ip: 47, line: 19 }, + { ip: 53, line: 21 }, + { ip: 58, line: 22 }, + { ip: 62, line: 23 }, + { ip: 77, line: 28 }, + { ip: 83, line: 29 }, + ], + sourceMap: '2:4:25:5;;;;;3:28:3:34;;:8::36:1;;7:16:7:32:0;:36::37;:8::39:1;10:27:10:28:0;:16::45:1;:49::84:0;:74::83;:49::84:1;;;:8::86;12:23:12:27:0;13:37:13:58;:27::65:1;14:26:14:38:0;:41::47;;:26:::1;:50::58:0;;:26:::1;18:12:18:23:0;:27::33;;:36::44;;:27:::1;:12;:46:20:9:0;19:31:19:32;:20::39:1;:43::66:0;;::::1;:12::68;20:15:24:9:0;21:31:21:32;:20::39:1;:43::49:0;;:12::51:1;22:31:22:32:0;:20::49:1;:63::84:0;:53::101:1;:12::103;23:31:23:32:0;:20::39:1;:43::54:0;:12::56:1;20:15:24:9;2:23:25:5;;;;:4;27::30::0;;;;28:24:28:26;;:16::27:1;:31::37:0;:8::39:1;29:25:29:26:0;;:28::30;;:8::33:1;27:39:30:5;;;1:0:31:1', + sourceTags: '79:81:sc', + }, + fingerprint: '82af4e70abe6257185f9fa2b9b65377949794a7f3f862a65eb3c61ec6bbff28a', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/multifunction.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/multifunction.ts new file mode 100644 index 000000000..78524d83b --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/multifunction.ts @@ -0,0 +1,39 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'MultiFunction', + constructorInputs: [{ name: 'sender', type: 'pubkey' }, { name: 'recipient', type: 'pubkey' }, { name: 'timeout', type: 'int' }], + abi: [ + { name: 'transfer', inputs: [{ name: 'recipientSig', type: 'sig' }] }, + { name: 'timeout', inputs: [{ name: 'senderSig', type: 'sig' }] }, + ], + bytecode: + // function transfer + 'OP_3 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' + // require(checkSig(recipientSig, recipient)) + + 'OP_4 OP_ROLL OP_ROT OP_CHECKSIG ' + + 'OP_NIP OP_NIP OP_NIP OP_ELSE ' + // function timeout + + 'OP_3 OP_ROLL OP_1 OP_NUMEQUALVERIFY ' + // require(checkSig(senderSig, sender)) + + 'OP_3 OP_ROLL OP_SWAP OP_CHECKSIGVERIFY ' + // require(tx.time >= timeout) + + 'OP_SWAP OP_CHECKLOCKTIMEVERIFY OP_2DROP OP_1 ' + + 'OP_ENDIF', + debug: { + bytecode: '5379009c63547a7bac77777767537a519d537a7cad7cb16d5168', + logs: [], + requires: [ + { ip: 12, line: 7 }, + { ip: 23, line: 11 }, + { ip: 25, line: 12 }, + ], + sourceMap: '6:4:8:5;;;;;7:25:7:37;;:39::48;:8::51:1;6:40:8:5;;;:4;10::13::0;;;;11:25:11:34;;:36::42;:8::45:1;12:27:12:34:0;:8::36:1;10:36:13:5;;1:0:14:1', + sourceTags: '9:11:sc', + }, + fingerprint: '4367893ec13aecfe4624b6d5b12681b9782de30dd657d1313eed269faba937e4', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/multifunction_if_statements.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/multifunction_if_statements.ts new file mode 100644 index 000000000..b7aa92c1a --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/multifunction_if_statements.ts @@ -0,0 +1,71 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'MultiFunctionIfStatements', + constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], + abi: [ + { name: 'transfer', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }] }, + { name: 'timeout', inputs: [{ name: 'b', type: 'int' }] }, + ], + bytecode: + // function transfer + 'OP_2 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' + // int d = a + b + + 'OP_3 OP_PICK OP_5 OP_PICK OP_ADD ' + // d = d - a + + 'OP_DUP OP_5 OP_PICK OP_SUB ' + // if (d == x && bool(x)) { + + 'OP_DUP OP_3 OP_PICK OP_NUMEQUAL OP_3 OP_ROLL OP_0NOTEQUAL OP_BOOLAND OP_IF ' + // int c = d + b + + 'OP_DUP OP_6 OP_PICK OP_ADD ' + // d = a + c + + 'OP_5 OP_PICK OP_OVER OP_ADD OP_ROT OP_DROP OP_SWAP ' + // require(c > d) + + 'OP_2DUP OP_LESSTHAN OP_VERIFY ' + // } else { + + 'OP_DROP OP_ELSE ' + // d = a } + + 'OP_4 OP_PICK OP_NIP OP_ENDIF ' + // d = d + a + + 'OP_DUP OP_5 OP_ROLL OP_ADD ' + // require(d == y) + + 'OP_3 OP_ROLL OP_NUMEQUALVERIFY ' + + 'OP_2DROP OP_2DROP OP_1 OP_ELSE ' + // function timeout + + 'OP_ROT OP_1 OP_NUMEQUALVERIFY ' + // int d = b + + 'OP_2 OP_PICK ' + // d = d + 2 + + 'OP_DUP OP_2 OP_ADD ' + // if (d == x) { + + 'OP_DUP OP_3 OP_ROLL OP_NUMEQUAL OP_IF ' + // int c = d + b + + 'OP_DUP OP_4 OP_PICK OP_ADD ' + // d = c + d + + 'OP_2DUP OP_ADD OP_ROT OP_DROP OP_SWAP ' + // require(c > d) } + + 'OP_2DUP OP_LESSTHAN OP_VERIFY ' + + 'OP_DROP OP_ENDIF ' + // d = b + + '' + // require(d == y) + + 'OP_2SWAP OP_NUMEQUAL ' + + 'OP_NIP OP_NIP OP_ENDIF', + debug: { + bytecode: '5279009c635379557993765579947653799c537a929a6376567993557978937b757c6e9f6975675479776876557a93537a9d6d6d51677b519d527976529376537a9c63765479936e937b757c6e9f697568729c777768', + logs: [], + requires: [ + { ip: 38, line: 8 }, + { ip: 51, line: 13 }, + { ip: 80, line: 22 }, + { ip: 85, line: 25 }, + ], + sourceMap: '2:4:14:5;;;;;3:16:3:17;;:20::21;;:16:::1;4:12:4:13:0;:16::17;;:12:::1;5::5:13:0;:17::18;;:12:::1;:27::28:0;;:22::29:1;:12;:31:9:9:0;6:20:6:21;:24::25;;:20:::1;7:16:7:17:0;;:20::21;:16:::1;:12::22;;;8:20:8:25:0;::::1;:12::27;5:31:9:9;9:15:11::0;10:16:10:17;;:12::18:1;9:15:11:9;12:12:12:13:0;:16::17;;:12:::1;13:21:13:22:0;;:8::24:1;2:36:14:5;;;:4;16::26::0;;;17:16:17:17;;18:12:18:13;:16::17;:12:::1;19::19:13:0;:17::18;;:12:::1;:20:23:9:0;20::20:21;:24::25;;:20:::1;21:16:21:21:0;::::1;:12::22;;;22:20:22:25:0;::::1;:12::27;19:20:23:9;;24:12:25:22:0;25:8::24:1;16:28:26:5;;1:0:27:1', + sourceTags: '37:37:sc;79:79:sc;83:84:sc', + }, + fingerprint: 'f57b39c9be272a31d1aedd678087b7dd327095fde647570149d237fb34401469', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/multiline_array_multisig.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/multiline_array_multisig.ts new file mode 100644 index 000000000..f0c0962bb --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/multiline_array_multisig.ts @@ -0,0 +1,31 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'cms', inputs: [{ name: 's', type: 'sig' }, { name: 'pk', type: 'pubkey' }] }], + bytecode: + // require(checkMultiSig( + 'OP_0 ' + // s, sig(0x00) + + 'OP_SWAP 00 ' + // ], [ + + 'OP_2 ' + // pk, pubkey(0x00) + + 'OP_4 OP_ROLL 00 ' + // ] + + 'OP_2 ' + // )); + + 'OP_CHECKMULTISIG', + fingerprint: '4a9d07771fb134fdd0b1b9ca1aa0e33a2621d9492e9d2bf9b8258fbd3f531296', + debug: { + bytecode: '007c010052547a010052ae', + sourceMap: '3:16:9:9;5::5:17;:23::27;4:12:6:13:1;7:16:7:18:0;;:27::31;6:15:8:13:1;3:8:9:11', + logs: [], + requires: [{ ip: 9, line: 3 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/multiline_statements.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/multiline_statements.ts new file mode 100644 index 000000000..104434604 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/multiline_statements.ts @@ -0,0 +1,23 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'MultilineStatements', + constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'string' }], + abi: [{ name: 'spend', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'string' }] }], + bytecode: 'OP_ROT OP_SWAP OP_2 OP_SUB OP_NUMEQUAL OP_2 OP_PICK OP_2 OP_PICK OP_EQUAL OP_BOOLAND OP_IF OP_0 OP_VERIFY OP_ELSE OP_OVER 48656c6c6f20 OP_2 OP_PICK OP_CAT OP_EQUAL OP_IF OP_DUP 576f726c64 OP_EQUALVERIFY OP_ELSE OP_1 OP_0 OP_NOT OP_NOT OP_NOT OP_NUMEQUALVERIFY OP_ENDIF OP_ENDIF OP_2DROP OP_1', + debug: { + bytecode: '7b7c52949c52795279879a63006967780648656c6c6f2052797e87637605576f726c64886751009191919d68686d51', + logs: [], + requires: [ + { ip: 15, line: 11 }, + { ip: 26, line: 14 }, + { ip: 33, line: 18 }, + ], + sourceMap: '9:12:9:13;:17::18;:21::22;:17:::1;:12;10::10:13:0;;:17::18;;:12:::1;9;10:20:12:9:0;11::11:25;:12::27:1;12:15:19:9:0;:19:12:20;:24::32;13:10:13:11;;12:24:::1;:19;13:13:17:9:0;15:16:15:17;:21::28;14:12:16:14:1;17:15:19:9:0;18:20:18:24;:31::36;:30:::1;:29;:28;:12::38;17:15:19:9;12;8:6:20:5;', + }, + fingerprint: 'd2aa37425c07883d3c7df823103f88a6a061d3efca1e6317b9e72e0ad4bd3611', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/multiplication.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/multiplication.ts new file mode 100644 index 000000000..e3b4618ef --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/multiplication.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'int' }], + abi: [{ name: 'hello', inputs: [] }], + bytecode: + // int myVariable = 10 - 4; + 'OP_10 OP_4 OP_SUB ' + // int myOtherVariable = 20 * myVariable % 2; + + '14 OP_MUL OP_2 OP_MOD ' + // require(myOtherVariable > x); + + 'OP_LESSTHAN', + fingerprint: '74e026fb37d71dac744827708122e9b318eda1b8beca52c272c4a6f888cc1617', + debug: { + bytecode: '5a549401149552979f', + sourceMap: '3:25:3:27;:30::31;:25:::1;4:30:4:32:0;:::45:1;:48::49:0;:30:::1;5:8:5:37', + logs: [], + requires: [{ ip: 9, line: 5 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/num2bin.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/num2bin.ts new file mode 100644 index 000000000..44755a7de --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/num2bin.ts @@ -0,0 +1,23 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [] }], + bytecode: + // bytes2 byte_ = toPaddedBytes(10, 2); + 'OP_10 OP_2 OP_NUM2BIN ' + // require(int(byte_) == 10); + + 'OP_BIN2NUM OP_10 OP_NUMEQUAL', + fingerprint: 'df5031d5e4eae8bc40921091e25734aeee6cb7e35b9f40103770e7394e721f63', + debug: { + bytecode: '5a5280815a9c', + sourceMap: '3:37:3:39;:41::42;:23::43:1;4:16:4:26;:30::32:0;:8::34:1', + logs: [], + requires: [{ ip: 6, line: 4 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/num2bin_variable.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/num2bin_variable.ts new file mode 100644 index 000000000..3ff3781fe --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/num2bin_variable.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Num2Bin', + constructorInputs: [], + abi: [ + { name: 'spend', inputs: [{ name: 'size', type: 'int' }] }, + ], + bytecode: 'OP_10 OP_SWAP OP_NUM2BIN OP_BIN2NUM OP_10 OP_NUMEQUAL', + debug: { + bytecode: '5a7c80815a9c', + logs: [], + requires: [{ ip: 6, line: 4 }], + sourceMap: '3:36:3:38;:40::44;:22::45:1;4:16:4:26;:30::32:0;:8::34:1', + }, + fingerprint: '7ebb008689b080dce1061a508173a617c58b68202899cfd17a32f1a5decd4bb6', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/p2palindrome.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/p2palindrome.ts new file mode 100644 index 000000000..d1fb7c1ac --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/p2palindrome.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'P2Palindrome', + constructorInputs: [], + abi: [ + { name: 'spend', inputs: [{ name: 'palindrome', type: 'string' }] }, + ], + bytecode: 'OP_DUP OP_REVERSEBYTES OP_EQUAL', + debug: { + bytecode: '76bc87', + logs: [], + requires: [{ ip: 3, line: 3 }], + sourceMap: '3:16:3:26;:::36:1;:8::52', + }, + fingerprint: '4e9480ee14cf131a78be8da27e585e3d62c0e9cfa75d8338f2d51a67d84df0c7', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh-logs.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh-logs.ts new file mode 100644 index 000000000..37aac3b25 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh-logs.ts @@ -0,0 +1,33 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'P2PKH', + constructorInputs: [{ name: 'pkh', type: 'bytes20' }], + abi: [{ name: 'spend', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }], + bytecode: + // require(hash160(pk) == pkh); + 'OP_OVER OP_HASH160 OP_EQUALVERIFY ' + // require(checkSig(s, pk)); + + 'OP_CHECKSIG', + fingerprint: '07f5c2c2cf10439f063f3b92b9420b110614fb57b5c5015120bfca2688fedcc7', + debug: { + bytecode: '78a988ac', + sourceMap: '3:24:3:26;:16::27:1;:8::36;5::5:33', + logs: [ + { + ip: 4, + line: 4, + data: [ + { stackIndex: 0, type: 'pubkey', ip: 4 }, + { type: 'bytes20', stackIndex: 1, ip: 3 }, + { stackIndex: 1, type: 'sig', ip: 4 }, + ], + }, + ], + requires: [{ ip: 3, line: 3 }, { ip: 5, line: 5 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh.ts new file mode 100644 index 000000000..247c93148 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh.ts @@ -0,0 +1,26 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'P2PKH', + constructorInputs: [{ name: 'pkh', type: 'bytes20' }], + abi: [{ name: 'spend', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }], + bytecode: + // require(hash160(pk) == pkh) + 'OP_OVER OP_HASH160 OP_EQUALVERIFY ' + // require(checkSig(s, pk)) + + 'OP_CHECKSIG', + debug: { + bytecode: '78a988ac', + logs: [], + requires: [ + { ip: 3, line: 3 }, + { ip: 5, line: 4 }, + ], + sourceMap: '3:24:3:26;:16::27:1;:8::36;4::4:33', + }, + fingerprint: '07f5c2c2cf10439f063f3b92b9420b110614fb57b5c5015120bfca2688fedcc7', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh_with_assignment.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh_with_assignment.ts new file mode 100644 index 000000000..fc2ca5fea --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh_with_assignment.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'P2PKH', + constructorInputs: [{ name: 'pkh', type: 'bytes20' }], + abi: [{ name: 'spend', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }], + bytecode: + // bytes20 passedPkh = hash160(pk); + 'OP_OVER OP_HASH160 ' + // require(passedPkh == pkh); + + 'OP_EQUALVERIFY ' + // require(checkSig(s, pk)); + + 'OP_CHECKSIG', + fingerprint: '07f5c2c2cf10439f063f3b92b9420b110614fb57b5c5015120bfca2688fedcc7', + debug: { + bytecode: '78a988ac', + sourceMap: '5:36:5:38;:28::39:1;6:8:6:34;7::7:33', + logs: [], + requires: [{ ip: 3, line: 6 }, { ip: 5, line: 7 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh_with_cast.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh_with_cast.ts new file mode 100644 index 000000000..0ede1036a --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/p2pkh_with_cast.ts @@ -0,0 +1,26 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'P2PKH', + constructorInputs: [{ name: 'pkh', type: 'bytes20' }], + abi: [{ name: 'spend', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'bytes65' }] }], + bytecode: + // Implicit parameter type enforcement + 'OP_ROT OP_SIZE 41 OP_EQUALVERIFY ' + // require(hash160(pk) == pkh); + + 'OP_2 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY ' + // require(checkSig(sig(s), pk)); + + 'OP_SWAP OP_CHECKSIG', + fingerprint: '3493678eec6aa5f1faf62552956f93d338eabc655157679978c406971658eaba', + debug: { + bytecode: '7b820141885279a97b887cac', + sourceMap: '4:30:4:39;;;;5:24:5:26;;:16::27:1;:31::34:0;:8::36:1;6:33:6:35:0;:8::38:1', + logs: [], + requires: [{ ip: 9, line: 5 }, { ip: 12, line: 6 }], + sourceTags: '0:3:pv', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/reassignment.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/reassignment.ts new file mode 100644 index 000000000..7ba3242c1 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/reassignment.ts @@ -0,0 +1,39 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Reassignment', + constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'string' }], + abi: [{ name: 'hello', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }], + bytecode: + // int myVariable = 10 - 4 + 'OP_10 OP_4 OP_SUB ' + // int myOtherVariable = 20 + myVariable % 2 + + '14 OP_SWAP OP_2 OP_MOD OP_ADD ' + // require(myOtherVariable > x) + + 'OP_LESSTHAN OP_VERIFY ' + // string hw = "Hello World" + + '48656c6c6f20576f726c64 ' + // hw = hw + y + + 'OP_DUP OP_ROT OP_CAT ' + // require(ripemd160(pk) == ripemd160(hw)) + + 'OP_2 OP_PICK OP_RIPEMD160 OP_SWAP OP_RIPEMD160 OP_EQUALVERIFY ' + // require(checkSig(s, pk)) + + 'OP_ROT OP_ROT OP_CHECKSIG ' + + 'OP_NIP', + debug: { + bytecode: '5a549401147c5297939f690b48656c6c6f20576f726c64767b7e5279a67ca6887b7bac77', + logs: [], + requires: [ + { ip: 11, line: 5 }, + { ip: 21, line: 10 }, + { ip: 25, line: 11 }, + ], + sourceMap: '3:25:3:27;:30::31;:25:::1;4:30:4:32:0;:35::45;:48::49;:35:::1;:30;5:16:5:35;:8::37;7:20:7:33:0;8:13:8:15;:18::19;:13:::1;10:26:10:28:0;;:16::29:1;:43::45:0;:33::46:1;:8::48;11:25:11:26:0;:28::30;:8::33:1;2:37:12:5', + sourceTags: '23:23:sc', + }, + fingerprint: '7dfcd01f0ecb5e1dec3d2fb363b5af79eb84a15395e1b57fe9c383cb3861d634', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_cast.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_cast.ts new file mode 100644 index 000000000..8d3a5d1f9 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_cast.ts @@ -0,0 +1,36 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'string' }], + abi: [{ name: 'hello', inputs: [{ name: 's', type: 'sig' }, { name: 'pk', type: 'pubkey' }] }], + bytecode: + // int myVariable = 10 - int(true); + 'OP_10 OP_1SUB ' + // int myOtherVariable = 20 + myVariable % 2; + + '14 OP_SWAP OP_2 OP_MOD OP_ADD ' + // require(myOtherVariable > x); + + 'OP_LESSTHAN OP_VERIFY ' + // string hw = "Hello World"; + + '48656c6c6f20576f726c64 ' + // hw = hw + y; + + 'OP_DUP OP_ROT OP_CAT ' + // require(ripemd160(pk) == ripemd160(bytes(hw) + bytes(pk))); + + 'OP_3 OP_PICK OP_RIPEMD160 OP_SWAP OP_4 OP_PICK OP_CAT OP_RIPEMD160 OP_EQUALVERIFY ' + // require(checkSig(s, pk)); + + 'OP_SWAP OP_ROT OP_CHECKSIG ' + // Cleanup + + 'OP_NIP', + fingerprint: '31251ad758a9a5e8869e01e1e32d8df2ff1e9ed9b26d3dc3cc07280d437bdac2', + debug: { + bytecode: '5a8c01147c5297939f690b48656c6c6f20576f726c64767b7e5379a67c54797ea6887c7bac77', + sourceMap: '3:25:3:27;:::39:1;4:30:4:32:0;:35::45;:48::49;:35:::1;:30;5:16:5:35;:8::37;7:20:7:33:0;8:13:8:15;:18::19;:13:::1;10:26:10:28:0;;:16::29:1;:49::51:0;:61::63;;:43::64:1;:33::65;:8::67;11:25:11:26:0;:28::30;:8::33:1;2:37:12:5', + logs: [], + requires: [{ ip: 10, line: 5 }, { ip: 23, line: 10 }, { ip: 27, line: 11 }], + sourceTags: '25:25:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_checkdatasig.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_checkdatasig.ts new file mode 100644 index 000000000..0fa49d8b0 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_checkdatasig.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 's', type: 'datasig' }, { name: 'pk', type: 'pubkey' }], + abi: [{ name: 'cds', inputs: [{ name: 'data', type: 'bytes' }] }], + bytecode: + // require(checkDataSig(s, data, pk)); + 'OP_ROT OP_ROT OP_CHECKDATASIG', + fingerprint: 'ae21c0109dbe19b96e779f3e6d9b4dad3016ee311dfee3fce8af717c8d81bfff', + debug: { + bytecode: '7b7bba', + sourceMap: '3:32:3:36;:38::40;:8::43:1', + logs: [], + requires: [{ ip: 5, line: 3 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_constant.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_constant.ts new file mode 100644 index 000000000..27c74a10b --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_constant.ts @@ -0,0 +1,23 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [] }], + bytecode: + // string constant m = "hello"; + '68656c6c6f ' + // require(m == "hello"); + + '68656c6c6f OP_EQUAL', + fingerprint: '96cc3caea92277647f1a513b9ca649fe93845566c0a29e69583a1e4bf67dbd71', + debug: { + bytecode: '0568656c6c6f0568656c6c6f87', + sourceMap: '3:28:3:35;4:21:4:28;:8::30:1', + logs: [], + requires: [{ ip: 3, line: 4 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_covenant.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_covenant.ts new file mode 100644 index 000000000..b0c70b7d9 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_covenant.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'covenant', inputs: [] }], + bytecode: + // require(tx.version == 2); + 'OP_TXVERSION OP_2 OP_NUMEQUAL', + fingerprint: '23acf2123933daf216d03e942aa31471f3a3e07987eeb591b5a3892c5a443579', + debug: { + bytecode: 'c2529c', + sourceMap: '3:16:3:26;:30::31;:8::33:1', + logs: [], + requires: [{ ip: 3, line: 3 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_functions.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_functions.ts new file mode 100644 index 000000000..183b1b2b9 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_functions.ts @@ -0,0 +1,37 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [ + { name: 'hello', inputs: [{ name: 's', type: 'sig' }, { name: 'pk', type: 'pubkey' }] }, + { name: 'world', inputs: [{ name: 'a', type: 'int' }] }, + ], + bytecode: + // function hello(sig s, pubkey pk) { + 'OP_DUP OP_0 OP_NUMEQUAL OP_IF ' + // require(checkSig(s, pk)); + + 'OP_SWAP OP_ROT OP_CHECKSIG ' + // Cleanup + + 'OP_NIP ' + // } + + 'OP_ELSE ' + // function world(int a) { + + 'OP_1 OP_NUMEQUALVERIFY ' + // require(a + 5 == 10); + + 'OP_5 OP_ADD OP_10 OP_NUMEQUAL ' + // } + + 'OP_ENDIF', + fingerprint: '88a901256f34c8c655657f1efad4389dc3465a1980090f817f5d1a7df7ffd701', + debug: { + bytecode: '76009c637c7bac7767519d55935a9c68', + sourceMap: '2:4:4:5;;;;3:25:3:26;:28::30;:8::33:1;2:37:4:5;:4;6::8::0;;7:20:7:21;:16:::1;:25::27:0;:8::29:1;1:0:9:1', + logs: [], + requires: [{ ip: 7, line: 3 }, { ip: 15, line: 7 }], + sourceTags: '7:7:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_if_statement.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_if_statement.ts new file mode 100644 index 000000000..8e54dc864 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_if_statement.ts @@ -0,0 +1,33 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'string' }], + abi: [{ name: 'hello', inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'string' }] }], + bytecode: + // if (a == x - 2) { + 'OP_ROT OP_SWAP OP_2 OP_SUB OP_NUMEQUAL OP_IF ' + // require(false); + + 'OP_0 OP_VERIFY ' + // } else if (b == "Hello " + y) + + 'OP_ELSE OP_OVER 48656c6c6f20 OP_2 OP_PICK OP_CAT OP_EQUAL ' + // require(y == "World"); + + 'OP_IF OP_DUP 576f726c64 OP_EQUALVERIFY ' + // else { + + 'OP_ELSE ' + // require(true == !!!false); + + 'OP_1 OP_0 OP_NOT OP_NOT OP_NOT OP_NUMEQUALVERIFY ' + // } + + 'OP_ENDIF OP_ENDIF OP_2DROP OP_1', + fingerprint: 'b3c859908dd64be7dcc8a9382cf371527c12d56973f4a291d97692d8c2215cb0', + debug: { + bytecode: '7b7c52949c63006967780648656c6c6f2052797e87637605576f726c64886751009191919d68686d51', + sourceMap: '3:12:3:13;:17::18;:21::22;:17:::1;:12;:24:5:9:0;4:20:4:25;:12::27:1;5:15:9:9:0;:19:5:20;:24::32;:35::36;;:24:::1;:19;6:12:6:34:0;:20::21;:25::32;:12::34:1;7:13:9:9:0;8:20:8:24;:31::36;:30:::1;:29;:28;:12::38;7:13:9:9;5:15;2:36:10:5;', + logs: [], + requires: [{ ip: 9, line: 4 }, { ip: 20, line: 6 }, { ip: 27, line: 8 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_multisig.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_multisig.ts new file mode 100644 index 000000000..a061a15ac --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_multisig.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'cms', inputs: [{ name: 's', type: 'sig' }, { name: 'pk', type: 'pubkey' }] }], + bytecode: + // require(checkMultiSig([s, sig(0x00)], [pk, pubkey(0x00)])); + 'OP_0 OP_SWAP 00 OP_2 OP_4 OP_ROLL 00 OP_2 OP_CHECKMULTISIG', + fingerprint: '4a9d07771fb134fdd0b1b9ca1aa0e33a2621d9492e9d2bf9b8258fbd3f531296', + debug: { + bytecode: '007c010052547a010052ae', + sourceMap: '3:16:3:65;:31::32;:38::42;:30::44:1;:47::49:0;;:58::62;:46::64:1;:8::67', + logs: [], + requires: [{ ip: 9, line: 3 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_splice.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_splice.ts new file mode 100644 index 000000000..580b086b1 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_splice.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'b', type: 'bytes' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // bytes x = b.split(5)[1]; + 'OP_DUP OP_5 OP_SPLIT OP_NIP ' + // require(x != b); + + 'OP_2DUP OP_EQUAL OP_NOT OP_VERIFY ' + // require (b.split(4)[0] != x); + + 'OP_SWAP OP_4 OP_SPLIT OP_DROP OP_EQUAL OP_NOT', + fingerprint: '02695f7d89ef8e5ca54c56e0b66c9313a0108f34fa5b0c4cebcfa2969f662cc4', + debug: { + bytecode: '76557f776e8791697c547f758791', + sourceMap: '3:18:3:19;:26::27;:18::28:1;:::31;4:16:4:22:0;::::1;;:8::24;5:17:5:18:0;:25::26;:17::27:1;:::30;:::35;:8::37', + logs: [], + requires: [{ ip: 8, line: 4 }, { ip: 15, line: 5 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simple_variables.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_variables.ts new file mode 100644 index 000000000..acff9379e --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simple_variables.ts @@ -0,0 +1,36 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'string' }], + abi: [{ name: 'hello', inputs: [{ name: 's', type: 'sig' }, { name: 'pk', type: 'pubkey' }] }], + bytecode: + // int myVariable = 10 - 4; + 'OP_10 OP_4 OP_SUB ' + // int myOtherVariable = 20 + myVariable % 2; + + '14 OP_SWAP OP_2 OP_MOD OP_ADD ' + // require(myOtherVariable > x); + + 'OP_LESSTHAN OP_VERIFY ' + // string hw = "Hello World"; + + '48656c6c6f20576f726c64 ' + // hw = hw + y; + + 'OP_DUP OP_ROT OP_CAT ' + // require(ripemd160(pk) == ripemd160(hw)); + + 'OP_3 OP_PICK OP_RIPEMD160 OP_SWAP OP_RIPEMD160 OP_EQUALVERIFY ' + // require(checkSig(s, pk)); + + 'OP_SWAP OP_ROT OP_CHECKSIG ' + // Cleanup + + 'OP_NIP', + fingerprint: '020af19263094d41bde5bc002db29a858c512709a15b7df1319bb75cbeacb289', + debug: { + bytecode: '5a549401147c5297939f690b48656c6c6f20576f726c64767b7e5379a67ca6887c7bac77', + sourceMap: '3:25:3:27;:30::31;:25:::1;4:30:4:32:0;:35::45;:48::49;:35:::1;:30;5:16:5:35;:8::37;7:20:7:33:0;8:13:8:15;:18::19;:13:::1;10:26:10:28:0;;:16::29:1;:43::45:0;:33::46:1;:8::48;11:25:11:26:0;:28::30;:8::33:1;2:37:12:5', + logs: [], + requires: [{ ip: 11, line: 5 }, { ip: 21, line: 10 }, { ip: 25, line: 11 }], + sourceTags: '23:23:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/simulating_state.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/simulating_state.ts new file mode 100644 index 000000000..bfb52fd4d --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/simulating_state.ts @@ -0,0 +1,87 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'SimulatingState', + constructorInputs: [ + { name: 'recipient', type: 'bytes20' }, + { name: 'funder', type: 'bytes20' }, + { name: 'pledgePerBlock', type: 'int' }, + { name: 'initialBlock', type: 'bytes8' }, + ], + abi: [ + { name: 'receive', inputs: [] }, + { name: 'reclaim', inputs: [{ name: 'pk', type: 'pubkey' }, { name: 's', type: 'sig' }] }, + ], + bytecode: + // function receive() { + 'OP_4 OP_PICK OP_0 OP_NUMEQUAL OP_IF ' + // bytes25 recipientLockingBytecode = new LockingBytecodeP2PKH(recipient); + + '76a914 OP_SWAP OP_CAT 88ac OP_CAT ' + // require(tx.outputs[0].lockingBytecode == recipientLockingBytecode); + + 'OP_0 OP_OUTPUTBYTECODE OP_EQUALVERIFY ' + // int initial = int(initialBlock); + + 'OP_ROT OP_BIN2NUM ' + // require(tx.time >= initial); + + 'OP_DUP OP_CHECKLOCKTIMEVERIFY OP_DROP ' + // int passedBlocks = tx.locktime - initial; + + 'OP_TXLOCKTIME OP_SWAP OP_SUB ' + // int pledge = passedBlocks * pledgePerBlock; + + 'OP_ROT OP_MUL ' + // int minerFee = 1000; + + 'e803 ' + // int currentValue = tx.inputs[this.activeInputIndex].value; + + 'OP_INPUTINDEX OP_UTXOVALUE ' + // int changeValue = currentValue - pledge - minerFee; + + 'OP_DUP OP_3 OP_PICK OP_SUB OP_2 OP_PICK OP_SUB ' + // if (changeValue <= pledge + minerFee) { + + 'OP_DUP OP_4 OP_PICK OP_4 OP_PICK OP_ADD OP_LESSTHANOREQUAL OP_IF ' + // require(tx.outputs[0].value == currentValue - minerFee); + + 'OP_0 OP_OUTPUTVALUE OP_2OVER OP_SWAP OP_SUB OP_NUMEQUALVERIFY ' + // } else { + + 'OP_ELSE ' + // require(tx.outputs[0].value == pledge); + + 'OP_0 OP_OUTPUTVALUE OP_4 OP_PICK OP_NUMEQUALVERIFY ' + // require(tx.outputs[1].value == changeValue); + + 'OP_1 OP_OUTPUTVALUE OP_OVER OP_NUMEQUALVERIFY ' + // bytes newContract = 0x08 + toPaddedBytes(tx.locktime, 8) + this.activeBytecode.split(9)... + + 'OP_8 OP_TXLOCKTIME OP_8 OP_NUM2BIN OP_CAT OP_ACTIVEBYTECODE OP_9 OP_SPLIT OP_NIP OP_CAT ' + // bytes23 newContractLock = new LockingBytecodeP2SH20(hash160(newContract)); + + 'a914 OP_OVER OP_HASH160 OP_CAT 87 OP_CAT ' + // require(tx.outputs[1].lockingBytecode == newContractLock); + + 'OP_1 OP_OUTPUTBYTECODE OP_OVER OP_EQUALVERIFY ' + // Cleanup + + 'OP_2DROP ' + // } + + 'OP_ENDIF OP_2DROP OP_2DROP OP_2DROP OP_1 OP_ELSE ' + // function reclaim(pubkey pk, sig s) { + + 'OP_4 OP_ROLL OP_1 OP_NUMEQUALVERIFY ' + // require(hash160(pk) == funder); + + 'OP_4 OP_PICK OP_HASH160 OP_ROT OP_EQUALVERIFY ' + // require(checkSig(s, pk)); + + 'OP_4 OP_ROLL OP_4 OP_ROLL OP_CHECKSIG ' + // Cleanup + + 'OP_NIP OP_NIP OP_NIP ' + // } + + 'OP_ENDIF', + fingerprint: 'b9b8bcda69ec19cdbdf4a9f9fadcc2834ed3302298c5b3c2086b55fc95db983d', + debug: { + bytecode: '5479009c630376a9147c7e0288ac7e00cd887b8176b175c57c947b9502e803c0c676537994527994765479547993a16300cc707c949d6700cc54799d51cc789d58c558807ec1597f777e02a91478a97e01877e51cd78886d686d6d6d5167547a519d5479a97b88547a547aac77777768', + sourceMap: '7:4:46:5;;;;;9:43:9:78;:68::77;:43::78:1;;;10:27:10:28:0;:16::45:1;:8::75;13:26:13:38:0;:22::39:1;14:27:14:34:0;:8::36:1;;17:27:17:38:0;:41::48;:27:::1;18:36:18:50:0;:21:::1;21:23:21:27:0;22:37:22:58;:27::65:1;23:26:23:38:0;:41::47;;:26:::1;:50::58:0;;:26:::1;28:12:28:23:0;:27::33;;:36::44;;:27:::1;:12;:46:30:9:0;29:31:29:32;:20::39:1;:43::66:0;;::::1;:12::68;30:15:45:9:0;32:31:32:32;:20::39:1;:43::49:0;;:12::51:1;33:31:33:32:0;:20::39:1;:43::54:0;:12::56:1;39:32:39:36:0;:53::64;:66::67;:39::68:1;:32;:71::90:0;:97::98;:71::99:1;:::102;:32;43:38:43:85:0;:72::83;:64::84:1;:38::85;;;44:31:44:32:0;:20::49:1;:53::68:0;:12::70:1;30:15:45:9;;7:23:46:5;;;;:4;48::51::0;;;;49:24:49:26;;:16::27:1;:31::37:0;:8::39:1;50:25:50:26:0;;:28::30;;:8::33:1;48:39:51:5;;;1:0:52:1', + logs: [], + requires: [ + { ip: 16, line: 10 }, + { ip: 20, line: 14 }, + { ip: 50, line: 29 }, + { ip: 56, line: 32 }, + { ip: 60, line: 33 }, + { ip: 80, line: 44 }, + { ip: 96, line: 49 }, + { ip: 102, line: 50 }, + ], + sourceTags: '77:77:sc;98:100:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/slice.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/slice.ts new file mode 100644 index 000000000..81cc393e1 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/slice.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Slice', + constructorInputs: [{ name: 'pkh', type: 'bytes20' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: 'OP_INPUTINDEX OP_UTXOBYTECODE 17 OP_SPLIT OP_DROP OP_3 OP_SPLIT OP_NIP OP_EQUAL', + debug: { + bytecode: 'c0c701177f75537f7787', + sourceMap: '3:36:3:57;:26::74:1;:84::86:0;:26::87:1;;:81::82:0;:26::87:1;;4:8:4:34', + logs: [], + requires: [ + { + ip: 10, + line: 4, + message: undefined, + }, + ], + }, + fingerprint: 'd8574d80ab674df33841526cf2767c09a9dc02d2faea91746465e22e3b81ae3a', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/slice_optimised.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/slice_optimised.ts new file mode 100644 index 000000000..f57698f4e --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/slice_optimised.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Slice', + constructorInputs: [{ name: 'data', type: 'bytes32' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: '14 OP_SPLIT OP_DROP OP_0 14 OP_NUM2BIN OP_EQUAL', + debug: { + bytecode: '01147f750001148087', + sourceMap: '3:36:3:38;:22::39:1;;4:37:4:38:0;:40::42;:23::43:1;:8::45', + logs: [], + requires: [ + { + ip: 8, + line: 4, + message: undefined, + }, + ], + }, + fingerprint: '779b8278e2831727686ad5c96b85bb01bab5f2692edd34d703b9d437da77ac03', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/slice_variable_parameter.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/slice_variable_parameter.ts new file mode 100644 index 000000000..6c961430c --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/slice_variable_parameter.ts @@ -0,0 +1,25 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Slice', + constructorInputs: [{ name: 'pkh', type: 'bytes20' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // int x = 3; + 'OP_3 ' + // bytes actualPkh = tx.inputs[this.activeInputIndex].lockingBytecode.slice(x, 23); + + 'OP_INPUTINDEX OP_UTXOBYTECODE 17 OP_SPLIT OP_DROP OP_SWAP OP_SPLIT OP_NIP ' + // require(pkh == actualPkh); + + 'OP_EQUAL', + fingerprint: '44e982ad69fd5e934e67da5c478f09dcfd07e925b6817e033c3ac2c1a379be56', + debug: { + bytecode: '53c0c701177f757c7f7787', + sourceMap: '3:16:3:17;4:36:4:57;:26::74:1;:84::86:0;:26::87:1;;:81::82:0;:26::87:1;;5:8:5:34', + logs: [], + requires: [{ ip: 11, line: 5 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/split_or_slice_signature.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/split_or_slice_signature.ts new file mode 100644 index 000000000..d90745ff6 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/split_or_slice_signature.ts @@ -0,0 +1,27 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'signature', type: 'sig' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // bytes hashtype1 = signature.split(64)[1]; + 'OP_DUP 40 OP_SPLIT OP_NIP ' + // bytes1 hashtype2 = signature.slice(64, 65); + + 'OP_SWAP 41 OP_SPLIT OP_DROP 40 OP_SPLIT OP_NIP ' + // require(hashtype1 == 0x01); + + 'OP_SWAP OP_1 OP_EQUALVERIFY ' + // require(hashtype2 == 0x01); + + 'OP_1 OP_EQUAL', + fingerprint: '8ff426163800a551833469b6746f32eee36dda458516a3684dce740263312a1b', + debug: { + bytecode: '7601407f777c01417f7501407f777c51885187', + sourceMap: '4:26:4:35;:42::44;:26::45:1;:::48;5:27:5:36:0;:47::49;:27::50:1;;:43::45:0;:27::50:1;;6:16:6:25:0;:29::33;:8::35:1;7:29:7:33:0;:8::35:1', + logs: [], + requires: [{ ip: 14, line: 6 }, { ip: 17, line: 7 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/split_size.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/split_size.ts new file mode 100644 index 000000000..ff0195029 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/split_size.ts @@ -0,0 +1,28 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'SplitSize', + constructorInputs: [{ name: 'b', type: 'bytes' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // bytes x = b.split(b.length / 2)[1] + 'OP_DUP OP_DUP OP_SIZE OP_NIP OP_2 OP_DIV OP_SPLIT OP_NIP ' + // require(x != b) + + 'OP_2DUP OP_EQUAL OP_NOT OP_VERIFY ' + // bytes x = b.split(b.length / 2)[1] + + 'OP_SWAP OP_4 OP_SPLIT OP_DROP OP_EQUAL OP_NOT', + debug: { + bytecode: '7676827752967f776e8791697c547f758791', + logs: [], + requires: [ + { ip: 12, line: 4 }, + { ip: 19, line: 5 }, + ], + sourceMap: '3:18:3:27;;:26::34:1;;:37::38:0;:26:::1;:18::39;:::42;4:16:4:22:0;::::1;;:8::24;5:16:5:17:0;:24::25;:16::26:1;:::29;:::34;:8::36', + }, + fingerprint: '49d50376d8aa76534f29c049b987238d577ce332202a2f0da0cb74d94a027b79', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/split_typed.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/split_typed.ts new file mode 100644 index 000000000..64941c7f7 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/split_typed.ts @@ -0,0 +1,23 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'SplitTyped', + constructorInputs: [{ name: 'b', type: 'bytes' }], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // bytes4 x = b.split(4)[0]; + 'OP_DUP OP_4 OP_SPLIT OP_DROP ' + // require(x != b); + + 'OP_EQUAL OP_NOT', + fingerprint: 'f7275cb70302001a89ebddc0a65f7ead064a0f0a8887a7b8317a912696d96654', + debug: { + bytecode: '76547f758791', + sourceMap: '3:19:3:20;:27::28;:19::29:1;:::32;4:16:4:22;:8::24', + logs: [], + requires: [{ ip: 7, line: 4 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/string_concatenation.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/string_concatenation.ts new file mode 100644 index 000000000..23b618ce2 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/string_concatenation.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'hello', inputs: [{ name: 'who', type: 'string' }] }], + bytecode: + // require(("hello " + who).length + 2 > 5); + '68656c6c6f20 OP_SWAP OP_CAT OP_SIZE OP_NIP OP_2 OP_ADD OP_5 OP_GREATERTHAN', + fingerprint: '142914f037f5f8f71cb7a5cad4be959f39db80fc6411fd1c0ddd02b14a620eb4', + debug: { + bytecode: '0668656c6c6f207c7e8277529355a0', + sourceMap: '3:17:3:25;:28::31;:17:::1;:16::39;;:42::43:0;:16:::1;:46::47:0;:8::49:1', + logs: [], + requires: [{ ip: 9, line: 3 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/string_with_escaped_characters.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/string_with_escaped_characters.ts new file mode 100644 index 000000000..6d2b921ea --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/string_with_escaped_characters.ts @@ -0,0 +1,31 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'int' }], + abi: [{ name: 'hello', inputs: [] }], + bytecode: + // int myVariable = 10 - 4; + 'OP_10 OP_4 OP_SUB ' + // int myOtherVariable = 20 + myVariable % 2; + + '14 OP_SWAP OP_2 OP_MOD OP_ADD ' + // require(myOtherVariable > x); + + 'OP_LESSTHAN OP_VERIFY ' + // string x1 = "Hello \n \\ ' '' \" World"; + + '48656c6c6f205c6e205c5c202720272720205c2220576f726c64 ' + // string x2 = 'Hello \n \\ " " \' World'; + + '48656c6c6f205c6e205c5c20222022205c2720576f726c64 ' + // require(ripemd160(x1) == hash160(x2)); + + 'OP_SWAP OP_RIPEMD160 OP_SWAP OP_HASH160 OP_EQUAL', + fingerprint: '71ca7d617d2d655b8d2f6dfdd9ef77cb2b1e5ca855b85b22bf791965b02f6517', + debug: { + bytecode: '5a549401147c5297939f691a48656c6c6f205c6e205c5c202720272720205c2220576f726c641848656c6c6f205c6e205c5c20222022205c2720576f726c647ca67ca987', + sourceMap: '3:25:3:27;:30::31;:25:::1;4:30:4:32:0;:35::45;:48::49;:35:::1;:30;5:16:5:35;:8::37;7:20:7:48:0;8::8:46;9:26:9:28;:16::29:1;:41::43:0;:33::44:1;:8::46', + logs: [], + requires: [{ ip: 10, line: 5 }, { ip: 18, line: 9 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/sum_input_amount.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/sum_input_amount.ts new file mode 100644 index 000000000..79a939efe --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/sum_input_amount.ts @@ -0,0 +1,36 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Loopy', + constructorInputs: [], + abi: [{ name: 'doLoop', inputs: [] }], + bytecode: + // int sum = 0; + 'OP_0 ' + // int i = 0; + + 'OP_0 ' + // do { + + 'OP_BEGIN ' + // sum = tx.inputs[i].value; + + 'OP_DUP OP_UTXOVALUE OP_ROT OP_DROP OP_SWAP ' + // i = i + 1; + + 'OP_DUP OP_1ADD OP_NIP ' + // } while (i < tx.inputs.length); + + 'OP_DUP OP_TXINPUTCOUNT OP_GREATERTHANOREQUAL OP_UNTIL ' + // require(sum > 2000); + + 'OP_SWAP d007 OP_GREATERTHAN ' + // Cleanup + + 'OP_NIP', + fingerprint: '8c4abe3e5702b4328f4d4c094e77bb69228aba3e7f7a2b51a84f9e5f119fd68d', + debug: { + bytecode: '00006576c67b757c768b7776c3a2667c02d007a077', + sourceMap: '3:18:3:19;4:16:4:17;6:8:9:39;7:28:7:29;:18::36:1;:12::37;;;8:16:8:17:0;:::21:1;:12::22;9:17:9:18:0;:21::37;6:8::39:1;;12:16:12:19:0;:22::26;:8::28:1;2:22:13:5', + logs: [{ ip: 15, line: 11, data: [{ stackIndex: 1, type: 'int', ip: 15 }] }], + requires: [{ ip: 18, line: 12 }], + sourceTags: '18:18:sc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/token_category_comparison.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/token_category_comparison.ts new file mode 100644 index 000000000..fdbf15106 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/token_category_comparison.ts @@ -0,0 +1,21 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'send', inputs: [] }], + bytecode: + // require(tx.inputs[1].tokenCategory == 0x); + 'OP_1 OP_UTXOTOKENCATEGORY OP_0 OP_EQUAL', + fingerprint: '40bc2bb628f3d2be50aa34a77c44dafd73f3a8a826bf32ef747bd77a583ea187', + debug: { + bytecode: '51ce0087', + sourceMap: '3:26:3:27;:16::42:1;:46::48:0;:8::50:1', + logs: [], + requires: [{ ip: 4, line: 3 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/trailing_comma.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/trailing_comma.ts new file mode 100644 index 000000000..51fabc3ff --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/trailing_comma.ts @@ -0,0 +1,50 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Contract', + constructorInputs: [{ name: 'ownerPk', type: 'pubkey' }, { name: 'oraclePk', type: 'pubkey' }], + abi: [ + { + name: 'spend', + inputs: [ + { name: 'ownerSig', type: 'sig' }, + { name: 'oracleMsgSig', type: 'datasig' }, + { name: 'oracleTxSig', type: 'sig' }, + ], + }, + ], + bytecode: + // bytes oracleMessage = bytes('Spend') + bytes(12,); + '5370656e64 OP_12 OP_CAT ' + // oracleMsgSig, + + 'OP_4 OP_ROLL ' + // oracleMessage, + + 'OP_SWAP ' + // oraclePk, + + 'OP_3 OP_PICK ' + // )); + + 'OP_CHECKDATASIGVERIFY ' + // require(checkMultiSig([ + + 'OP_0 ' + // ownerSig, + + 'OP_3 OP_ROLL ' + // oracleTxSig, + + 'OP_4 OP_ROLL ' + // ], [ + + 'OP_2 ' + // ownerPk, + + 'OP_2ROT OP_SWAP ' + // ])); + + 'OP_2 OP_CHECKMULTISIG', + fingerprint: '653df414836629dae799aa48f05529eb33462214bbb29534483bc72aabb4bceb', + debug: { + bytecode: '055370656e645c7e547a7c5379bb00537a547a52717c52ae', + sourceMap: '10:36:10:43;:53::55;:30::57:1;12:12:12:24:0;;13::13:25;14::14:20;;11:8:15:11:1;16:16:22:10:0;17:12:17:20;;18::18:23;;16:30:19:9:1;20:12:21:20:0;;19:11:22:9:1;16:8::12', + logs: [], + requires: [{ ip: 10, line: 11 }, { ip: 21, line: 16 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment.ts new file mode 100644 index 000000000..de47583e3 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment.ts @@ -0,0 +1,46 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + // Tuple destructuring into existing variables: top-level renames (with the small helpers + // inlined at the call sites), pure and mixed reassignment in loops, and the interleaved + // order that parks a declaration value on the altstack mid-fold. + artifact: { + contractName: 'TupleReassignment', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'seed', type: 'int' }] }], + bytecode: 'OP_DUP OP_1ADD OP_2DUP OP_SWAP OP_2DUP OP_SWAP OP_0 OP_BEGIN OP_DUP OP_4 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_SWAP OP_5 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_ROT OP_DROP OP_SWAP OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_0 OP_BEGIN OP_DUP OP_4 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_OVER OP_2 OP_PICK OP_MUL OP_1ADD OP_SWAP OP_ROT OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_0 OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_OVER OP_4 OP_PICK OP_OVER OP_2 OP_PICK OP_MUL OP_1ADD OP_SWAP OP_ROT OP_6 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_FROMALTSTACK OP_TOALTSTACK OP_ROT OP_DROP OP_SWAP OP_FROMALTSTACK OP_DUP OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_OVER OP_1ADD OP_ROT OP_DROP OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_DROP OP_2DUP OP_ROT OP_ROT OP_ADD OP_ROT OP_ADD OP_ADD OP_0 OP_GREATERTHANOREQUAL OP_VERIFY OP_2DROP OP_2DROP OP_1', + debug: { + bytecode: '768b6e7c6e7c006576549f766b637854797c557a757c6b7c6b7c6b7c6c6c6c7b757c768b77686c916675006576549f766b63785479785279958b7c7b567a757c6b7c6b7c6b7c6b7c6c6c6c6c537a757c6b7c6c7600a269788b7b7577686c916675006576529f766b63785479785279958b7c7b567a757c6b7c6b7c6b7c6b7c6c6c6c6c6b7b757c6c7600a269788b7b7577686c9166756e7b7b937b939300a2696d6d51', + sourceMap: '17:16:18:20;18:::24:1;21:22:21:26:0;:17::27:1;24:26:24:30:0;:21::31:1;27::27:22:0;:8:29:9;:24:27:25;:28::29;:24:::1;;;:42:29:9:0;28:26:28:27;:29::30;;:21::31:1;:12::32;;;;;;;;;;;;;;;;27:35:27:36:0;:::40:1;:31;:42:29:9;;:8;;;33:21:33:22:0;:8:36:9;:24:33:25;:28::29;:24:::1;;;:42:36:9:0;34:34:34:35;:37::38;;:29::39:1;;;;;;;:12::40;;;;;;;;;;;;;;;;;;;;;;;35:20:35:22:0;:26::27;:20:::1;:12::29;33:35:33:36:0;:::40:1;:31;;::36:9;:42;;:8;;;40:21:40:22:0;:8:43:9;:24:40:25;:28::29;:24:::1;;;:42:43:9:0;41:34:41:35;:37::38;;:29::39:1;;;;;;;:12::40;;;;;;;;;;;;;;;;;;;;;42:20:42:22:0;:26::27;:20:::1;:12::29;40:35:40:36:0;:::40:1;:31;;::43:9;:42;;:8;;;46:24:46:28:0;48:16:48:17;:20::21;:16:::1;:24::25:0;:16:::1;:::29;:33::34:0;:16:::1;:8::36;16:29:49:5;;', + logs: [], + requires: [ + { ip: 86, line: 35 }, + { ip: 139, line: 42 }, + { ip: 159, line: 48 }, + ], + sourceTags: '34:36:fu;37:40:lc;41:41:sc;87:91:fu;92:95:lc;96:96:sc;140:144:fu;145:148:lc;149:149:sc', + functions: [ + { + name: 'swap', + inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], + bytecode: '7c', + sourceMap: '7:14:7:15', + logs: [], + requires: [], + }, + { + name: 'step', + inputs: [{ name: 'x', type: 'int' }, { name: 'y', type: 'int' }], + bytecode: '785279958b7c7b', + sourceMap: '12:11:12:12;:15::16;;:11:::1;:::20;:22::23:0;:25::26', + logs: [], + requires: [], + }, + ], + inlineRanges: '3:3:swap;5:5:swap;17:17:swap;53:59:step;108:114:step;151:151:swap', + }, + fingerprint: '3ab69a954ec4bf9ceeb58eceb8ead206195032edf6627155eb82f528403c94dd', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment_after_final_read.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment_after_final_read.ts new file mode 100644 index 000000000..21bc2d29d --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment_after_final_read.ts @@ -0,0 +1,76 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'ReassignAfterFinalRead', + constructorInputs: [], + abi: [ + { name: 'ifBranch', inputs: [{ name: 'x', type: 'int' }] }, + { name: 'whileLoop', inputs: [{ name: 'x', type: 'int' }] }, + ], + bytecode: + // function ifBranch(int x) { + 'OP_DUP OP_0 OP_NUMEQUAL OP_IF ' + // int p = 10; + + 'OP_10 ' + // int q = 0; + + 'OP_0 ' + // require(p == 10); + + 'OP_OVER OP_10 OP_NUMEQUALVERIFY ' + // if (x == 1) { + + 'OP_3 OP_PICK OP_1 OP_NUMEQUAL OP_IF ' + // (p, q) = pair(x); + + 'OP_3 OP_PICK OP_DUP OP_2 OP_MUL OP_SWAP OP_1ADD OP_ROT OP_DROP OP_SWAP OP_ROT OP_DROP OP_SWAP ' + // } + + 'OP_ENDIF ' + // require(q == 0 || q == 2); + + 'OP_DUP OP_0 OP_NUMEQUAL OP_SWAP OP_2 OP_NUMEQUAL OP_BOOLOR ' + // Cleanup + + 'OP_NIP OP_NIP OP_NIP ' + // } + + 'OP_ELSE ' + // function whileLoop(int x) { + + 'OP_1 OP_NUMEQUALVERIFY ' + // int p = 10; + + 'OP_10 ' + // int q = 0; + + 'OP_0 ' + // require(p == 10); + + 'OP_OVER OP_10 OP_NUMEQUALVERIFY ' + // while (x == 1) { + + 'OP_BEGIN OP_2 OP_PICK OP_1 OP_NUMEQUAL OP_DUP OP_TOALTSTACK OP_IF ' + // (p, q) = pair(x); + + 'OP_2 OP_PICK OP_DUP OP_2 OP_MUL OP_SWAP OP_1ADD OP_ROT OP_DROP OP_SWAP OP_ROT OP_DROP OP_SWAP ' + // x = x + 1; + + 'OP_2 OP_PICK OP_1ADD OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK ' + // Loop condition + + 'OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL ' + // require(q == 0 || q == 2); + + 'OP_DUP OP_0 OP_NUMEQUAL OP_SWAP OP_2 OP_NUMEQUAL OP_BOOLOR ' + // Cleanup + + 'OP_NIP OP_NIP ' + // } + + 'OP_ENDIF', + fingerprint: '510ff239ab3ec7cc5d4301e1ef31a179c01bc4b6e73e800f03bd2674c9996ae3', + debug: { + bytecode: '76009c635a00785a9d5379519c6353797652957c8b7b757c7b757c6876009c7c529c9b77777767519d5a00785a9d655279519c766b6352797652957c8b7b757c7b757c52798b537a757c6b7c6c686c916676009c7c529c9b777768', + sourceMap: '11:4:19:5;;;;12:16:12:18;13::13:17;14::14;:21::23;:8::25:1;15:12:15:13:0;;:17::18;:12:::1;:20:17:9:0;16:26:16:27;;:21::28:1;;;;;:12::29;;;;;;15:20:17:9;18:16:18:17:0;:21::22;:16:::1;:26::27:0;:31::32;:26:::1;:8::34;11:29:19:5;;;:4;21::30::0;;22:16:22:18;23::23:17;24::24;:21::23;:8::25:1;25::28:9:0;:15:25:16;;:20::21;:15:::1;;;:23:28:9:0;26:26:26:27;;:21::28:1;;;;;:12::29;;;;;;27:16:27:17:0;;:::21:1;:12::22;;;;;;;25:23:28:9;;:8;;29:16:29:17:0;:21::22;:16:::1;:26::27:0;:31::32;:26:::1;:8::34;21:30:30:5;;10:0:31:1', + logs: [], + requires: [{ ip: 8, line: 14 }, { ip: 35, line: 18 }, { ip: 45, line: 24 }, { ip: 88, line: 29 }], + sourceTags: '35:37:sc;77:80:lc;88:89:sc', + functions: [ + { + name: 'pair', + inputs: [{ name: 'n', type: 'int' }], + bytecode: '7652957c8b', + sourceMap: '7:11:7:12;:15::16;:11:::1;:18::19:0;:::23:1', + logs: [], + requires: [], + }, + ], + inlineRanges: '16:20:pair;56:60:pair', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment_branches.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment_branches.ts new file mode 100644 index 000000000..406602dec --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_reassignment_branches.ts @@ -0,0 +1,74 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + // Tuple destructuring into existing variables inside branches. Scoped reassignment values are + // folded into the existing slots; a declaration value above a reassignment value is parked on + // the altstack while the fold runs (OP_TOALTSTACK ... OP_FROMALTSTACK in reassignmentFirst). + artifact: { + contractName: 'TupleReassignmentBranches', + constructorInputs: [], + abi: [ + { name: 'declarationFirst', inputs: [{ name: 'a', type: 'int' }] }, + { name: 'reassignmentFirst', inputs: [{ name: 'a', type: 'int' }] }, + ], + bytecode: + // OP_DEFINE branchPair (id 0) — called from both functions, too large to inline + '7653957857979378529693768b7c52957b94 OP_0 OP_DEFINE ' + // function declarationFirst + + 'OP_DUP OP_0 OP_NUMEQUAL OP_IF ' + // int total = 0 + + 'OP_0 ' + // if (a > 10) + + 'OP_2 OP_PICK OP_10 OP_GREATERTHAN OP_IF ' + // int d, total = branchPair(a) — call, then fold total's value (top) into its slot; + // d's value stays in place (declarations-first needs no parking) + + 'OP_2 OP_PICK OP_0 OP_INVOKE OP_ROT OP_DROP OP_SWAP ' + // require(d != 0) + + 'OP_DUP OP_0 OP_NUMNOTEQUAL OP_VERIFY ' + // scope cleanup (drop d) + + 'OP_DROP OP_ENDIF ' + // require(total >= 0) + cleanup + + 'OP_0 OP_GREATERTHANOREQUAL OP_NIP OP_NIP ' + // function reassignmentFirst + + 'OP_ELSE OP_1 OP_NUMEQUALVERIFY ' + // int total = 0 + + 'OP_0 ' + // if (a > 10) + + 'OP_OVER OP_10 OP_GREATERTHAN OP_IF ' + // (total, int extra) = branchPair(a + 1) — call, park extra's value on the altstack, + // fold total's value into its slot (OP_NIP), restore extra's value + + 'OP_OVER OP_1ADD OP_0 OP_INVOKE OP_TOALTSTACK OP_NIP OP_FROMALTSTACK ' + // require(extra != 0) + + 'OP_DUP OP_0 OP_NUMNOTEQUAL OP_VERIFY ' + // scope cleanup (drop extra) + + 'OP_DROP OP_ENDIF ' + // require(total >= 0) + cleanup + + 'OP_0 OP_GREATERTHANOREQUAL OP_NIP OP_ENDIF', + debug: { + bytecode: '127653957857979378529693768b7c52957b94008976009c630052795aa0635279008a7b757c76009e69756800a2777767519d00785aa063788b008a6b776c76009e69756800a27768', + sourceMap: '7::10:1;;::::1;14:4:21:5:0;;;;15:20:15:21;16:12:16:13;;:16::18;:12:::1;:20:19:9:0;17:38:17:39;;:27::40:1;;:12::41;;;18:20:18:21:0;:25::26;:20:::1;:12::28;16:20:19:9;;20:25:20:26:0;:8::28:1;14:37:21:5;;:4;25::32::0;;26:20:26:21;27:12:27:13;:16::18;:12:::1;:20:30:9:0;28:44:28:45;:::49:1;:33::50;;:12::51;;;29:20:29:25:0;:29::30;:20:::1;:12::32;27:20:30:9;;31:25:31:26:0;:8::28:1;25:38:32:5;12:0:33:1', + logs: [], + requires: [ + { ip: 23, line: 18 }, + { ip: 28, line: 20 }, + { ip: 48, line: 29 }, + { ip: 53, line: 31 }, + ], + sourceTags: '24:24:sc;28:29:sc;49:49:sc;53:53:sc', + functions: [ + { + id: 0, + name: 'branchPair', + inputs: [{ name: 'x', type: 'int' }], + bytecode: '7653957857979378529693768b7c52957b94', + sourceMap: '8:12:8:13;:16::17;:12:::1;:21::22:0;:25::26;:21:::1;:12::27;:31::32:0;:35::36;:31:::1;:12::37;9:11:9:12:0;:::16:1;:18::19:0;:22::23;:18:::1;:26::27:0;:18:::1', + logs: [], + requires: [], + }, + ], + }, + fingerprint: 'da4982948327a26f2c708b13af6977715747aa0b5c64bc00b04e3ddbc11ca67d', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking.ts new file mode 100644 index 000000000..61e046c57 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking.ts @@ -0,0 +1,27 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'split', inputs: [] }], + bytecode: + // string s1 = "hello"; + '68656c6c6f ' + // string s2 = "there"; + + '7468657265 ' + // string hello, string there = (s1+s2).split(5); + + 'OP_CAT OP_5 OP_SPLIT ' + // require(hello == there); + + 'OP_EQUAL', + fingerprint: '0d6e8f27e53878ab15977e6a093b90a8fd56869d924697254575b181712ce989', + debug: { + bytecode: '0568656c6c6f0574686572657e557f87', + sourceMap: '3:20:3:27;4::4;5:38:5:43:1;:51::52:0;:37::53:1;6:8:6:32', + logs: [], + requires: [{ ip: 6, line: 6 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking_parameter.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking_parameter.ts new file mode 100644 index 000000000..c9879a7b3 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking_parameter.ts @@ -0,0 +1,26 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'split', inputs: [{ name: 'b', type: 'bytes32' }] }], + bytecode: + // Implicit parameter type enforcement + 'OP_SIZE 20 OP_EQUALVERIFY ' + // bytes16 x, bytes16 y = b.split(16); + + 'OP_16 OP_SPLIT ' + // require(x == y); + + 'OP_EQUAL', + fingerprint: 'a99422ca4eb162381e18295a9ac1ff2aca6f511a7e72d12342ef4f61904a3094', + debug: { + bytecode: '82012088607f87', + sourceMap: '2:19:2:28;;;3:40:3:42;:32::43:1;4:8:4:24', + logs: [], + requires: [{ ip: 6, line: 4 }], + sourceTags: '0:2:pv', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking_single_side_type.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking_single_side_type.ts new file mode 100644 index 000000000..df79ddecb --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_unpacking_single_side_type.ts @@ -0,0 +1,23 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [], + abi: [{ name: 'split', inputs: [{ name: 'b', type: 'bytes' }] }], + bytecode: + // bytes16 x, bytes y = b.split(16); + 'OP_16 OP_SPLIT ' + // require(x == y); + + 'OP_EQUAL', + fingerprint: '470f52cf7c1f819e3a5492c7964c2b737a9c3586aba1e257e7bb8b65d341fa48', + debug: { + bytecode: '607f87', + sourceMap: '3:37:3:39;:29::40:1;4:8:4:24', + logs: [], + requires: [{ ip: 3, line: 4 }], + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/type_enforcement.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/type_enforcement.ts new file mode 100644 index 000000000..7daa585ee --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/type_enforcement.ts @@ -0,0 +1,86 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'TypeEnforcement', + constructorInputs: [], + abi: [{ + name: 'spend', inputs: [ + { name: 'nonEnforcedInt', type: 'int' }, + { name: 'enforcedBool', type: 'bool' }, + { name: 'enforcedBytes', type: 'bytes4' }, + { name: 'nonEnforcedBytes', type: 'bytes' }, + ], + }], + bytecode: + // Implicit type enforcement for enforcedBool: enforcedBool = bool(enforcedBool) + 'OP_SWAP OP_0NOTEQUAL ' + // Implicit type enforcement for enforcedBytes: require(enforcedBytes.length == 4) + + 'OP_ROT OP_SIZE OP_4 OP_EQUALVERIFY ' + // if(enforcedBool == true) ) + + 'OP_OVER OP_1 OP_NUMEQUAL OP_IF ' + // require(nonEnforcedInt > 6) + + 'OP_2 OP_PICK OP_6 OP_GREATERTHAN OP_VERIFY ' + // Cleanup + + 'OP_ENDIF ' + // if(enforcedBool == false) { + + 'OP_SWAP OP_0 OP_NUMEQUAL OP_IF ' + // require(enforcedBytes == nonEnforcedBytes) + + 'OP_DUP OP_3 OP_PICK OP_EQUALVERIFY ' + // Cleanup + + 'OP_ENDIF OP_2DROP OP_DROP OP_1', + debug: { + bytecode: '7c927b82548878519c63527956a069687c009c6376537988686d7551', + sourceMap: '4:8:4:25;;5::5:28;;;;8:12:8:24;:28::32;:12:::1;:34:10:9:0;9:20:9:34;;:37::38;:20:::1;:12::40;8:34:10:9;12:12:12:24:0;:28::33;:12:::1;:35:14:9:0;13:20:13:33;:37::53;;:12::55:1;12:35:14:9;7:6:15:5;;', + sourceTags: '0:1:pv;2:5:pv', + logs: [], + requires: [ + { ip: 14, line: 9 }, + { ip: 23, line: 13 }, + ], + }, + fingerprint: 'afc9b61abaaef4b60d435309b83b2cbd5750e2c1755ca903cfd3f438f7dc6126', + }, + }, + { + compilerOptions: { + enforceFunctionParameterTypes: false, + }, + artifact: { + contractName: 'TypeEnforcement', + constructorInputs: [], + abi: [{ + name: 'spend', inputs: [ + { name: 'nonEnforcedInt', type: 'int' }, + { name: 'enforcedBool', type: 'bool' }, + { name: 'enforcedBytes', type: 'bytes4' }, + { name: 'nonEnforcedBytes', type: 'bytes' }, + ], + }], + bytecode: + // if(enforcedBool == true) + 'OP_OVER OP_1 OP_NUMEQUAL OP_IF ' + // require(nonEnforcedInt > 6) + + 'OP_DUP OP_6 OP_GREATERTHAN OP_VERIFY ' + // Cleanup + + 'OP_ENDIF ' + // if(enforcedBool == false) { + + 'OP_SWAP OP_0 OP_NUMEQUAL OP_IF ' + // require(enforcedBytes == nonEnforcedBytes) + + 'OP_OVER OP_3 OP_PICK OP_EQUALVERIFY ' + // Cleanup + + 'OP_ENDIF OP_2DROP OP_DROP OP_1', + debug: { + bytecode: '78519c637656a069687c009c6378537988686d7551', + sourceMap: '8:12:8:24;:28::32;:12:::1;:34:10:9:0;9:20:9:34;:37::38;:20:::1;:12::40;8:34:10:9;12:12:12:24:0;:28::33;:12:::1;:35:14:9:0;13:20:13:33;:37::53;;:12::55:1;12:35:14:9;7:6:15:5;;', + logs: [], + requires: [ + { ip: 7, line: 9 }, + { ip: 16, line: 13 }, + ], + }, + fingerprint: '606e540c38f161868964b683aeb0ddf93094dc36607397ef9b9f507f9028bc37', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/unsafe_bool_cast.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/unsafe_bool_cast.ts new file mode 100644 index 000000000..e4635dd67 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/unsafe_bool_cast.ts @@ -0,0 +1,14 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'int' }], + abi: [{ name: 'test', inputs: [] }], + bytecode: '', + fingerprint: '4ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc33260', + debug: { bytecode: '', sourceMap: '', logs: [], requires: [{ ip: 1, line: 3 }] }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/unsafe_int_cast.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/unsafe_int_cast.ts new file mode 100644 index 000000000..8597c9635 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/unsafe_int_cast.ts @@ -0,0 +1,24 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Test', + constructorInputs: [{ name: 'x', type: 'bytes4' }], + abi: [{ name: 'test', inputs: [{ name: 'y', type: 'bytes4' }] }], + bytecode: + // Implicit parameter type enforcement + 'OP_SWAP OP_SIZE OP_4 OP_EQUALVERIFY ' + // require(unsafe_int(x) > unsafe_int(y)); + + 'OP_GREATERTHAN', + fingerprint: 'f46c0c6d3ac4de281708e6abe5b28f03eb7f3878ba6554c53a102e2bca1d4676', + debug: { + bytecode: '7c825488a0', + sourceMap: '2:18:2:26;;;;3:8:3:47:1', + logs: [], + requires: [{ ip: 6, line: 3 }], + sourceTags: '0:3:pv', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/unused_modifier.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/unused_modifier.ts new file mode 100644 index 000000000..01be0fd12 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/unused_modifier.ts @@ -0,0 +1,93 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'UnusedModifier', + constructorInputs: [{ name: 'salt', type: 'int' }], + abi: [ + { + name: 'spend', + inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }, { name: 'zeroPadding', type: 'bytes' }], + }, + ], + bytecode: + // contract UnusedModifier(int unused salt) { + 'OP_DROP ' + // function spend(int a, int b, bytes unused zeroPadding) { + + 'OP_ROT OP_DROP ' + // int unused scratch = a + b; + + 'OP_2DUP OP_ADD OP_DROP ' + // int constant unused magic = 42; + + '2a OP_DROP ' + // require(pad(a, 100) + b == 5); + + '64 OP_DROP OP_ADD OP_5 OP_NUMEQUAL', + fingerprint: '63c5ea2b3fc243e80628e119b8ffa9b873bf2a5aed664c8529b58d6f79116f7c', + debug: { + bytecode: '757b756e9375012a7501647593559c', + sourceMap: '5:24:5:39;6:33:6:57;;7:29:7:34;::::1;:8::35;8:36:8:38:0;:8::39:1;9:23:9:26:0;:16::27:1;:::31;:35::36:0;:8::38:1', + logs: [], + requires: [{ ip: 14, line: 9 }], + functions: [ + { + name: 'pad', + inputs: [{ name: 'value', type: 'int' }, { name: 'padding', type: 'int' }], + bytecode: '75', + sourceMap: '1:24:1:42', + logs: [], + requires: [], + }, + ], + inlineRanges: '10:10:pad', + }, + }, + }, + { + // The `unused` modifier — unused parameters keep their slot in constructorInputs / abi / frame + // inputs, but are dropped from the stack: constructor and contract function parameters in the + // contract prologue (rolled up first if buried), locals right after their initialiser, and + // global-function parameters in the function-body prologue. + compilerOptions: { disableInlining: true }, + artifact: { + contractName: 'UnusedModifier', + constructorInputs: [{ name: 'salt', type: 'int' }], + abi: [{ + name: 'spend', + inputs: [{ name: 'a', type: 'int' }, { name: 'b', type: 'int' }, { name: 'zeroPadding', type: 'bytes' }], + }], + bytecode: + // OP_DEFINE pad (id 0): drop unused param `padding`, leaving `value` as the return value + '75 OP_0 OP_DEFINE ' + // drop unused constructor param `salt` (top of stack) + + 'OP_DROP ' + // roll up and drop unused function param `zeroPadding` + + 'OP_ROT OP_DROP ' + // int unused scratch = a + b — initialiser is evaluated, then dropped + + 'OP_2DUP OP_ADD OP_DROP ' + // int constant unused magic = 42 — dropped as well + + '2a OP_DROP ' + // require(pad(a, 100) + b == 5) + + '64 OP_0 OP_INVOKE OP_ADD OP_5 OP_NUMEQUAL', + debug: { + bytecode: '01750089757b756e9375012a750164008a93559c', + logs: [], + requires: [ + { ip: 18, line: 9 }, + ], + sourceMap: '1::3:1;;::::1;5:24:5:39:0;6:33:6:57;;7:29:7:34;::::1;:8::35;8:36:8:38:0;:8::39:1;9:23:9:26:0;:16::27:1;;:::31;:35::36:0;:8::38:1', + functions: [ + { + id: 0, + name: 'pad', + inputs: [{ name: 'value', type: 'int' }, { name: 'padding', type: 'int' }], + bytecode: '75', + sourceMap: '1:24:1:42', + logs: [], + requires: [], + }, + ], + }, + fingerprint: '4fcac7e0c885a2d3d6a344866c39c4febdffcaf9bb658ac08a87ed7dea9808b6', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop.ts new file mode 100644 index 000000000..79812f925 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop.ts @@ -0,0 +1,24 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'Loopy', + constructorInputs: [], + abi: [{ name: 'doLoop', inputs: [] }], + bytecode: 'OP_0 OP_BEGIN OP_DUP OP_TXINPUTCOUNT OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_2 OP_GREATERTHAN', + debug: { + bytecode: '006576c39f766b63768b77686c916652a0', + sourceMap: '3:16:3:17;5:8:7:9;:15:5:16;:19::35;:15:::1;;;:37:7:9:0;6:16:6:17;:::21:1;:12::22;5:37:7:9;;:8;;10:20:10:21:0;:8::23:1', + logs: [ + { ip: 15, line: 9, data: [{ stackIndex: 0, type: 'int', ip: 15 }] }, + ], + requires: [ + { ip: 17, line: 10 }, + ], + sourceTags: '11:14:lc', + }, + fingerprint: '00fc9253e439b8a2f39ba60d1d173ff4d19f557802b40b750eb6df5f92b1001e', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop_basic.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop_basic.ts new file mode 100644 index 000000000..09635a1c1 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop_basic.ts @@ -0,0 +1,22 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'WhileLoopBasic', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: 'OP_0 OP_BEGIN OP_DUP OP_3 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF OP_DUP OP_1ADD OP_NIP OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL OP_3 OP_NUMEQUAL', + debug: { + bytecode: '006576539f766b63768b77686c9166539c', + sourceMap: '3:16:3:17;5:8:7:9;:15:5:16;:19::20;:15:::1;;;:22:7:9:0;6:16:6:17;:::21:1;:12::22;5:22:7:9;;:8;;9:21:9:22:0;:8::24:1', + logs: [], + requires: [ + { ip: 17, line: 9 }, + ], + sourceTags: '11:14:lc', + }, + fingerprint: '5a456e72142ae6beb6f64a3af7edfe9e14295b17724c4dfec0d84940c545d457', + }, + }, +]; diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop_nested.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop_nested.ts new file mode 100644 index 000000000..b2d0036a1 --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/while_loop_nested.ts @@ -0,0 +1,46 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'WhileLoopNested', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [] }], + bytecode: + // int i = 0; + 'OP_0 ' + // int total = 0; + + 'OP_0 ' + // while (i < 2) { + + 'OP_BEGIN OP_OVER OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF ' + // int j = 0; + + 'OP_0 ' + // while (j < 2) { + + 'OP_BEGIN OP_DUP OP_2 OP_LESSTHAN OP_DUP OP_TOALTSTACK OP_IF ' + // total = total + 1; + + 'OP_OVER OP_1ADD OP_ROT OP_DROP OP_SWAP ' + // j = j + 1; + + 'OP_DUP OP_1ADD OP_NIP ' + // Loop condition + + 'OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL ' + // i = i + 1; + + 'OP_2 OP_PICK OP_1ADD OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK ' + // Cleanup + + 'OP_DROP ' + // Loop condition + + 'OP_ENDIF OP_FROMALTSTACK OP_NOT OP_UNTIL ' + // require(i == 2); + + 'OP_SWAP OP_2 OP_NUMEQUALVERIFY ' + // require(total == 4); + + 'OP_4 OP_NUMEQUAL', + fingerprint: '1305b87f8914755fb2e52934624cd80fc3bf61117d6957730845fcbc2002e8b4', + debug: { + bytecode: '00006578529f766b63006576529f766b63788b7b757c768b77686c916652798b537a757c6b7c6c75686c91667c529d549c', + sourceMap: '3:16:3:17;4:20:4:21;6:8:15:9;:15:6:16;:19::20;:15:::1;;;:22:15:9:0;7:20:7:21;9:12:12:13;:19:9:20;:23::24;:19:::1;;;:26:12:13:0;10:24:10:29;:::33:1;:16::34;;;11:20:11:21:0;:::25:1;:16::26;9:26:12:13;;:12;;14:16:14:17:0;;:::21:1;:12::22;;;;;;;6:22:15:9;;;:8;;17:16:17:17:0;:21::22;:8::24:1;18:25:18:26:0;:8::28:1', + logs: [], + requires: [{ ip: 46, line: 17 }, { ip: 49, line: 18 }], + sourceTags: '25:28:lc;39:39:sc;40:43:lc', + }, + }, + }, +]; diff --git a/packages/cashc/test/generation/generation.test.ts b/packages/cashc/test/generation/generation.test.ts index 4d5c71226..2846c45ff 100644 --- a/packages/cashc/test/generation/generation.test.ts +++ b/packages/cashc/test/generation/generation.test.ts @@ -1,17 +1,46 @@ -/* generation.test.ts - * - * - This file is used to test the IR and target code generation - */ - +import fs from 'fs'; import { URL } from 'url'; -import { compileFile } from '../../src/internal.js'; -import { fixtures } from './fixtures.js'; +import { CompilerOptions } from '@cashscript/utils'; +import { compileFile, DEFAULT_COMPILER_OPTIONS, InternalCompilerOptions } from '../../src/internal.js'; +import { version } from '../../src/index.js'; +import { loadFixtureModules } from './fixture-utils.js'; + +const fixtureModules = await loadFixtureModules(); describe('Code generation & target code optimisation', () => { - fixtures.forEach((fixture) => { - it(`should compile ${fixture.fn} to correct Script and artifact`, () => { - const artifact = compileFile(new URL(`../valid-contract-files/${fixture.fn}`, import.meta.url), fixture.compilerOptions); - expect(artifact).toEqual({ ...fixture.artifact, updatedAt: expect.any(String) }); + it('should have a fixture module for every valid contract file', () => { + const cashFiles = fs.readdirSync(new URL('../valid-contract-files', import.meta.url)) + .filter((fn) => fn.endsWith('.cash')) + .map((fn) => `valid-contract-files/${fn}`); + + const coveredCashFiles = fixtureModules + .map((fixtureModule) => fixtureModule.cashFile) + .filter((fn) => fn.startsWith('valid-contract-files/')); + + expect(coveredCashFiles.sort()).toEqual(cashFiles.sort()); + }); + + fixtureModules.forEach(({ cashFile, fixtures }) => { + fixtures.forEach((fixture) => { + const variant = fixture.compilerOptions ? ` (${JSON.stringify(fixture.compilerOptions)})` : ''; + it(`should compile ${cashFile} to correct Script and artifact${variant}`, () => { + const sourceFile = new URL(`../${cashFile}`, import.meta.url); + const artifact = compileFile(sourceFile, fixture.compilerOptions); + + expect(artifact).toEqual({ + ...fixture.artifact, + source: fs.readFileSync(sourceFile, { encoding: 'utf-8' }), + compiler: { name: 'cashc', version, options: artifactCompilerOptions(fixture.compilerOptions) }, + updatedAt: expect.any(String), + }); + }); }); }); }); + +// The artifact records the merged public compiler options (internal-only options are stripped) +function artifactCompilerOptions(compilerOptions: InternalCompilerOptions = {}): CompilerOptions { + const mergedOptions: InternalCompilerOptions = { ...DEFAULT_COMPILER_OPTIONS, ...compilerOptions }; + delete mergedOptions.disableInlining; + return mergedOptions; +} diff --git a/packages/cashc/test/global-definitions.test.ts b/packages/cashc/test/global-definitions.test.ts index f2a61d872..8560e86cb 100644 --- a/packages/cashc/test/global-definitions.test.ts +++ b/packages/cashc/test/global-definitions.test.ts @@ -5,7 +5,7 @@ * definitions at their call sites or to share them as OP_DEFINE / OP_INVOKE definitions, the * lowering of constants to zero-argument functions, and stable VM function-ID assignment. * - Compile errors are tested with the fixture files in ./compiler, and the exact compiled output - * is locked in by the fixtures in generation/fixtures.ts. + * is locked in by the fixture modules in generation/fixtures. */ import { compileString } from '../src/internal.js'; diff --git a/packages/utils/src/script.ts b/packages/utils/src/script.ts index 180bf9f45..cb6077716 100644 --- a/packages/utils/src/script.ts +++ b/packages/utils/src/script.ts @@ -236,7 +236,7 @@ function replaceOps( const replacementLength = replacement === '' ? 0 : replacement.split(/\s+/).length; const lengthDiff = patternLength - replacementLength; - // (?=\s|$) requires the pattern to end at a token boundary (no partial matches) withoutconsuming the separator + // (?=\s|$) requires the pattern to end at a token boundary (no partial matches) without consuming the separator const regex = new RegExp(`${pattern}(?=\\s|$)`, 'g'); // Most rules match nothing on any given script, and must leave the ASM untouched. From 40d7e01e5b0c466a6583ef45afa746963719454a Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 1 Sep 2026 10:27:23 +0200 Subject: [PATCH 29/37] Fix date parsing timezone dependence issue --- packages/cashc/src/ast/AstBuilder.ts | 3 ++- .../fixtures/valid-contract-files/date_literal.ts | 4 ++-- .../valid-contract-files/global_constant_literals.ts | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index 53e16bce3..c9b80c808 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -552,7 +552,8 @@ export default class AstBuilder throw new ParseError('Date should be in format `YYYY-MM-DDThh:mm:ss`', Location.fromCtx(ctx)); } - const timestamp = Math.round(Date.parse(stringValue) / 1000); + // Date literals should always be in UTC, so we append 'Z' to the string + const timestamp = Math.round(Date.parse(`${stringValue}Z`) / 1000); if (Number.isNaN(timestamp)) { throw new ParseError(`Incorrectly formatted date "${stringValue}"`, Location.fromCtx(ctx)); diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/date_literal.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/date_literal.ts index 59321bcff..1cf348e3a 100644 --- a/packages/cashc/test/generation/fixtures/valid-contract-files/date_literal.ts +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/date_literal.ts @@ -8,12 +8,12 @@ export const fixtures: Fixture[] = [ abi: [{ name: 'test', inputs: [] }], bytecode: // int d = date("2021-02-17T01:30:00"); //YYYY-MM-DDThh:mm:ss - '88632c60 ' + '98712c60 ' // require(d == 0); + 'OP_0 OP_NUMEQUAL', fingerprint: '3584793ef9b31561ca87330a348b586c6352c8fa413985079b7d8ca3aca5bdf0', debug: { - bytecode: '0488632c60009c', + bytecode: '0498712c60009c', sourceMap: '5:16:5:43;6:21:6:22;:8::24:1', logs: [], requires: [{ ip: 3, line: 6 }], diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_literals.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_literals.ts index e1aebed30..18106ac26 100644 --- a/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_literals.ts +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/global_constant_literals.ts @@ -28,14 +28,14 @@ export const fixtures: Fixture[] = [ // require(interval == INTERVAL); + 'OP_SWAP 201c OP_NUMEQUALVERIFY ' // require(deadline == DEADLINE); - + 'OP_SWAP 88632c60 OP_NUMEQUALVERIFY ' + + 'OP_SWAP 98712c60 OP_NUMEQUALVERIFY ' // require(greeting == GREETING); + 'OP_SWAP 68656c6c6f OP_EQUALVERIFY ' // require(magic == MAGIC); + '01020304 OP_EQUAL', fingerprint: '74578f6eb254c7cb367434c6754d27e684bd1b3c7362fac7a0024397c9f73331', debug: { - bytecode: '92557a8254887c519d7c01879d7c02201c9d7c0488632c609d7c0568656c6c6f88040102030487', + bytecode: '92557a8254887c519d7c01879d7c02201c9d7c0498712c609d7c0568656c6c6f88040102030487', sourceMap: '9:19:9:31;:92::104;;;;;10:16:10:23;:27::34:1;:8::36;11:16:11:24:0;:28::36:1;:8::38;12:16:12:24:0;:28::36:1;:8::38;13:16:13:24:0;:28::36:1;:8::38;14:16:14:24:0;:28::36:1;:8::38;15:25:15:30;:8::32', logs: [], requires: [ @@ -79,7 +79,7 @@ export const fixtures: Fixture[] = [ name: 'DEADLINE', kind: 'constant', inputs: [], - bytecode: '0488632c60', + bytecode: '0498712c60', sourceMap: '4:24:4:51', logs: [], requires: [], From 42be089101e847d93fd4fb024e4707056f21492a Mon Sep 17 00:00:00 2001 From: mr-zwets <53938059+mr-zwets@users.noreply.github.com> Date: Tue, 1 Sep 2026 10:45:44 +0200 Subject: [PATCH 30/37] docs: add documentation for sighash flags (#421) --- website/docs/language/types.md | 2 +- website/docs/sdk/signature-templates.md | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/website/docs/language/types.md b/website/docs/language/types.md index 06c42f429..368173694 100644 --- a/website/docs/language/types.md +++ b/website/docs/language/types.md @@ -127,7 +127,7 @@ Operators: - `!=` (inequality) ### Transaction Signature -`sig`: Byte sequence representing a transaction signature. Generally 65 bytes long. +`sig`: Byte sequence representing a transaction signature. Generally 65 bytes long: a 64-byte Schnorr signature followed by a single sighash flag byte that indicates which parts of the transaction were signed. See [HashType](/docs/sdk/signature-templates#hashtype) for the meaning of this byte. Operators: diff --git a/website/docs/sdk/signature-templates.md b/website/docs/sdk/signature-templates.md index b9e51b029..da6a4dc29 100644 --- a/website/docs/sdk/signature-templates.md +++ b/website/docs/sdk/signature-templates.md @@ -120,6 +120,16 @@ export enum SighashType { } ``` +`SIGHASH_ALL`, `SIGHASH_NONE` and `SIGHASH_SINGLE` choose which outputs are signed, while `SIGHASH_UTXOS` and `SIGHASH_ANYONECANPAY` are modifiers that can be OR'd on top to change what else is committed to. For a full technical breakdown of the signing serialization and every valid flag combination, see the [Bitcoin Cash transaction signing reference][tx-signing]. + +| Flag | Value | Commits to | Typical use | +| --- | --- | --- | --- | +| `SIGHASH_ALL` | `0x01` | all inputs and **all** outputs | sign the exact transaction | +| `SIGHASH_NONE` | `0x02` | all inputs, but **no** outputs | let the outputs be decided after signing | +| `SIGHASH_SINGLE` | `0x03` | all inputs, and only the **one** output at the same index as the signed input | pair a single input to a single output | +| `SIGHASH_UTXOS` | `0x20` | *(modifier)* additionally commits to the full contents of the UTXOs being spent | recommended for all contracts — see below | +| `SIGHASH_ANYONECANPAY` | `0x80` | *(modifier)* only the **current** input, allowing other inputs to be added | crowdfunding-style transactions where anyone can add an input | + #### Example ```ts const wif = 'L4vmKsStbQaCvaKPnCzdRArZgdAxTqVx8vjMGLW5nHtWdRguiRi1'; @@ -156,3 +166,4 @@ const configuredSignatureAlgorithm = signatureTemplate.signatureAlgorithm [wif]: https://en.bitcoin.it/wiki/Wallet_import_format [ecpair]: https://bchjs.fullstack.cash/#api-ECPair [privatekey]: https://github.com/bitpay/bitcore/blob/master/packages/bitcore-lib-cash/docs/privatekey.md +[tx-signing]: https://documentation.cash/protocol/blockchain/transaction/transaction-signing.html From 616996b5a3641858f4e258c68932922187802b31 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 1 Sep 2026 10:54:21 +0200 Subject: [PATCH 31/37] fix: don't throw on tx resubmission in MockNetworkProvider --- packages/cashscript/src/network/MockNetworkProvider.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/cashscript/src/network/MockNetworkProvider.ts b/packages/cashscript/src/network/MockNetworkProvider.ts index b7209db77..0cb4d0e77 100644 --- a/packages/cashscript/src/network/MockNetworkProvider.ts +++ b/packages/cashscript/src/network/MockNetworkProvider.ts @@ -77,7 +77,8 @@ export default class MockNetworkProvider implements NetworkProvider { const txid = binToHex(sha256(sha256(transactionBin)).reverse()); if (this.options.updateUtxoSet && this.transactionMap[txid]) { - throw new Error(`Transaction with txid ${txid} was already submitted`); + console.warn(`Transaction with txid ${txid} was already submitted`); + return txid; } this.transactionMap[txid] = txHex; From ee2804c3bc8e5aa3a2991a2475fd341d729e723c Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 1 Sep 2026 11:20:39 +0200 Subject: [PATCH 32/37] fix: fix failing test after MockNetworkProvider fix --- .../test/e2e/network/MockNetworkProvider.test.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/cashscript/test/e2e/network/MockNetworkProvider.test.ts b/packages/cashscript/test/e2e/network/MockNetworkProvider.test.ts index 3f14a954b..75198caa8 100644 --- a/packages/cashscript/test/e2e/network/MockNetworkProvider.test.ts +++ b/packages/cashscript/test/e2e/network/MockNetworkProvider.test.ts @@ -55,7 +55,7 @@ describe.skipIf(Boolean(process.env.TESTS_USE_CHIPNET))('MockNetworkProvider', ( await expect(provider.sendRawTransaction(tx.slice(0, -2))).rejects.toThrow('Error reading transaction.'); // send valid transaction - await expect(provider.sendRawTransaction(tx)).resolves.not.toThrow(); + const txid = await provider.sendRawTransaction(tx); // utxos should be removed from the provider expect(await provider.getUtxos(aliceAddress)).toHaveLength(0); @@ -64,7 +64,11 @@ describe.skipIf(Boolean(process.env.TESTS_USE_CHIPNET))('MockNetworkProvider', ( // utxo should be added to bob expect(await provider.getUtxos(bobAddress)).toHaveLength(1); - await expect(provider.sendRawTransaction(tx)).rejects.toThrow('already submitted'); + // resubmission resolves with the same txid and doesn't change the utxo set + await expect(provider.sendRawTransaction(tx)).resolves.toBe(txid); + expect(await provider.getUtxos(aliceAddress)).toHaveLength(0); + expect(await provider.getUtxos(p2pkhInstance.address)).toHaveLength(0); + expect(await provider.getUtxos(bobAddress)).toHaveLength(1); }); }); From 07a1667b7c225ee028df7b1f5cbe6b5fadbdf14e Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 1 Sep 2026 11:26:02 +0200 Subject: [PATCH 33/37] feat: allow using constant and unused modifiers in tuple assignment --- packages/cashc/src/ast/AST.ts | 1 + packages/cashc/src/ast/AstBuilder.ts | 1 + .../src/generation/GenerateTargetTraversal.ts | 18 + packages/cashc/src/grammar/CashScript.g4 | 2 +- packages/cashc/src/grammar/CashScript.interp | 2 +- .../cashc/src/grammar/CashScriptParser.ts | 739 +++++++++--------- .../src/print/OutputSourceCodeTraversal.ts | 6 +- .../src/semantic/SymbolTableTraversal.ts | 4 +- packages/cashc/test/ast/fixtures.ts | 4 +- .../reassign_constant_tuple_target.cash | 7 + .../duplicate_modifier_tuple_target.cash | 7 + .../reference_unused_tuple_target.cash | 7 + .../modifier_on_tuple_reassignment.cash | 7 + .../unused_tuple_target.cash | 6 + .../valid-contract-files/tuple_modifiers.ts | 95 +++ .../valid-contract-files/tuple_modifiers.cash | 27 + website/docs/language/types.md | 6 + 17 files changed, 575 insertions(+), 364 deletions(-) create mode 100644 packages/cashc/test/compiler/ConstantModificationError/reassign_constant_tuple_target.cash create mode 100644 packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier_tuple_target.cash create mode 100644 packages/cashc/test/compiler/InvalidModifierError/reference_unused_tuple_target.cash create mode 100644 packages/cashc/test/compiler/ParseError/modifier_on_tuple_reassignment.cash create mode 100644 packages/cashc/test/compiler/UnusedVariableError/unused_tuple_target.cash create mode 100644 packages/cashc/test/generation/fixtures/valid-contract-files/tuple_modifiers.ts create mode 100644 packages/cashc/test/valid-contract-files/tuple_modifiers.cash diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index 3b787b5ea..b10c36ec5 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -157,6 +157,7 @@ export class VariableDefinitionNode extends NonControlStatementNode implements N export interface TupleAssignmentTarget { identifier: IdentifierNode; type?: Type; + modifiers: Modifier[]; isReassignment?: boolean; } diff --git a/packages/cashc/src/ast/AstBuilder.ts b/packages/cashc/src/ast/AstBuilder.ts index c9b80c808..4362b8ab5 100644 --- a/packages/cashc/src/ast/AstBuilder.ts +++ b/packages/cashc/src/ast/AstBuilder.ts @@ -256,6 +256,7 @@ export default class AstBuilder return { identifier, type: typeName ? parseType(typeName.getText()) : undefined, + modifiers: target.modifier_list().map((modifier) => modifier.getText() as Modifier), isReassignment: !typeName, }; }); diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index ad905b8fc..c8ff35fdd 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -514,6 +514,7 @@ export default class GenerateTargetTraversal extends AstTraversal { if (!scopedReassign) { this.popFromStack(node.targets.length); node.targets.forEach((target) => this.pushToStack(target.identifier.name)); + this.dropUnusedTupleTargets(node); return node; } @@ -524,6 +525,8 @@ export default class GenerateTargetTraversal extends AstTraversal { reversedTargets.forEach((target) => { if (target.isReassignment) { this.emitReplace(this.getStackIndex(target.identifier.name), node); + } else if (target.modifiers.includes(Modifier.UNUSED)) { + this.emit(Op.OP_DROP, locationData); } else { this.emit(Op.OP_TOALTSTACK, locationData); parkedDeclarations.push(target.identifier.name); @@ -539,6 +542,21 @@ export default class GenerateTargetTraversal extends AstTraversal { return node; } + private dropUnusedTupleTargets(node: TupleAssignmentNode): void { + const locationData = { location: node.location, positionHint: PositionHint.END }; + + node.targets + .filter((target) => target.modifiers.includes(Modifier.UNUSED)) + .sort((a, b) => this.getStackIndex(a.identifier.name) - this.getStackIndex(b.identifier.name)) + .forEach((target) => { + const stackIndex = this.getStackIndex(target.identifier.name); + this.emit(encodeInt(BigInt(stackIndex)), locationData); + this.emit(Op.OP_ROLL, locationData); + this.emit(Op.OP_DROP, locationData); + this.removeFromStack(stackIndex); + }); + } + visitAssign(node: AssignNode): Node { node.expression = this.visit(node.expression); if (this.scopeDepth > 0) { diff --git a/packages/cashc/src/grammar/CashScript.g4 b/packages/cashc/src/grammar/CashScript.g4 index 5e6ed26b6..3ed22c30c 100644 --- a/packages/cashc/src/grammar/CashScript.g4 +++ b/packages/cashc/src/grammar/CashScript.g4 @@ -106,7 +106,7 @@ tupleAssignment ; tupleTarget - : typeName Identifier + : typeName modifier* Identifier | Identifier ; diff --git a/packages/cashc/src/grammar/CashScript.interp b/packages/cashc/src/grammar/CashScript.interp index 04be55783..b3c240aa7 100644 --- a/packages/cashc/src/grammar/CashScript.interp +++ b/packages/cashc/src/grammar/CashScript.interp @@ -223,4 +223,4 @@ typeCast atn: -[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, 8, 5, 8, 146, 8, 8, 10, 8, 12, 8, 149, 9, 8, 1, 8, 1, 8, 3, 8, 153, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 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, 17, 17, 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, 156, 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, 16, 8, 0, 133, 136, 3, 18, 9, 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, 5, 12, 0, 0, 138, 139, 5, 82, 0, 0, 139, 152, 3, 26, 13, 0, 140, 141, 5, 13, 0, 0, 141, 142, 5, 14, 0, 0, 142, 147, 3, 86, 43, 0, 143, 144, 5, 15, 0, 0, 144, 146, 3, 86, 43, 0, 145, 143, 1, 0, 0, 0, 146, 149, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 147, 148, 1, 0, 0, 0, 148, 150, 1, 0, 0, 0, 149, 147, 1, 0, 0, 0, 150, 151, 5, 16, 0, 0, 151, 153, 1, 0, 0, 0, 152, 140, 1, 0, 0, 0, 152, 153, 1, 0, 0, 0, 153, 154, 1, 0, 0, 0, 154, 155, 3, 24, 12, 0, 155, 17, 1, 0, 0, 0, 156, 157, 3, 86, 43, 0, 157, 158, 5, 17, 0, 0, 158, 159, 5, 82, 0, 0, 159, 160, 5, 10, 0, 0, 160, 161, 3, 78, 39, 0, 161, 162, 5, 2, 0, 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, 12, 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, 14, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 15, 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, 15, 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, 16, 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, 15, 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, 15, 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, 14, 0, 0, 278, 281, 3, 46, 23, 0, 279, 280, 5, 15, 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, 16, 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, 14, 0, 0, 306, 307, 5, 79, 0, 0, 307, 308, 5, 6, 0, 0, 308, 311, 3, 78, 39, 0, 309, 310, 5, 15, 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, 16, 0, 0, 314, 51, 1, 0, 0, 0, 315, 316, 5, 26, 0, 0, 316, 317, 5, 14, 0, 0, 317, 320, 3, 78, 39, 0, 318, 319, 5, 15, 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, 16, 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, 14, 0, 0, 329, 330, 3, 78, 39, 0, 330, 331, 5, 16, 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, 14, 0, 0, 345, 346, 3, 78, 39, 0, 346, 347, 5, 16, 0, 0, 347, 348, 5, 2, 0, 0, 348, 61, 1, 0, 0, 0, 349, 350, 5, 31, 0, 0, 350, 351, 5, 14, 0, 0, 351, 352, 3, 78, 39, 0, 352, 353, 5, 16, 0, 0, 353, 354, 3, 30, 15, 0, 354, 63, 1, 0, 0, 0, 355, 356, 5, 32, 0, 0, 356, 357, 5, 14, 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, 16, 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, 14, 0, 0, 376, 381, 3, 70, 35, 0, 377, 378, 5, 15, 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, 15, 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, 16, 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, 14, 0, 0, 395, 400, 3, 78, 39, 0, 396, 397, 5, 15, 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, 15, 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, 16, 0, 0, 409, 77, 1, 0, 0, 0, 410, 411, 6, 39, -1, 0, 411, 412, 5, 14, 0, 0, 412, 413, 3, 78, 39, 0, 413, 414, 5, 16, 0, 0, 414, 460, 1, 0, 0, 0, 415, 416, 3, 88, 44, 0, 416, 417, 5, 14, 0, 0, 417, 419, 3, 78, 39, 0, 418, 420, 5, 15, 0, 0, 419, 418, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 420, 421, 1, 0, 0, 0, 421, 422, 5, 16, 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, 15, 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, 15, 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, 14, 0, 0, 500, 501, 3, 78, 39, 0, 501, 502, 5, 16, 0, 0, 502, 512, 1, 0, 0, 0, 503, 504, 10, 16, 0, 0, 504, 505, 5, 50, 0, 0, 505, 506, 5, 14, 0, 0, 506, 507, 3, 78, 39, 0, 507, 508, 5, 15, 0, 0, 508, 509, 3, 78, 39, 0, 509, 510, 5, 16, 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, 147, 152, 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 +[4, 1, 85, 540, 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, 8, 5, 8, 146, 8, 8, 10, 8, 12, 8, 149, 9, 8, 1, 8, 1, 8, 3, 8, 153, 8, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 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, 5, 23, 294, 8, 23, 10, 23, 12, 23, 297, 9, 23, 1, 23, 1, 23, 1, 23, 3, 23, 302, 8, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 3, 24, 309, 8, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 3, 25, 318, 8, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 3, 26, 327, 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, 341, 8, 28, 1, 29, 1, 29, 1, 29, 3, 29, 346, 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, 374, 8, 33, 1, 34, 1, 34, 1, 35, 1, 35, 3, 35, 380, 8, 35, 1, 36, 1, 36, 1, 36, 1, 36, 5, 36, 386, 8, 36, 10, 36, 12, 36, 389, 9, 36, 1, 36, 3, 36, 392, 8, 36, 3, 36, 394, 8, 36, 1, 36, 1, 36, 1, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 405, 8, 38, 10, 38, 12, 38, 408, 9, 38, 1, 38, 3, 38, 411, 8, 38, 3, 38, 413, 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, 426, 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, 452, 8, 39, 10, 39, 12, 39, 455, 9, 39, 1, 39, 3, 39, 458, 8, 39, 3, 39, 460, 8, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 466, 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, 518, 8, 39, 10, 39, 12, 39, 521, 9, 39, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 530, 8, 41, 1, 42, 1, 42, 3, 42, 534, 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, 17, 17, 65, 65, 1, 0, 72, 74, 2, 0, 72, 73, 80, 80, 574, 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, 156, 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, 301, 1, 0, 0, 0, 48, 308, 1, 0, 0, 0, 50, 310, 1, 0, 0, 0, 52, 321, 1, 0, 0, 0, 54, 330, 1, 0, 0, 0, 56, 333, 1, 0, 0, 0, 58, 345, 1, 0, 0, 0, 60, 347, 1, 0, 0, 0, 62, 355, 1, 0, 0, 0, 64, 361, 1, 0, 0, 0, 66, 373, 1, 0, 0, 0, 68, 375, 1, 0, 0, 0, 70, 379, 1, 0, 0, 0, 72, 381, 1, 0, 0, 0, 74, 397, 1, 0, 0, 0, 76, 400, 1, 0, 0, 0, 78, 465, 1, 0, 0, 0, 80, 522, 1, 0, 0, 0, 82, 529, 1, 0, 0, 0, 84, 531, 1, 0, 0, 0, 86, 535, 1, 0, 0, 0, 88, 537, 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, 16, 8, 0, 133, 136, 3, 18, 9, 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, 5, 12, 0, 0, 138, 139, 5, 82, 0, 0, 139, 152, 3, 26, 13, 0, 140, 141, 5, 13, 0, 0, 141, 142, 5, 14, 0, 0, 142, 147, 3, 86, 43, 0, 143, 144, 5, 15, 0, 0, 144, 146, 3, 86, 43, 0, 145, 143, 1, 0, 0, 0, 146, 149, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 147, 148, 1, 0, 0, 0, 148, 150, 1, 0, 0, 0, 149, 147, 1, 0, 0, 0, 150, 151, 5, 16, 0, 0, 151, 153, 1, 0, 0, 0, 152, 140, 1, 0, 0, 0, 152, 153, 1, 0, 0, 0, 153, 154, 1, 0, 0, 0, 154, 155, 3, 24, 12, 0, 155, 17, 1, 0, 0, 0, 156, 157, 3, 86, 43, 0, 157, 158, 5, 17, 0, 0, 158, 159, 5, 82, 0, 0, 159, 160, 5, 10, 0, 0, 160, 161, 3, 78, 39, 0, 161, 162, 5, 2, 0, 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, 12, 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, 14, 0, 0, 190, 195, 3, 28, 14, 0, 191, 192, 5, 15, 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, 15, 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, 16, 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, 15, 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, 15, 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, 14, 0, 0, 278, 281, 3, 46, 23, 0, 279, 280, 5, 15, 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, 16, 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, 295, 3, 86, 43, 0, 292, 294, 3, 80, 40, 0, 293, 292, 1, 0, 0, 0, 294, 297, 1, 0, 0, 0, 295, 293, 1, 0, 0, 0, 295, 296, 1, 0, 0, 0, 296, 298, 1, 0, 0, 0, 297, 295, 1, 0, 0, 0, 298, 299, 5, 82, 0, 0, 299, 302, 1, 0, 0, 0, 300, 302, 5, 82, 0, 0, 301, 291, 1, 0, 0, 0, 301, 300, 1, 0, 0, 0, 302, 47, 1, 0, 0, 0, 303, 304, 5, 82, 0, 0, 304, 305, 7, 1, 0, 0, 305, 309, 3, 78, 39, 0, 306, 307, 5, 82, 0, 0, 307, 309, 7, 2, 0, 0, 308, 303, 1, 0, 0, 0, 308, 306, 1, 0, 0, 0, 309, 49, 1, 0, 0, 0, 310, 311, 5, 26, 0, 0, 311, 312, 5, 14, 0, 0, 312, 313, 5, 79, 0, 0, 313, 314, 5, 6, 0, 0, 314, 317, 3, 78, 39, 0, 315, 316, 5, 15, 0, 0, 316, 318, 3, 68, 34, 0, 317, 315, 1, 0, 0, 0, 317, 318, 1, 0, 0, 0, 318, 319, 1, 0, 0, 0, 319, 320, 5, 16, 0, 0, 320, 51, 1, 0, 0, 0, 321, 322, 5, 26, 0, 0, 322, 323, 5, 14, 0, 0, 323, 326, 3, 78, 39, 0, 324, 325, 5, 15, 0, 0, 325, 327, 3, 68, 34, 0, 326, 324, 1, 0, 0, 0, 326, 327, 1, 0, 0, 0, 327, 328, 1, 0, 0, 0, 328, 329, 5, 16, 0, 0, 329, 53, 1, 0, 0, 0, 330, 331, 5, 27, 0, 0, 331, 332, 3, 72, 36, 0, 332, 55, 1, 0, 0, 0, 333, 334, 5, 28, 0, 0, 334, 335, 5, 14, 0, 0, 335, 336, 3, 78, 39, 0, 336, 337, 5, 16, 0, 0, 337, 340, 3, 30, 15, 0, 338, 339, 5, 29, 0, 0, 339, 341, 3, 30, 15, 0, 340, 338, 1, 0, 0, 0, 340, 341, 1, 0, 0, 0, 341, 57, 1, 0, 0, 0, 342, 346, 3, 60, 30, 0, 343, 346, 3, 62, 31, 0, 344, 346, 3, 64, 32, 0, 345, 342, 1, 0, 0, 0, 345, 343, 1, 0, 0, 0, 345, 344, 1, 0, 0, 0, 346, 59, 1, 0, 0, 0, 347, 348, 5, 30, 0, 0, 348, 349, 3, 30, 15, 0, 349, 350, 5, 31, 0, 0, 350, 351, 5, 14, 0, 0, 351, 352, 3, 78, 39, 0, 352, 353, 5, 16, 0, 0, 353, 354, 5, 2, 0, 0, 354, 61, 1, 0, 0, 0, 355, 356, 5, 31, 0, 0, 356, 357, 5, 14, 0, 0, 357, 358, 3, 78, 39, 0, 358, 359, 5, 16, 0, 0, 359, 360, 3, 30, 15, 0, 360, 63, 1, 0, 0, 0, 361, 362, 5, 32, 0, 0, 362, 363, 5, 14, 0, 0, 363, 364, 3, 66, 33, 0, 364, 365, 5, 2, 0, 0, 365, 366, 3, 78, 39, 0, 366, 367, 5, 2, 0, 0, 367, 368, 3, 48, 24, 0, 368, 369, 5, 16, 0, 0, 369, 370, 3, 30, 15, 0, 370, 65, 1, 0, 0, 0, 371, 374, 3, 42, 21, 0, 372, 374, 3, 48, 24, 0, 373, 371, 1, 0, 0, 0, 373, 372, 1, 0, 0, 0, 374, 67, 1, 0, 0, 0, 375, 376, 5, 76, 0, 0, 376, 69, 1, 0, 0, 0, 377, 380, 5, 82, 0, 0, 378, 380, 3, 82, 41, 0, 379, 377, 1, 0, 0, 0, 379, 378, 1, 0, 0, 0, 380, 71, 1, 0, 0, 0, 381, 393, 5, 14, 0, 0, 382, 387, 3, 70, 35, 0, 383, 384, 5, 15, 0, 0, 384, 386, 3, 70, 35, 0, 385, 383, 1, 0, 0, 0, 386, 389, 1, 0, 0, 0, 387, 385, 1, 0, 0, 0, 387, 388, 1, 0, 0, 0, 388, 391, 1, 0, 0, 0, 389, 387, 1, 0, 0, 0, 390, 392, 5, 15, 0, 0, 391, 390, 1, 0, 0, 0, 391, 392, 1, 0, 0, 0, 392, 394, 1, 0, 0, 0, 393, 382, 1, 0, 0, 0, 393, 394, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 396, 5, 16, 0, 0, 396, 73, 1, 0, 0, 0, 397, 398, 5, 82, 0, 0, 398, 399, 3, 76, 38, 0, 399, 75, 1, 0, 0, 0, 400, 412, 5, 14, 0, 0, 401, 406, 3, 78, 39, 0, 402, 403, 5, 15, 0, 0, 403, 405, 3, 78, 39, 0, 404, 402, 1, 0, 0, 0, 405, 408, 1, 0, 0, 0, 406, 404, 1, 0, 0, 0, 406, 407, 1, 0, 0, 0, 407, 410, 1, 0, 0, 0, 408, 406, 1, 0, 0, 0, 409, 411, 5, 15, 0, 0, 410, 409, 1, 0, 0, 0, 410, 411, 1, 0, 0, 0, 411, 413, 1, 0, 0, 0, 412, 401, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 414, 1, 0, 0, 0, 414, 415, 5, 16, 0, 0, 415, 77, 1, 0, 0, 0, 416, 417, 6, 39, -1, 0, 417, 418, 5, 14, 0, 0, 418, 419, 3, 78, 39, 0, 419, 420, 5, 16, 0, 0, 420, 466, 1, 0, 0, 0, 421, 422, 3, 88, 44, 0, 422, 423, 5, 14, 0, 0, 423, 425, 3, 78, 39, 0, 424, 426, 5, 15, 0, 0, 425, 424, 1, 0, 0, 0, 425, 426, 1, 0, 0, 0, 426, 427, 1, 0, 0, 0, 427, 428, 5, 16, 0, 0, 428, 466, 1, 0, 0, 0, 429, 466, 3, 74, 37, 0, 430, 431, 5, 33, 0, 0, 431, 432, 5, 82, 0, 0, 432, 466, 3, 76, 38, 0, 433, 434, 5, 36, 0, 0, 434, 435, 5, 34, 0, 0, 435, 436, 3, 78, 39, 0, 436, 437, 5, 35, 0, 0, 437, 438, 7, 3, 0, 0, 438, 466, 1, 0, 0, 0, 439, 440, 5, 42, 0, 0, 440, 441, 5, 34, 0, 0, 441, 442, 3, 78, 39, 0, 442, 443, 5, 35, 0, 0, 443, 444, 7, 4, 0, 0, 444, 466, 1, 0, 0, 0, 445, 446, 7, 5, 0, 0, 446, 466, 3, 78, 39, 15, 447, 459, 5, 34, 0, 0, 448, 453, 3, 78, 39, 0, 449, 450, 5, 15, 0, 0, 450, 452, 3, 78, 39, 0, 451, 449, 1, 0, 0, 0, 452, 455, 1, 0, 0, 0, 453, 451, 1, 0, 0, 0, 453, 454, 1, 0, 0, 0, 454, 457, 1, 0, 0, 0, 455, 453, 1, 0, 0, 0, 456, 458, 5, 15, 0, 0, 457, 456, 1, 0, 0, 0, 457, 458, 1, 0, 0, 0, 458, 460, 1, 0, 0, 0, 459, 448, 1, 0, 0, 0, 459, 460, 1, 0, 0, 0, 460, 461, 1, 0, 0, 0, 461, 466, 5, 35, 0, 0, 462, 466, 5, 81, 0, 0, 463, 466, 5, 82, 0, 0, 464, 466, 3, 82, 41, 0, 465, 416, 1, 0, 0, 0, 465, 421, 1, 0, 0, 0, 465, 429, 1, 0, 0, 0, 465, 430, 1, 0, 0, 0, 465, 433, 1, 0, 0, 0, 465, 439, 1, 0, 0, 0, 465, 445, 1, 0, 0, 0, 465, 447, 1, 0, 0, 0, 465, 462, 1, 0, 0, 0, 465, 463, 1, 0, 0, 0, 465, 464, 1, 0, 0, 0, 466, 519, 1, 0, 0, 0, 467, 468, 10, 14, 0, 0, 468, 469, 7, 6, 0, 0, 469, 518, 3, 78, 39, 15, 470, 471, 10, 13, 0, 0, 471, 472, 7, 7, 0, 0, 472, 518, 3, 78, 39, 14, 473, 474, 10, 12, 0, 0, 474, 475, 7, 8, 0, 0, 475, 518, 3, 78, 39, 13, 476, 477, 10, 11, 0, 0, 477, 478, 7, 9, 0, 0, 478, 518, 3, 78, 39, 12, 479, 480, 10, 10, 0, 0, 480, 481, 7, 10, 0, 0, 481, 518, 3, 78, 39, 11, 482, 483, 10, 9, 0, 0, 483, 484, 5, 61, 0, 0, 484, 518, 3, 78, 39, 10, 485, 486, 10, 8, 0, 0, 486, 487, 5, 4, 0, 0, 487, 518, 3, 78, 39, 9, 488, 489, 10, 7, 0, 0, 489, 490, 5, 62, 0, 0, 490, 518, 3, 78, 39, 8, 491, 492, 10, 6, 0, 0, 492, 493, 5, 63, 0, 0, 493, 518, 3, 78, 39, 7, 494, 495, 10, 5, 0, 0, 495, 496, 5, 64, 0, 0, 496, 518, 3, 78, 39, 6, 497, 498, 10, 21, 0, 0, 498, 499, 5, 34, 0, 0, 499, 500, 5, 69, 0, 0, 500, 518, 5, 35, 0, 0, 501, 502, 10, 18, 0, 0, 502, 518, 7, 11, 0, 0, 503, 504, 10, 17, 0, 0, 504, 505, 5, 49, 0, 0, 505, 506, 5, 14, 0, 0, 506, 507, 3, 78, 39, 0, 507, 508, 5, 16, 0, 0, 508, 518, 1, 0, 0, 0, 509, 510, 10, 16, 0, 0, 510, 511, 5, 50, 0, 0, 511, 512, 5, 14, 0, 0, 512, 513, 3, 78, 39, 0, 513, 514, 5, 15, 0, 0, 514, 515, 3, 78, 39, 0, 515, 516, 5, 16, 0, 0, 516, 518, 1, 0, 0, 0, 517, 467, 1, 0, 0, 0, 517, 470, 1, 0, 0, 0, 517, 473, 1, 0, 0, 0, 517, 476, 1, 0, 0, 0, 517, 479, 1, 0, 0, 0, 517, 482, 1, 0, 0, 0, 517, 485, 1, 0, 0, 0, 517, 488, 1, 0, 0, 0, 517, 491, 1, 0, 0, 0, 517, 494, 1, 0, 0, 0, 517, 497, 1, 0, 0, 0, 517, 501, 1, 0, 0, 0, 517, 503, 1, 0, 0, 0, 517, 509, 1, 0, 0, 0, 518, 521, 1, 0, 0, 0, 519, 517, 1, 0, 0, 0, 519, 520, 1, 0, 0, 0, 520, 79, 1, 0, 0, 0, 521, 519, 1, 0, 0, 0, 522, 523, 7, 12, 0, 0, 523, 81, 1, 0, 0, 0, 524, 530, 5, 67, 0, 0, 525, 530, 3, 84, 42, 0, 526, 530, 5, 76, 0, 0, 527, 530, 5, 77, 0, 0, 528, 530, 5, 78, 0, 0, 529, 524, 1, 0, 0, 0, 529, 525, 1, 0, 0, 0, 529, 526, 1, 0, 0, 0, 529, 527, 1, 0, 0, 0, 529, 528, 1, 0, 0, 0, 530, 83, 1, 0, 0, 0, 531, 533, 5, 69, 0, 0, 532, 534, 5, 68, 0, 0, 533, 532, 1, 0, 0, 0, 533, 534, 1, 0, 0, 0, 534, 85, 1, 0, 0, 0, 535, 536, 7, 13, 0, 0, 536, 87, 1, 0, 0, 0, 537, 538, 7, 14, 0, 0, 538, 89, 1, 0, 0, 0, 48, 93, 99, 105, 119, 122, 135, 147, 152, 170, 184, 195, 199, 201, 209, 218, 223, 229, 239, 249, 254, 260, 272, 283, 289, 295, 301, 308, 317, 326, 340, 345, 373, 379, 387, 391, 393, 406, 410, 412, 425, 453, 457, 459, 465, 517, 519, 529, 533] \ No newline at end of file diff --git a/packages/cashc/src/grammar/CashScriptParser.ts b/packages/cashc/src/grammar/CashScriptParser.ts index d08aa12af..fae77537c 100644 --- a/packages/cashc/src/grammar/CashScriptParser.ts +++ b/packages/cashc/src/grammar/CashScriptParser.ts @@ -1360,8 +1360,9 @@ export default class CashScriptParser extends Parser { public tupleTarget(): TupleTargetContext { let localctx: TupleTargetContext = new TupleTargetContext(this, this._ctx, this.state); this.enterRule(localctx, 46, CashScriptParser.RULE_tupleTarget); + let _la: number; try { - this.state = 295; + this.state = 301; this._errHandler.sync(this); switch (this._input.LA(1)) { case 72: @@ -1371,14 +1372,28 @@ export default class CashScriptParser extends Parser { { this.state = 291; this.typeName(); - this.state = 292; + this.state = 295; + this._errHandler.sync(this); + _la = this._input.LA(1); + while (_la===17 || _la===65) { + { + { + this.state = 292; + this.modifier(); + } + } + this.state = 297; + this._errHandler.sync(this); + _la = this._input.LA(1); + } + this.state = 298; this.match(CashScriptParser.Identifier); } break; case 82: this.enterOuterAlt(localctx, 2); { - this.state = 294; + this.state = 300; this.match(CashScriptParser.Identifier); } break; @@ -1406,15 +1421,15 @@ export default class CashScriptParser extends Parser { this.enterRule(localctx, 48, CashScriptParser.RULE_assignStatement); let _la: number; try { - this.state = 302; + this.state = 308; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 25, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 26, this._ctx) ) { case 1: this.enterOuterAlt(localctx, 1); { - this.state = 297; + this.state = 303; this.match(CashScriptParser.Identifier); - this.state = 298; + this.state = 304; localctx._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 12583936) !== 0))) { @@ -1424,16 +1439,16 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 299; + this.state = 305; this.expression(0); } break; case 2: this.enterOuterAlt(localctx, 2); { - this.state = 300; + this.state = 306; this.match(CashScriptParser.Identifier); - this.state = 301; + this.state = 307; localctx._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===24 || _la===25)) { @@ -1469,29 +1484,29 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 304; + this.state = 310; this.match(CashScriptParser.T__25); - this.state = 305; + this.state = 311; this.match(CashScriptParser.T__13); - this.state = 306; + this.state = 312; this.match(CashScriptParser.TxVar); - this.state = 307; + this.state = 313; this.match(CashScriptParser.T__5); - this.state = 308; + this.state = 314; this.expression(0); - this.state = 311; + this.state = 317; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 309; + this.state = 315; this.match(CashScriptParser.T__14); - this.state = 310; + this.state = 316; this.requireMessage(); } } - this.state = 313; + this.state = 319; this.match(CashScriptParser.T__15); } } @@ -1517,25 +1532,25 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 315; + this.state = 321; this.match(CashScriptParser.T__25); - this.state = 316; + this.state = 322; this.match(CashScriptParser.T__13); - this.state = 317; + this.state = 323; this.expression(0); - this.state = 320; + this.state = 326; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 318; + this.state = 324; this.match(CashScriptParser.T__14); - this.state = 319; + this.state = 325; this.requireMessage(); } } - this.state = 322; + this.state = 328; this.match(CashScriptParser.T__15); } } @@ -1560,9 +1575,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 324; + this.state = 330; this.match(CashScriptParser.T__26); - this.state = 325; + this.state = 331; this.consoleParameterList(); } } @@ -1587,24 +1602,24 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 327; + this.state = 333; this.match(CashScriptParser.T__27); - this.state = 328; + this.state = 334; this.match(CashScriptParser.T__13); - this.state = 329; + this.state = 335; this.expression(0); - this.state = 330; + this.state = 336; this.match(CashScriptParser.T__15); - this.state = 331; + this.state = 337; localctx._ifBlock = this.block(); - this.state = 334; + this.state = 340; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 28, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 29, this._ctx) ) { case 1: { - this.state = 332; + this.state = 338; this.match(CashScriptParser.T__28); - this.state = 333; + this.state = 339; localctx._elseBlock = this.block(); } break; @@ -1630,27 +1645,27 @@ export default class CashScriptParser extends Parser { let localctx: LoopStatementContext = new LoopStatementContext(this, this._ctx, this.state); this.enterRule(localctx, 58, CashScriptParser.RULE_loopStatement); try { - this.state = 339; + this.state = 345; this._errHandler.sync(this); switch (this._input.LA(1)) { case 30: this.enterOuterAlt(localctx, 1); { - this.state = 336; + this.state = 342; this.doWhileStatement(); } break; case 31: this.enterOuterAlt(localctx, 2); { - this.state = 337; + this.state = 343; this.whileStatement(); } break; case 32: this.enterOuterAlt(localctx, 3); { - this.state = 338; + this.state = 344; this.forStatement(); } break; @@ -1679,19 +1694,19 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 341; + this.state = 347; this.match(CashScriptParser.T__29); - this.state = 342; + this.state = 348; this.block(); - this.state = 343; + this.state = 349; this.match(CashScriptParser.T__30); - this.state = 344; + this.state = 350; this.match(CashScriptParser.T__13); - this.state = 345; + this.state = 351; this.expression(0); - this.state = 346; + this.state = 352; this.match(CashScriptParser.T__15); - this.state = 347; + this.state = 353; this.match(CashScriptParser.T__1); } } @@ -1716,15 +1731,15 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 349; + this.state = 355; this.match(CashScriptParser.T__30); - this.state = 350; + this.state = 356; this.match(CashScriptParser.T__13); - this.state = 351; + this.state = 357; this.expression(0); - this.state = 352; + this.state = 358; this.match(CashScriptParser.T__15); - this.state = 353; + this.state = 359; this.block(); } } @@ -1749,23 +1764,23 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 355; + this.state = 361; this.match(CashScriptParser.T__31); - this.state = 356; + this.state = 362; this.match(CashScriptParser.T__13); - this.state = 357; + this.state = 363; this.forInit(); - this.state = 358; + this.state = 364; this.match(CashScriptParser.T__1); - this.state = 359; + this.state = 365; this.expression(0); - this.state = 360; + this.state = 366; this.match(CashScriptParser.T__1); - this.state = 361; + this.state = 367; this.assignStatement(); - this.state = 362; + this.state = 368; this.match(CashScriptParser.T__15); - this.state = 363; + this.state = 369; this.block(); } } @@ -1788,7 +1803,7 @@ export default class CashScriptParser extends Parser { let localctx: ForInitContext = new ForInitContext(this, this._ctx, this.state); this.enterRule(localctx, 66, CashScriptParser.RULE_forInit); try { - this.state = 367; + this.state = 373; this._errHandler.sync(this); switch (this._input.LA(1)) { case 72: @@ -1796,14 +1811,14 @@ export default class CashScriptParser extends Parser { case 74: this.enterOuterAlt(localctx, 1); { - this.state = 365; + this.state = 371; this.variableDefinition(); } break; case 82: this.enterOuterAlt(localctx, 2); { - this.state = 366; + this.state = 372; this.assignStatement(); } break; @@ -1832,7 +1847,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 369; + this.state = 375; this.match(CashScriptParser.StringLiteral); } } @@ -1855,13 +1870,13 @@ export default class CashScriptParser extends Parser { let localctx: ConsoleParameterContext = new ConsoleParameterContext(this, this._ctx, this.state); this.enterRule(localctx, 70, CashScriptParser.RULE_consoleParameter); try { - this.state = 373; + this.state = 379; this._errHandler.sync(this); switch (this._input.LA(1)) { case 82: this.enterOuterAlt(localctx, 1); { - this.state = 371; + this.state = 377; this.match(CashScriptParser.Identifier); } break; @@ -1872,7 +1887,7 @@ export default class CashScriptParser extends Parser { case 78: this.enterOuterAlt(localctx, 2); { - this.state = 372; + this.state = 378; this.literal(); } break; @@ -1903,39 +1918,39 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 375; + this.state = 381; this.match(CashScriptParser.T__13); - this.state = 387; + this.state = 393; this._errHandler.sync(this); _la = this._input.LA(1); if (((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 36357) !== 0)) { { - this.state = 376; + this.state = 382; this.consoleParameter(); - this.state = 381; + this.state = 387; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 33, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 377; + this.state = 383; this.match(CashScriptParser.T__14); - this.state = 378; + this.state = 384; this.consoleParameter(); } } } - this.state = 383; + this.state = 389; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 32, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 33, this._ctx); } - this.state = 385; + this.state = 391; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 384; + this.state = 390; this.match(CashScriptParser.T__14); } } @@ -1943,7 +1958,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 389; + this.state = 395; this.match(CashScriptParser.T__15); } } @@ -1968,9 +1983,9 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 391; + this.state = 397; this.match(CashScriptParser.Identifier); - this.state = 392; + this.state = 398; this.expressionList(); } } @@ -1997,39 +2012,39 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 394; + this.state = 400; this.match(CashScriptParser.T__13); - this.state = 406; + this.state = 412; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===5 || _la===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 61029) !== 0)) { { - this.state = 395; + this.state = 401; this.expression(0); - this.state = 400; + this.state = 406; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 36, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 396; + this.state = 402; this.match(CashScriptParser.T__14); - this.state = 397; + this.state = 403; this.expression(0); } } } - this.state = 402; + this.state = 408; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 35, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 36, this._ctx); } - this.state = 404; + this.state = 410; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 403; + this.state = 409; this.match(CashScriptParser.T__14); } } @@ -2037,7 +2052,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 408; + this.state = 414; this.match(CashScriptParser.T__15); } } @@ -2075,20 +2090,20 @@ export default class CashScriptParser extends Parser { let _alt: number; this.enterOuterAlt(localctx, 1); { - this.state = 459; + this.state = 465; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 42, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 43, this._ctx) ) { case 1: { localctx = new ParenthesisedContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 411; + this.state = 417; this.match(CashScriptParser.T__13); - this.state = 412; + this.state = 418; this.expression(0); - this.state = 413; + this.state = 419; this.match(CashScriptParser.T__15); } break; @@ -2097,23 +2112,23 @@ export default class CashScriptParser extends Parser { localctx = new CastContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 415; + this.state = 421; this.typeCast(); - this.state = 416; + this.state = 422; this.match(CashScriptParser.T__13); - this.state = 417; + this.state = 423; (localctx as CastContext)._castable = this.expression(0); - this.state = 419; + this.state = 425; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 418; + this.state = 424; this.match(CashScriptParser.T__14); } } - this.state = 421; + this.state = 427; this.match(CashScriptParser.T__15); } break; @@ -2122,7 +2137,7 @@ export default class CashScriptParser extends Parser { localctx = new FunctionCallExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 423; + this.state = 429; this.functionCall(); } break; @@ -2131,11 +2146,11 @@ export default class CashScriptParser extends Parser { localctx = new InstantiationContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 424; + this.state = 430; this.match(CashScriptParser.T__32); - this.state = 425; + this.state = 431; this.match(CashScriptParser.Identifier); - this.state = 426; + this.state = 432; this.expressionList(); } break; @@ -2144,15 +2159,15 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 427; + this.state = 433; (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__35); - this.state = 428; + this.state = 434; this.match(CashScriptParser.T__33); - this.state = 429; + this.state = 435; this.expression(0); - this.state = 430; + this.state = 436; this.match(CashScriptParser.T__34); - this.state = 431; + this.state = 437; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 37)) & ~0x1F) === 0 && ((1 << (_la - 37)) & 31) !== 0))) { @@ -2169,15 +2184,15 @@ export default class CashScriptParser extends Parser { localctx = new UnaryIntrospectionOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 433; + this.state = 439; (localctx as UnaryIntrospectionOpContext)._scope = this.match(CashScriptParser.T__41); - this.state = 434; + this.state = 440; this.match(CashScriptParser.T__33); - this.state = 435; + this.state = 441; this.expression(0); - this.state = 436; + this.state = 442; this.match(CashScriptParser.T__34); - this.state = 437; + this.state = 443; (localctx as UnaryIntrospectionOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 37)) & ~0x1F) === 0 && ((1 << (_la - 37)) & 991) !== 0))) { @@ -2194,7 +2209,7 @@ export default class CashScriptParser extends Parser { localctx = new UnaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 439; + this.state = 445; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===5 || _la===51 || _la===52)) { @@ -2204,7 +2219,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 440; + this.state = 446; this.expression(15); } break; @@ -2213,39 +2228,39 @@ export default class CashScriptParser extends Parser { localctx = new ArrayContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 441; + this.state = 447; this.match(CashScriptParser.T__33); - this.state = 453; + this.state = 459; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===5 || _la===14 || ((((_la - 33)) & ~0x1F) === 0 && ((1 << (_la - 33)) & 786955) !== 0) || ((((_la - 67)) & ~0x1F) === 0 && ((1 << (_la - 67)) & 61029) !== 0)) { { - this.state = 442; + this.state = 448; this.expression(0); - this.state = 447; + this.state = 453; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { { { - this.state = 443; + this.state = 449; this.match(CashScriptParser.T__14); - this.state = 444; + this.state = 450; this.expression(0); } } } - this.state = 449; + this.state = 455; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 39, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 40, this._ctx); } - this.state = 451; + this.state = 457; this._errHandler.sync(this); _la = this._input.LA(1); if (_la===15) { { - this.state = 450; + this.state = 456; this.match(CashScriptParser.T__14); } } @@ -2253,7 +2268,7 @@ export default class CashScriptParser extends Parser { } } - this.state = 455; + this.state = 461; this.match(CashScriptParser.T__34); } break; @@ -2262,7 +2277,7 @@ export default class CashScriptParser extends Parser { localctx = new NullaryOpContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 456; + this.state = 462; this.match(CashScriptParser.NullaryOp); } break; @@ -2271,7 +2286,7 @@ export default class CashScriptParser extends Parser { localctx = new IdentifierContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 457; + this.state = 463; this.match(CashScriptParser.Identifier); } break; @@ -2280,15 +2295,15 @@ export default class CashScriptParser extends Parser { localctx = new LiteralExpressionContext(this, localctx); this._ctx = localctx; _prevctx = localctx; - this.state = 458; + this.state = 464; this.literal(); } break; } this._ctx.stop = this._input.LT(-1); - this.state = 513; + this.state = 519; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 45, this._ctx); while (_alt !== 2 && _alt !== ATN.INVALID_ALT_NUMBER) { if (_alt === 1) { if (this._parseListeners != null) { @@ -2296,19 +2311,19 @@ export default class CashScriptParser extends Parser { } _prevctx = localctx; { - this.state = 511; + this.state = 517; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 43, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 44, 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 = 461; + this.state = 467; if (!(this.precpred(this._ctx, 14))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 14)"); } - this.state = 462; + this.state = 468; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(((((_la - 53)) & ~0x1F) === 0 && ((1 << (_la - 53)) & 7) !== 0))) { @@ -2318,7 +2333,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 463; + this.state = 469; (localctx as BinaryOpContext)._right = this.expression(15); } break; @@ -2327,11 +2342,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 = 464; + this.state = 470; if (!(this.precpred(this._ctx, 13))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 13)"); } - this.state = 465; + this.state = 471; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===52 || _la===56)) { @@ -2341,7 +2356,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 466; + this.state = 472; (localctx as BinaryOpContext)._right = this.expression(14); } break; @@ -2350,11 +2365,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 = 467; + this.state = 473; if (!(this.precpred(this._ctx, 12))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 12)"); } - this.state = 468; + this.state = 474; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===57 || _la===58)) { @@ -2364,7 +2379,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 469; + this.state = 475; (localctx as BinaryOpContext)._right = this.expression(13); } break; @@ -2373,11 +2388,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 = 470; + this.state = 476; if (!(this.precpred(this._ctx, 11))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 11)"); } - this.state = 471; + this.state = 477; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!((((_la) & ~0x1F) === 0 && ((1 << _la) & 960) !== 0))) { @@ -2387,7 +2402,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 472; + this.state = 478; (localctx as BinaryOpContext)._right = this.expression(12); } break; @@ -2396,11 +2411,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 = 473; + this.state = 479; if (!(this.precpred(this._ctx, 10))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 10)"); } - this.state = 474; + this.state = 480; (localctx as BinaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===59 || _la===60)) { @@ -2410,7 +2425,7 @@ export default class CashScriptParser extends Parser { this._errHandler.reportMatch(this); this.consume(); } - this.state = 475; + this.state = 481; (localctx as BinaryOpContext)._right = this.expression(11); } break; @@ -2419,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 = 476; + this.state = 482; if (!(this.precpred(this._ctx, 9))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 9)"); } - this.state = 477; + this.state = 483; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__60); - this.state = 478; + this.state = 484; (localctx as BinaryOpContext)._right = this.expression(10); } break; @@ -2434,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 = 479; + this.state = 485; if (!(this.precpred(this._ctx, 8))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 8)"); } - this.state = 480; + this.state = 486; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__3); - this.state = 481; + this.state = 487; (localctx as BinaryOpContext)._right = this.expression(9); } break; @@ -2449,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 = 482; + this.state = 488; if (!(this.precpred(this._ctx, 7))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 7)"); } - this.state = 483; + this.state = 489; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__61); - this.state = 484; + this.state = 490; (localctx as BinaryOpContext)._right = this.expression(8); } break; @@ -2464,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 = 485; + this.state = 491; if (!(this.precpred(this._ctx, 6))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 6)"); } - this.state = 486; + this.state = 492; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__62); - this.state = 487; + this.state = 493; (localctx as BinaryOpContext)._right = this.expression(7); } break; @@ -2479,13 +2494,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 = 488; + this.state = 494; if (!(this.precpred(this._ctx, 5))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 5)"); } - this.state = 489; + this.state = 495; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__63); - this.state = 490; + this.state = 496; (localctx as BinaryOpContext)._right = this.expression(6); } break; @@ -2493,15 +2508,15 @@ export default class CashScriptParser extends Parser { { localctx = new TupleIndexOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 491; + this.state = 497; if (!(this.precpred(this._ctx, 21))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 21)"); } - this.state = 492; + this.state = 498; this.match(CashScriptParser.T__33); - this.state = 493; + this.state = 499; (localctx as TupleIndexOpContext)._index = this.match(CashScriptParser.NumberLiteral); - this.state = 494; + this.state = 500; this.match(CashScriptParser.T__34); } break; @@ -2509,11 +2524,11 @@ export default class CashScriptParser extends Parser { { localctx = new UnaryOpContext(this, new ExpressionContext(this, _parentctx, _parentState)); this.pushNewRecursionContext(localctx, _startState, CashScriptParser.RULE_expression); - this.state = 495; + this.state = 501; if (!(this.precpred(this._ctx, 18))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 18)"); } - this.state = 496; + this.state = 502; (localctx as UnaryOpContext)._op = this._input.LT(1); _la = this._input.LA(1); if(!(_la===47 || _la===48)) { @@ -2530,17 +2545,17 @@ 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 = 497; + this.state = 503; if (!(this.precpred(this._ctx, 17))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 17)"); } - this.state = 498; + this.state = 504; (localctx as BinaryOpContext)._op = this.match(CashScriptParser.T__48); - this.state = 499; + this.state = 505; this.match(CashScriptParser.T__13); - this.state = 500; + this.state = 506; (localctx as BinaryOpContext)._right = this.expression(0); - this.state = 501; + this.state = 507; this.match(CashScriptParser.T__15); } break; @@ -2549,30 +2564,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 = 503; + this.state = 509; if (!(this.precpred(this._ctx, 16))) { throw this.createFailedPredicateException("this.precpred(this._ctx, 16)"); } - this.state = 504; + this.state = 510; this.match(CashScriptParser.T__49); - this.state = 505; + this.state = 511; this.match(CashScriptParser.T__13); - this.state = 506; + this.state = 512; (localctx as SliceContext)._start = this.expression(0); - this.state = 507; + this.state = 513; this.match(CashScriptParser.T__14); - this.state = 508; + this.state = 514; (localctx as SliceContext)._end = this.expression(0); - this.state = 509; + this.state = 515; this.match(CashScriptParser.T__15); } break; } } } - this.state = 515; + this.state = 521; this._errHandler.sync(this); - _alt = this._interp.adaptivePredict(this._input, 44, this._ctx); + _alt = this._interp.adaptivePredict(this._input, 45, this._ctx); } } } @@ -2598,7 +2613,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 516; + this.state = 522; _la = this._input.LA(1); if(!(_la===17 || _la===65)) { this._errHandler.recoverInline(this); @@ -2628,41 +2643,41 @@ export default class CashScriptParser extends Parser { let localctx: LiteralContext = new LiteralContext(this, this._ctx, this.state); this.enterRule(localctx, 82, CashScriptParser.RULE_literal); try { - this.state = 523; + this.state = 529; this._errHandler.sync(this); switch (this._input.LA(1)) { case 67: this.enterOuterAlt(localctx, 1); { - this.state = 518; + this.state = 524; this.match(CashScriptParser.BooleanLiteral); } break; case 69: this.enterOuterAlt(localctx, 2); { - this.state = 519; + this.state = 525; this.numberLiteral(); } break; case 76: this.enterOuterAlt(localctx, 3); { - this.state = 520; + this.state = 526; this.match(CashScriptParser.StringLiteral); } break; case 77: this.enterOuterAlt(localctx, 4); { - this.state = 521; + this.state = 527; this.match(CashScriptParser.DateLiteral); } break; case 78: this.enterOuterAlt(localctx, 5); { - this.state = 522; + this.state = 528; this.match(CashScriptParser.HexLiteral); } break; @@ -2691,14 +2706,14 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 525; + this.state = 531; this.match(CashScriptParser.NumberLiteral); - this.state = 527; + this.state = 533; this._errHandler.sync(this); - switch ( this._interp.adaptivePredict(this._input, 46, this._ctx) ) { + switch ( this._interp.adaptivePredict(this._input, 47, this._ctx) ) { case 1: { - this.state = 526; + this.state = 532; this.match(CashScriptParser.NumberUnit); } break; @@ -2727,7 +2742,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 529; + this.state = 535; _la = this._input.LA(1); if(!(((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 7) !== 0))) { this._errHandler.recoverInline(this); @@ -2760,7 +2775,7 @@ export default class CashScriptParser extends Parser { try { this.enterOuterAlt(localctx, 1); { - this.state = 531; + this.state = 537; _la = this._input.LA(1); if(!(((((_la - 72)) & ~0x1F) === 0 && ((1 << (_la - 72)) & 259) !== 0))) { this._errHandler.recoverInline(this); @@ -2827,7 +2842,7 @@ export default class CashScriptParser extends Parser { return true; } - public static readonly _serializedATN: number[] = [4,1,85,534,2,0,7,0,2, + public static readonly _serializedATN: number[] = [4,1,85,540,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, @@ -2849,161 +2864,163 @@ export default class CashScriptParser extends Parser { 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, + 290,8,22,1,23,1,23,5,23,294,8,23,10,23,12,23,297,9,23,1,23,1,23,1,23,3, + 23,302,8,23,1,24,1,24,1,24,1,24,1,24,3,24,309,8,24,1,25,1,25,1,25,1,25, + 1,25,1,25,1,25,3,25,318,8,25,1,25,1,25,1,26,1,26,1,26,1,26,1,26,3,26,327, + 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,341, + 8,28,1,29,1,29,1,29,3,29,346,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,374,8,33,1,34,1,34,1,35,1,35,3,35,380,8,35,1,36, + 1,36,1,36,1,36,5,36,386,8,36,10,36,12,36,389,9,36,1,36,3,36,392,8,36,3, + 36,394,8,36,1,36,1,36,1,37,1,37,1,37,1,38,1,38,1,38,1,38,5,38,405,8,38, + 10,38,12,38,408,9,38,1,38,3,38,411,8,38,3,38,413,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,426,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,452,8,39,10,39,12,39,455,9,39,1,39,3,39, + 458,8,39,3,39,460,8,39,1,39,1,39,1,39,1,39,3,39,466,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,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,17,17,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,156,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,16,8,0,133,136,3, - 18,9,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,5,12,0,0,138,139,5,82,0,0,139,152,3,26,13,0,140, - 141,5,13,0,0,141,142,5,14,0,0,142,147,3,86,43,0,143,144,5,15,0,0,144,146, - 3,86,43,0,145,143,1,0,0,0,146,149,1,0,0,0,147,145,1,0,0,0,147,148,1,0,0, - 0,148,150,1,0,0,0,149,147,1,0,0,0,150,151,5,16,0,0,151,153,1,0,0,0,152, - 140,1,0,0,0,152,153,1,0,0,0,153,154,1,0,0,0,154,155,3,24,12,0,155,17,1, - 0,0,0,156,157,3,86,43,0,157,158,5,17,0,0,158,159,5,82,0,0,159,160,5,10, - 0,0,160,161,3,78,39,0,161,162,5,2,0,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,12,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,14,0,0,190,195,3,28,14,0,191,192,5,15,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,15,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,16,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,15,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,15,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,14,0,0,278,281,3,46,23,0,279, - 280,5,15,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,16,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,14, - 0,0,306,307,5,79,0,0,307,308,5,6,0,0,308,311,3,78,39,0,309,310,5,15,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,16,0,0,314,51,1,0,0,0,315,316,5,26,0,0,316,317,5,14,0,0,317,320,3,78, - 39,0,318,319,5,15,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,16,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,14,0,0,329,330,3,78, - 39,0,330,331,5,16,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,14,0,0,345,346,3,78,39,0,346,347,5,16,0,0,347,348,5,2,0,0, - 348,61,1,0,0,0,349,350,5,31,0,0,350,351,5,14,0,0,351,352,3,78,39,0,352, - 353,5,16,0,0,353,354,3,30,15,0,354,63,1,0,0,0,355,356,5,32,0,0,356,357, - 5,14,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,16,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,14,0,0,376, - 381,3,70,35,0,377,378,5,15,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,15,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,16,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,14,0,0,395, - 400,3,78,39,0,396,397,5,15,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,15,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,16,0,0,409,77,1,0,0,0, - 410,411,6,39,-1,0,411,412,5,14,0,0,412,413,3,78,39,0,413,414,5,16,0,0,414, - 460,1,0,0,0,415,416,3,88,44,0,416,417,5,14,0,0,417,419,3,78,39,0,418,420, - 5,15,0,0,419,418,1,0,0,0,419,420,1,0,0,0,420,421,1,0,0,0,421,422,5,16,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,15,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,15,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,14,0,0,500,501,3,78,39,0,501,502,5,16,0,0,502, - 512,1,0,0,0,503,504,10,16,0,0,504,505,5,50,0,0,505,506,5,14,0,0,506,507, - 3,78,39,0,507,508,5,15,0,0,508,509,3,78,39,0,509,510,5,16,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,147,152,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]; + 39,1,39,1,39,1,39,5,39,518,8,39,10,39,12,39,521,9,39,1,40,1,40,1,41,1,41, + 1,41,1,41,1,41,3,41,530,8,41,1,42,1,42,3,42,534,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,17,17,65,65,1,0,72,74,2,0,72,73,80,80,574,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,156,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,301,1,0,0,0,48,308,1,0,0,0,50,310,1,0,0,0, + 52,321,1,0,0,0,54,330,1,0,0,0,56,333,1,0,0,0,58,345,1,0,0,0,60,347,1,0, + 0,0,62,355,1,0,0,0,64,361,1,0,0,0,66,373,1,0,0,0,68,375,1,0,0,0,70,379, + 1,0,0,0,72,381,1,0,0,0,74,397,1,0,0,0,76,400,1,0,0,0,78,465,1,0,0,0,80, + 522,1,0,0,0,82,529,1,0,0,0,84,531,1,0,0,0,86,535,1,0,0,0,88,537,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,16,8,0,133,136,3,18,9,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,5,12,0,0,138,139,5,82, + 0,0,139,152,3,26,13,0,140,141,5,13,0,0,141,142,5,14,0,0,142,147,3,86,43, + 0,143,144,5,15,0,0,144,146,3,86,43,0,145,143,1,0,0,0,146,149,1,0,0,0,147, + 145,1,0,0,0,147,148,1,0,0,0,148,150,1,0,0,0,149,147,1,0,0,0,150,151,5,16, + 0,0,151,153,1,0,0,0,152,140,1,0,0,0,152,153,1,0,0,0,153,154,1,0,0,0,154, + 155,3,24,12,0,155,17,1,0,0,0,156,157,3,86,43,0,157,158,5,17,0,0,158,159, + 5,82,0,0,159,160,5,10,0,0,160,161,3,78,39,0,161,162,5,2,0,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,12,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,14,0,0,190,195,3,28,14,0, + 191,192,5,15,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,15, + 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,16,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,15,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,15,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,14, + 0,0,278,281,3,46,23,0,279,280,5,15,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,16,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,295,3,86,43,0,292,294,3,80,40,0, + 293,292,1,0,0,0,294,297,1,0,0,0,295,293,1,0,0,0,295,296,1,0,0,0,296,298, + 1,0,0,0,297,295,1,0,0,0,298,299,5,82,0,0,299,302,1,0,0,0,300,302,5,82,0, + 0,301,291,1,0,0,0,301,300,1,0,0,0,302,47,1,0,0,0,303,304,5,82,0,0,304,305, + 7,1,0,0,305,309,3,78,39,0,306,307,5,82,0,0,307,309,7,2,0,0,308,303,1,0, + 0,0,308,306,1,0,0,0,309,49,1,0,0,0,310,311,5,26,0,0,311,312,5,14,0,0,312, + 313,5,79,0,0,313,314,5,6,0,0,314,317,3,78,39,0,315,316,5,15,0,0,316,318, + 3,68,34,0,317,315,1,0,0,0,317,318,1,0,0,0,318,319,1,0,0,0,319,320,5,16, + 0,0,320,51,1,0,0,0,321,322,5,26,0,0,322,323,5,14,0,0,323,326,3,78,39,0, + 324,325,5,15,0,0,325,327,3,68,34,0,326,324,1,0,0,0,326,327,1,0,0,0,327, + 328,1,0,0,0,328,329,5,16,0,0,329,53,1,0,0,0,330,331,5,27,0,0,331,332,3, + 72,36,0,332,55,1,0,0,0,333,334,5,28,0,0,334,335,5,14,0,0,335,336,3,78,39, + 0,336,337,5,16,0,0,337,340,3,30,15,0,338,339,5,29,0,0,339,341,3,30,15,0, + 340,338,1,0,0,0,340,341,1,0,0,0,341,57,1,0,0,0,342,346,3,60,30,0,343,346, + 3,62,31,0,344,346,3,64,32,0,345,342,1,0,0,0,345,343,1,0,0,0,345,344,1,0, + 0,0,346,59,1,0,0,0,347,348,5,30,0,0,348,349,3,30,15,0,349,350,5,31,0,0, + 350,351,5,14,0,0,351,352,3,78,39,0,352,353,5,16,0,0,353,354,5,2,0,0,354, + 61,1,0,0,0,355,356,5,31,0,0,356,357,5,14,0,0,357,358,3,78,39,0,358,359, + 5,16,0,0,359,360,3,30,15,0,360,63,1,0,0,0,361,362,5,32,0,0,362,363,5,14, + 0,0,363,364,3,66,33,0,364,365,5,2,0,0,365,366,3,78,39,0,366,367,5,2,0,0, + 367,368,3,48,24,0,368,369,5,16,0,0,369,370,3,30,15,0,370,65,1,0,0,0,371, + 374,3,42,21,0,372,374,3,48,24,0,373,371,1,0,0,0,373,372,1,0,0,0,374,67, + 1,0,0,0,375,376,5,76,0,0,376,69,1,0,0,0,377,380,5,82,0,0,378,380,3,82,41, + 0,379,377,1,0,0,0,379,378,1,0,0,0,380,71,1,0,0,0,381,393,5,14,0,0,382,387, + 3,70,35,0,383,384,5,15,0,0,384,386,3,70,35,0,385,383,1,0,0,0,386,389,1, + 0,0,0,387,385,1,0,0,0,387,388,1,0,0,0,388,391,1,0,0,0,389,387,1,0,0,0,390, + 392,5,15,0,0,391,390,1,0,0,0,391,392,1,0,0,0,392,394,1,0,0,0,393,382,1, + 0,0,0,393,394,1,0,0,0,394,395,1,0,0,0,395,396,5,16,0,0,396,73,1,0,0,0,397, + 398,5,82,0,0,398,399,3,76,38,0,399,75,1,0,0,0,400,412,5,14,0,0,401,406, + 3,78,39,0,402,403,5,15,0,0,403,405,3,78,39,0,404,402,1,0,0,0,405,408,1, + 0,0,0,406,404,1,0,0,0,406,407,1,0,0,0,407,410,1,0,0,0,408,406,1,0,0,0,409, + 411,5,15,0,0,410,409,1,0,0,0,410,411,1,0,0,0,411,413,1,0,0,0,412,401,1, + 0,0,0,412,413,1,0,0,0,413,414,1,0,0,0,414,415,5,16,0,0,415,77,1,0,0,0,416, + 417,6,39,-1,0,417,418,5,14,0,0,418,419,3,78,39,0,419,420,5,16,0,0,420,466, + 1,0,0,0,421,422,3,88,44,0,422,423,5,14,0,0,423,425,3,78,39,0,424,426,5, + 15,0,0,425,424,1,0,0,0,425,426,1,0,0,0,426,427,1,0,0,0,427,428,5,16,0,0, + 428,466,1,0,0,0,429,466,3,74,37,0,430,431,5,33,0,0,431,432,5,82,0,0,432, + 466,3,76,38,0,433,434,5,36,0,0,434,435,5,34,0,0,435,436,3,78,39,0,436,437, + 5,35,0,0,437,438,7,3,0,0,438,466,1,0,0,0,439,440,5,42,0,0,440,441,5,34, + 0,0,441,442,3,78,39,0,442,443,5,35,0,0,443,444,7,4,0,0,444,466,1,0,0,0, + 445,446,7,5,0,0,446,466,3,78,39,15,447,459,5,34,0,0,448,453,3,78,39,0,449, + 450,5,15,0,0,450,452,3,78,39,0,451,449,1,0,0,0,452,455,1,0,0,0,453,451, + 1,0,0,0,453,454,1,0,0,0,454,457,1,0,0,0,455,453,1,0,0,0,456,458,5,15,0, + 0,457,456,1,0,0,0,457,458,1,0,0,0,458,460,1,0,0,0,459,448,1,0,0,0,459,460, + 1,0,0,0,460,461,1,0,0,0,461,466,5,35,0,0,462,466,5,81,0,0,463,466,5,82, + 0,0,464,466,3,82,41,0,465,416,1,0,0,0,465,421,1,0,0,0,465,429,1,0,0,0,465, + 430,1,0,0,0,465,433,1,0,0,0,465,439,1,0,0,0,465,445,1,0,0,0,465,447,1,0, + 0,0,465,462,1,0,0,0,465,463,1,0,0,0,465,464,1,0,0,0,466,519,1,0,0,0,467, + 468,10,14,0,0,468,469,7,6,0,0,469,518,3,78,39,15,470,471,10,13,0,0,471, + 472,7,7,0,0,472,518,3,78,39,14,473,474,10,12,0,0,474,475,7,8,0,0,475,518, + 3,78,39,13,476,477,10,11,0,0,477,478,7,9,0,0,478,518,3,78,39,12,479,480, + 10,10,0,0,480,481,7,10,0,0,481,518,3,78,39,11,482,483,10,9,0,0,483,484, + 5,61,0,0,484,518,3,78,39,10,485,486,10,8,0,0,486,487,5,4,0,0,487,518,3, + 78,39,9,488,489,10,7,0,0,489,490,5,62,0,0,490,518,3,78,39,8,491,492,10, + 6,0,0,492,493,5,63,0,0,493,518,3,78,39,7,494,495,10,5,0,0,495,496,5,64, + 0,0,496,518,3,78,39,6,497,498,10,21,0,0,498,499,5,34,0,0,499,500,5,69,0, + 0,500,518,5,35,0,0,501,502,10,18,0,0,502,518,7,11,0,0,503,504,10,17,0,0, + 504,505,5,49,0,0,505,506,5,14,0,0,506,507,3,78,39,0,507,508,5,16,0,0,508, + 518,1,0,0,0,509,510,10,16,0,0,510,511,5,50,0,0,511,512,5,14,0,0,512,513, + 3,78,39,0,513,514,5,15,0,0,514,515,3,78,39,0,515,516,5,16,0,0,516,518,1, + 0,0,0,517,467,1,0,0,0,517,470,1,0,0,0,517,473,1,0,0,0,517,476,1,0,0,0,517, + 479,1,0,0,0,517,482,1,0,0,0,517,485,1,0,0,0,517,488,1,0,0,0,517,491,1,0, + 0,0,517,494,1,0,0,0,517,497,1,0,0,0,517,501,1,0,0,0,517,503,1,0,0,0,517, + 509,1,0,0,0,518,521,1,0,0,0,519,517,1,0,0,0,519,520,1,0,0,0,520,79,1,0, + 0,0,521,519,1,0,0,0,522,523,7,12,0,0,523,81,1,0,0,0,524,530,5,67,0,0,525, + 530,3,84,42,0,526,530,5,76,0,0,527,530,5,77,0,0,528,530,5,78,0,0,529,524, + 1,0,0,0,529,525,1,0,0,0,529,526,1,0,0,0,529,527,1,0,0,0,529,528,1,0,0,0, + 530,83,1,0,0,0,531,533,5,69,0,0,532,534,5,68,0,0,533,532,1,0,0,0,533,534, + 1,0,0,0,534,85,1,0,0,0,535,536,7,13,0,0,536,87,1,0,0,0,537,538,7,14,0,0, + 538,89,1,0,0,0,48,93,99,105,119,122,135,147,152,170,184,195,199,201,209, + 218,223,229,239,249,254,260,272,283,289,295,301,308,317,326,340,345,373, + 379,387,391,393,406,410,412,425,453,457,459,465,517,519,529,533]; private static __ATN: ATN; public static get _ATN(): ATN { @@ -3662,6 +3679,12 @@ export class TupleTargetContext 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_tupleTarget; } diff --git a/packages/cashc/src/print/OutputSourceCodeTraversal.ts b/packages/cashc/src/print/OutputSourceCodeTraversal.ts index 851ae88ec..cdf7fead6 100644 --- a/packages/cashc/src/print/OutputSourceCodeTraversal.ts +++ b/packages/cashc/src/print/OutputSourceCodeTraversal.ts @@ -142,7 +142,11 @@ export default class OutputSourceCodeTraversal extends AstTraversal { visitTupleAssignment(node: TupleAssignmentNode): Node { const targets = node.targets - .map((target) => (target.isReassignment ? target.identifier.name : `${target.type} ${target.identifier.name}`)) + .map((target) => { + if (target.isReassignment) return target.identifier.name; + const modifiers = target.modifiers.length > 0 ? `${target.modifiers.join(' ')} ` : ''; + return `${target.type} ${modifiers}${target.identifier.name}`; + }) .join(', '); this.addOutput(`${targets} = `, true); this.visit(node.tuple); diff --git a/packages/cashc/src/semantic/SymbolTableTraversal.ts b/packages/cashc/src/semantic/SymbolTableTraversal.ts index b27b2ebf9..2dc708379 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -199,6 +199,8 @@ export default class SymbolTableTraversal extends AstTraversal { throw new RedefinitionError(definition, target.identifier.name); } + validateModifiers(definition, definition.modifiers, [Modifier.CONSTANT, Modifier.UNUSED]); + this.symbolTables[0].set(Symbol.variable(definition)); } }); @@ -289,7 +291,7 @@ function createTupleVariableDefinition( node: TupleAssignmentNode, target: TupleAssignmentTarget, ): VariableDefinitionNode { - const definition = new VariableDefinitionNode(target.type!, [], target.identifier.name, node.tuple); + const definition = new VariableDefinitionNode(target.type!, target.modifiers, target.identifier.name, node.tuple); definition.location = node.location; return definition; } diff --git a/packages/cashc/test/ast/fixtures.ts b/packages/cashc/test/ast/fixtures.ts index d3468bd9b..e31b273cd 100644 --- a/packages/cashc/test/ast/fixtures.ts +++ b/packages/cashc/test/ast/fixtures.ts @@ -367,8 +367,8 @@ export const fixtures: Fixture[] = [ new BlockNode([ new TupleAssignmentNode( [ - { identifier: new IdentifierNode('blockHeightBin'), type: new BytesType(4) }, - { identifier: new IdentifierNode('priceBin'), type: new BytesType(4) }, + { identifier: new IdentifierNode('blockHeightBin'), type: new BytesType(4), modifiers: [] }, + { identifier: new IdentifierNode('priceBin'), type: new BytesType(4), modifiers: [] }, ], new BinaryOpNode( new IdentifierNode('oracleMessage'), diff --git a/packages/cashc/test/compiler/ConstantModificationError/reassign_constant_tuple_target.cash b/packages/cashc/test/compiler/ConstantModificationError/reassign_constant_tuple_target.cash new file mode 100644 index 000000000..fd0dcb216 --- /dev/null +++ b/packages/cashc/test/compiler/ConstantModificationError/reassign_constant_tuple_target.cash @@ -0,0 +1,7 @@ +contract Test() { + function spend() { + bytes constant head, bytes tail = 0x1234.split(1); + head = tail; + require(head == 0x34); + } +} diff --git a/packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier_tuple_target.cash b/packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier_tuple_target.cash new file mode 100644 index 000000000..f0df88095 --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/duplicate_modifier_tuple_target.cash @@ -0,0 +1,7 @@ +contract Test() { + function spend() { + bytes constant constant head, bytes tail = 0x1234.split(1); + require(head == 0x12); + require(tail == 0x34); + } +} diff --git a/packages/cashc/test/compiler/InvalidModifierError/reference_unused_tuple_target.cash b/packages/cashc/test/compiler/InvalidModifierError/reference_unused_tuple_target.cash new file mode 100644 index 000000000..1d17fcebd --- /dev/null +++ b/packages/cashc/test/compiler/InvalidModifierError/reference_unused_tuple_target.cash @@ -0,0 +1,7 @@ +contract Test() { + function spend() { + bytes unused head, bytes tail = 0x1234.split(1); + require(head == 0x12); + require(tail == 0x34); + } +} diff --git a/packages/cashc/test/compiler/ParseError/modifier_on_tuple_reassignment.cash b/packages/cashc/test/compiler/ParseError/modifier_on_tuple_reassignment.cash new file mode 100644 index 000000000..9311e4e4f --- /dev/null +++ b/packages/cashc/test/compiler/ParseError/modifier_on_tuple_reassignment.cash @@ -0,0 +1,7 @@ +contract Test() { + function spend() { + bytes head = 0x00; + constant head, bytes tail = 0x1234.split(1); + require(tail == 0x34); + } +} diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_tuple_target.cash b/packages/cashc/test/compiler/UnusedVariableError/unused_tuple_target.cash new file mode 100644 index 000000000..e89cb3c01 --- /dev/null +++ b/packages/cashc/test/compiler/UnusedVariableError/unused_tuple_target.cash @@ -0,0 +1,6 @@ +contract Test() { + function spend() { + bytes head, bytes tail = 0x1234.split(1); + require(tail == 0x34); + } +} diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_modifiers.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_modifiers.ts new file mode 100644 index 000000000..bbeb92c9b --- /dev/null +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/tuple_modifiers.ts @@ -0,0 +1,95 @@ +import { Fixture } from '../../fixture-utils.js'; + +export const fixtures: Fixture[] = [ + { + artifact: { + contractName: 'TupleModifiers', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'n', type: 'int' }] }], + bytecode: + // int unused incremented, int constant doubled = pair(n); + // pair is inlined; the unused first target is nipped from under `doubled` + 'OP_DUP OP_DUP OP_1ADD OP_SWAP OP_2 OP_MUL OP_NIP ' + // bytes payload, bytes unused padding = 0x1234.split(1); + // the unused last target is dropped straight off the top of the stack + + '1234 OP_1 OP_SPLIT OP_DROP ' + // int acc = n; + + 'OP_ROT ' + // if (acc > 0) { + + 'OP_DUP OP_0 OP_GREATERTHAN OP_IF ' + // (acc, int unused scratch) = pair(acc); + // the unused declaration is dropped instead of parked, then the reassignment + // value folds into acc's slot + + 'OP_DUP OP_DUP OP_1ADD OP_SWAP OP_2 OP_MUL OP_DROP OP_NIP OP_ENDIF ' + // require(acc + doubled >= 0); + + 'OP_ROT OP_ADD OP_0 OP_GREATERTHANOREQUAL OP_VERIFY ' + // require(payload == 0x12); + + '12 OP_EQUAL', + fingerprint: '77f06b3b6cfe6d5e97768ab4c1649870173bfaedd960771ceec13a89356867cb', + debug: { + bytecode: '76768b7c529577021234517f757b7600a06376768b7c52957577687b9300a269011287', + sourceMap: '12:60:12:61;:55::62:1;;;;;:8::63;15:46:15:52:0;:59::60;:46::61:1;:8::62;19:18:19:19:0;' + + '20:12:20:15;:18::19;:12:::1;:21:22:9:0;21:45:21:48;:40::49:1;;;;;:12::50;;20:21:22:9;' + + '24:22:24:29:0;:16:::1;:33::34:0;:16:::1;:8::36;25:27:25:31:0;:8::33:1', + logs: [], + requires: [{ ip: 29, line: 24 }, { ip: 32, line: 25 }], + functions: [ + { + name: 'pair', + inputs: [{ name: 'x', type: 'int' }], + bytecode: '768b7c5295', + sourceMap: '6:11:6:12;:::16:1;:18::19:0;:22::23;:18:::1', + logs: [], + requires: [], + }, + ], + inlineRanges: '1:5:pair;17:21:pair', + }, + }, + }, + { + // Same contract without inlining: the unused-target drops behave identically around the + // OP_INVOKE call sites + compilerOptions: { disableInlining: true }, + artifact: { + contractName: 'TupleModifiers', + constructorInputs: [], + abi: [{ name: 'spend', inputs: [{ name: 'n', type: 'int' }] }], + bytecode: + // OP_DEFINE pair (id 0) + '768b7c5295 OP_0 OP_DEFINE ' + // int unused incremented, int constant doubled = pair(n); + + 'OP_DUP OP_0 OP_INVOKE OP_NIP ' + // bytes payload, bytes unused padding = 0x1234.split(1); + + '1234 OP_1 OP_SPLIT OP_DROP ' + // int acc = n; + + 'OP_ROT ' + // if (acc > 0) { (acc, int unused scratch) = pair(acc); } + + 'OP_DUP OP_0 OP_GREATERTHAN OP_IF OP_DUP OP_0 OP_INVOKE OP_DROP OP_NIP OP_ENDIF ' + // require(acc + doubled >= 0); + + 'OP_ROT OP_ADD OP_0 OP_GREATERTHANOREQUAL OP_VERIFY ' + // require(payload == 0x12); + + '12 OP_EQUAL', + fingerprint: '9ded2366c857eb6d3a9405021cac16d4b2b52f740c7ed24176253851727990c4', + debug: { + bytecode: '05768b7c5295008976008a77021234517f757b7600a06376008a7577687b9300a269011287', + sourceMap: '5::7:1;;::::1;12:60:12:61:0;:55::62:1;;:8::63;15:46:15:52:0;:59::60;:46::61:1;:8::62;' + + '19:18:19:19:0;20:12:20:15;:18::19;:12:::1;:21:22:9:0;21:45:21:48;:40::49:1;;:12::50;;' + + '20:21:22:9;24:22:24:29:0;:16:::1;:33::34:0;:16:::1;:8::36;25:27:25:31:0;:8::33:1', + logs: [], + requires: [{ ip: 26, line: 24 }, { ip: 29, line: 25 }], + functions: [ + { + id: 0, + name: 'pair', + inputs: [{ name: 'x', type: 'int' }], + bytecode: '768b7c5295', + sourceMap: '6:11:6:12;:::16:1;:18::19:0;:22::23;:18:::1', + logs: [], + requires: [], + }, + ], + }, + }, + }, +]; diff --git a/packages/cashc/test/valid-contract-files/tuple_modifiers.cash b/packages/cashc/test/valid-contract-files/tuple_modifiers.cash new file mode 100644 index 000000000..c603d6640 --- /dev/null +++ b/packages/cashc/test/valid-contract-files/tuple_modifiers.cash @@ -0,0 +1,27 @@ +// Tuple assignment targets accept the same modifiers as variable definitions: `constant` makes +// the declared variable immutable and `unused` drops the value right after the assignment, so a +// destructuring can keep just part of a tuple. + +function pair(int x) returns (int, int) { + return x + 1, x * 2; +} + +contract TupleModifiers() { + function spend(int n) { + // `unused` on the first target: the kept value is nipped from under the dropped one + int unused incremented, int constant doubled = pair(n); + + // `unused` on the last target: dropped straight off the top of the stack + bytes payload, bytes unused padding = 0x1234.split(1); + + // mixed in-branch reassignment: the unused declaration is dropped instead of being + // parked on the altstack + int acc = n; + if (acc > 0) { + (acc, int unused scratch) = pair(acc); + } + + require(acc + doubled >= 0); + require(payload == 0x12); + } +} diff --git a/website/docs/language/types.md b/website/docs/language/types.md index 368173694..4263202f0 100644 --- a/website/docs/language/types.md +++ b/website/docs/language/types.md @@ -170,6 +170,12 @@ require(hello + "World" == "Hello " + world); Declarations and reassignments can be mixed freely in a single destructuring (e.g. `(bytes fresh, existing) = x.split(1);`). The target list may optionally be wrapped in parentheses. +Newly declared targets accept the same modifiers as regular variable declarations: `constant` prevents later reassignment, while `unused` discards the value immediately, which is useful when only part of the tuple is needed: + +```solidity +bytes unused ignored, bytes constant tail = someBytes.split(4); +``` + ## Type Casting Type casting can be done both explicitly and implicitly depending on the type. `pubkey`, `sig` and `datasig` can be implicitly cast to `bytes`, meaning they can be used anywhere where you would normally use a `bytes` type. Explicit type casting can be done with a broader range of types, but is still limited. The syntax of this explicit type casting is illustrated below: From a16604059787b776c2f1c1587ae1a589cf8bc877 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 3 Sep 2026 12:02:11 +0200 Subject: [PATCH 34/37] feat: make unused variables a warning rather than an error --- packages/cashc/src/Errors.ts | 10 +-- packages/cashc/src/Warnings.ts | 33 +++++++ packages/cashc/src/ast/AST.ts | 4 + packages/cashc/src/ast/SymbolTable.ts | 10 ++- packages/cashc/src/compiler.ts | 12 ++- .../src/generation/GenerateTargetTraversal.ts | 25 ++++-- packages/cashc/src/index.ts | 1 + .../semantic/LowerGlobalConstantsTraversal.ts | 2 +- .../src/semantic/SymbolTableTraversal.ts | 86 +++++++++++-------- packages/cashc/test/compiler/compiler.test.ts | 63 +++++++++++++- .../final_variable_definition.cash | 0 .../unused_contract_parameter.cash | 0 .../unused_function_parameter.cash | 0 .../unused_global_function_local.cash | 0 .../unused_global_function_parameter.cash | 0 .../unused_scope_variable.cash | 0 .../unused_tuple_target.cash | 0 .../unused_variable.cash | 0 .../write_only_scoped_variables.cash | 12 +++ .../write_only_tuple_target.cash | 8 ++ .../write_only_variable.cash | 7 ++ website/docs/compiler/compiler.md | 15 ++++ website/docs/language/contracts.md | 6 +- website/docs/releases/release-notes.md | 1 + 24 files changed, 229 insertions(+), 66 deletions(-) create mode 100644 packages/cashc/src/Warnings.ts rename packages/cashc/test/{compiler/UnusedVariableError => warnings/UnusedVariableWarning}/final_variable_definition.cash (100%) rename packages/cashc/test/{compiler/UnusedVariableError => warnings/UnusedVariableWarning}/unused_contract_parameter.cash (100%) rename packages/cashc/test/{compiler/UnusedVariableError => warnings/UnusedVariableWarning}/unused_function_parameter.cash (100%) rename packages/cashc/test/{compiler/UnusedVariableError => warnings/UnusedVariableWarning}/unused_global_function_local.cash (100%) rename packages/cashc/test/{compiler/UnusedVariableError => warnings/UnusedVariableWarning}/unused_global_function_parameter.cash (100%) rename packages/cashc/test/{compiler/UnusedVariableError => warnings/UnusedVariableWarning}/unused_scope_variable.cash (100%) rename packages/cashc/test/{compiler/UnusedVariableError => warnings/UnusedVariableWarning}/unused_tuple_target.cash (100%) rename packages/cashc/test/{compiler/UnusedVariableError => warnings/UnusedVariableWarning}/unused_variable.cash (100%) create mode 100644 packages/cashc/test/warnings/UnusedVariableWarning/write_only_scoped_variables.cash create mode 100644 packages/cashc/test/warnings/UnusedVariableWarning/write_only_tuple_target.cash create mode 100644 packages/cashc/test/warnings/UnusedVariableWarning/write_only_variable.cash diff --git a/packages/cashc/src/Errors.ts b/packages/cashc/src/Errors.ts index 05ca2d22e..fd3551216 100644 --- a/packages/cashc/src/Errors.ts +++ b/packages/cashc/src/Errors.ts @@ -22,7 +22,7 @@ import { IntLiteralNode, TupleAssignmentNode, } from './ast/AST.js'; -import { Symbol, SymbolType } from './ast/SymbolTable.js'; +import { SymbolType } from './ast/SymbolTable.js'; import { Location } from './ast/Location.js'; import { BinaryOperator } from './ast/Operator.js'; @@ -98,14 +98,6 @@ export class ImportResolutionError extends CashScriptError { } } -export class UnusedVariableError extends CashScriptError { - constructor( - public symbol: Symbol, - ) { - super(symbol.definition as Node, `Unused variable ${symbol.name}`); - } -} - export class EmptyContractError extends CashScriptError { constructor( public node: ContractNode, diff --git a/packages/cashc/src/Warnings.ts b/packages/cashc/src/Warnings.ts new file mode 100644 index 000000000..5f4cd944f --- /dev/null +++ b/packages/cashc/src/Warnings.ts @@ -0,0 +1,33 @@ +import { Node } from './ast/AST.js'; +import { Symbol } from './ast/SymbolTable.js'; + +export class CashScriptWarning { + name: string; + message: string; + + constructor( + public node: Node, + message: string, + ) { + if (node.location) { + message += ` at ${node.location.start}`; + } + + this.name = this.constructor.name; + this.message = message; + } +} + +export class UnusedVariableWarning extends CashScriptWarning { + constructor( + public symbol: Symbol, + ) { + super(symbol.definition as Node, `Unused variable '${symbol.name}'`); + } +} + +export type CashScriptWarningListener = (warnings: CashScriptWarning[]) => void; + +export const defaultWarningListener: CashScriptWarningListener = (warnings) => { + warnings.forEach((warning) => console.warn(`Warning: ${warning.message}`)); +}; diff --git a/packages/cashc/src/ast/AST.ts b/packages/cashc/src/ast/AST.ts index b10c36ec5..864db595b 100644 --- a/packages/cashc/src/ast/AST.ts +++ b/packages/cashc/src/ast/AST.ts @@ -120,6 +120,8 @@ export class FunctionDefinitionNode extends Node implements Named { } export class ParameterNode extends Node implements Named, Typed { + symbol?: Symbol; + constructor( public type: Type, public modifiers: Modifier[], @@ -140,6 +142,8 @@ export abstract class ControlStatementNode extends StatementNode { } export abstract class NonControlStatementNode extends StatementNode { } export class VariableDefinitionNode extends NonControlStatementNode implements Named, Typed { + symbol?: Symbol; + constructor( public type: Type, public modifiers: Modifier[], diff --git a/packages/cashc/src/ast/SymbolTable.ts b/packages/cashc/src/ast/SymbolTable.ts index 136169b41..51c5bb8ea 100644 --- a/packages/cashc/src/ast/SymbolTable.ts +++ b/packages/cashc/src/ast/SymbolTable.ts @@ -11,7 +11,7 @@ import { Modifier } from './Globals.js'; import { functionReturnType } from '../utils.js'; export class Symbol { - references: IdentifierNode[] = []; + uses: IdentifierNode[] = []; inlinedFrame?: DebugFrame; private constructor( @@ -30,6 +30,10 @@ export class Symbol { && this.definition.modifiers.includes(modifier); } + isUnused(): boolean { + return this.uses.length === 0; + } + static variable(node: VariableDefinitionNode | ParameterNode): Symbol { return new Symbol(node.name, node.type, SymbolType.VARIABLE, node); } @@ -103,10 +107,10 @@ export class SymbolTable { return `[${Array.from(this.symbols).map((e) => e[1])}]`; } - unusedSymbols(): Symbol[] { + getUnmarkedUnusedSymbols(): Symbol[] { return Array.from(this.symbols) .map((e) => e[1]) .filter((s) => !s.hasModifier(Modifier.UNUSED)) - .filter((s) => s.references.length === 0); + .filter((s) => s.isUnused()); } } diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index 6724d8c18..240d3920b 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -18,6 +18,7 @@ import { Ast } from './ast/AST.js'; import { checkVersionConstraints } from './ast/Pragma.js'; import { CashScriptErrorListener } from './ast/error-listeners.js'; import { MissingContractError } from './Errors.js'; +import { CashScriptWarningListener, defaultWarningListener } from './Warnings.js'; import { parseCode } from './parser.js'; import { createDiskResolver, @@ -42,6 +43,7 @@ export const DEFAULT_COMPILER_OPTIONS: CompilerOptions = { export interface CompileOptions extends CompilerOptions { errorListener?: CashScriptErrorListener; + warningListener?: CashScriptWarningListener; } export interface CompileStringOptions extends CompileOptions { @@ -55,6 +57,8 @@ export interface CompileStringOptions extends CompileOptions { * @param compilerOptions - Optional compiler options that override the defaults. * @returns The compiled CashScript artifact, including ABI, bytecode and debug information. * @throws If the source code contains a syntax, semantic, or type error, or an import cannot be resolved. + * @remarks Compilation warnings (e.g. unused variables) are passed to the `warningListener` compiler + * option, or printed with `console.warn` when no listener is provided. */ export const compileString: (code: string, compilerOptions?: CompileStringOptions) => Artifact = compileStringInternal; @@ -103,7 +107,7 @@ function compileCode( resolver: ImportResolver, compilerOptions: CompileOptions & InternalCompilerOptions, ): Artifact { - const { errorListener, disableInlining, ...artifactCompilerOptions } = compilerOptions; + const { errorListener, warningListener, disableInlining, ...artifactCompilerOptions } = compilerOptions; const mergedCompilerOptions = { ...DEFAULT_COMPILER_OPTIONS, ...artifactCompilerOptions }; // Lexing + parsing @@ -117,7 +121,11 @@ function compileCode( // Semantic analysis ast = ast.accept(new FoldGlobalConstantsTraversal()) as Ast; - ast = ast.accept(new SymbolTableTraversal()) as Ast; + + const symbolTableTraversal = new SymbolTableTraversal(); + ast = ast.accept(symbolTableTraversal) as Ast; + (warningListener ?? defaultWarningListener)(symbolTableTraversal.warnings); + ast = ast.accept(new TypeCheckTraversal()) as Ast; ast = ast.accept(new EnsureFunctionsSafeTraversal()) as Ast; ast = ast.accept(new EnsureFinalRequireTraversal()) as Ast; diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index c8ff35fdd..ddc25171a 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -63,7 +63,7 @@ import { ForNode, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; -import { GlobalFunction, Class, Modifier } from '../ast/Globals.js'; +import { GlobalFunction, Class } from '../ast/Globals.js'; import { BinaryOperator } from '../ast/Operator.js'; import { compileBinaryOp, @@ -428,7 +428,7 @@ export default class GenerateTargetTraversal extends AstTraversal { private dropUnusedParameters(parameters: ParameterNode[]): void { parameters - .filter((parameter) => parameter.modifiers.includes(Modifier.UNUSED)) + .filter((parameter) => parameter.symbol!.isUnused()) .sort((a, b) => this.getStackIndex(a.name) - this.getStackIndex(b.name)) .forEach((parameter) => { const stackIndex = this.getStackIndex(parameter.name); @@ -481,7 +481,7 @@ export default class GenerateTargetTraversal extends AstTraversal { } shouldEnforceFunctionParameterType(node: ParameterNode): boolean { - if (node.modifiers.includes(Modifier.UNUSED)) return false; + if (node.symbol!.isUnused()) return false; if (node.type === PrimitiveType.BOOL) return true; if (node.type instanceof BytesType && node.type.bound !== undefined) return true; return false; @@ -495,7 +495,7 @@ export default class GenerateTargetTraversal extends AstTraversal { visitVariableDefinition(node: VariableDefinitionNode): Node { node.expression = this.visit(node.expression); - if (node.modifiers.includes(Modifier.UNUSED)) { + if (node.symbol!.isUnused()) { this.emit(Op.OP_DROP, { location: node.location, positionHint: PositionHint.END }); this.popFromStack(); return node; @@ -523,10 +523,11 @@ export default class GenerateTargetTraversal extends AstTraversal { const reversedTargets = [...node.targets].reverse(); reversedTargets.forEach((target) => { - if (target.isReassignment) { - this.emitReplace(this.getStackIndex(target.identifier.name), node); - } else if (target.modifiers.includes(Modifier.UNUSED)) { + // Unused variables are never added the stack, so their defined or re-assigned value is dropped + if (target.identifier.symbol!.isUnused()) { this.emit(Op.OP_DROP, locationData); + } else if (target.isReassignment) { + this.emitReplace(this.getStackIndex(target.identifier.name), node); } else { this.emit(Op.OP_TOALTSTACK, locationData); parkedDeclarations.push(target.identifier.name); @@ -546,7 +547,7 @@ export default class GenerateTargetTraversal extends AstTraversal { const locationData = { location: node.location, positionHint: PositionHint.END }; node.targets - .filter((target) => target.modifiers.includes(Modifier.UNUSED)) + .filter((target) => target.identifier.symbol!.isUnused()) .sort((a, b) => this.getStackIndex(a.identifier.name) - this.getStackIndex(b.identifier.name)) .forEach((target) => { const stackIndex = this.getStackIndex(target.identifier.name); @@ -559,6 +560,14 @@ export default class GenerateTargetTraversal extends AstTraversal { visitAssign(node: AssignNode): Node { node.expression = this.visit(node.expression); + + // An unused variable never gets added to the stack, so the assigned value is dropped as well + if (node.identifier.symbol!.isUnused()) { + this.emit(Op.OP_DROP, { location: node.location, positionHint: PositionHint.END }); + this.popFromStack(); + return node; + } + if (this.scopeDepth > 0) { this.emitReplace(this.getStackIndex(node.identifier.name), node); this.popFromStack(); diff --git a/packages/cashc/src/index.ts b/packages/cashc/src/index.ts index 85f011e49..773eddcc2 100644 --- a/packages/cashc/src/index.ts +++ b/packages/cashc/src/index.ts @@ -1,4 +1,5 @@ export * from './Errors.js'; +export * from './Warnings.js'; export * as utils from '@cashscript/utils'; export { compileFile, compileString, type CompileOptions, type CompileStringOptions, diff --git a/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts b/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts index c6f4e68f9..e4ede498e 100644 --- a/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts +++ b/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts @@ -71,7 +71,7 @@ export class LowerGlobalConstantsTraversal extends AstTraversal { identifier.location = node.location; identifier.type = node.type; identifier.symbol = symbol; - symbol.references.push(identifier); + symbol.uses.push(identifier); const call = new FunctionCallNode(identifier, []); call.location = node.location; diff --git a/packages/cashc/src/semantic/SymbolTableTraversal.ts b/packages/cashc/src/semantic/SymbolTableTraversal.ts index 2dc708379..c90fc3941 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -26,14 +26,16 @@ import { createConstantLiteral } from './LowerGlobalConstantsTraversal.js'; import { RedefinitionError, UndefinedReferenceError, - UnusedVariableError, InvalidSymbolTypeError, ConstantModificationError, DuplicateTupleTargetError, InvalidModifierError, } from '../Errors.js'; +import { CashScriptWarning, UnusedVariableWarning } from '../Warnings.js'; export default class SymbolTableTraversal extends AstTraversal { + warnings: CashScriptWarning[] = []; + private symbolTables: SymbolTable[] = [GLOBAL_SYMBOL_TABLE]; private contractFunctionNames: Map = new Map(); private currentFunction: FunctionDefinitionNode; @@ -70,10 +72,7 @@ export default class SymbolTableTraversal extends AstTraversal { node.parameters = this.visitList(node.parameters) as ParameterNode[]; node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; - const unusedSymbols = node.symbolTable.unusedSymbols(); - if (unusedSymbols.length !== 0) { - throw new UnusedVariableError(unusedSymbols[0]); - } + this.collectUnusedSymbolWarnings(node.symbolTable); this.symbolTables.shift(); return node; @@ -86,7 +85,8 @@ export default class SymbolTableTraversal extends AstTraversal { validateModifiers(node, node.modifiers, [Modifier.UNUSED]); - this.symbolTables[0].set(Symbol.variable(node)); + node.symbol = Symbol.variable(node); + this.symbolTables[0].set(node.symbol); return node; } @@ -106,10 +106,7 @@ export default class SymbolTableTraversal extends AstTraversal { node.parameters = this.visitList(node.parameters) as ParameterNode[]; node.body = this.visit(node.body); - const unusedSymbols = node.symbolTable.unusedSymbols(); - if (unusedSymbols.length !== 0) { - throw new UnusedVariableError(unusedSymbols[0]); - } + this.collectUnusedSymbolWarnings(node.symbolTable); this.symbolTables.shift(); return node; @@ -121,10 +118,7 @@ export default class SymbolTableTraversal extends AstTraversal { node.statements = this.visitOptionalList(node.statements) as StatementNode[]; - const unusedSymbols = node.symbolTable.unusedSymbols(); - if (unusedSymbols.length !== 0) { - throw new UnusedVariableError(unusedSymbols[0]); - } + this.collectUnusedSymbolWarnings(node.symbolTable); this.symbolTables.shift(); return node; @@ -139,10 +133,7 @@ export default class SymbolTableTraversal extends AstTraversal { node.update = this.visit(node.update) as AssignNode; node.block = this.visit(node.block); - const unusedSymbols = node.symbolTable.unusedSymbols(); - if (unusedSymbols.length !== 0) { - throw new UnusedVariableError(unusedSymbols[0]); - } + this.collectUnusedSymbolWarnings(node.symbolTable); this.symbolTables.shift(); return node; @@ -157,23 +148,15 @@ export default class SymbolTableTraversal extends AstTraversal { node.expression = this.visit(node.expression); - this.symbolTables[0].set(Symbol.variable(node)); + node.symbol = Symbol.variable(node); + this.symbolTables[0].set(node.symbol); return node; } visitAssign(node: AssignNode): Node { - const symbol = this.symbolTables[0].get(node.identifier.name); - - if (!symbol) { - throw new UndefinedReferenceError(node.identifier); - } - - if (symbol.hasModifier(Modifier.CONSTANT)) { - throw new ConstantModificationError(node, node.identifier.name); - } - - super.visitAssign(node); + node.identifier.symbol = this.resolveAssignmentTarget(node, node.identifier); + node.expression = this.visit(node.expression); return node; } @@ -186,12 +169,8 @@ export default class SymbolTableTraversal extends AstTraversal { seenTargetNames.add(target.identifier.name); if (target.isReassignment) { - if (this.symbolTables[0].get(target.identifier.name)?.hasModifier(Modifier.CONSTANT)) { - throw new ConstantModificationError(node, target.identifier.name); - } - - target.identifier = this.visit(target.identifier) as IdentifierNode; - target.type = target.identifier.symbol!.type; + target.identifier.symbol = this.resolveAssignmentTarget(node, target.identifier); + target.type = target.identifier.symbol.type; } else { const definition = createTupleVariableDefinition(node, target); @@ -201,7 +180,8 @@ export default class SymbolTableTraversal extends AstTraversal { validateModifiers(definition, definition.modifiers, [Modifier.CONSTANT, Modifier.UNUSED]); - this.symbolTables[0].set(Symbol.variable(definition)); + target.identifier.symbol = Symbol.variable(definition); + this.symbolTables[0].set(target.identifier.symbol); } }); @@ -255,7 +235,7 @@ export default class SymbolTableTraversal extends AstTraversal { } node.symbol = symbol; - node.symbol.references.push(node); + node.symbol.uses.push(node); // Keep track of final use of variables for code generation (excluding console statements) if (!this.insideConsoleStatement) { @@ -264,6 +244,36 @@ export default class SymbolTableTraversal extends AstTraversal { return node; } + + // Assignment targets are resolved without counting as a use of the variable, since only reads count + private resolveAssignmentTarget(node: AssignNode | TupleAssignmentNode, identifier: IdentifierNode): Symbol { + const symbol = this.symbolTables[0].get(identifier.name); + + if (!symbol) { + throw new UndefinedReferenceError(identifier); + } + + if (symbol.hasModifier(Modifier.CONSTANT)) { + throw new ConstantModificationError(node, identifier.name); + } + + if (symbol.symbolType !== SymbolType.VARIABLE) { + throw new InvalidSymbolTypeError(identifier, SymbolType.VARIABLE); + } + + if (symbol.hasModifier(Modifier.UNUSED)) { + throw new InvalidModifierError(identifier, `Cannot assign to variable '${identifier.name}' because it is marked 'unused'`); + } + + // An assignment still needs the variable to be on the stack, so it does count as its final use for code generation + this.currentFunction.opRolls.set(identifier.name, identifier); + + return symbol; + } + + private collectUnusedSymbolWarnings(symbolTable: SymbolTable): void { + this.warnings.push(...symbolTable.getUnmarkedUnusedSymbols().map((symbol) => new UnusedVariableWarning(symbol))); + } } function validateModifiers( diff --git a/packages/cashc/test/compiler/compiler.test.ts b/packages/cashc/test/compiler/compiler.test.ts index 19fef16ce..f589d11a7 100644 --- a/packages/cashc/test/compiler/compiler.test.ts +++ b/packages/cashc/test/compiler/compiler.test.ts @@ -1,6 +1,7 @@ import { URL } from 'url'; import { getSubdirectories, readCashFiles } from '../test-utils.js'; import * as Errors from '../../src/Errors.js'; +import * as Warnings from '../../src/Warnings.js'; import { compileString } from '../../src/index.js'; import type { CashScriptErrorListener } from '../../src/index.js'; @@ -12,6 +13,14 @@ contract Test() { } `; const INVALID_SOURCE = 'contract Test() { function unlock() { require(true) } }'; +const UNUSED_VARIABLE_SOURCE = ` +contract Test() { + function hello(sig s, pubkey pk) { + string x = 'Hello'; + require(checkSig(s, pk)); + } +} +`; describe('Compiler', () => { describe('Compilation errors', () => { @@ -23,7 +32,6 @@ describe('Compiler', () => { it(`${file.fn} should throw ${errorType}`, () => { // Retrieve the correct Error constructor from the Errors.ts file const expectedError = Errors[errorType as keyof typeof Errors]; - if (!expectedError) throw new Error(`Invalid test configuration: error ${errorType} does not exist`); expect(() => compileString(file.contents)).toThrow(expectedError); @@ -33,6 +41,31 @@ describe('Compiler', () => { }); }); + describe('Compilation warnings', () => { + const warningTypes = getSubdirectories(new URL('../warnings/', import.meta.url)); + + warningTypes.forEach((warningType) => { + describe(warningType.toString(), () => { + readCashFiles(new URL(`../warnings/${warningType}`, import.meta.url)).forEach((file) => { + it(`${file.fn} should report ${warningType}`, () => { + // Retrieve the correct Warning constructor from the Warnings.ts file + const expectedWarning = Warnings[warningType as keyof typeof Warnings]; + if (!expectedWarning) throw new Error(`Invalid test configuration: warning ${warningType} does not exist`); + + let warnings: Warnings.CashScriptWarning[] = []; + try { + compileString(file.contents, { warningListener: (reported) => { warnings = reported; } }); + } catch { + // ignore compilation errors from later phases + } + + expect(warnings).toContainEqual(expect.any(expectedWarning)); + }); + }); + }); + }); + }); + describe('Custom error listener', () => { it('uses the custom error listener for parse errors', () => { const errors: string[] = []; @@ -59,14 +92,15 @@ describe('Compiler', () => { expect(errors).toHaveLength(1); }); - it('does not include custom error listeners in compiler artifact options', () => { + it('does not include custom error or warning listeners in compiler artifact options', () => { const errorListener: CashScriptErrorListener = { syntaxError(): void { throw new Error('Unexpected parse error'); }, }; - const artifact = compileString(VALID_SOURCE, { enforceLocktimeGuard: false, errorListener }); + const compileOptions = { enforceLocktimeGuard: false, errorListener, warningListener: () => {} }; + const artifact = compileString(VALID_SOURCE, compileOptions); expect(artifact.compiler.options).toEqual({ enforceFunctionParameterTypes: true, @@ -74,4 +108,27 @@ describe('Compiler', () => { }); }); }); + + describe('Custom warning listener', () => { + it('uses the custom warning listener for compilation warnings', () => { + const warnings: Warnings.CashScriptWarning[] = []; + compileString(UNUSED_VARIABLE_SOURCE, { warningListener: (reported) => { warnings.push(...reported); } }); + + expect(warnings).toHaveLength(1); + expect(warnings[0]).toBeInstanceOf(Warnings.UnusedVariableWarning); + expect(warnings[0].message).toEqual("Unused variable 'x' at Line 4, Column 8"); + }); + + it('prints warnings with console.warn when no warning listener is provided', () => { + const consoleWarn = vi.spyOn(console, 'warn').mockImplementation(() => {}); + + try { + compileString(UNUSED_VARIABLE_SOURCE); + expect(consoleWarn).toHaveBeenCalledTimes(1); + expect(consoleWarn).toHaveBeenCalledWith("Warning: Unused variable 'x' at Line 4, Column 8"); + } finally { + consoleWarn.mockRestore(); + } + }); + }); }); diff --git a/packages/cashc/test/compiler/UnusedVariableError/final_variable_definition.cash b/packages/cashc/test/warnings/UnusedVariableWarning/final_variable_definition.cash similarity index 100% rename from packages/cashc/test/compiler/UnusedVariableError/final_variable_definition.cash rename to packages/cashc/test/warnings/UnusedVariableWarning/final_variable_definition.cash diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_contract_parameter.cash b/packages/cashc/test/warnings/UnusedVariableWarning/unused_contract_parameter.cash similarity index 100% rename from packages/cashc/test/compiler/UnusedVariableError/unused_contract_parameter.cash rename to packages/cashc/test/warnings/UnusedVariableWarning/unused_contract_parameter.cash diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_function_parameter.cash b/packages/cashc/test/warnings/UnusedVariableWarning/unused_function_parameter.cash similarity index 100% rename from packages/cashc/test/compiler/UnusedVariableError/unused_function_parameter.cash rename to packages/cashc/test/warnings/UnusedVariableWarning/unused_function_parameter.cash diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash b/packages/cashc/test/warnings/UnusedVariableWarning/unused_global_function_local.cash similarity index 100% rename from packages/cashc/test/compiler/UnusedVariableError/unused_global_function_local.cash rename to packages/cashc/test/warnings/UnusedVariableWarning/unused_global_function_local.cash diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_global_function_parameter.cash b/packages/cashc/test/warnings/UnusedVariableWarning/unused_global_function_parameter.cash similarity index 100% rename from packages/cashc/test/compiler/UnusedVariableError/unused_global_function_parameter.cash rename to packages/cashc/test/warnings/UnusedVariableWarning/unused_global_function_parameter.cash diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_scope_variable.cash b/packages/cashc/test/warnings/UnusedVariableWarning/unused_scope_variable.cash similarity index 100% rename from packages/cashc/test/compiler/UnusedVariableError/unused_scope_variable.cash rename to packages/cashc/test/warnings/UnusedVariableWarning/unused_scope_variable.cash diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_tuple_target.cash b/packages/cashc/test/warnings/UnusedVariableWarning/unused_tuple_target.cash similarity index 100% rename from packages/cashc/test/compiler/UnusedVariableError/unused_tuple_target.cash rename to packages/cashc/test/warnings/UnusedVariableWarning/unused_tuple_target.cash diff --git a/packages/cashc/test/compiler/UnusedVariableError/unused_variable.cash b/packages/cashc/test/warnings/UnusedVariableWarning/unused_variable.cash similarity index 100% rename from packages/cashc/test/compiler/UnusedVariableError/unused_variable.cash rename to packages/cashc/test/warnings/UnusedVariableWarning/unused_variable.cash diff --git a/packages/cashc/test/warnings/UnusedVariableWarning/write_only_scoped_variables.cash b/packages/cashc/test/warnings/UnusedVariableWarning/write_only_scoped_variables.cash new file mode 100644 index 000000000..ce3b7e0b2 --- /dev/null +++ b/packages/cashc/test/warnings/UnusedVariableWarning/write_only_scoped_variables.cash @@ -0,0 +1,12 @@ +contract Test() { + function spend(int a) { + int x = 0; + bytes head = 0x00; + bytes tail = 0x01; + if (a > 0) { + x = a; + (head, tail) = 0x1234.split(1); + } + require(tail == 0x34); + } +} diff --git a/packages/cashc/test/warnings/UnusedVariableWarning/write_only_tuple_target.cash b/packages/cashc/test/warnings/UnusedVariableWarning/write_only_tuple_target.cash new file mode 100644 index 000000000..b6a490b9c --- /dev/null +++ b/packages/cashc/test/warnings/UnusedVariableWarning/write_only_tuple_target.cash @@ -0,0 +1,8 @@ +contract Test() { + function spend() { + bytes head = 0x00; + bytes tail = 0x01; + (head, tail) = 0x1234.split(1); + require(tail == 0x34); + } +} diff --git a/packages/cashc/test/warnings/UnusedVariableWarning/write_only_variable.cash b/packages/cashc/test/warnings/UnusedVariableWarning/write_only_variable.cash new file mode 100644 index 000000000..f52980095 --- /dev/null +++ b/packages/cashc/test/warnings/UnusedVariableWarning/write_only_variable.cash @@ -0,0 +1,7 @@ +contract Test() { + function spend() { + int x = 1; + x = 2; + require(true); + } +} diff --git a/website/docs/compiler/compiler.md b/website/docs/compiler/compiler.md index 3f509b762..25a8224f3 100644 --- a/website/docs/compiler/compiler.md +++ b/website/docs/compiler/compiler.md @@ -127,6 +127,21 @@ const Doubler = compileString(source, { files: { './math.cash': mathSource } }); Imports inside imported files are resolved relative to the *importing* file, but their keys in `files` remain relative to the main source. For example, if `lib/a.cash` contains `import "./b.cash";`, that file must be provided under the key `lib/b.cash`. Package imports such as `import "@example/math-lib/math.cash"` are looked up verbatim, so they must be provided under exactly that key. ::: +### Compilation Warnings + +Some issues, such as unused variables that are not marked [`unused`](/docs/language/contracts#intentionally-unused-values), do not prevent compilation but produce a compiler warning instead. By default these warnings are printed with `console.warn`. When compiling from JavaScript, a custom `warningListener` can be passed as a compiler option to capture the structured warnings instead. It is called once per compilation with the full (possibly empty) list of warnings. The default listener is exported as `defaultWarningListener`, so a custom listener can compose with it to keep the standard console output. + +```ts +import { compileString, defaultWarningListener } from 'cashc'; + +const P2PKH = compileString(source, { + warningListener: (warnings) => { + defaultWarningListener(warnings); // still print the warnings to the console + myDiagnostics.push(...warnings); + }, +}); +``` + ### Compiler Options ```ts interface CompilerOptions { diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index 4bec99458..feca2ef75 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -265,7 +265,7 @@ contract P2PKH(bytes20 pkh) { Variables can be declared by specifying their type and name. All variables need to be initialised at the time of their declaration, but can be reassigned later on — unless specifying the `constant` keyword. Since CashScript is strongly typed and has no type inference, it is not possible to use keywords such as `var` or `let` to declare variables. :::note -CashScript disallows variable shadowing and unused variables unless they are explicitly marked `unused`. +CashScript disallows variable shadowing, and the compiler emits a warning for unused variables unless they are explicitly marked `unused`. ::: #### Example @@ -276,7 +276,9 @@ string constant myString = 'Bitcoin Cash'; ### Intentionally unused values -Parameters and local variables that intentionally have no references can use the `unused` modifier. These values are dropped from the stack immediately after their declaration. A declaration marked `unused` cannot be referenced later. Some use cases for this include padding the contract bytecode in order to get a higher opcost budget, or nonces in order to differentiate between similar contracts. +A parameter or local variable that is declared but never used results in a compiler warning. If the variable is intended to be unused, this warning can be silenced by marking the variable as `unused`. Unused parameters and local variables are dropped from the stack immediately after their declaration, and no [parameter type enforcement](/docs/compiler#enforcefunctionparametertypes) is generated for unused parameters. + +Some use cases for intentionally unused values include padding the contract bytecode in order to get a higher opcost budget, or nonces in order to differentiate between similar contracts. #### Example diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 5f8cf21da..8cfd4c0f0 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -12,6 +12,7 @@ title: Release Notes - :sparkles: Add support for top-level global constants. - :sparkles: Allow for simple arithmetic / concatenation operations in global constant definitions. - :sparkles: Add `unused` modifier for parameters or variables that are intentionally unused. +- :hammer_and_wrench: Unused variables that are not marked `unused` now produce a compiler warning instead of a compilation error. Warnings are printed with `console.warn`, or passed to the new `warningListener` compiler option. - :sparkles: Add support for `import` directives to share user-defined functions across files. - :sparkles: Resolve package imports (e.g. `import "pkg/math.cash"`) from `node_modules`, so contract libraries can be installed as npm packages. - :sparkles: Add support for reassigning existing variables in tuple destructuring (e.g. `(a, b) = swap(a, b)`), optionally mixed with fresh declarations. From 7b699480ad74e05258ea47c1c1fcda9a021358f3 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Thu, 3 Sep 2026 13:04:17 +0200 Subject: [PATCH 35/37] feat: add compiler warning for assignments that don't get read after --- packages/cashc/src/Warnings.ts | 16 ++- packages/cashc/src/ast/SymbolTable.ts | 18 ++- packages/cashc/src/compiler.ts | 6 +- .../semantic/LowerGlobalConstantsTraversal.ts | 1 - .../src/semantic/SymbolTableTraversal.ts | 31 ++--- .../cashc/src/semantic/UnusedCodeTraversal.ts | 129 ++++++++++++++++++ packages/cashc/test/compiler/compiler.test.ts | 6 +- .../loop_reassignment_after_final_read.cash | 12 ++ .../parameter_reassignment.cash | 7 + .../reassignment_after_final_read.cash | 8 ++ .../reassignment_in_branch.cash | 10 ++ .../self_referencing_reassignment.cash | 8 ++ .../tuple_reassignment_after_final_read.cash | 9 ++ website/docs/compiler/compiler.md | 8 +- website/docs/language/contracts.md | 2 + website/docs/releases/release-notes.md | 4 +- 16 files changed, 240 insertions(+), 35 deletions(-) create mode 100644 packages/cashc/src/semantic/UnusedCodeTraversal.ts create mode 100644 packages/cashc/test/warnings/UnusedAssignmentWarning/loop_reassignment_after_final_read.cash create mode 100644 packages/cashc/test/warnings/UnusedAssignmentWarning/parameter_reassignment.cash create mode 100644 packages/cashc/test/warnings/UnusedAssignmentWarning/reassignment_after_final_read.cash create mode 100644 packages/cashc/test/warnings/UnusedAssignmentWarning/reassignment_in_branch.cash create mode 100644 packages/cashc/test/warnings/UnusedAssignmentWarning/self_referencing_reassignment.cash create mode 100644 packages/cashc/test/warnings/UnusedAssignmentWarning/tuple_reassignment_after_final_read.cash diff --git a/packages/cashc/src/Warnings.ts b/packages/cashc/src/Warnings.ts index 5f4cd944f..68eb7e147 100644 --- a/packages/cashc/src/Warnings.ts +++ b/packages/cashc/src/Warnings.ts @@ -1,4 +1,4 @@ -import { Node } from './ast/AST.js'; +import { IdentifierNode, Node } from './ast/AST.js'; import { Symbol } from './ast/SymbolTable.js'; export class CashScriptWarning { @@ -26,8 +26,16 @@ export class UnusedVariableWarning extends CashScriptWarning { } } -export type CashScriptWarningListener = (warnings: CashScriptWarning[]) => void; +export class UnusedAssignmentWarning extends CashScriptWarning { + constructor( + public identifier: IdentifierNode, + ) { + super(identifier, `Value assigned to '${identifier.name}' is never read`); + } +} + +export type CashScriptWarningListener = (warning: CashScriptWarning) => void; -export const defaultWarningListener: CashScriptWarningListener = (warnings) => { - warnings.forEach((warning) => console.warn(`Warning: ${warning.message}`)); +export const defaultWarningListener: CashScriptWarningListener = (warning) => { + console.warn(`Warning: ${warning.message}`); }; diff --git a/packages/cashc/src/ast/SymbolTable.ts b/packages/cashc/src/ast/SymbolTable.ts index 51c5bb8ea..32bf1b163 100644 --- a/packages/cashc/src/ast/SymbolTable.ts +++ b/packages/cashc/src/ast/SymbolTable.ts @@ -10,8 +10,18 @@ import { import { Modifier } from './Globals.js'; import { functionReturnType } from '../utils.js'; +export enum ReferenceKind { + READ = 'read', + WRITE = 'write', +} + +export interface Reference { + kind: ReferenceKind; + node: IdentifierNode; +} + export class Symbol { - uses: IdentifierNode[] = []; + references: Reference[] = []; inlinedFrame?: DebugFrame; private constructor( @@ -30,8 +40,12 @@ export class Symbol { && this.definition.modifiers.includes(modifier); } + getReferences(kind: ReferenceKind): Reference[] { + return this.references.filter((reference) => reference.kind === kind); + } + isUnused(): boolean { - return this.uses.length === 0; + return this.getReferences(ReferenceKind.READ).length === 0; } static variable(node: VariableDefinitionNode | ParameterNode): Symbol { diff --git a/packages/cashc/src/compiler.ts b/packages/cashc/src/compiler.ts index 240d3920b..dcfcf5fac 100644 --- a/packages/cashc/src/compiler.ts +++ b/packages/cashc/src/compiler.ts @@ -29,6 +29,7 @@ import { import GenerateTargetTraversal from './generation/GenerateTargetTraversal.js'; import { FoldGlobalConstantsTraversal } from './semantic/FoldGlobalConstantsTraversal.js'; import SymbolTableTraversal from './semantic/SymbolTableTraversal.js'; +import UnusedCodeWarningsTraversal from './semantic/UnusedCodeTraversal.js'; import TypeCheckTraversal from './semantic/TypeCheckTraversal.js'; import EnsureFinalRequireTraversal from './semantic/EnsureFinalRequireTraversal.js'; import EnsureFunctionsSafeTraversal from './semantic/EnsureFunctionsSafeTraversal.js'; @@ -122,9 +123,8 @@ function compileCode( // Semantic analysis ast = ast.accept(new FoldGlobalConstantsTraversal()) as Ast; - const symbolTableTraversal = new SymbolTableTraversal(); - ast = ast.accept(symbolTableTraversal) as Ast; - (warningListener ?? defaultWarningListener)(symbolTableTraversal.warnings); + ast = ast.accept(new SymbolTableTraversal()) as Ast; + ast = ast.accept(new UnusedCodeWarningsTraversal(warningListener ?? defaultWarningListener)) as Ast; ast = ast.accept(new TypeCheckTraversal()) as Ast; ast = ast.accept(new EnsureFunctionsSafeTraversal()) as Ast; diff --git a/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts b/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts index e4ede498e..7a38b0577 100644 --- a/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts +++ b/packages/cashc/src/semantic/LowerGlobalConstantsTraversal.ts @@ -71,7 +71,6 @@ export class LowerGlobalConstantsTraversal extends AstTraversal { identifier.location = node.location; identifier.type = node.type; identifier.symbol = symbol; - symbol.uses.push(identifier); const call = new FunctionCallNode(identifier, []); call.location = node.location; diff --git a/packages/cashc/src/semantic/SymbolTableTraversal.ts b/packages/cashc/src/semantic/SymbolTableTraversal.ts index c90fc3941..b95bf2b07 100644 --- a/packages/cashc/src/semantic/SymbolTableTraversal.ts +++ b/packages/cashc/src/semantic/SymbolTableTraversal.ts @@ -21,7 +21,9 @@ import { TupleAssignmentTarget, } from '../ast/AST.js'; import AstTraversal from '../ast/AstTraversal.js'; -import { SymbolTable, Symbol, SymbolType } from '../ast/SymbolTable.js'; +import { + SymbolTable, Symbol, SymbolType, ReferenceKind, +} from '../ast/SymbolTable.js'; import { createConstantLiteral } from './LowerGlobalConstantsTraversal.js'; import { RedefinitionError, @@ -31,11 +33,8 @@ import { DuplicateTupleTargetError, InvalidModifierError, } from '../Errors.js'; -import { CashScriptWarning, UnusedVariableWarning } from '../Warnings.js'; export default class SymbolTableTraversal extends AstTraversal { - warnings: CashScriptWarning[] = []; - private symbolTables: SymbolTable[] = [GLOBAL_SYMBOL_TABLE]; private contractFunctionNames: Map = new Map(); private currentFunction: FunctionDefinitionNode; @@ -72,8 +71,6 @@ export default class SymbolTableTraversal extends AstTraversal { node.parameters = this.visitList(node.parameters) as ParameterNode[]; node.functions = this.visitList(node.functions) as FunctionDefinitionNode[]; - this.collectUnusedSymbolWarnings(node.symbolTable); - this.symbolTables.shift(); return node; } @@ -106,8 +103,6 @@ export default class SymbolTableTraversal extends AstTraversal { node.parameters = this.visitList(node.parameters) as ParameterNode[]; node.body = this.visit(node.body); - this.collectUnusedSymbolWarnings(node.symbolTable); - this.symbolTables.shift(); return node; } @@ -118,8 +113,6 @@ export default class SymbolTableTraversal extends AstTraversal { node.statements = this.visitOptionalList(node.statements) as StatementNode[]; - this.collectUnusedSymbolWarnings(node.symbolTable); - this.symbolTables.shift(); return node; } @@ -133,8 +126,6 @@ export default class SymbolTableTraversal extends AstTraversal { node.update = this.visit(node.update) as AssignNode; node.block = this.visit(node.block); - this.collectUnusedSymbolWarnings(node.symbolTable); - this.symbolTables.shift(); return node; } @@ -157,6 +148,7 @@ export default class SymbolTableTraversal extends AstTraversal { visitAssign(node: AssignNode): Node { node.identifier.symbol = this.resolveAssignmentTarget(node, node.identifier); node.expression = this.visit(node.expression); + this.addReference(ReferenceKind.WRITE, node.identifier); return node; } @@ -186,6 +178,11 @@ export default class SymbolTableTraversal extends AstTraversal { }); node.tuple = this.visit(node.tuple); + + node.targets + .filter((target) => target.isReassignment) + .forEach((target) => this.addReference(ReferenceKind.WRITE, target.identifier)); + return node; } @@ -235,7 +232,7 @@ export default class SymbolTableTraversal extends AstTraversal { } node.symbol = symbol; - node.symbol.uses.push(node); + this.addReference(ReferenceKind.READ, node); // Keep track of final use of variables for code generation (excluding console statements) if (!this.insideConsoleStatement) { @@ -245,6 +242,10 @@ export default class SymbolTableTraversal extends AstTraversal { return node; } + private addReference(kind: ReferenceKind, node: IdentifierNode): void { + node.symbol!.references.push({ kind, node }); + } + // Assignment targets are resolved without counting as a use of the variable, since only reads count private resolveAssignmentTarget(node: AssignNode | TupleAssignmentNode, identifier: IdentifierNode): Symbol { const symbol = this.symbolTables[0].get(identifier.name); @@ -270,10 +271,6 @@ export default class SymbolTableTraversal extends AstTraversal { return symbol; } - - private collectUnusedSymbolWarnings(symbolTable: SymbolTable): void { - this.warnings.push(...symbolTable.getUnmarkedUnusedSymbols().map((symbol) => new UnusedVariableWarning(symbol))); - } } function validateModifiers( diff --git a/packages/cashc/src/semantic/UnusedCodeTraversal.ts b/packages/cashc/src/semantic/UnusedCodeTraversal.ts new file mode 100644 index 000000000..32276d932 --- /dev/null +++ b/packages/cashc/src/semantic/UnusedCodeTraversal.ts @@ -0,0 +1,129 @@ +import { + AssignNode, + BlockNode, + ContractNode, + DoWhileNode, + ForNode, + FunctionDefinitionNode, + IdentifierNode, + Node, + TupleAssignmentNode, + WhileNode, +} from '../ast/AST.js'; +import AstTraversal from '../ast/AstTraversal.js'; +import { Symbol, SymbolTable } from '../ast/SymbolTable.js'; +import { CashScriptWarningListener, UnusedAssignmentWarning, UnusedVariableWarning } from '../Warnings.js'; + +export default class UnusedCodeWarningsTraversal extends AstTraversal { + private pendingWrites: Map> = new Map>(); + private readWrites: Set = new Set(); + private reportedScopes: Set = new Set(); + + constructor(private warningListener: CashScriptWarningListener) { + super(); + } + + visitContract(node: ContractNode): Node { + super.visitContract(node); + this.collectUnusedVariableWarnings(node.symbolTable!); + return node; + } + + visitFunctionDefinition(node: FunctionDefinitionNode): Node { + super.visitFunctionDefinition(node); + this.collectUnusedVariableWarnings(node.symbolTable!); + this.collectUnusedAssignmentWarnings(); + return node; + } + + visitBlock(node: BlockNode): Node { + super.visitBlock(node); + this.collectUnusedVariableWarnings(node.symbolTable!); + return node; + } + + visitFor(node: ForNode): Node { + this.visit(node.init); + this.visitLoop(() => { + this.visit(node.condition); + this.visit(node.block); + this.visit(node.update); + }); + this.collectUnusedVariableWarnings(node.symbolTable!); + return node; + } + + visitWhile(node: WhileNode): Node { + this.visitLoop(() => { + this.visit(node.condition); + this.visit(node.block); + }); + return node; + } + + visitDoWhile(node: DoWhileNode): Node { + this.visitLoop(() => { + this.visit(node.block); + this.visit(node.condition); + }); + return node; + } + + // Loops are visited twice (in execution order), so that a read at the start of the loop is seen to follow + // a write later in the loop, as it does in the next iteration + private visitLoop(visitIteration: () => void): void { + visitIteration(); + visitIteration(); + } + + visitAssign(node: AssignNode): Node { + // The expression is visited before the write is recorded, so that reads inside the expression + // (e.g. x = x + 1) do not count as reading the assigned value + this.visit(node.expression); + this.recordWrite(node.identifier); + return node; + } + + visitTupleAssignment(node: TupleAssignmentNode): Node { + this.visit(node.tuple); + node.targets + .filter((target) => target.isReassignment) + .forEach((target) => this.recordWrite(target.identifier)); + return node; + } + + visitIdentifier(node: IdentifierNode): Node { + this.pendingWrites.get(node.symbol!)?.forEach((write) => this.readWrites.add(write)); + this.pendingWrites.delete(node.symbol!); + return node; + } + + private recordWrite(identifier: IdentifierNode): void { + if (this.readWrites.has(identifier)) return; + + const symbol = identifier.symbol!; + const pendingWrites = this.pendingWrites.get(symbol) ?? new Set(); + pendingWrites.add(identifier); + this.pendingWrites.set(symbol, pendingWrites); + } + + // Each scope is reported once, even though scopes inside loops are visited twice + private collectUnusedVariableWarnings(symbolTable: SymbolTable): void { + if (this.reportedScopes.has(symbolTable)) return; + this.reportedScopes.add(symbolTable); + + symbolTable.getUnmarkedUnusedSymbols().forEach((symbol) => this.warningListener(new UnusedVariableWarning(symbol))); + } + + // At the end of a function, every read that could follow its assignments has been visited + private collectUnusedAssignmentWarnings(): void { + this.pendingWrites.forEach((writes, symbol) => { + // Writes to a variable that is never read at all are covered by its unused variable warning + if (symbol.isUnused()) return; + writes.forEach((write) => this.warningListener(new UnusedAssignmentWarning(write))); + }); + + this.pendingWrites.clear(); + this.readWrites.clear(); + } +} diff --git a/packages/cashc/test/compiler/compiler.test.ts b/packages/cashc/test/compiler/compiler.test.ts index f589d11a7..7c5050007 100644 --- a/packages/cashc/test/compiler/compiler.test.ts +++ b/packages/cashc/test/compiler/compiler.test.ts @@ -52,9 +52,9 @@ describe('Compiler', () => { const expectedWarning = Warnings[warningType as keyof typeof Warnings]; if (!expectedWarning) throw new Error(`Invalid test configuration: warning ${warningType} does not exist`); - let warnings: Warnings.CashScriptWarning[] = []; + const warnings: Warnings.CashScriptWarning[] = []; try { - compileString(file.contents, { warningListener: (reported) => { warnings = reported; } }); + compileString(file.contents, { warningListener: (warning) => { warnings.push(warning); } }); } catch { // ignore compilation errors from later phases } @@ -112,7 +112,7 @@ describe('Compiler', () => { describe('Custom warning listener', () => { it('uses the custom warning listener for compilation warnings', () => { const warnings: Warnings.CashScriptWarning[] = []; - compileString(UNUSED_VARIABLE_SOURCE, { warningListener: (reported) => { warnings.push(...reported); } }); + compileString(UNUSED_VARIABLE_SOURCE, { warningListener: (warning) => { warnings.push(warning); } }); expect(warnings).toHaveLength(1); expect(warnings[0]).toBeInstanceOf(Warnings.UnusedVariableWarning); diff --git a/packages/cashc/test/warnings/UnusedAssignmentWarning/loop_reassignment_after_final_read.cash b/packages/cashc/test/warnings/UnusedAssignmentWarning/loop_reassignment_after_final_read.cash new file mode 100644 index 000000000..84bc843bf --- /dev/null +++ b/packages/cashc/test/warnings/UnusedAssignmentWarning/loop_reassignment_after_final_read.cash @@ -0,0 +1,12 @@ +contract Test() { + function spend(int a) { + int x = 1; + require(x == 1); + int i = 0; + while (i < a) { + x = i; + i = i + 1; + } + require(true); + } +} diff --git a/packages/cashc/test/warnings/UnusedAssignmentWarning/parameter_reassignment.cash b/packages/cashc/test/warnings/UnusedAssignmentWarning/parameter_reassignment.cash new file mode 100644 index 000000000..0c6c3fb8e --- /dev/null +++ b/packages/cashc/test/warnings/UnusedAssignmentWarning/parameter_reassignment.cash @@ -0,0 +1,7 @@ +contract Test() { + function spend(int a) { + require(a == 1); + a = 2; + require(true); + } +} diff --git a/packages/cashc/test/warnings/UnusedAssignmentWarning/reassignment_after_final_read.cash b/packages/cashc/test/warnings/UnusedAssignmentWarning/reassignment_after_final_read.cash new file mode 100644 index 000000000..605a93048 --- /dev/null +++ b/packages/cashc/test/warnings/UnusedAssignmentWarning/reassignment_after_final_read.cash @@ -0,0 +1,8 @@ +contract Test() { + function spend() { + int x = 1; + require(x == 1); + x = 2; + require(true); + } +} diff --git a/packages/cashc/test/warnings/UnusedAssignmentWarning/reassignment_in_branch.cash b/packages/cashc/test/warnings/UnusedAssignmentWarning/reassignment_in_branch.cash new file mode 100644 index 000000000..4dfdcf798 --- /dev/null +++ b/packages/cashc/test/warnings/UnusedAssignmentWarning/reassignment_in_branch.cash @@ -0,0 +1,10 @@ +contract Test(int a) { + function spend() { + int x = 1; + require(x == 1); + if (a > 0) { + x = 2; + } + require(true); + } +} diff --git a/packages/cashc/test/warnings/UnusedAssignmentWarning/self_referencing_reassignment.cash b/packages/cashc/test/warnings/UnusedAssignmentWarning/self_referencing_reassignment.cash new file mode 100644 index 000000000..6d865705e --- /dev/null +++ b/packages/cashc/test/warnings/UnusedAssignmentWarning/self_referencing_reassignment.cash @@ -0,0 +1,8 @@ +contract Test() { + function spend() { + int x = 1; + require(x == 1); + x = x + 1; + require(true); + } +} diff --git a/packages/cashc/test/warnings/UnusedAssignmentWarning/tuple_reassignment_after_final_read.cash b/packages/cashc/test/warnings/UnusedAssignmentWarning/tuple_reassignment_after_final_read.cash new file mode 100644 index 000000000..e04d9fa2a --- /dev/null +++ b/packages/cashc/test/warnings/UnusedAssignmentWarning/tuple_reassignment_after_final_read.cash @@ -0,0 +1,9 @@ +contract Test() { + function spend() { + bytes head = 0x00; + bytes tail = 0x01; + require(head == 0x00 && tail == 0x01); + (head, tail) = 0x1234.split(1); + require(true); + } +} diff --git a/website/docs/compiler/compiler.md b/website/docs/compiler/compiler.md index 25a8224f3..262083fc0 100644 --- a/website/docs/compiler/compiler.md +++ b/website/docs/compiler/compiler.md @@ -129,15 +129,15 @@ Imports inside imported files are resolved relative to the *importing* file, but ### Compilation Warnings -Some issues, such as unused variables that are not marked [`unused`](/docs/language/contracts#intentionally-unused-values), do not prevent compilation but produce a compiler warning instead. By default these warnings are printed with `console.warn`. When compiling from JavaScript, a custom `warningListener` can be passed as a compiler option to capture the structured warnings instead. It is called once per compilation with the full (possibly empty) list of warnings. The default listener is exported as `defaultWarningListener`, so a custom listener can compose with it to keep the standard console output. +Some issues, such as unused variables that are not marked [`unused`](/docs/language/contracts#intentionally-unused-values), do not prevent compilation but produce a compiler warning instead. By default these warnings are printed with `console.warn`. When compiling from JavaScript, a custom `warningListener` can be passed as a compiler option to capture the structured warnings instead. It is called for each warning. The default listener is exported as `defaultWarningListener`, so a custom listener can compose with it to keep the standard console output. ```ts import { compileString, defaultWarningListener } from 'cashc'; const P2PKH = compileString(source, { - warningListener: (warnings) => { - defaultWarningListener(warnings); // still print the warnings to the console - myDiagnostics.push(...warnings); + warningListener: (warning) => { + defaultWarningListener(warning); // still print the warning to the console + myDiagnostics.push(warning); }, }); ``` diff --git a/website/docs/language/contracts.md b/website/docs/language/contracts.md index feca2ef75..5712dd939 100644 --- a/website/docs/language/contracts.md +++ b/website/docs/language/contracts.md @@ -280,6 +280,8 @@ A parameter or local variable that is declared but never used results in a compi Some use cases for intentionally unused values include padding the contract bytecode in order to get a higher opcost budget, or nonces in order to differentiate between similar contracts. +The compiler also warns when a value is assigned to a variable that is never read afterwards, since such an assignment has no effect on the contract. + #### Example ```solidity diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 8cfd4c0f0..00432bf0e 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -12,7 +12,9 @@ title: Release Notes - :sparkles: Add support for top-level global constants. - :sparkles: Allow for simple arithmetic / concatenation operations in global constant definitions. - :sparkles: Add `unused` modifier for parameters or variables that are intentionally unused. -- :hammer_and_wrench: Unused variables that are not marked `unused` now produce a compiler warning instead of a compilation error. Warnings are printed with `console.warn`, or passed to the new `warningListener` compiler option. +- :hammer_and_wrench: Unused variables that are not marked `unused` now produce a compiler warning instead of a compilation error. Only reads count as usage, so variables that are only assigned to are reported as well. Warnings are printed with `console.warn`, or passed to the new `warningListener` compiler option. +- :sparkles: Add a compiler warning for values assigned to a variable that are never read afterwards. +- :racehorse: Treat parameters and variables that are never read the same as explicitly `unused`-marked ones: they are dropped from the stack immediately, and no parameter type enforcement is generated for them. - :sparkles: Add support for `import` directives to share user-defined functions across files. - :sparkles: Resolve package imports (e.g. `import "pkg/math.cash"`) from `node_modules`, so contract libraries can be installed as npm packages. - :sparkles: Add support for reassigning existing variables in tuple destructuring (e.g. `(a, b) = swap(a, b)`), optionally mixed with fresh declarations. From a39275c9a4b8af644d42bc098072b3a3e58545fd Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 15 Sep 2026 11:39:50 +0200 Subject: [PATCH 36/37] fix: check inputs' locking bytecode against unlocker locking bytecode + add tx validation to MockNetworkProvider --- packages/cashscript/src/Contract.ts | 8 +- packages/cashscript/src/Errors.ts | 17 ++++ packages/cashscript/src/SignatureTemplate.ts | 1 - packages/cashscript/src/TransactionBuilder.ts | 13 ++- packages/cashscript/src/debugging.ts | 27 +----- packages/cashscript/src/interfaces.ts | 10 +- .../cashscript/src/libauth-template/utils.ts | 43 ++++++++- .../src/network/ElectrumNetworkProvider.ts | 7 +- .../src/network/MockNetworkProvider.ts | 93 +++++++++++++------ .../cashscript/src/network/NetworkProvider.ts | 6 +- packages/cashscript/src/transaction-utils.ts | 14 +-- packages/cashscript/src/utils.ts | 69 ++++++++++++-- .../cashscript/src/walletconnect-utils.ts | 5 +- packages/cashscript/test/Contract.test.ts | 5 +- .../cashscript/test/SignatureTemplate.test.ts | 3 +- .../test/TransactionBuilder.test.ts | 79 ++++++++++++---- packages/cashscript/test/debugging.test.ts | 16 ++-- .../cashscript/test/e2e/MultiContract.test.ts | 8 +- .../e2e/network/MockNetworkProvider.test.ts | 53 +++++++++++ .../test/fixture/libauth-template/fixtures.ts | 5 +- packages/cashscript/test/test-util.ts | 19 ++-- .../test/types/Contract.types.test.ts | 6 +- website/docs/guides/cashtokens.md | 1 + website/docs/guides/optimization.md | 3 +- website/docs/releases/migration-notes.md | 16 ++++ website/docs/releases/release-notes.md | 9 +- website/docs/sdk/electrum-network-provider.md | 9 +- website/docs/sdk/instantiation.md | 7 +- website/docs/sdk/network-provider.md | 13 ++- website/docs/sdk/other-network-providers.md | 23 +++-- website/docs/sdk/transaction-builder.md | 6 +- 31 files changed, 434 insertions(+), 160 deletions(-) diff --git a/packages/cashscript/src/Contract.ts b/packages/cashscript/src/Contract.ts index ff784aeee..fc4170244 100644 --- a/packages/cashscript/src/Contract.ts +++ b/packages/cashscript/src/Contract.ts @@ -13,7 +13,7 @@ import { ConstructorArgument, encodeFunctionArgument, encodeConstructorArguments, FunctionArgument, } from './Argument.js'; import { - Unlocker, ContractOptions, GenerateUnlockingBytecodeOptions, Utxo, ContractType, ContractFunctionUnlocker, + Unlocker, ContractOptions, GenerateUnlockingBytecodeOptions, SpendableUtxo, ContractType, ContractFunctionUnlocker, } from './interfaces.js'; import NetworkProvider from './network/NetworkProvider.js'; import { @@ -84,7 +84,7 @@ class ContractBase { * * @returns A list of UTXOs spendable by this contract. */ - async getUtxos(): Promise { + async getUtxos(): Promise { if (this.contractType === 'p2s') { return this.provider.getUtxosForLockingBytecode(this.bytecode); } @@ -204,9 +204,7 @@ class ContractInternal< return unlockingBytecode; }; - const generateLockingBytecode = (): Uint8Array => hexToBin(this.lockingBytecode); - - return { generateUnlockingBytecode, generateLockingBytecode, contract: this, params: args, abiFunction }; + return { generateUnlockingBytecode, contract: this, params: args, abiFunction }; }; } } diff --git a/packages/cashscript/src/Errors.ts b/packages/cashscript/src/Errors.ts index dd12a9f07..9dc6ed82c 100644 --- a/packages/cashscript/src/Errors.ts +++ b/packages/cashscript/src/Errors.ts @@ -19,6 +19,12 @@ export class UndefinedInputError extends Error { } } +export class InputMissingLockingBytecodeError extends Error { + constructor() { + super('Input UTXO is missing its lockingBytecode. UTXOs fetched from a network provider include it automatically; when constructing UTXOs manually, set lockingBytecode to the hex-encoded locking script of the output.'); + } +} + export class OutputSatoshisTooSmallError extends Error { constructor(satoshis: bigint, minimumAmount: bigint) { super(`Tried to add an output with ${satoshis} satoshis, which is less than the required minimum for this output-type (${minimumAmount})`); @@ -97,6 +103,17 @@ export class UnlockingBytecodeTooLargeError extends Error { } } +export class UnlockerLockingBytecodeMismatchError extends Error { + constructor( + public inputIndex: number, + utxoLockScript: string, + unlockerLockScript: string, + unlockerDescription: string, + ) { + super(`Input #${inputIndex} is locked by ${utxoLockScript}, which does not match the provided unlocker (${unlockerDescription}, corresponding to ${unlockerLockScript}). This transaction would be rejected by the network. Make sure to use an unlocker that matches the address/contract holding the UTXO.`); + } +} + export class TransactionTooLargeError extends Error { constructor(size: number, maximumSize: number) { super(`Transaction size of ${size} is greater than the maximum standard transaction size of ${maximumSize}`); diff --git a/packages/cashscript/src/SignatureTemplate.ts b/packages/cashscript/src/SignatureTemplate.ts index eae5d5fad..f80246efe 100644 --- a/packages/cashscript/src/SignatureTemplate.ts +++ b/packages/cashscript/src/SignatureTemplate.ts @@ -87,7 +87,6 @@ export default class SignatureTemplate { const prevOutScript = publicKeyToP2PKHLockingBytecode(this.publicKey); return { - generateLockingBytecode: () => prevOutScript, generateUnlockingBytecode: ({ transaction, sourceOutputs, inputIndex }: GenerateUnlockingBytecodeOptions) => { const preimage = createSighashPreimage(transaction, sourceOutputs, inputIndex, prevOutScript, this.sighashType); const sighash = hash256(preimage); diff --git a/packages/cashscript/src/TransactionBuilder.ts b/packages/cashscript/src/TransactionBuilder.ts index 171c70285..daad50f24 100644 --- a/packages/cashscript/src/TransactionBuilder.ts +++ b/packages/cashscript/src/TransactionBuilder.ts @@ -12,7 +12,7 @@ import { Output, TransactionDetails, UnlockableUtxo, - Utxo, + SpendableUtxo, InputOptions, isUnlockableUtxo, isStandardUnlockableUtxo, @@ -34,6 +34,7 @@ import { getOutputSize, validateInput, validateOutput, + validateUnlocker, } from './utils.js'; import { FailedTransactionError, @@ -109,7 +110,7 @@ export class TransactionBuilder { * @returns This builder for chaining. * @throws If the UTXO is invalid. */ - addInput(utxo: Utxo, unlocker: Unlocker, options?: InputOptions): this { + addInput(utxo: SpendableUtxo, unlocker: Unlocker, options?: InputOptions): this { return this.addInputs([utxo], unlocker, options); } @@ -122,7 +123,7 @@ export class TransactionBuilder { * @returns This builder for chaining. * @throws If any UTXO is invalid. */ - addInputs(utxos: Utxo[], unlocker: Unlocker, options?: InputOptions): this; + addInputs(utxos: SpendableUtxo[], unlocker: Unlocker, options?: InputOptions): this; /** * Add multiple UTXOs that each carry their own unlocker. @@ -133,7 +134,7 @@ export class TransactionBuilder { */ addInputs(utxos: UnlockableUtxo[]): this; - addInputs(utxos: Utxo[] | UnlockableUtxo[], unlocker?: Unlocker, options?: InputOptions): this { + addInputs(utxos: SpendableUtxo[] | UnlockableUtxo[], unlocker?: Unlocker, options?: InputOptions): this { utxos.forEach((utxo) => validateInput(utxo, this.changeLocks)); if ( (!unlocker && utxos.some((utxo) => !isUnlockableUtxo(utxo))) @@ -142,6 +143,10 @@ export class TransactionBuilder { throw new Error('Either all UTXOs must have an individual unlocker specified, or no UTXOs must have an individual unlocker specified and a shared unlocker must be provided'); } + utxos.forEach((utxo, i) => ( + validateUnlocker(utxo, unlocker ?? (utxo as UnlockableUtxo).unlocker, this.inputs.length + i, this.provider.network) + )); + if (!unlocker) { this.inputs = this.inputs.concat(utxos as UnlockableUtxo[]); return this; diff --git a/packages/cashscript/src/debugging.ts b/packages/cashscript/src/debugging.ts index 3ad2a5df5..ca1d17dcc 100644 --- a/packages/cashscript/src/debugging.ts +++ b/packages/cashscript/src/debugging.ts @@ -1,38 +1,15 @@ -import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationProgramCommon, AuthenticationProgramStateCommon, AuthenticationVirtualMachine, ResolvedTransactionCommon, WalletTemplate, WalletTemplateScriptUnlocking, binToHex, createCompiler, createVirtualMachineBch2023, createVirtualMachineBch2025, createVirtualMachineBch2026, createVirtualMachineBchSpec, decodeAuthenticationInstructions, encodeAuthenticationInstruction, walletTemplateToCompilerConfiguration } from '@bitauth/libauth'; +import { AuthenticationErrorCommon, AuthenticationInstruction, AuthenticationProgramCommon, AuthenticationProgramStateCommon, WalletTemplate, WalletTemplateScriptUnlocking, binToHex, createCompiler, decodeAuthenticationInstructions, encodeAuthenticationInstruction, walletTemplateToCompilerConfiguration } from '@bitauth/libauth'; import { Artifact, LogData, LogEntry, Op, PrimitiveType, StackItem, asmToBytecode, bytecodeToAsm, decodeBool, decodeInt, decodeString } from '@cashscript/utils'; import { findLastIndex, toRegExp } from './utils.js'; import { FailedRequireError, FailedTransactionError, FailedTransactionEvaluationError } from './Errors.js'; import { attributeLogEntry, buildCallStack, getActiveBytecode, resolveFrame } from './debug-frame.js'; import { getBitauthUri } from './libauth-template/LibauthTemplate.js'; +import { createVirtualMachine, VM } from './libauth-template/utils.js'; import { VmTarget } from './interfaces.js'; export type DebugResult = AuthenticationProgramStateCommon[]; export type DebugResults = Record; -/* eslint-disable @typescript-eslint/indent */ -type VM = AuthenticationVirtualMachine< - ResolvedTransactionCommon, - AuthenticationProgramCommon, - AuthenticationProgramStateCommon ->; -/* eslint-enable @typescript-eslint/indent */ - -const createVirtualMachine = (vmTarget: VmTarget): VM => { - switch (vmTarget) { - case 'BCH_2023_05': - return createVirtualMachineBch2023(); - case 'BCH_2025_05': - return createVirtualMachineBch2025(); - case 'BCH_2026_05': - return createVirtualMachineBch2026(); - case 'BCH_SPEC': - // TODO: This typecast is shitty, but it's hard to fix - return createVirtualMachineBchSpec() as unknown as VM; - default: - throw new Error(`Debugging is not supported for the ${vmTarget} virtual machine.`); - } -}; - // debugs the template, optionally logging the execution data export const debugTemplate = (template: WalletTemplate, artifacts: Artifact[]): DebugResults => { // If a contract has the same name, but a different bytecode, then it is considered a name collision diff --git a/packages/cashscript/src/interfaces.ts b/packages/cashscript/src/interfaces.ts index 009b672eb..793b02e23 100644 --- a/packages/cashscript/src/interfaces.ts +++ b/packages/cashscript/src/interfaces.ts @@ -10,9 +10,14 @@ export interface Utxo { vout: number; satoshis: bigint; token?: TokenDetails; + lockingBytecode?: string; } -export interface UnlockableUtxo extends Utxo { +export interface SpendableUtxo extends Utxo { + lockingBytecode: string; +} + +export interface UnlockableUtxo extends SpendableUtxo { unlocker: Unlocker; options?: InputOptions; } @@ -40,7 +45,6 @@ export interface GenerateUnlockingBytecodeOptions { } export interface Unlocker { - generateLockingBytecode: () => Uint8Array; generateUnlockingBytecode: (options: GenerateUnlockingBytecodeOptions) => Uint8Array; } @@ -56,7 +60,7 @@ export interface P2PKHUnlocker extends Unlocker { export type StandardUnlocker = ContractUnlocker | P2PKHUnlocker; -export type PlaceholderP2PKHUnlocker = Unlocker & { placeholder: true }; +export type PlaceholderP2PKHUnlocker = Unlocker & { placeholder: true, lockingBytecode: string }; export type ContractFunctionUnlocker = (...args: FunctionArgument[]) => ContractUnlocker; diff --git a/packages/cashscript/src/libauth-template/utils.ts b/packages/cashscript/src/libauth-template/utils.ts index 8c4d0a5c7..7e3f0bea2 100644 --- a/packages/cashscript/src/libauth-template/utils.ts +++ b/packages/cashscript/src/libauth-template/utils.ts @@ -1,6 +1,23 @@ import { AbiFunction, AbiInput, Artifact, formatBitAuthScript, sha256 } from '@cashscript/utils'; import { LibauthTokenDetails, SighashType, SignatureAlgorithm, TokenDetails, VmTarget } from '../interfaces.js'; -import { hexToBin, binToHex, isHex, decodeCashAddress, Input, assertSuccess, decodeAuthenticationInstructions, AuthenticationInstructionPush } from '@bitauth/libauth'; +import { + hexToBin, + binToHex, + isHex, + decodeCashAddress, + Input, + assertSuccess, + decodeAuthenticationInstructions, + AuthenticationInstructionPush, + AuthenticationProgramCommon, + AuthenticationProgramStateCommon, + AuthenticationVirtualMachine, + ResolvedTransactionCommon, + createVirtualMachineBch2023, + createVirtualMachineBch2025, + createVirtualMachineBch2026, + createVirtualMachineBchSpec, +} from '@bitauth/libauth'; import { EncodedFunctionArgument } from '../Argument.js'; import { zip } from '../utils.js'; import SignatureTemplate from '../SignatureTemplate.js'; @@ -8,6 +25,30 @@ import { Contract } from '../Contract.js'; export const DEFAULT_VM_TARGET = VmTarget.BCH_2026_05; +/* eslint-disable @typescript-eslint/indent */ +export type VM = AuthenticationVirtualMachine< + ResolvedTransactionCommon, + AuthenticationProgramCommon, + AuthenticationProgramStateCommon +>; +/* eslint-enable @typescript-eslint/indent */ + +export const createVirtualMachine = (vmTarget: VmTarget): VM => { + switch (vmTarget) { + case 'BCH_2023_05': + return createVirtualMachineBch2023(); + case 'BCH_2025_05': + return createVirtualMachineBch2025(); + case 'BCH_2026_05': + return createVirtualMachineBch2026(); + case 'BCH_SPEC': + // TODO: This typecast is shitty, but it's hard to fix + return createVirtualMachineBchSpec() as unknown as VM; + default: + throw new Error(`Evaluation is not supported for the ${vmTarget} virtual machine.`); + } +}; + export const getLockScriptName = (contract: Contract): string => { if (contract.contractType === 'p2s') { return `${contract.artifact.contractName}_${binToHex(sha256(hexToBin(contract.lockingBytecode)))}_lock`; diff --git a/packages/cashscript/src/network/ElectrumNetworkProvider.ts b/packages/cashscript/src/network/ElectrumNetworkProvider.ts index 432e014ff..f3e06a0a5 100644 --- a/packages/cashscript/src/network/ElectrumNetworkProvider.ts +++ b/packages/cashscript/src/network/ElectrumNetworkProvider.ts @@ -5,7 +5,7 @@ import { type RequestResponse, type ElectrumClientEvents, } from '@electrum-cash/network'; -import { Utxo, Network } from '../interfaces.js'; +import { SpendableUtxo, Network } from '../interfaces.js'; import NetworkProvider from './NetworkProvider.js'; import { addressToLockScript } from '../utils.js'; import { @@ -75,12 +75,12 @@ export default class ElectrumNetworkProvider implements NetworkProvider { } } - async getUtxos(address: string): Promise { + async getUtxos(address: string): Promise { const lockingBytecode = addressToLockScript(address); return this.getUtxosForLockingBytecode(lockingBytecode); } - async getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise { + async getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise { if (typeof lockingBytecode === 'string' && !isHex(lockingBytecode)) { throw new Error(`Invalid locking bytecode: ${lockingBytecode} is not a valid hex string`); } @@ -94,6 +94,7 @@ export default class ElectrumNetworkProvider implements NetworkProvider { txid: utxo.tx_hash, vout: utxo.tx_pos, satoshis: BigInt(utxo.value), + lockingBytecode: binToHex(lockingBytecodeBin), token: utxo.token_data ? { ...utxo.token_data, amount: BigInt(utxo.token_data.amount), diff --git a/packages/cashscript/src/network/MockNetworkProvider.ts b/packages/cashscript/src/network/MockNetworkProvider.ts index 0cb4d0e77..6fe888e54 100644 --- a/packages/cashscript/src/network/MockNetworkProvider.ts +++ b/packages/cashscript/src/network/MockNetworkProvider.ts @@ -1,9 +1,9 @@ -import { binToHex, decodeTransactionUnsafe, hexToBin, isHex } from '@bitauth/libauth'; +import { binToHex, decodeTransactionUnsafe, hexToBin, isHex, Transaction as LibauthTransaction } from '@bitauth/libauth'; import { sha256 } from '@cashscript/utils'; -import { Utxo, Network, VmTarget } from '../interfaces.js'; +import { SpendableUtxo, Utxo, Network, VmTarget } from '../interfaces.js'; import NetworkProvider from './NetworkProvider.js'; -import { addressToLockScript, libauthTokenDetailsToCashScriptTokenDetails } from '../utils.js'; -import { DEFAULT_VM_TARGET } from '../libauth-template/utils.js'; +import { addressToLockScript, cashScriptOutputToLibauthOutput, libauthTokenDetailsToCashScriptTokenDetails } from '../utils.js'; +import { createVirtualMachine, DEFAULT_VM_TARGET } from '../libauth-template/utils.js'; /** * Options accepted by the `MockNetworkProvider` constructor. @@ -15,7 +15,14 @@ export interface MockNetworkProviderOptions { * keep the UTXO set static. */ updateUtxoSet?: boolean; - /** The BCH VM target used for local debugging. Defaults to the current stable VM. */ + /** + * When `true` (default), broadcasting a transaction via `sendRawTransaction` evaluates it + * against the BCH VM using the *actual* locking bytecode of the spent UTXOs (like a real node + * would), rejecting invalid transactions. Requires `updateUtxoSet` to be enabled, since spent + * UTXOs are only looked up when the UTXO set is tracked. + */ + validateTransactions?: boolean; + /** The BCH VM target used for local debugging and transaction validation. Defaults to the current stable VM. */ vmTarget?: VmTarget; } @@ -26,7 +33,7 @@ export interface MockNetworkProviderOptions { */ export default class MockNetworkProvider implements NetworkProvider { // we use lockingBytecode hex as the key for utxoMap to make cash addresses and token addresses interchangeable - private utxoSet: Array<[string, Utxo]> = []; + private utxoSet: Array<[string, SpendableUtxo]> = []; private transactionMap: Record = {}; private blockHeight: number = 133700; public network: Network = Network.MOCKNET; @@ -40,16 +47,16 @@ export default class MockNetworkProvider implements NetworkProvider { * `TransactionBuilder.debug`. */ constructor(options?: Partial) { - this.options = { updateUtxoSet: true, ...options }; + this.options = { updateUtxoSet: true, validateTransactions: true, ...options }; this.vmTarget = this.options.vmTarget ?? DEFAULT_VM_TARGET; } - async getUtxos(address: string): Promise { + async getUtxos(address: string): Promise { const addressLockingBytecode = addressToLockScript(address); return this.getUtxosForLockingBytecode(addressLockingBytecode); } - async getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise { + async getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise { const lockingBytecodeHex = typeof lockingBytecode === 'string' ? lockingBytecode : binToHex(lockingBytecode); return this.utxoSet.filter(([key]) => key === lockingBytecodeHex).map(([, utxo]) => utxo); } @@ -81,25 +88,21 @@ export default class MockNetworkProvider implements NetworkProvider { return txid; } - this.transactionMap[txid] = txHex; - - // If updateUtxoSet is false, we don't need to update the utxo set, and just return the txid - if (!this.options.updateUtxoSet) return txid; + // If updateUtxoSet is false, we don't track spent UTXOs, so we cannot validate the transaction either + if (!this.options.updateUtxoSet) { + this.transactionMap[txid] = txHex; + return txid; + } const decodedTransaction = decodeTransactionUnsafe(transactionBin); + const spentUtxoEntries = this.findSpentUtxoEntries(decodedTransaction, txid); - decodedTransaction.inputs.forEach((input) => { - const utxoIndex = this.utxoSet.findIndex( - ([, utxo]) => utxo.txid === binToHex(input.outpointTransactionHash) && utxo.vout === input.outpointIndex, - ); - - // TODO: we should check what error a BCHN node throws, so we can throw the same error here - if (utxoIndex === -1) { - throw new Error(`UTXO not found for input ${input.outpointIndex} of transaction ${txid}`); - } + if (this.options.validateTransactions) { + this.validateTransaction(decodedTransaction, spentUtxoEntries); + } - this.utxoSet.splice(utxoIndex, 1); - }); + this.transactionMap[txid] = txHex; + this.utxoSet = this.utxoSet.filter((entry) => !spentUtxoEntries.includes(entry)); decodedTransaction.outputs.forEach((output, vout) => { this.addUtxo(binToHex(output.lockingBytecode), { @@ -113,6 +116,39 @@ export default class MockNetworkProvider implements NetworkProvider { return txid; } + private findSpentUtxoEntries(transaction: LibauthTransaction, txid: string): Array<[string, SpendableUtxo]> { + const remainingUtxoEntries = [...this.utxoSet]; + + return transaction.inputs.map((input) => { + const utxoIndex = remainingUtxoEntries.findIndex( + ([, utxo]) => utxo.txid === binToHex(input.outpointTransactionHash) && utxo.vout === input.outpointIndex, + ); + + // TODO: we should check what error a BCHN node throws, so we can throw the same error here + if (utxoIndex === -1) { + throw new Error(`UTXO not found for input ${input.outpointIndex} of transaction ${txid}`); + } + + return remainingUtxoEntries.splice(utxoIndex, 1)[0]; + }); + } + + // Evaluates the transaction against the BCH VM using the spent UTXOs (like a real node would) + private validateTransaction(transaction: LibauthTransaction, spentUtxoEntries: Array<[string, SpendableUtxo]>): void { + const sourceOutputs = spentUtxoEntries.map(([lockingBytecode, utxo]) => cashScriptOutputToLibauthOutput({ + to: hexToBin(lockingBytecode), + amount: utxo.satoshis, + token: utxo.token, + })); + + const vm = createVirtualMachine(this.vmTarget); + const verificationResult = vm.verify({ transaction, sourceOutputs }); + + if (verificationResult !== true) { + throw new Error(verificationResult); + } + } + // Note: the user can technically add the same UTXO multiple times (txid + vout), to the same or different addresses // but we don't check for this in the sendRawTransaction method. We might want to prevent duplicates from being added // in the first place. @@ -122,14 +158,15 @@ export default class MockNetworkProvider implements NetworkProvider { * * @param addressOrLockingBytecode - Either a CashAddress or a hex-encoded locking bytecode. * @param utxo - The UTXO to make spendable. - * @returns The added UTXO. + * @returns The added UTXO, annotated with the locking bytecode it was added under. */ - addUtxo(addressOrLockingBytecode: string, utxo: Utxo): Utxo { + addUtxo(addressOrLockingBytecode: string, utxo: Utxo): SpendableUtxo { const lockingBytecode = isHex(addressOrLockingBytecode) ? addressOrLockingBytecode : binToHex(addressToLockScript(addressOrLockingBytecode)); - this.utxoSet.push([lockingBytecode, utxo]); - return utxo; + const annotatedUtxo = { ...utxo, lockingBytecode }; + this.utxoSet.push([lockingBytecode, annotatedUtxo]); + return annotatedUtxo; } /** diff --git a/packages/cashscript/src/network/NetworkProvider.ts b/packages/cashscript/src/network/NetworkProvider.ts index e966982b4..62e95145e 100644 --- a/packages/cashscript/src/network/NetworkProvider.ts +++ b/packages/cashscript/src/network/NetworkProvider.ts @@ -1,4 +1,4 @@ -import { Utxo, Network } from '../interfaces.js'; +import { SpendableUtxo, Network } from '../interfaces.js'; export default interface NetworkProvider { /** @@ -11,14 +11,14 @@ export default interface NetworkProvider { * @param address The CashAddress for which we wish to retrieve UTXOs. * @returns List of UTXOs spendable by the provided address. */ - getUtxos(address: string): Promise; + getUtxos(address: string): Promise; /** * Retrieve all UTXOs (confirmed and unconfirmed) for a given locking bytecode. * @param lockingBytecode The locking bytecode for which we wish to retrieve UTXOs. * @returns List of UTXOs spendable by the provided locking bytecode. */ - getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise; + getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise; /** * @returns The current block height. diff --git a/packages/cashscript/src/transaction-utils.ts b/packages/cashscript/src/transaction-utils.ts index 9f4c7741e..1373ef2c6 100644 --- a/packages/cashscript/src/transaction-utils.ts +++ b/packages/cashscript/src/transaction-utils.ts @@ -5,8 +5,8 @@ import { isFungibleTokenUtxo, isNonTokenUtxo } from './utils.js'; * Result of `gatherBchUtxos` and `gatherFungibleTokenUtxos`: the selected UTXOs and the total * amount they cover (satoshis for BCH, token amount for fungible tokens). */ -export interface GatherUtxosResult { - utxos: Utxo[]; +export interface GatherUtxosResult { + utxos: U[]; totalAmount: bigint; } @@ -19,12 +19,12 @@ export interface GatherUtxosResult { * @returns The selected UTXOs and their cumulative satoshi amount. * @throws If the available non-token UTXOs do not cover the requested amount. */ -export function gatherBchUtxos(utxos: Utxo[], amount: bigint): GatherUtxosResult { +export function gatherBchUtxos(utxos: U[], amount: bigint): GatherUtxosResult { const sortedBchUtxos = utxos .filter(isNonTokenUtxo) .toSorted((a, b) => Number(b.satoshis - a.satoshis)); - const targetUtxos: Utxo[] = []; + const targetUtxos: U[] = []; let total = 0n; for (const utxo of sortedBchUtxos) { @@ -50,12 +50,14 @@ export function gatherBchUtxos(utxos: Utxo[], amount: bigint): GatherUtxosResult * @returns The selected UTXOs and their cumulative token amount. * @throws If the available fungible token UTXOs do not cover the requested amount. */ -export function gatherFungibleTokenUtxos(utxos: Utxo[], tokenCategory: string, amount: bigint): GatherUtxosResult { +export function gatherFungibleTokenUtxos( + utxos: U[], tokenCategory: string, amount: bigint, +): GatherUtxosResult { const sortedTokenUtxos = utxos .filter((utxo) => isFungibleTokenUtxo(utxo) && utxo.token!.category === tokenCategory) .toSorted((a, b) => Number(b.token!.amount - a.token!.amount)); - const targetUtxos: Utxo[] = []; + const targetUtxos: U[] = []; let total = 0n; for (const utxo of sortedTokenUtxos) { diff --git a/packages/cashscript/src/utils.ts b/packages/cashscript/src/utils.ts index d13b96cff..e8a2744bf 100644 --- a/packages/cashscript/src/utils.ts +++ b/packages/cashscript/src/utils.ts @@ -37,13 +37,20 @@ import { LibauthTokenDetails, ContractType, SighashType, + SpendableUtxo, + Unlocker, + isContractUnlocker, + isP2PKHUnlocker, + isPlaceholderUnlocker, } from './interfaces.js'; import { VERSION_SIZE, LOCKTIME_SIZE } from './constants.js'; import { OutputSatoshisTooSmallError, OutputTokenAmountTooSmallError, TokensToNonTokenAddressError, + InputMissingLockingBytecodeError, UndefinedInputError, + UnlockerLockingBytecodeMismatchError, OutputAddressNetworkMismatchError, OutputTokenCategoryInvalidError, OutputTokenCommitmentInvalidError, @@ -59,9 +66,57 @@ export function validateInput(utxo: Utxo, changeLocks: Record): throw new UndefinedInputError(); } + if (!utxo.lockingBytecode) { + throw new InputMissingLockingBytecodeError(); + } + validateChangeLocks(changeLocks, utxo.token?.category); } +// A UTXO/unlocker mismatch would be rejected by the network, so we catch it locally with a descriptive error +export function validateUnlocker(utxo: SpendableUtxo, unlocker: Unlocker, inputIndex: number, network: Network): void { + const unlockerLockingBytecode = getUnlockerLockingBytecode(unlocker); + if (unlockerLockingBytecode === undefined || utxo.lockingBytecode === unlockerLockingBytecode) return; + + throw new UnlockerLockingBytecodeMismatchError( + inputIndex, + formatLockingBytecode(utxo.lockingBytecode, network), + formatLockingBytecode(unlockerLockingBytecode, network), + describeUnlocker(unlocker), + ); +} + +// The locking bytecode this unlocker is able to unlock +function getUnlockerLockingBytecode(unlocker: Unlocker): string | undefined { + if (isContractUnlocker(unlocker)) return unlocker.contract.lockingBytecode; + if (isP2PKHUnlocker(unlocker)) return binToHex(publicKeyToP2PKHLockingBytecode(unlocker.template.publicKey)); + if (isPlaceholderUnlocker(unlocker)) return unlocker.lockingBytecode; + return undefined; +} + +function describeUnlocker(unlocker: Unlocker): string { + if (isContractUnlocker(unlocker)) { + return `unlocker for function "${unlocker.abiFunction.name}" of contract "${unlocker.contract.name}"`; + } + + if (isP2PKHUnlocker(unlocker)) { + return `P2PKH unlocker for public key ${binToHex(unlocker.template.publicKey)}`; + } + + if (isPlaceholderUnlocker(unlocker)) { + return 'placeholder P2PKH unlocker'; + } + + return 'custom unlocker'; +} + +function formatLockingBytecode(lockingBytecode: string, network: Network): string { + const prefix = getNetworkPrefix(network); + const result = lockingBytecodeToCashAddress({ bytecode: hexToBin(lockingBytecode), prefix }); + if (typeof result === 'string') return `locking bytecode ${lockingBytecode}`; + return `address ${result.address} (locking bytecode ${lockingBytecode})`; +} + export function validateOutput(output: Output, network: Network, changeLocks: Record): void { validateChangeLocks(changeLocks, output.token?.category); @@ -179,7 +234,7 @@ export function generateLibauthSourceOutputs(inputs: UnlockableUtxo[]): LibauthO const sourceOutputs = inputs.map((input) => { const sourceOutput = { amount: input.satoshis, - to: input.unlocker.generateLockingBytecode(), + to: hexToBin(input.lockingBytecode), token: input.token, }; @@ -371,14 +426,12 @@ const randomInt = (): bigint => BigInt(Math.floor(Math.random() * 10000)); * @param defaults - Values that override the randomly generated fields. * @returns A synthetic UTXO with random `txid`, `vout`, and `satoshis`. */ -export const randomUtxo = (defaults?: Partial): Utxo => ({ - ...{ - txid: binToHex(sha256(bigIntToVmNumber(randomInt()))), - vout: Math.floor(Math.random() * 10), - satoshis: 100_000n + randomInt(), - }, +export const randomUtxo = >(defaults?: T): Utxo & T => ({ + txid: binToHex(sha256(bigIntToVmNumber(randomInt()))), + vout: Math.floor(Math.random() * 10), + satoshis: 100_000n + randomInt(), ...defaults, -}); +} as Utxo & T); /** * Generate random fungible `TokenDetails` for use in tests and examples. Fields can be overridden diff --git a/packages/cashscript/src/walletconnect-utils.ts b/packages/cashscript/src/walletconnect-utils.ts index d4c7cd3a2..140ab3427 100644 --- a/packages/cashscript/src/walletconnect-utils.ts +++ b/packages/cashscript/src/walletconnect-utils.ts @@ -1,6 +1,6 @@ import { type LibauthOutput, isContractUnlocker, type PlaceholderP2PKHUnlocker, type UnlockableUtxo } from './interfaces.js'; import { type AbiFunction, type Artifact } from '@cashscript/utils'; -import { cashAddressToLockingBytecode, hexToBin, type Input, type TransactionCommon } from '@bitauth/libauth'; +import { binToHex, cashAddressToLockingBytecode, hexToBin, type Input, type TransactionCommon } from '@bitauth/libauth'; // Wallet Connect interfaces according to the spec // see https://github.com/mainnet-pat/wc2-bch-bcr @@ -80,10 +80,9 @@ export const placeholderP2PKHUnlocker = (userAddress: string): PlaceholderP2PKHU throw new Error(`Invalid address: ${decodeAddressResult}`); } - const lockingBytecode = decodeAddressResult.bytecode; return { - generateLockingBytecode: () => lockingBytecode, generateUnlockingBytecode: () => Uint8Array.from(Array(0)), placeholder: true, + lockingBytecode: binToHex(decodeAddressResult.bytecode), }; }; diff --git a/packages/cashscript/test/Contract.test.ts b/packages/cashscript/test/Contract.test.ts index 0125f070b..bd9c39b41 100644 --- a/packages/cashscript/test/Contract.test.ts +++ b/packages/cashscript/test/Contract.test.ts @@ -182,8 +182,8 @@ describe('Contract', () => { }); it('generates correct locking bytecode', () => { - expect(instance.unlock.spend(alicePub, new SignatureTemplate(alicePriv)).generateLockingBytecode()) - .toEqual(hexToBin('aa2034d9ffce86b4d136ca74e9db6f6433d3548966a6be064052e728a4c1d16aa3a587')); + expect(instance.lockingBytecode) + .toEqual('aa2034d9ffce86b4d136ca74e9db6f6433d3548966a6be064052e728a4c1d16aa3a587'); }); it('can spend from a p2s contract', async () => { @@ -205,6 +205,7 @@ describe('Contract', () => { txid: 'e5ac1aa9730d7514b541895e466c987327a4b0c57fcbbd50fc73788f5c0f65d9', vout: 4, satoshis: 102745n, + lockingBytecode: instance.lockingBytecode, }; const unlocker = instance.unlock.spend(alicePub, new SignatureTemplate(alicePriv)); diff --git a/packages/cashscript/test/SignatureTemplate.test.ts b/packages/cashscript/test/SignatureTemplate.test.ts index c21f9588f..24fd070bf 100644 --- a/packages/cashscript/test/SignatureTemplate.test.ts +++ b/packages/cashscript/test/SignatureTemplate.test.ts @@ -69,13 +69,12 @@ describe('SignatureTemplate', () => { txid: '043ec3826702c45460a6dd6b13e343a8f1bc06bc047b63ca484f791dfdfd92c2', vout: 8, satoshis: 109759n, + lockingBytecode: '76a914512dbb2c8c02efbac8d92431aa0ac33f6b0bf97088ac', }; const signatureTemplate = new SignatureTemplate(alicePriv); const unlocker = signatureTemplate.unlockP2PKH(); - expect(unlocker.generateLockingBytecode()).toEqual(hexToBin('76a914512dbb2c8c02efbac8d92431aa0ac33f6b0bf97088ac')); - const transactionBuilder = new TransactionBuilder({ provider: new MockNetworkProvider() }) .addInput(utxo, unlocker) .addOutput({ to: aliceAddress, amount: 1000n }); diff --git a/packages/cashscript/test/TransactionBuilder.test.ts b/packages/cashscript/test/TransactionBuilder.test.ts index bb81be5b7..c07c4e5a3 100644 --- a/packages/cashscript/test/TransactionBuilder.test.ts +++ b/packages/cashscript/test/TransactionBuilder.test.ts @@ -14,7 +14,7 @@ import { carolTokenAddress, alicePriv, } from './fixture/vars.js'; -import { Network } from '../src/interfaces.js'; +import { Network, SpendableUtxo, Utxo } from '../src/interfaces.js'; import { utxoComparator, calculateDust, randomUtxo, randomToken, isNonTokenUtxo, isFungibleTokenUtxo } from '../src/utils.js'; import p2pkhArtifact from './fixture/p2pkh.artifact.js'; import twtArtifact from './fixture/transfer_with_timeout.artifact.js'; @@ -22,9 +22,11 @@ import { TransactionBuilder } from '../src/TransactionBuilder.js'; import { addUtxo, getTxOutputs } from './test-util.js'; import { generateWcTransactionObjectFixture } from './fixture/walletconnect/fixtures.js'; import { + InputMissingLockingBytecodeError, OutputBchChangeLockedError, OutputTokenChangeLockedError, TokensToNonTokenAddressError, + UnlockerLockingBytecodeMismatchError, } from '../src/Errors.js'; import { FailingMockNetworkProvider } from '../src/network/MockNetworkProvider.js'; @@ -223,6 +225,45 @@ describe('Transaction Builder', () => { }); }); + describe('UTXO / unlocker mismatch checks', () => { + it('should fail when spending a contract UTXO with an unlocker of a different contract', async () => { + const p2pkhUtxos = (await p2pkhInstance.getUtxos()).filter(isNonTokenUtxo); + + expect(() => ( + new TransactionBuilder({ provider }) + .addInput(p2pkhUtxos[0], twtInstance.unlock.transfer(new SignatureTemplate(carolPriv))) + )).toThrow(UnlockerLockingBytecodeMismatchError); + }); + + it('should fail when spending a contract UTXO with an unlocker of the same contract with a different address type', async () => { + const p2sh20Instance = new Contract(p2pkhArtifact, [carolPkh], { provider, contractType: 'p2sh20' }); + const p2pkhUtxos = (await p2pkhInstance.getUtxos()).filter(isNonTokenUtxo); + + expect(() => ( + new TransactionBuilder({ provider }) + .addInput(p2pkhUtxos[0], p2sh20Instance.unlock.spend(carolPub, new SignatureTemplate(carolPriv))) + )).toThrow(UnlockerLockingBytecodeMismatchError); + }); + + it('should fail when spending a P2PKH UTXO with a SignatureTemplate for a different key', async () => { + const aliceUtxos = (await provider.getUtxos(aliceAddress)).filter(isNonTokenUtxo); + + expect(() => ( + new TransactionBuilder({ provider }) + .addInput(aliceUtxos[0], new SignatureTemplate(bobPriv).unlockP2PKH()) + )).toThrow(UnlockerLockingBytecodeMismatchError); + }); + + it('should fail when adding a UTXO without a lockingBytecode', async () => { + const utxoWithoutLockingBytecode = randomUtxo() as SpendableUtxo; + + expect(() => ( + new TransactionBuilder({ provider }) + .addInput(utxoWithoutLockingBytecode, new SignatureTemplate(bobPriv).unlockP2PKH()) + )).toThrow(InputMissingLockingBytecodeError); + }); + }); + describe('test TransactionBuilder.generateWcTransactionObject', () => { it('should match the generateWcTransactionObjectFixture ', async () => { const p2pkhUtxos = (await p2pkhInstance.getUtxos()).filter(isNonTokenUtxo).sort(utxoComparator).reverse(); @@ -304,7 +345,7 @@ describe('Transaction Builder', () => { it('should preserve the Bitauth URI when broadcast fails', async () => { const failingProvider = new FailingMockNetworkProvider(); const contract = new Contract(p2pkhArtifact, [carolPkh], { provider: failingProvider }); - const utxo = randomUtxo({ satoshis: 100_000n }); + const utxo = failingProvider.addUtxo(contract.address, randomUtxo({ satoshis: 100_000n })); const transaction = new TransactionBuilder({ provider: failingProvider }) .addInput(utxo, contract.unlock.spend(carolPub, new SignatureTemplate(carolPriv))) @@ -356,14 +397,18 @@ describe('Transaction Builder', () => { p2pkhInstance.unlock.spend(carolPub, new SignatureTemplate(carolPriv)) ); + const randomContractUtxo = (defaults?: Partial): SpendableUtxo => ( + randomUtxo({ ...defaults, lockingBytecode: p2pkhInstance.lockingBytecode }) + ); + describe('BCH change lock', () => { it('should prevent further inputs or outputs after a BCH change output was added', () => { const builder = new TransactionBuilder({ provider }) - .addInput(randomUtxo(), carolUnlocker()) + .addInput(randomContractUtxo(), carolUnlocker()) .addOutput({ to: bobAddress, amount: 1000n }) .addBchChangeOutputIfNeeded({ to: aliceAddress, feeRate: 1.0 }); - expect(() => builder.addInput(randomUtxo(), carolUnlocker())).toThrow(OutputBchChangeLockedError); + expect(() => builder.addInput(randomContractUtxo(), carolUnlocker())).toThrow(OutputBchChangeLockedError); expect(() => builder.addOutput({ to: bobAddress, amount: 1000n })).toThrow(OutputBchChangeLockedError); expect(() => builder.addOpReturnOutput(['hello'])).toThrow(OutputBchChangeLockedError); }); @@ -371,7 +416,7 @@ describe('Transaction Builder', () => { it('should still lock when no change output was added because the surplus would be dust', () => { // Output leaves only a few satoshis of surplus, well below dust — no change output is added const builder = new TransactionBuilder({ provider }) - .addInput(randomUtxo({ satoshis: 2_000n }), carolUnlocker()) + .addInput(randomContractUtxo({ satoshis: 2_000n }), carolUnlocker()) .addOutput({ to: bobAddress, amount: 1_500n }); const outputCountBefore = builder.outputs.length; builder.addBchChangeOutputIfNeeded({ to: aliceAddress, feeRate: 1.0 }); @@ -385,10 +430,10 @@ describe('Transaction Builder', () => { it('should prevent further inputs or outputs of the same category after a token change output was added', () => { const token = randomToken(); const builder = new TransactionBuilder({ provider }) - .addInput(randomUtxo({ token }), carolUnlocker()) + .addInput(randomContractUtxo({ token }), carolUnlocker()) .addTokenChangeOutputIfNeeded({ category: token.category, to: aliceTokenAddress }); - expect(() => builder.addInput(randomUtxo({ token }), carolUnlocker())).toThrow(OutputTokenChangeLockedError); + expect(() => builder.addInput(randomContractUtxo({ token }), carolUnlocker())).toThrow(OutputTokenChangeLockedError); expect(() => builder.addOutput({ to: bobTokenAddress, amount: 1000n, token: { amount: 100n, category: token.category }, })).toThrow(OutputTokenChangeLockedError); @@ -398,13 +443,13 @@ describe('Transaction Builder', () => { const tokenA = randomToken(); const tokenB = randomToken(); const builder = new TransactionBuilder({ provider }) - .addInput(randomUtxo({ token: tokenA }), carolUnlocker()) + .addInput(randomContractUtxo({ token: tokenA }), carolUnlocker()) .addTokenChangeOutputIfNeeded({ category: tokenA.category, to: aliceTokenAddress }); expect(() => { - builder.addInput(randomUtxo({ token: tokenB }), carolUnlocker()); + builder.addInput(randomContractUtxo({ token: tokenB }), carolUnlocker()); builder.addOutput({ to: bobTokenAddress, amount: 1000n, token: { amount: 100n, category: tokenB.category } }); - builder.addInput(randomUtxo(), carolUnlocker()); + builder.addInput(randomContractUtxo(), carolUnlocker()); builder.addOutput({ to: bobAddress, amount: 1000n }); builder.addOpReturnOutput(['hello']); }).not.toThrow(); @@ -416,7 +461,7 @@ describe('Transaction Builder', () => { const token = randomToken({ amount: 1000n }); const tx = new TransactionBuilder({ provider }) - .addInput(randomUtxo({ token }), carolUnlocker()) + .addInput(randomContractUtxo({ token }), carolUnlocker()) .addOutput({ to: bobTokenAddress, amount: 1000n, token: { amount: 400n, category: token.category } }) .addTokenChangeOutputIfNeeded({ category: token.category, to: aliceTokenAddress }) .build(); @@ -431,14 +476,14 @@ describe('Transaction Builder', () => { it('should lock the category without adding an output when no change is needed', () => { const token = randomToken({ amount: 1000n }); const builder = new TransactionBuilder({ provider }) - .addInput(randomUtxo({ token }), carolUnlocker()) + .addInput(randomContractUtxo({ token }), carolUnlocker()) // Match input amount with an explicit output so there's no surplus .addOutput({ to: bobTokenAddress, amount: 1000n, token: { amount: 1000n, category: token.category } }); const outputCountBefore = builder.outputs.length; builder.addTokenChangeOutputIfNeeded({ category: token.category, to: aliceTokenAddress }); expect(builder.outputs.length).toBe(outputCountBefore); - expect(() => builder.addInput(randomUtxo({ token }), carolUnlocker())).toThrow(OutputTokenChangeLockedError); + expect(() => builder.addInput(randomContractUtxo({ token }), carolUnlocker())).toThrow(OutputTokenChangeLockedError); }); it('should scope the change output to the configured category across multiple invocations', () => { @@ -446,8 +491,8 @@ describe('Transaction Builder', () => { const tokenB = randomToken({ amount: 5000n }); const tx = new TransactionBuilder({ provider }) - .addInput(randomUtxo({ token: tokenA }), carolUnlocker()) - .addInput(randomUtxo({ token: tokenB }), carolUnlocker()) + .addInput(randomContractUtxo({ token: tokenA }), carolUnlocker()) + .addInput(randomContractUtxo({ token: tokenB }), carolUnlocker()) .addOutput({ to: bobTokenAddress, amount: 1000n, token: { amount: 700n, category: tokenA.category } }) .addOutput({ to: bobTokenAddress, amount: 1000n, token: { amount: 2000n, category: tokenB.category } }) .addTokenChangeOutputIfNeeded({ category: tokenA.category, to: aliceTokenAddress }) @@ -464,7 +509,7 @@ describe('Transaction Builder', () => { it('should fail when the change address does not support tokens', () => { const token = randomToken(); const builder = new TransactionBuilder({ provider }) - .addInput(randomUtxo({ token }), carolUnlocker()); + .addInput(randomContractUtxo({ token }), carolUnlocker()); expect(() => { builder.addTokenChangeOutputIfNeeded({ category: token.category, to: aliceAddress }); @@ -474,7 +519,7 @@ describe('Transaction Builder', () => { it('should fail when a BCH change output was already added', () => { const token = randomToken(); const builder = new TransactionBuilder({ provider }) - .addInput(randomUtxo({ token }), carolUnlocker()) + .addInput(randomContractUtxo({ token }), carolUnlocker()) .addBchChangeOutputIfNeeded({ to: aliceAddress, feeRate: 1.0 }); expect(() => { diff --git a/packages/cashscript/test/debugging.test.ts b/packages/cashscript/test/debugging.test.ts index e023c6666..36fe4f473 100644 --- a/packages/cashscript/test/debugging.test.ts +++ b/packages/cashscript/test/debugging.test.ts @@ -1,4 +1,4 @@ -import { Contract, FailedTransactionError, MockNetworkProvider, SignatureAlgorithm, SignatureTemplate, TransactionBuilder, VmTarget } from '../src/index.js'; +import { Contract, MockNetworkProvider, SignatureAlgorithm, SignatureTemplate, TransactionBuilder, UnlockerLockingBytecodeMismatchError, VmTarget } from '../src/index.js'; import { DEFAULT_VM_TARGET, getLockScriptName } from '../src/libauth-template/utils.js'; import { aliceAddress, alicePriv, alicePub, bobPriv, bobPub } from './fixture/vars.js'; import { randomUtxo } from '../src/utils.js'; @@ -177,7 +177,7 @@ describe('Debugging tests', () => { it('should log inside a loop', async () => { const transaction = new TransactionBuilder({ provider }) - .addInput(contractUtxo, contractTestLogInsideLoop.unlock.test_log_inside_loop()) + .addInput(contractTestLogInsideLoopUtxo, contractTestLogInsideLoop.unlock.test_log_inside_loop()) .addOutput({ to: contractTestLogInsideLoop.address, amount: 10000n }); expect(transaction).toLog(new RegExp('^\\[Input #0] Test.cash:6 i: 0$')); @@ -751,18 +751,16 @@ describe('Debugging tests', () => { expect(Object.keys(result).length).toBeGreaterThan(0); }); - // We currently don't have a way to properly handle non-matching UTXOs and unlockers - // Note: that also goes for Contract UTXOs where a user uses an unlocker of a different contract - it.skip('should fail when spending from P2PKH inputs with an unlocker for a different public key', async () => { + it('should fail when spending from P2PKH inputs with an unlocker for a different public key', async () => { const provider = new MockNetworkProvider(); provider.addUtxo(aliceAddress, randomUtxo()); provider.addUtxo(aliceAddress, randomUtxo()); - const transactionBuilder = new TransactionBuilder({ provider }) - .addInputs(await provider.getUtxos(aliceAddress), new SignatureTemplate(bobPriv).unlockP2PKH()) - .addOutput({ to: aliceAddress, amount: 5000n }); + const utxos = await provider.getUtxos(aliceAddress); - expect(() => transactionBuilder.debug()).toThrow(FailedTransactionError); + expect(() => ( + new TransactionBuilder({ provider }).addInputs(utxos, new SignatureTemplate(bobPriv).unlockP2PKH()) + )).toThrow(UnlockerLockingBytecodeMismatchError); }); }); diff --git a/packages/cashscript/test/e2e/MultiContract.test.ts b/packages/cashscript/test/e2e/MultiContract.test.ts index 734941962..2004cbf26 100644 --- a/packages/cashscript/test/e2e/MultiContract.test.ts +++ b/packages/cashscript/test/e2e/MultiContract.test.ts @@ -18,7 +18,7 @@ import { carolPriv, carolPub, } from '../fixture/vars.js'; -import { Network, Utxo } from '../../src/interfaces.js'; +import { Network, SpendableUtxo } from '../../src/interfaces.js'; import { addressToLockScript, randomUtxo } from '../../src/utils.js'; import p2pkhArtifact from '../fixture/p2pkh.artifact.js'; import twtArtifact from '../fixture/transfer_with_timeout.artifact.js'; @@ -214,9 +214,9 @@ describe('Multi Contract', () => { const correctLockingBytecode = addressToLockScript(correctContract.address); const siblingIntrospectionContract = new Contract(SiblingIntrospectionArtifact, [correctLockingBytecode], { provider }); - let correctContractUtxo: Utxo; - let incorrectContractUtxo: Utxo; - let siblingIntrospectionUtxo: Utxo; + let correctContractUtxo: SpendableUtxo; + let incorrectContractUtxo: SpendableUtxo; + let siblingIntrospectionUtxo: SpendableUtxo; beforeAll(async () => { correctContractUtxo = await addUtxo(provider, correctContract.address, randomUtxo()); diff --git a/packages/cashscript/test/e2e/network/MockNetworkProvider.test.ts b/packages/cashscript/test/e2e/network/MockNetworkProvider.test.ts index 75198caa8..756d56182 100644 --- a/packages/cashscript/test/e2e/network/MockNetworkProvider.test.ts +++ b/packages/cashscript/test/e2e/network/MockNetworkProvider.test.ts @@ -9,6 +9,7 @@ import { alicePriv, alicePub, bobAddress, + bobPriv, } from '../../fixture/vars.js'; describe.skipIf(Boolean(process.env.TESTS_USE_CHIPNET))('MockNetworkProvider', () => { @@ -72,6 +73,58 @@ describe.skipIf(Boolean(process.env.TESTS_USE_CHIPNET))('MockNetworkProvider', ( }); }); + describe('transaction validation', () => { + const provider = new MockNetworkProvider(); + + beforeEach(() => { + provider.reset(); + }); + + it('should annotate UTXOs with the locking bytecode they were added under', async () => { + const aliceLockingBytecode = binToHex(addressToLockScript(aliceAddress)); + const addedUtxo = provider.addUtxo(aliceAddress, randomUtxo()); + + expect(addedUtxo.lockingBytecode).toBe(aliceLockingBytecode); + + const fetchedUtxos = await provider.getUtxos(aliceAddress); + expect(fetchedUtxos[0].lockingBytecode).toBe(aliceLockingBytecode); + }); + + it('should reject a transaction that spends a UTXO with a mismatched unlocker', async () => { + // We deliberately set the lockingBytecode to bob's lock script so the TransactionBuilder + // mismatch check does not trigger, allowing us to build a transaction that spends alice's + // UTXO with bob's key + const bobLockingBytecode = binToHex(addressToLockScript(bobAddress)); + const utxo = { ...provider.addUtxo(aliceAddress, randomUtxo()), lockingBytecode: bobLockingBytecode }; + + const transaction = new TransactionBuilder({ provider }) + .addInput(utxo, new SignatureTemplate(bobPriv).unlockP2PKH()) + .addOutput({ to: aliceAddress, amount: 5000n }) + .build(); + + await expect(provider.sendRawTransaction(transaction)).rejects.toThrow(); + + // the failed transaction should not have updated the utxo set + expect(await provider.getUtxos(aliceAddress)).toHaveLength(1); + }); + + it('should accept invalid transactions when validateTransactions is set to false', async () => { + const nonValidatingProvider = new MockNetworkProvider({ validateTransactions: false }); + const bobLockingBytecode = binToHex(addressToLockScript(bobAddress)); + const utxo = { + ...nonValidatingProvider.addUtxo(aliceAddress, randomUtxo()), + lockingBytecode: bobLockingBytecode, + }; + + const transaction = new TransactionBuilder({ provider: nonValidatingProvider }) + .addInput(utxo, new SignatureTemplate(bobPriv).unlockP2PKH()) + .addOutput({ to: aliceAddress, amount: 5000n }) + .build(); + + await expect(nonValidatingProvider.sendRawTransaction(transaction)).resolves.toBeTruthy(); + }); + }); + describe('when updateUtxoSet is set to false', () => { const provider = new MockNetworkProvider({ updateUtxoSet: false }); diff --git a/packages/cashscript/test/fixture/libauth-template/fixtures.ts b/packages/cashscript/test/fixture/libauth-template/fixtures.ts index 0a145f3b2..84684c0f9 100644 --- a/packages/cashscript/test/fixture/libauth-template/fixtures.ts +++ b/packages/cashscript/test/fixture/libauth-template/fixtures.ts @@ -3,7 +3,7 @@ import TransferWithTimeout from '../transfer_with_timeout.artifact.js'; import Mecenas from '../mecenas.artifact.js'; import P2PKH from '../p2pkh.artifact.js'; import HoldVault from '../hodl_vault.artifact.js'; -import { aliceAddress, alicePkh, alicePriv, alicePub, bobPkh, bobPriv, bobPub, oracle, oraclePub } from '../vars.js'; +import { aliceAddress, alicePkh, alicePriv, alicePub, bobAddress, bobPkh, bobPriv, bobPub, oracle, oraclePub } from '../vars.js'; import { WalletTemplate, hexToBin } from '@bitauth/libauth'; const provider = new MockNetworkProvider(); @@ -1290,6 +1290,7 @@ export const fixtures: Fixture[] = [ const contractUtxo = provider.addUtxo(contract.address, randomUtxo()); const p2pkhUtxo = provider.addUtxo(aliceAddress, randomUtxo()); + const bobP2pkhUtxo = provider.addUtxo(bobAddress, randomUtxo()); const to = contract.tokenAddress; const amount = 1000n; @@ -1301,7 +1302,7 @@ export const fixtures: Fixture[] = [ const tx = new TransactionBuilder({ provider }) .addInput(p2pkhUtxo, aliceDefaultTemplate.unlockP2PKH()) .addInput(contractUtxo, contract.unlock.spend(alicePub, aliceCustomTemplate)) - .addInput(p2pkhUtxo, bobCustomTemplate.unlockP2PKH()) + .addInput(bobP2pkhUtxo, bobCustomTemplate.unlockP2PKH()) .addOutput({ to, amount }); return tx; diff --git a/packages/cashscript/test/test-util.ts b/packages/cashscript/test/test-util.ts index a809a68d7..e29c158e2 100644 --- a/packages/cashscript/test/test-util.ts +++ b/packages/cashscript/test/test-util.ts @@ -6,9 +6,9 @@ import { } from '@bitauth/libauth'; import PQueue from 'p-queue'; import pRetry from 'p-retry'; -import { Output, Network, Utxo } from '../src/interfaces.js'; +import { Output, Network, SpendableUtxo, Utxo } from '../src/interfaces.js'; import { network as defaultNetwork, funderAddress, funderPriv } from './fixture/vars.js'; -import { getNetworkPrefix, isNonTokenUtxo, libauthOutputToCashScriptOutput } from '../src/utils.js'; +import { addressToLockScript, getNetworkPrefix, isNonTokenUtxo, libauthOutputToCashScriptOutput } from '../src/utils.js'; import { utxoComparator } from '../src/utils.js'; import MockNetworkProvider from '../src/network/MockNetworkProvider.js'; import NetworkProvider from '../src/network/NetworkProvider.js'; @@ -38,7 +38,7 @@ export function getTxOutputs(tx: Transaction, network: Network = defaultNetwork) }); } -export function getLargestUtxo(utxos: Utxo[]): Utxo { +export function getLargestUtxo(utxos: U[]): U { return [...utxos].sort(utxoComparator).reverse()[0]; } @@ -59,7 +59,7 @@ export async function addUtxo( provider: NetworkProvider, address: string, utxo: Utxo, -): Promise { +): Promise { if (provider instanceof MockNetworkProvider) { return provider.addUtxo(address, utxo); } @@ -89,7 +89,7 @@ async function sendLiveAddUtxo( provider: NetworkProvider, address: string, utxo: Utxo, -): Promise { +): Promise { const funderUtxos = (await provider.getUtxos(funderAddress)) .filter(isNonTokenUtxo) .sort(utxoComparator) @@ -107,14 +107,15 @@ async function sendLiveAddUtxo( txid: tx.txid, vout: 0, satoshis: utxo.satoshis, + lockingBytecode: binToHex(addressToLockScript(address)), }; } -export function gatherUtxos( - utxos: Utxo[], +export function gatherUtxos( + utxos: U[], options?: { amount?: bigint, fee?: bigint }, -): { utxos: Utxo[], total: bigint, changeAmount: bigint } { - const targetUtxos: Utxo[] = []; +): { utxos: U[], total: bigint, changeAmount: bigint } { + const targetUtxos: U[] = []; let total = 0n; // 1000 for fees diff --git a/packages/cashscript/test/types/Contract.types.test.ts b/packages/cashscript/test/types/Contract.types.test.ts index 0eb6d8f2f..d94bc1244 100644 --- a/packages/cashscript/test/types/Contract.types.test.ts +++ b/packages/cashscript/test/types/Contract.types.test.ts @@ -119,7 +119,7 @@ const provider = new MockNetworkProvider(); const contract = new Contract(p2pkhArtifact, [alicePkh], { provider }); // it('should not give type errors when using correct function inputs') - contract.unlock.spend(alicePub, new SignatureTemplate(alicePriv)).generateLockingBytecode(); + contract.unlock.spend(alicePub, new SignatureTemplate(alicePriv)).generateUnlockingBytecode; // it('should give type errors when calling a function that does not exist') // @ts-expect-error @@ -137,14 +137,14 @@ const provider = new MockNetworkProvider(); // it('should not perform type checking when cast to any') const contractAsAny = new Contract(p2pkhArtifact as any, [alicePkh, 1000n], { provider }); - contractAsAny.unlock.notAFunction().generateLockingBytecode(); + contractAsAny.unlock.notAFunction().generateUnlockingBytecode; contractAsAny.unlock.spend(); contractAsAny.unlock.spend(1000n, true); // it('should not perform type checking when cannot infer type') // Note: would be very nice if it *could* infer the type from static json const contractFromUnknown = new Contract(p2pkhArtifactJsonNotConst, [alicePkh, 1000n], { provider }); - contractFromUnknown.unlock.notAFunction().generateLockingBytecode(); + contractFromUnknown.unlock.notAFunction().generateUnlockingBytecode; contractFromUnknown.unlock.spend(); contractFromUnknown.unlock.spend(1000n, true); diff --git a/website/docs/guides/cashtokens.md b/website/docs/guides/cashtokens.md index 0c0393af0..fefd2e2c9 100644 --- a/website/docs/guides/cashtokens.md +++ b/website/docs/guides/cashtokens.md @@ -20,6 +20,7 @@ interface Utxo { vout: number; satoshis: bigint; token?: TokenDetails; + lockingBytecode?: string; } interface TokenDetails { diff --git a/website/docs/guides/optimization.md b/website/docs/guides/optimization.md index e19e0b09f..8252f7c02 100644 --- a/website/docs/guides/optimization.md +++ b/website/docs/guides/optimization.md @@ -184,14 +184,13 @@ You can create an `Artifact` for a fully hand-written contract so it becomes pos In the [addInput() method][addInput()] on the TransactionBuilder you can provide a custom `Unlocker` ```ts -transactionBuilder.addInput(utxo: Utxo, unlocker: Unlocker, options?: InputOptions): this +transactionBuilder.addInput(utxo: SpendableUtxo, unlocker: Unlocker, options?: InputOptions): this ``` the `Unlocker` interface is the following: ```ts interface Unlocker { - generateLockingBytecode: () => Uint8Array; generateUnlockingBytecode: (options: GenerateUnlockingBytecodeOptions) => Uint8Array; } diff --git a/website/docs/releases/migration-notes.md b/website/docs/releases/migration-notes.md index d981afe46..e182753af 100644 --- a/website/docs/releases/migration-notes.md +++ b/website/docs/releases/migration-notes.md @@ -44,6 +44,22 @@ const signatureTemplate = new SignatureTemplate(wif, HashType.SIGHASH_ALL | Hash const signatureTemplate = new SignatureTemplate(wif, SighashType.SIGHASH_ALL | SighashType.SIGHASH_UTXOS); ``` +#### UTXOs must include their locking bytecode + +UTXOs returned by network providers now include a `lockingBytecode` field with the actual locking bytecode of the UTXO, and input UTXOs passed to the `TransactionBuilder` are required to include this field. + +If you fetch UTXOs from a standard network provider, no code changes are needed. If you construct UTXOs manually (e.g. from your own indexer or persisted data), you need to add the `lockingBytecode` field: + +```ts +// before +const utxo = { txid, vout, satoshis }; + +// after +const utxo = { txid, vout, satoshis, lockingBytecode }; +``` + +Since the spent UTXO's `lockingBytecode` is now the source of truth for the locking script, the `generateLockingBytecode()` method was removed from the `Unlocker` interface. If you implement custom unlockers, remove the `generateLockingBytecode()` method from your implementation. + ## v0.12 to v0.13 ### cashc compiler diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index d876754e6..45b3e90ab 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -4,7 +4,7 @@ title: Release Notes ## v0.14.0-next.4 -⚠️ Note that this is a pre-release version and is not yet stable. There will likely be breaking changes to the APIs and compiler output in subsequent pre-releases. +This release contains several breaking changes, please refer to the [migration notes](/docs/releases/migration-notes) for more information. #### cashc compiler - :sparkles: Add support for user-defined reusable functions. @@ -25,14 +25,19 @@ title: Release Notes #### CashScript SDK - :sparkles: Add support for debugging user-defined functions. - :sparkles: Add stack trace when debugging failed requires inside nested functions. +- :sparkles: Add a `validateTransactions` option (default: `true`) to the `MockNetworkProvider` to validate sent transactions against the BCH VM using the actual locking bytecode of the spent UTXOs. +- :hammer_and_wrench: Add `lockingBytecode` field to the `Utxo` interface, set automatically on all UTXOs returned by network providers. - :hammer_and_wrench: **BREAKING**: Replace the `SignatureTemplate`'s `getHashType()`, `getPublicKey()` and `getSignatureAlgorithm()` methods with the `sighashType`, `publicKey` and `signatureAlgorithm` properties. - :hammer_and_wrench: **BREAKING**: Remove the `bchForkId` parameter from `SignatureTemplate`'s `generateSignature()` method, since BCH consensus rules always require the fork ID flag. - :hammer_and_wrench: **BREAKING**: Rename the `HashType` enum to `SighashType`. +- :hammer_and_wrench: **BREAKING**: The `TransactionBuilder` now requires UTXOs to include their `lockingBytecode`, and validates it against the provided unlocker. +- :boom: **BREAKING**: Remove `generateLockingBytecode()` from the `Unlocker` interface. + ## v0.13.3 #### CashScript SDK -- :bug: Fix issue where `getTransactionSize()` undersized inputs when using `placeholderP2PKHUnlocker()` +- :bug: Fix issue where `getTransactionSize()` undersized inputs when using `placeholderP2PKHUnlocker()`. ## v0.13.2 diff --git a/website/docs/sdk/electrum-network-provider.md b/website/docs/sdk/electrum-network-provider.md index 51e37f936..25fa5ac78 100644 --- a/website/docs/sdk/electrum-network-provider.md +++ b/website/docs/sdk/electrum-network-provider.md @@ -54,16 +54,21 @@ const provider = new ElectrumNetworkProvider('chipnet', { hostname }); ### getUtxos() ```ts -async provider.getUtxos(address: string): Promise; +async provider.getUtxos(address: string): Promise; ``` Returns all UTXOs on specific address. Both confirmed and unconfirmed UTXOs are included. ```ts +interface SpendableUtxo extends Utxo { + lockingBytecode: string; +} + interface Utxo { txid: string; vout: number; satoshis: bigint; token?: TokenDetails; + lockingBytecode?: string; } interface TokenDetails { @@ -82,7 +87,7 @@ const userUtxos = await provider.getUtxos(userAddress) ``` ### getUtxosForLockingBytecode() ```ts -async provider.getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise; +async provider.getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise; ``` Returns all UTXOs for a specific locking bytecode. Both confirmed and unconfirmed UTXOs are included. diff --git a/website/docs/sdk/instantiation.md b/website/docs/sdk/instantiation.md index 858aa066c..d6ef2d8c5 100644 --- a/website/docs/sdk/instantiation.md +++ b/website/docs/sdk/instantiation.md @@ -161,17 +161,22 @@ const contractBalance = await contract.getBalance() ### getUtxos() ```ts -async contract.getUtxos(): Promise +async contract.getUtxos(): Promise ``` Returns all UTXOs that can be spent by the contract. Both confirmed and unconfirmed UTXOs are included. ```ts +interface SpendableUtxo extends Utxo { + lockingBytecode: string; +} + interface Utxo { txid: string; vout: number; satoshis: bigint; token?: TokenDetails; + lockingBytecode?: string; } ``` diff --git a/website/docs/sdk/network-provider.md b/website/docs/sdk/network-provider.md index 24062f68b..cd21ad9bd 100644 --- a/website/docs/sdk/network-provider.md +++ b/website/docs/sdk/network-provider.md @@ -24,16 +24,21 @@ const connectedNetwork = provider.network; ### getUtxos() ```ts -async provider.getUtxos(address: string): Promise; +async provider.getUtxos(address: string): Promise; ``` Returns all UTXOs on specific address. Both confirmed and unconfirmed UTXOs are included. ```ts +interface SpendableUtxo extends Utxo { + lockingBytecode: string; +} + interface Utxo { txid: string; vout: number; satoshis: bigint; token?: TokenDetails; + lockingBytecode?: string; } interface TokenDetails { @@ -46,6 +51,8 @@ interface TokenDetails { } ``` +The `lockingBytecode` field contains the hex-encoded locking bytecode of the UTXO. It is set automatically on all UTXOs returned by network providers, and is required by the `TransactionBuilder` to spend the UTXO. + #### Example ```ts const userUtxos = await provider.getUtxos(userAddress) @@ -53,7 +60,7 @@ const userUtxos = await provider.getUtxos(userAddress) ### getUtxosForLockingBytecode() ```ts -async provider.getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise; +async provider.getUtxosForLockingBytecode(lockingBytecode: Uint8Array | string): Promise; ``` Returns all UTXOs for a specific locking bytecode. Both confirmed and unconfirmed UTXOs are included. @@ -98,7 +105,7 @@ const txId = await provider.sendRawTransaction(txHex) ## Custom NetworkProviders -A big strength of the NetworkProvider setup is that it allows you to implement custom providers. So if you want to use a new or different BCH indexer for network information, it is simple to add support for it by creating your own `NetworkProvider` adapter by implementing the [NetworkProvider interface](https://github.com/CashScript/cashscript/blob/master/packages/cashscript/src/network/NetworkProvider.ts). +A big strength of the NetworkProvider setup is that it allows you to implement custom providers. So if you want to use a new or different BCH indexer for network information, it is simple to add support for it by creating your own `NetworkProvider` adapter by implementing the [NetworkProvider interface](https://github.com/CashScript/cashscript/blob/master/packages/cashscript/src/network/NetworkProvider.ts). Note that UTXOs returned by a `NetworkProvider` must include their `lockingBytecode`, which is required by the `TransactionBuilder` to spend them. You can create a PR to add your custom `NetworkProvider` to the CashScript codebase to share this functionality with others. It is required to have basic automated tests for any new `NetworkProvider`. diff --git a/website/docs/sdk/other-network-providers.md b/website/docs/sdk/other-network-providers.md index 019a50d8a..e66d1e3f6 100644 --- a/website/docs/sdk/other-network-providers.md +++ b/website/docs/sdk/other-network-providers.md @@ -15,11 +15,6 @@ The `MockNetworkProvider` has extra methods to enable this local emulation such You can read more about the `MockNetworkProvider` and automated tests on the [testing setup](/docs/sdk/testing-setup) page. ```ts -interface MockNetworkProviderOptions { - updateUtxoSet?: boolean; - vmTarget?: VmTarget; -} - interface MockNetworkProvider extends NetworkProvider { options: MockNetworkProviderOptions; vmTarget: VmTarget; @@ -29,17 +24,27 @@ interface MockNetworkProvider extends NetworkProvider { // Hardcode the block height setBlockHeight(newBlockHeight: number): void; - // Add a UTXO to the UTXO set of the mock network - addUtxo(addressOrLockingBytecode: string, utxo: Utxo): Utxo; + // Add a UTXO to the UTXO set of the mock network, returns the UTXO including its locking bytecode + addUtxo(addressOrLockingBytecode: string, utxo: Utxo): SpendableUtxo; // Reset the UTXO set and transaction list of the mock network reset(): void; } ``` -The `updateUtxoSet` option is used to determine whether the UTXO set should be updated after a transaction is sent. If `updateUtxoSet` is `true` (default), the UTXO set will be updated to reflect the new state of the mock network. If `updateUtxoSet` is `false`, the UTXO set will not be updated. +### Options + +```ts +interface MockNetworkProviderOptions { + updateUtxoSet?: boolean; + validateTransactions?: boolean; + vmTarget?: VmTarget; +} +``` -The `vmTarget` option defaults to the current VM of `BCH_2026_05`, but this can be changed to test your contract against different BCH virtual machine targets. +- `updateUtxoSet` (default `true`) — update the in-memory UTXO set after a transaction is sent, consuming the spent UTXOs and adding the transaction's outputs. +- `validateTransactions` (default `true`) — evaluate sent transactions against the BCH VM using the actual locking bytecode of the spent UTXOs, rejecting transactions that a real node would reject. Requires `updateUtxoSet`. +- `vmTarget` (default `BCH_2026_05`) — the BCH virtual machine version used for local debugging and transaction validation. #### Example ```ts diff --git a/website/docs/sdk/transaction-builder.md b/website/docs/sdk/transaction-builder.md index 6871f3179..ea322a7f6 100644 --- a/website/docs/sdk/transaction-builder.md +++ b/website/docs/sdk/transaction-builder.md @@ -54,7 +54,7 @@ The `allowImplicitFungibleTokenBurn` option is used to specify whether implicit ### addInput() ```ts -transactionBuilder.addInput(utxo: Utxo, unlocker: Unlocker, options?: InputOptions): this +transactionBuilder.addInput(utxo: SpendableUtxo, unlocker: Unlocker, options?: InputOptions): this ``` Adds a single input UTXO to the transaction that can be unlocked using the provided unlocker. The unlocker can be derived from a `SignatureTemplate` or a `Contract` instance's spending functions. The `InputOptions` object can be used to specify the sequence number of the input. The default sequence number is `0xfffffffe` (non-final sequence number). @@ -76,12 +76,12 @@ transactionBuilder.addInput(aliceUtxos[0], aliceTemplate.unlockP2PKH()); ### addInputs() ```ts -transactionBuilder.addInputs(utxos: Utxo[], unlocker: Unlocker, options?: InputOptions): this +transactionBuilder.addInputs(utxos: SpendableUtxo[], unlocker: Unlocker, options?: InputOptions): this transactionBuilder.addInputs(utxos: UnlockableUtxo[]): this ``` ```ts -interface UnlockableUtxo extends Utxo { +interface UnlockableUtxo extends SpendableUtxo { unlocker: Unlocker; options?: InputOptions; } From 3ed8b46bb9f3552f4eb16d7ae714a113c9e66da1 Mon Sep 17 00:00:00 2001 From: Rosco Kalis Date: Tue, 15 Sep 2026 11:58:30 +0200 Subject: [PATCH 37/37] chore: bump version to 0.14.0-next.5 & update release notes --- examples/package.json | 6 +++--- examples/testing-suite/package.json | 6 +++--- packages/cashc/package.json | 4 ++-- packages/cashc/src/index.ts | 2 +- packages/cashscript/package.json | 4 ++-- packages/utils/package.json | 2 +- website/docs/releases/release-notes.md | 29 ++++++++++++-------------- 7 files changed, 25 insertions(+), 28 deletions(-) diff --git a/examples/package.json b/examples/package.json index 215f3cc89..67c9fd3df 100644 --- a/examples/package.json +++ b/examples/package.json @@ -1,7 +1,7 @@ { "name": "cashscript-examples", "private": true, - "version": "0.14.0-next.4", + "version": "0.14.0-next.5", "description": "Usage examples of the CashScript SDK", "main": "p2pkh.js", "type": "module", @@ -13,8 +13,8 @@ "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", "@types/node": "^24.13.3", - "cashc": "^0.14.0-next.4", - "cashscript": "^0.14.0-next.4", + "cashc": "^0.14.0-next.5", + "cashscript": "^0.14.0-next.5", "eslint": "^8.56.0", "typescript": "^5.9.2" } diff --git a/examples/testing-suite/package.json b/examples/testing-suite/package.json index 6564205f3..6778fbf83 100644 --- a/examples/testing-suite/package.json +++ b/examples/testing-suite/package.json @@ -1,6 +1,6 @@ { "name": "testing-suite", - "version": "0.14.0-next.4", + "version": "0.14.0-next.5", "description": "Example project to develop and test CashScript contracts", "main": "index.js", "type": "module", @@ -18,8 +18,8 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "cashc": "^0.14.0-next.4", - "cashscript": "^0.14.0-next.4" + "cashc": "^0.14.0-next.5", + "cashscript": "^0.14.0-next.5" }, "devDependencies": { "tsx": "^4.23.12", diff --git a/packages/cashc/package.json b/packages/cashc/package.json index 06569be7b..8e581c4f6 100644 --- a/packages/cashc/package.json +++ b/packages/cashc/package.json @@ -1,6 +1,6 @@ { "name": "cashc", - "version": "0.14.0-next.4", + "version": "0.14.0-next.5", "description": "Compile Bitcoin Cash contracts to Bitcoin Cash Script or artifacts", "keywords": [ "bitcoin", @@ -48,7 +48,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.4", + "@cashscript/utils": "^0.14.0-next.5", "antlr4": "^4.13.2", "commander": "^14.0.0", "semver": "^7.8.5" diff --git a/packages/cashc/src/index.ts b/packages/cashc/src/index.ts index 773eddcc2..708f394a6 100644 --- a/packages/cashc/src/index.ts +++ b/packages/cashc/src/index.ts @@ -7,4 +7,4 @@ export { export * from './ast/Location.js'; export * from './ast/error-listeners.js'; -export const version = '0.14.0-next.4'; +export const version = '0.14.0-next.5'; diff --git a/packages/cashscript/package.json b/packages/cashscript/package.json index 37b7e8865..012ec7ed5 100644 --- a/packages/cashscript/package.json +++ b/packages/cashscript/package.json @@ -1,6 +1,6 @@ { "name": "cashscript", - "version": "0.14.0-next.4", + "version": "0.14.0-next.5", "description": "Easily write and interact with Bitcoin Cash contracts", "keywords": [ "bitcoin cash", @@ -42,7 +42,7 @@ }, "dependencies": { "@bitauth/libauth": "^3.1.0-next.8", - "@cashscript/utils": "^0.14.0-next.4", + "@cashscript/utils": "^0.14.0-next.5", "@electrum-cash/network": "^4.2.2", "fflate": "^0.8.3", "semver": "^7.8.5" diff --git a/packages/utils/package.json b/packages/utils/package.json index 33b4616f0..b1c7058b4 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,6 +1,6 @@ { "name": "@cashscript/utils", - "version": "0.14.0-next.4", + "version": "0.14.0-next.5", "description": "CashScript utilities and types", "keywords": [ "bitcoin cash", diff --git a/website/docs/releases/release-notes.md b/website/docs/releases/release-notes.md index 45b3e90ab..441502143 100644 --- a/website/docs/releases/release-notes.md +++ b/website/docs/releases/release-notes.md @@ -2,30 +2,27 @@ title: Release Notes --- -## v0.14.0-next.4 +## v0.14.0-next.5 This release contains several breaking changes, please refer to the [migration notes](/docs/releases/migration-notes) for more information. #### cashc compiler -- :sparkles: Add support for user-defined reusable functions. -- :sparkles: Add support for multiple return values in user-defined functions, destructured at the call site. -- :sparkles: Add support for top-level global constants. -- :sparkles: Allow for simple arithmetic / concatenation operations in global constant definitions. -- :sparkles: Add `unused` modifier for parameters or variables that are intentionally unused. -- :hammer_and_wrench: Unused variables that are not marked `unused` now produce a compiler warning instead of a compilation error. Only reads count as usage, so variables that are only assigned to are reported as well. Warnings are printed with `console.warn`, or passed to the new `warningListener` compiler option. -- :sparkles: Add a compiler warning for values assigned to a variable that are never read afterwards. -- :racehorse: Treat parameters and variables that are never read the same as explicitly `unused`-marked ones: they are dropped from the stack immediately, and no parameter type enforcement is generated for them. -- :sparkles: Add support for `import` directives to share user-defined functions across files. -- :sparkles: Resolve package imports (e.g. `import "pkg/math.cash"`) from `node_modules`, so contract libraries can be installed as npm packages. +- :sparkles: Add support for user-defined reusable functions, including multiple return values. +- :sparkles: Add support for top-level global constants, including simple arithmetic / concatenation operations. +- :sparkles: Add support for `import` directives to share user-defined functions across files, including imports from `node_modules`. - :sparkles: Add support for reassigning existing variables in tuple destructuring (e.g. `(a, b) = swap(a, b)`), optionally mixed with fresh declarations. +- :sparkles: Add `unused` modifier for parameters or variables that are intentionally unused. - :hammer_and_wrench: Update `compileString` to take an optional `files` object for filesystem-free import resolution. -- :racehorse: Inline global functions and constants when this is no larger than `OP_DEFINE`/`OP_INVOKE`. -- :racehorse: Add new `OP_SWAP OP_MUL` and `OP_NOT OP_NOT` optimisations. +- :hammer_and_wrench: Unused variables that are not marked `unused` now produce a compiler warning instead of a compilation error. Warnings are printed with `console.warn`, or passed to the new `warningListener` compiler option. +- :hammer_and_wrench: Add a compiler warning for values assigned to a variable that are never read afterwards. +- :bug: Fix bug where date literal parsing was different per locale, it now uses UTC. +- :racehorse: Add new `OP_SWAP OP_MUL`, `OP_NOT OP_NOT` and `TO_ALTSTACK OP_FROMALTSTACK` optimisations. +- :racehorse: Greatly improve compiler speed for very large contracts. #### CashScript SDK -- :sparkles: Add support for debugging user-defined functions. -- :sparkles: Add stack trace when debugging failed requires inside nested functions. -- :sparkles: Add a `validateTransactions` option (default: `true`) to the `MockNetworkProvider` to validate sent transactions against the BCH VM using the actual locking bytecode of the spent UTXOs. +- :sparkles: Add support for debugging user-defined functions, including stack traces for nested functions. +- :sparkles: Add a `validateTransactions` option (default: `true`) to the `MockNetworkProvider` to validate sent transactions against the BCH VM. +- :hammer_and_wrench: MockNetworkProvider now warns instead of errors when resubmitting an already-seen transaction. - :hammer_and_wrench: Add `lockingBytecode` field to the `Utxo` interface, set automatically on all UTXOs returned by network providers. - :hammer_and_wrench: **BREAKING**: Replace the `SignatureTemplate`'s `getHashType()`, `getPublicKey()` and `getSignatureAlgorithm()` methods with the `sighashType`, `publicKey` and `signatureAlgorithm` properties. - :hammer_and_wrench: **BREAKING**: Remove the `bchForkId` parameter from `SignatureTemplate`'s `generateSignature()` method, since BCH consensus rules always require the fork ID flag.