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