UNPKG

@gobstones/gobstones-lang

Version:
1 lines 491 kB
{"version":3,"file":"index.cjs","sources":["../node_modules/@gobstones/gobstones-parser/dist/index.js","../src/interpreter/instruction.ts","../src/i18n/es.ts","../src/i18n/en.ts","../src/i18n/pt.ts","../src/interpreter/i18n.ts","../src/interpreter/value.ts","../src/interpreter/runtime.ts","../src/interpreter/compiler.ts","../src/interpreter/vm.ts","../src/interpreter/runner.ts"],"sourcesContent":["/* eslint-disable no-underscore-dangle */\n/* A SourceReader represents the current position in a source file.\n * It keeps track of line and column numbers.\n * Methods are non-destructive. For example:\n *\n * let r = new SourceReader('foo.gbs', 'if\\n(True)');\n *\n * r.peek(); // ~~> 'i'\n * r = r.consumeCharacter(); // Note: returns a new file reader.\n *\n * r.peek(); // ~~> 'f'\n * r = r.consumeCharacter();\n *\n * r.peek(); // ~~> '\\n'\n * r = r.consumeCharacter('\\n');\n *\n * r.line(); // ~~> 2\n */\nclass SourceReader {\n constructor(filename, string) {\n this._filename = filename; // Filename\n this._string = string; // Source of the current file\n this._index = 0; // Index in the current file\n this._line = 1; // Line in the current file\n this._column = 1; // Column in the current file\n this._regions = []; // Lexical (static) stack of regions\n }\n _clone() {\n const r = new SourceReader(this._filename, this._string);\n r._index = this._index;\n r._line = this._line;\n r._column = this._column;\n r._regions = this._regions;\n return r;\n }\n get filename() {\n return this._filename;\n }\n get line() {\n return this._line;\n }\n get column() {\n return this._column;\n }\n get region() {\n if (this._regions.length > 0) {\n return this._regions[0];\n }\n else {\n return '';\n }\n }\n /* Consume one character */\n consumeCharacter() {\n const r = this._clone();\n if (r.peek() === '\\n') {\n r._line++;\n r._column = 1;\n }\n else {\n r._column++;\n }\n r._index++;\n return r;\n }\n /* Consume characters from the input, one per each character in the string\n * (the contents of the string are ignored). */\n consumeString(string) {\n let r = this._clone();\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for (const _ of string) {\n r = r.consumeCharacter();\n }\n return r;\n }\n /* Returns the SourceReader after consuming an 'invisible' character.\n * Invisible characters affect the index but not the line or column.\n */\n consumeInvisibleCharacter() {\n const r = this._clone();\n r._index++;\n return r;\n }\n /* Consume 'invisible' characters from the input, one per each character\n * in the string */\n consumeInvisibleString(string) {\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n let r = this;\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n for (const _ of string) {\n r = r.consumeInvisibleCharacter();\n }\n return r;\n }\n /* Return true if the substring occurs at the current point. */\n startsWith(sub) {\n const i = this._index;\n const j = this._index + sub.length;\n return j <= this._string.length && this._string.substring(i, j) === sub;\n }\n /* Return true if we have reached the end of the current file */\n eof() {\n return this._index >= this._string.length;\n }\n /* Return the current character, assuming we have not reached EOF */\n peek() {\n return this._string[this._index];\n }\n /* Push a region to the stack of regions (non-destructively) */\n beginRegion(region) {\n const r = this._clone();\n r._regions = [region].concat(r._regions);\n return r;\n }\n /* Pop a region from the stack of regions (non-destructively) */\n endRegion() {\n const r = this._clone();\n if (r._regions.length > 0) {\n r._regions = r._regions.slice(1);\n }\n return r;\n }\n}\n/* Return a source reader that represents an unknown position */\nconst UnknownPosition = new SourceReader('(?)', '');\n/* An instance of MultifileReader represents a scanner for reading\n * source code from a list of files.\n */\nclass MultifileReader {\n /* The 'input' parameter should be either:\n * (1) a string. e.g. 'program {}', or\n * (2) a map from filenames to strings, e.g.\n * {\n * 'foo.gbs': 'program { P() }',\n * 'bar.gbs': 'procedure P() {}',\n * }\n */\n constructor(input) {\n if (typeof input === 'string') {\n input = { '(?)': input };\n }\n this._filenames = Object.keys(input);\n this._filenames.sort();\n this._input = input;\n this._index = 0;\n }\n /* Return true if there are more files */\n moreFiles() {\n return this._index + 1 < this._filenames.length;\n }\n /* Advance to the next file */\n nextFile() {\n this._index++;\n }\n /* Return a SourceReader for the current files */\n readCurrentFile() {\n if (this._index < this._filenames.length) {\n const filename = this._filenames[this._index];\n return new SourceReader(filename, this._input[filename]);\n }\n else {\n return new SourceReader('(?)', '');\n }\n }\n}\n\n/* Token tags are constant symbols */\nconst T_EOF = Symbol.for('T_EOF'); // End of file\nconst T_NUM = Symbol.for('T_NUM'); // Number\nconst T_STRING = Symbol.for('T_STRING'); // String constant\nconst T_UPPERID = Symbol.for('T_UPPERID'); // Uppercase identifier\nconst T_LOWERID = Symbol.for('T_LOWERID'); // Lowercase identifier\n/* Keywords */\nconst T_PROGRAM = Symbol.for('T_PROGRAM');\nconst T_INTERACTIVE = Symbol.for('T_INTERACTIVE');\nconst T_PROCEDURE = Symbol.for('T_PROCEDURE');\nconst T_FUNCTION = Symbol.for('T_FUNCTION');\nconst T_RETURN = Symbol.for('T_RETURN');\nconst T_IF = Symbol.for('T_IF');\nconst T_THEN = Symbol.for('T_THEN');\nconst T_ELSEIF = Symbol.for('T_ELSEIF');\nconst T_ELSE = Symbol.for('T_ELSE');\nconst T_CHOOSE = Symbol.for('T_CHOOSE');\nconst T_WHEN = Symbol.for('T_WHEN');\nconst T_OTHERWISE = Symbol.for('T_OTHERWISE');\nconst T_MATCHING = Symbol.for('T_MATCHING');\nconst T_SELECT = Symbol.for('T_SELECT');\nconst T_ON = Symbol.for('T_ON');\nconst T_REPEAT = Symbol.for('T_REPEAT');\nconst T_FOREACH = Symbol.for('T_FOREACH');\nconst T_IN = Symbol.for('T_IN');\nconst T_WHILE = Symbol.for('T_WHILE');\nconst T_SWITCH = Symbol.for('T_SWITCH');\nconst T_TO = Symbol.for('T_TO');\nconst T_LET = Symbol.for('T_LET');\nconst T_NOT = Symbol.for('T_NOT');\nconst T_DIV = Symbol.for('T_DIV');\nconst T_MOD = Symbol.for('T_MOD');\nconst T_TYPE = Symbol.for('T_TYPE');\nconst T_IS = Symbol.for('T_IS');\nconst T_RECORD = Symbol.for('T_RECORD');\nconst T_VARIANT = Symbol.for('T_VARIANT');\nconst T_CASE = Symbol.for('T_CASE');\nconst T_FIELD = Symbol.for('T_FIELD');\nconst T_UNDERSCORE = Symbol.for('T_UNDERSCORE');\nconst T_TIMEOUT = Symbol.for('T_TIMEOUT');\n/* Symbols */\nconst T_LPAREN = Symbol.for('T_LPAREN');\nconst T_RPAREN = Symbol.for('T_RPAREN');\nconst T_LBRACE = Symbol.for('T_LBRACE');\nconst T_RBRACE = Symbol.for('T_RBRACE');\nconst T_LBRACK = Symbol.for('T_LBRACK');\nconst T_RBRACK = Symbol.for('T_RBRACK');\nconst T_COMMA = Symbol.for('T_COMMA');\nconst T_SEMICOLON = Symbol.for('T_SEMICOLON');\nconst T_ELLIPSIS = Symbol.for('T_ELLIPSIS');\nconst T_RANGE = Symbol.for('T_RANGE');\nconst T_GETS = Symbol.for('T_GETS');\nconst T_PIPE = Symbol.for('T_PIPE');\nconst T_ARROW = Symbol.for('T_ARROW');\nconst T_ASSIGN = Symbol.for('T_ASSIGN');\nconst T_EQ = Symbol.for('T_EQ');\nconst T_NE = Symbol.for('T_NE');\nconst T_LE = Symbol.for('T_LE');\nconst T_GE = Symbol.for('T_GE');\nconst T_LT = Symbol.for('T_LT');\nconst T_GT = Symbol.for('T_GT');\nconst T_AND = Symbol.for('T_AND');\nconst T_OR = Symbol.for('T_OR');\nconst T_CONCAT = Symbol.for('T_CONCAT');\nconst T_PLUS = Symbol.for('T_PLUS');\nconst T_MINUS = Symbol.for('T_MINUS');\nconst T_TIMES = Symbol.for('T_TIMES');\nconst T_POW = Symbol.for('T_POW');\n/* A token is given by:\n * - A token tag (e.g. T_LOWERID, T_NUM).\n * - Possibly, a value (e.g. 'nroBolitas', 8).\n * When the value is irrelevant, we provide null by convention.\n * - Two positions, representing its location in the source. */\nclass Token {\n constructor(tag, value, startPos, endPos) {\n this._tag = tag;\n this._value = value;\n this._startPos = startPos;\n this._endPos = endPos;\n }\n toString() {\n const _tag = this._tag;\n const tag = typeof _tag === 'symbol' ? Symbol.keyFor(_tag).substring(2) : _tag;\n switch (tag) {\n case 'NUM':\n case 'STRING':\n case 'UPPERID':\n case 'LOWERID':\n return tag + '(\"' + this._value.toString() + '\")';\n default:\n return tag;\n }\n }\n get tag() {\n return this._tag;\n }\n get value() {\n return this._value;\n }\n get startPos() {\n return this._startPos;\n }\n get endPos() {\n return this._endPos;\n }\n}\n\n/* eslint-disable camelcase */\nconst N_Main = Symbol.for('N_Main');\n/* Definitions */\nconst N_DefProgram = Symbol.for('N_DefProgram');\nconst N_DefInteractiveProgram = Symbol.for('N_DefInteractiveProgram');\nconst N_DefProcedure = Symbol.for('N_DefProcedure');\nconst N_DefFunction = Symbol.for('N_DefFunction');\nconst N_DefType = Symbol.for('N_DefType');\n/* Statements */\nconst N_StmtBlock = Symbol.for('N_StmtBlock');\nconst N_StmtReturn = Symbol.for('N_StmtReturn');\nconst N_StmtIf = Symbol.for('N_StmtIf');\nconst N_StmtRepeat = Symbol.for('N_StmtRepeat');\nconst N_StmtForeach = Symbol.for('N_StmtForeach');\nconst N_StmtWhile = Symbol.for('N_StmtWhile');\nconst N_StmtSwitch = Symbol.for('N_StmtSwitch');\nconst N_StmtAssignVariable = Symbol.for('N_StmtAssignVariable');\nconst N_StmtAssignTuple = Symbol.for('N_StmtAssignTuple');\nconst N_StmtProcedureCall = Symbol.for('N_StmtProcedureCall');\n/* Patterns */\nconst N_PatternWildcard = Symbol.for('N_PatternWildcard');\nconst N_PatternVariable = Symbol.for('N_PatternVariable');\nconst N_PatternNumber = Symbol.for('N_PatternNumber');\nconst N_PatternStructure = Symbol.for('N_PatternStructure');\nconst N_PatternTuple = Symbol.for('N_PatternTuple');\nconst N_PatternTimeout = Symbol.for('N_PatternTimeout');\n/* Expressions */\nconst N_ExprVariable = Symbol.for('N_ExprVariable');\nconst N_ExprConstantNumber = Symbol.for('N_ExprConstantNumber');\nconst N_ExprConstantString = Symbol.for('N_ExprConstantString');\nconst N_ExprChoose = Symbol.for('N_ExprChoose');\nconst N_ExprMatching = Symbol.for('N_ExprMatching');\nconst N_ExprList = Symbol.for('N_ExprList');\nconst N_ExprRange = Symbol.for('N_ExprRange');\nconst N_ExprTuple = Symbol.for('N_ExprTuple');\nconst N_ExprStructure = Symbol.for('N_ExprStructure');\nconst N_ExprStructureUpdate = Symbol.for('N_ExprStructureUpdate');\nconst N_ExprFunctionCall = Symbol.for('N_ExprFunctionCall');\n/* SwitchBranch: pattern -> body */\nconst N_SwitchBranch = Symbol.for('N_SwitchBranch');\n/* MatchingBranch: pattern -> body */\nconst N_MatchingBranch = Symbol.for('N_MatchingBranch');\n/* FieldBinding: fieldName <- value */\nconst N_FieldBinding = Symbol.for('N_FieldBinding');\n/* ConstructorDeclaration */\nconst N_ConstructorDeclaration = Symbol.for('N_ConstructorDeclaration');\n/* Helper functions for the ASTNode toString method */\nfunction indent(string) {\n const lines = [];\n for (const line of string.split('\\n')) {\n lines.push(' ' + line);\n }\n return lines.join('\\n');\n}\nfunction showAST(node) {\n if (node === undefined) {\n return 'null';\n }\n else if (node instanceof Array) {\n return '[\\n' + showASTs(node).join(',\\n') + '\\n]';\n }\n else if (node instanceof Token) {\n return node.toString();\n }\n const tag = Symbol.keyFor(node.tag).substring(2);\n return tag + '(\\n' + showASTs(node.children).join(',\\n') + '\\n)';\n}\nfunction showASTs(nodes) {\n const res = [];\n for (const node of nodes) {\n res.push(indent(showAST(node)));\n }\n return res;\n}\n/** An instance of ASTNode represents a node of the abstract syntax tree.\n * - tag should be a node tag symbol.\n * - children should be (recursively) a possibly empty array of ASTNode's.\n * - startPos and endPos represent the starting and ending\n * position of the code fragment in the source code, to aid error\n * reporting.\n **/\nclass ASTNode {\n constructor(tag, children) {\n this._tag = tag;\n this._children = children;\n this._startPos = UnknownPosition;\n this._endPos = UnknownPosition;\n this._attributes = {};\n /* Assert this invariant to protect against common mistakes. */\n if (!(children instanceof Array)) {\n throw Error('The children of an ASTNode should be an array.');\n }\n }\n toMulangLike() {\n return {\n tag: this._tag.toString().replace(/(^Symbol\\(|\\)$)/g, ''),\n contents: this._children.map((node) => {\n if (node === undefined) {\n return 'null';\n }\n else if (node instanceof Array) {\n return new ASTNode(Symbol('?'), node).toMulangLike().contents;\n }\n else if (node instanceof ASTNode) {\n return node.toMulangLike();\n }\n else if (node instanceof Token) {\n return node.toString();\n }\n else {\n return '?';\n }\n })\n };\n }\n toString() {\n return showAST(this);\n }\n get tag() {\n return this._tag;\n }\n get children() {\n return this._children;\n }\n set startPos(position) {\n this._startPos = position;\n }\n get startPos() {\n return this._startPos;\n }\n set endPos(position) {\n this._endPos = position;\n }\n get endPos() {\n return this._endPos;\n }\n get attributes() {\n return this._attributes;\n }\n set attributes(attributes) {\n this._attributes = attributes;\n }\n}\n/* Main */\nclass ASTMain extends ASTNode {\n constructor(definitions) {\n super(N_Main, definitions);\n }\n get definitions() {\n return this.children;\n }\n}\n/* Definitions */\nclass ASTDefProgram extends ASTNode {\n constructor(body) {\n super(N_DefProgram, [body]);\n }\n get body() {\n return this.children[0];\n }\n}\nclass ASTNodeWithBranches extends ASTNode {\n get branches() {\n return this.children;\n }\n}\nclass ASTDefInteractiveProgram extends ASTNodeWithBranches {\n constructor(branches) {\n super(N_DefInteractiveProgram, branches);\n }\n get branches() {\n return this.children;\n }\n}\nclass ASTDefProcedure extends ASTNode {\n constructor(name, parameters, body) {\n super(N_DefProcedure, [name, parameters, body]);\n }\n get name() {\n return this.children[0];\n }\n get parameters() {\n return this.children[1];\n }\n get body() {\n return this.children[2];\n }\n}\nclass ASTDefFunction extends ASTNode {\n constructor(name, parameters, body) {\n super(N_DefFunction, [name, parameters, body]);\n }\n get name() {\n return this.children[0];\n }\n get parameters() {\n return this.children[1];\n }\n get body() {\n return this.children[2];\n }\n}\nclass ASTDefType extends ASTNode {\n constructor(typeName, constructorDeclarations) {\n super(N_DefType, [typeName, constructorDeclarations]);\n }\n get typeName() {\n return this.children[0];\n }\n get constructorDeclarations() {\n return this.children[1];\n }\n}\n/* Statements */\nclass ASTStmtBlock extends ASTNode {\n constructor(statements) {\n super(N_StmtBlock, statements);\n }\n get statements() {\n return this.children;\n }\n}\nclass ASTStmtReturn extends ASTNode {\n constructor(result) {\n super(N_StmtReturn, [result]);\n }\n get result() {\n return this.children[0];\n }\n}\nclass ASTStmtIf extends ASTNode {\n // Note: elseBlock may be null\n constructor(condition, thenBlock, elseBlock) {\n super(N_StmtIf, [condition, thenBlock, elseBlock]);\n }\n get condition() {\n return this.children[0];\n }\n get thenBlock() {\n return this.children[1];\n }\n get elseBlock() {\n return this.children[2];\n }\n}\nclass ASTStmtRepeat extends ASTNode {\n constructor(times, body) {\n super(N_StmtRepeat, [times, body]);\n }\n get times() {\n return this.children[0];\n }\n get body() {\n return this.children[1];\n }\n}\nclass ASTNodeWithPattern extends ASTNode {\n get pattern() {\n return this.children[0];\n }\n}\nclass ASTStmtForeach extends ASTNodeWithPattern {\n constructor(pattern, range, body) {\n super(N_StmtForeach, [pattern, range, body]);\n }\n get pattern() {\n return this.children[0];\n }\n get range() {\n return this.children[1];\n }\n get body() {\n return this.children[2];\n }\n}\nclass ASTStmtWhile extends ASTNode {\n constructor(condition, body) {\n super(N_StmtWhile, [condition, body]);\n }\n get condition() {\n return this.children[0];\n }\n get body() {\n return this.children[1];\n }\n}\nclass ASTStmtSwitch extends ASTNodeWithBranches {\n constructor(subject, branches) {\n super(N_StmtSwitch, [subject, branches]);\n }\n get subject() {\n return this.children[0];\n }\n get branches() {\n return this.children[1];\n }\n}\nclass ASTSwitchBranch extends ASTNodeWithPattern {\n constructor(pattern, body) {\n super(N_SwitchBranch, [pattern, body]);\n }\n get pattern() {\n return this.children[0];\n }\n get body() {\n return this.children[1];\n }\n}\nclass ASTMatchingBranch extends ASTNodeWithPattern {\n constructor(pattern, body) {\n super(N_MatchingBranch, [pattern, body]);\n }\n get pattern() {\n return this.children[0];\n }\n get body() {\n return this.children[1];\n }\n}\nclass ASTStmtAssignVariable extends ASTNode {\n constructor(variable, value) {\n super(N_StmtAssignVariable, [variable, value]);\n }\n get variable() {\n return this.children[0];\n }\n get value() {\n return this.children[1];\n }\n}\nclass ASTStmtAssignTuple extends ASTNode {\n constructor(variables, value) {\n super(N_StmtAssignTuple, [variables, value]);\n }\n get variables() {\n return this.children[0];\n }\n get value() {\n return this.children[1];\n }\n}\nclass ASTStmtProcedureCall extends ASTNode {\n constructor(procedureName, args) {\n super(N_StmtProcedureCall, [procedureName, args]);\n }\n get procedureName() {\n return this.children[0];\n }\n get args() {\n return this.children[1];\n }\n}\nclass ASTPatternWildcard extends ASTNode {\n constructor(statement) {\n super(N_PatternWildcard, []);\n }\n get boundVariables() {\n return [];\n }\n}\nclass ASTPatternVariable extends ASTNode {\n constructor(variableName) {\n super(N_PatternVariable, [variableName]);\n }\n get variableName() {\n return this.children[0];\n }\n get boundVariables() {\n return [this.children[0]];\n }\n}\nclass ASTPatternNumber extends ASTNode {\n constructor(number) {\n super(N_PatternNumber, [number]);\n }\n get number() {\n return this.children[0];\n }\n get boundVariables() {\n return [];\n }\n}\nclass ASTPatternStructure extends ASTNode {\n constructor(constructorName, parameters) {\n super(N_PatternStructure, [constructorName, parameters]);\n }\n get constructorName() {\n return this.children[0];\n }\n get boundVariables() {\n return this.children[1];\n }\n}\nclass ASTPatternTuple extends ASTNode {\n constructor(parameters) {\n super(N_PatternTuple, parameters);\n }\n get boundVariables() {\n return this.children;\n }\n}\nclass ASTPatternTimeout extends ASTNode {\n constructor(timeout) {\n super(N_PatternTimeout, [timeout]);\n }\n get boundVariables() {\n return [];\n }\n get timeout() {\n return parseInt(this.children[0].value, 10);\n }\n}\nclass ASTExprVariable extends ASTNode {\n constructor(variableName) {\n super(N_ExprVariable, [variableName]);\n }\n get variableName() {\n return this.children[0];\n }\n}\nclass ASTExprConstantNumber extends ASTNode {\n constructor(number) {\n super(N_ExprConstantNumber, [number]);\n }\n get number() {\n return this.children[0];\n }\n}\nclass ASTExprConstantString extends ASTNode {\n constructor(string) {\n super(N_ExprConstantString, [string]);\n }\n get string() {\n return this.children[0];\n }\n}\nclass ASTExprChoose extends ASTNode {\n constructor(condition, trueExpr, falseExpr) {\n super(N_ExprChoose, [condition, trueExpr, falseExpr]);\n }\n get condition() {\n return this.children[0];\n }\n get trueExpr() {\n return this.children[1];\n }\n get falseExpr() {\n return this.children[2];\n }\n}\nclass ASTExprMatching extends ASTNodeWithBranches {\n constructor(subject, branches) {\n super(N_ExprMatching, [subject, branches]);\n }\n get subject() {\n return this.children[0];\n }\n get branches() {\n return this.children[1];\n }\n}\nclass ASTExprList extends ASTNode {\n constructor(elements) {\n super(N_ExprList, elements);\n }\n get elements() {\n return this.children;\n }\n}\nclass ASTExprRange extends ASTNode {\n // Note: second may be null\n constructor(first, second, last) {\n super(N_ExprRange, [first, second, last]);\n }\n get first() {\n return this.children[0];\n }\n get second() {\n return this.children[1];\n }\n get last() {\n return this.children[2];\n }\n}\nclass ASTExprTuple extends ASTNode {\n constructor(elements) {\n super(N_ExprTuple, elements);\n }\n get elements() {\n return this.children;\n }\n}\nclass ASTExprStructure extends ASTNode {\n constructor(constructorName, fieldBindings) {\n super(N_ExprStructure, [constructorName, fieldBindings]);\n }\n get constructorName() {\n return this.children[0];\n }\n get fieldBindings() {\n return this.children[1];\n }\n fieldNames() {\n const names = [];\n for (const fieldBinding of this.fieldBindings) {\n names.push(fieldBinding.fieldName.value);\n }\n return names;\n }\n}\nclass ASTExprStructureUpdate extends ASTNode {\n constructor(constructorName, original, fieldBindings) {\n super(N_ExprStructureUpdate, [constructorName, original, fieldBindings]);\n }\n get constructorName() {\n return this.children[0];\n }\n get original() {\n return this.children[1];\n }\n get fieldBindings() {\n return this.children[2];\n }\n fieldNames() {\n const names = [];\n for (const fieldBinding of this.fieldBindings) {\n names.push(fieldBinding.fieldName.value);\n }\n return names;\n }\n}\nclass ASTExprFunctionCall extends ASTNode {\n constructor(functionName, args) {\n super(N_ExprFunctionCall, [functionName, args]);\n }\n get functionName() {\n return this.children[0];\n }\n get args() {\n return this.children[1];\n }\n}\nclass ASTFieldBinding extends ASTNode {\n constructor(fieldName, value) {\n super(N_FieldBinding, [fieldName, value]);\n }\n get fieldName() {\n return this.children[0];\n }\n get value() {\n return this.children[1];\n }\n}\nclass ASTConstructorDeclaration extends ASTNode {\n constructor(constructorName, fieldNames) {\n super(N_ConstructorDeclaration, [constructorName, fieldNames]);\n }\n get constructorName() {\n return this.children[0];\n }\n get fieldNames() {\n return this.children[1];\n }\n}\n\n/* eslint-disable camelcase */\n/* eslint-disable @typescript-eslint/explicit-function-return-type */\n/* eslint-disable quote-props */\n/* istanbul ignore file */\nconst keyword$1 = (palabra) => 'la palabra clave \"' + palabra + '\"';\nfunction pluralize$1(n, singular, plural) {\n if (n === 0) {\n return 'ningún ' + singular;\n }\n else if (n === 1) {\n return 'un ' + singular;\n }\n else {\n return n.toString() + ' ' + plural;\n }\n}\n// Only for typing purposes\n// eslint-disable-next-line @typescript-eslint/ban-types\nconst toFunc$2 = (x) => x;\nfunction ordinalNumber(n) {\n const units = [\n '',\n 'primer',\n 'segundo',\n 'tercer',\n 'cuarto',\n 'quinto',\n 'sexto',\n 'séptimo',\n 'octavo',\n 'noveno'\n ];\n if (n >= 1 && n <= 9) {\n return units[n];\n }\n else {\n return '#' + n.toString();\n }\n}\nfunction describeType(type) {\n if (type.isInteger()) {\n return ['m', 'número', 'números'];\n }\n else if (type.isBoolean()) {\n return ['m', 'booleano', 'booleanos'];\n }\n else if (type.isColor()) {\n return ['m', 'color', 'colores'];\n }\n else if (type.isDirection()) {\n return ['f', 'dirección', 'direcciones'];\n }\n else if (type.isList() && type.contentType.isAny()) {\n return ['f', 'lista', 'listas'];\n }\n else if (type.isList()) {\n const description = describeType(type.contentType);\n if (description === undefined) {\n return undefined;\n }\n else {\n const plural = description[2];\n return ['f', 'lista de ' + plural, 'listas de ' + plural];\n }\n }\n else {\n return undefined;\n }\n}\nfunction describeTypeSingular(type) {\n const description = describeType(type);\n if (description === undefined) {\n return type.toString();\n }\n else {\n const singular = description[1];\n return singular;\n }\n}\nfunction typeAsNoun(type) {\n const description = describeType(type);\n if (description === undefined) {\n return 'un valor de tipo ' + type.toString();\n }\n else {\n const gender = description[0];\n const singular = description[1];\n if (gender === 'm') {\n return 'un ' + singular;\n }\n else {\n return 'una ' + singular;\n }\n }\n}\nfunction typeAsQualifierSingular(type) {\n const description = describeType(type);\n if (description === undefined) {\n return 'de tipo ' + type.toString();\n }\n else {\n const gender = description[0];\n const singular = description[1];\n if (gender === 'm') {\n return 'un ' + singular;\n }\n else {\n return 'una ' + singular;\n }\n }\n}\nfunction typeAsQualifierPlural(type) {\n const description = describeType(type);\n if (description === undefined) {\n return 'de tipo ' + type.toString();\n }\n else {\n const gender = description[0];\n const plural = description[2];\n if (gender === 'm') {\n return plural;\n }\n else {\n return plural;\n }\n }\n}\nfunction listOfTypes(types) {\n const typeStrings = [];\n for (const type of types) {\n typeStrings.push(describeTypeSingular(type));\n }\n return typeStrings.join(', ');\n}\nfunction openingDelimiterName(delimiter) {\n if (delimiter === '(' || delimiter === ')') {\n return 'un paréntesis abierto \"(\"';\n }\n else if (delimiter === '[' || delimiter === ']') {\n return 'un corchete abierto \"[\"';\n }\n else if (delimiter === '{' || delimiter === '}') {\n return 'una llave abierta \"{\"';\n }\n else {\n return delimiter;\n }\n}\nfunction formatTypes(string, type1, type2) {\n let result = '';\n for (let i = 0; i < string.length; i++) {\n if (string[i] === '%' && i + 1 < string.length) {\n if (string[i + 1] === '%') {\n result += '%';\n i++;\n }\n else if (string[i + 1] === '1') {\n result += typeAsNoun(type1);\n i++;\n }\n else if (string[i + 1] === '2') {\n result += typeAsNoun(type2);\n i++;\n }\n else {\n result += '%';\n }\n }\n else {\n result += string[i];\n }\n }\n return result;\n}\n// eslint-disable-next-line @typescript-eslint/ban-types\nconst LOCALE_ES = {\n /* Descriptions of syntactic constructions and tokens */\n definition: 'una definición (de programa, función, procedimiento, o tipo)',\n pattern: 'un patrón (comodín \"_\", constructor aplicado a variables, o tupla)',\n statement: 'un comando',\n expression: 'una expresión',\n 'procedure call': 'una invocación a un procedimiento',\n 'field name': 'el nombre de un campo',\n T_EOF: 'el final del archivo',\n T_NUM: 'un número',\n T_STRING: 'una cadena (string)',\n T_UPPERID: 'un identificador con mayúsculas',\n T_LOWERID: 'un identificador con minúsculas',\n T_PROGRAM: keyword$1('program'),\n T_INTERACTIVE: keyword$1('interactive'),\n T_PROCEDURE: keyword$1('procedure'),\n T_FUNCTION: keyword$1('function'),\n T_RETURN: keyword$1('return'),\n T_IF: keyword$1('if'),\n T_THEN: keyword$1('then'),\n T_ELSE: keyword$1('else'),\n T_REPEAT: keyword$1('repeat'),\n T_FOREACH: keyword$1('foreach'),\n T_IN: keyword$1('in'),\n T_WHILE: keyword$1('while'),\n T_SWITCH: keyword$1('switch'),\n T_TO: keyword$1('to'),\n T_LET: keyword$1('let'),\n T_NOT: keyword$1('not'),\n T_DIV: keyword$1('div'),\n T_MOD: keyword$1('mod'),\n T_TYPE: keyword$1('type'),\n T_IS: keyword$1('is'),\n T_CHOOSE: keyword$1('choose'),\n T_WHEN: keyword$1('when'),\n T_OTHERWISE: keyword$1('otherwise'),\n T_MATCHING: keyword$1('matching'),\n T_SELECT: keyword$1('select'),\n T_ON: keyword$1('on'),\n T_RECORD: keyword$1('record'),\n T_VARIANT: keyword$1('variant'),\n T_CASE: keyword$1('case'),\n T_FIELD: keyword$1('field'),\n T_UNDERSCORE: 'un guión bajo (\"_\")',\n T_LPAREN: 'un paréntesis izquierdo (\"(\")',\n T_RPAREN: 'un paréntesis derecho (\")\")',\n T_LBRACE: 'una llave izquierda (\"{\")',\n T_RBRACE: 'una llave derecha (\"}\")',\n T_LBRACK: 'un corchete izquierdo (\"[\")',\n T_RBRACK: 'un corchete derecho (\"]\")',\n T_COMMA: 'una coma (\",\")',\n T_SEMICOLON: 'un punto y coma (\";\")',\n T_RANGE: 'un separador de rango (\"..\")',\n T_GETS: 'una flecha hacia la izquierda (\"<-\")',\n T_PIPE: 'una barra vertical (\"|\")',\n T_ARROW: 'una flecha (\"->\")',\n T_ASSIGN: 'un operador de asignación (\":=\")',\n T_EQ: 'una comparación por igualdad (\"==\")',\n T_NE: 'una comparación por desigualdad (\"/=\")',\n T_LE: 'un menor o igual (\"<=\")',\n T_GE: 'un mayor o igual (\">=\")',\n T_LT: 'un menor estricto (\"<\")',\n T_GT: 'un mayor estricto (\">\")',\n T_AND: 'el \"y\" lógico (\"&&\")',\n T_OR: 'el \"o\" lógico (\"||\")',\n T_CONCAT: 'el operador de concatenación de listas (\"++\")',\n T_PLUS: 'el operador de suma (\"+\")',\n T_MINUS: 'el operador de resta (\"-\")',\n T_TIMES: 'el operador de producto (\"*\")',\n T_POW: 'el operador de potencia (\"^\")',\n /* Local name categories */\n LocalVariable: 'variable',\n LocalIndex: 'índice',\n LocalParameter: 'parámetro',\n /* Descriptions of value types */\n V_Integer: 'un número',\n V_String: 'una cadena',\n V_Tuple: 'una tupla',\n V_List: 'una lista',\n V_Structure: 'una estructura',\n /* Lexer */\n 'errmsg:unclosed-multiline-comment': 'El comentario se abre pero nunca se cierra.',\n 'errmsg:unclosed-string-constant': 'La comilla que abre no tiene una comilla que cierra correspondiente.',\n // eslint-disable-next-line max-len\n 'errmsg:numeric-constant-should-not-have-leading-zeroes': `Las constantes numéricas no se pueden escribir con ceros a la izquierda.`,\n // eslint-disable-next-line max-len\n 'errmsg:identifier-must-start-with-alphabetic-character': `Los identificadores deben empezar con un caracter alfabético (a...z,A...Z).`,\n 'errmsg:unknown-token': (symbol) => 'Símbolo desconocido en la entrada: \"' + symbol + '\".',\n 'warning:empty-pragma': 'Directiva pragma vacía.',\n 'warning:unknown-pragma': (pragmaName) => 'Directiva pragma desconocida: \"' + pragmaName + '\".',\n 'errmsg:unmatched-opening-delimiter': (delimiter) => 'Se encontró ' + openingDelimiterName(delimiter) + ' pero nunca se cierra.',\n 'errmsg:unmatched-closing-delimiter': (delimiter) => 'Se encontró un \"' +\n delimiter +\n '\" ' +\n 'pero no había ' +\n openingDelimiterName(delimiter) +\n '.',\n 'errmsg:unknown-language-option': (option) => 'Opción desconocida. \"' + option + '\".',\n /* Parser */\n 'errmsg:empty-source': 'El programa está vacío.',\n 'errmsg:expected-but-found': (expected, found) => `Se esperaba ${expected}. Se encontró: ${found}.`,\n 'errmsg:pattern-number-cannot-be-negative-zero': 'El patrón numérico no puede ser \"-0\".',\n 'errmsg:return-tuple-cannot-be-empty': 'El return tiene que devolver algo.',\n 'errmsg:pattern-tuple-cannot-be-singleton': 'El patrón para una tupla no puede tener una sola componente. ' +\n 'Las tuplas tienen 0, 2, 3, o más componentes, pero no 1.',\n 'errmsg:assignment-tuple-cannot-be-singleton': 'La asignación a una tupla no puede constar de una sola componente. ' +\n 'Las tuplas tienen 0, 2, 3, o más componentes, pero no 1.',\n 'errmsg:operators-are-not-associative': (op1, op2) => 'La expresión usa ' +\n op1 +\n ' y ' +\n op2 +\n ', pero estos operadores no se pueden asociar. ' +\n 'Quizás faltan paréntesis.',\n 'errmsg:obsolete-tuple-assignment': 'Se esperaba un comando pero se encontró un paréntesis izquierdo. ' +\n 'Nota: la sintaxis de asignación de tuplas \"(x1, ..., xN) := y\" ' +\n 'está obsoleta. Usar \"let (x1, ..., xN) := y\".',\n /* Linter */\n 'errmsg:program-already-defined': (pos1, pos2) => 'Ya había un programa definido en ' +\n pos1 +\n '.\\n' +\n 'No se puede definir un programa en ' +\n pos2 +\n '.',\n 'errmsg:procedure-already-defined': (name, pos1, pos2) => 'El procedimiento \"' +\n name +\n '\" está definido dos veces: ' +\n 'en ' +\n pos1 +\n ' y en ' +\n pos2 +\n '.',\n 'errmsg:function-already-defined': (name, pos1, pos2) => 'La función \"' +\n name +\n '\" está definida dos veces: ' +\n 'en ' +\n pos1 +\n ' y en ' +\n pos2 +\n '.',\n 'errmsg:type-already-defined': (name, pos1, pos2) => `El tipo \"${name}\" está definido dos veces: en ${pos1} y en ${pos2}.`,\n 'errmsg:constructor-already-defined': (name, pos1, pos2) => 'El constructor \"' +\n name +\n '\" está definido dos veces: ' +\n 'en ' +\n pos1 +\n ' y en ' +\n pos2 +\n '.',\n 'errmsg:repeated-field-name': (constructorName, fieldName) => 'El campo \"' +\n fieldName +\n '\" no puede estar repetido ' +\n 'para el constructor \"' +\n constructorName +\n '\".',\n 'errmsg:function-and-field-cannot-have-the-same-name': (name, posFunction, posField) => 'El nombre \"' +\n name +\n '\" se usa ' +\n 'para una función en ' +\n posFunction +\n ' y ' +\n 'para un campo en ' +\n posField +\n '.',\n 'errmsg:source-should-have-a-program-definition': \n /* Note: the code may actually be completely empty, but\n * we avoid this technicality since the message could be\n * confusing. */\n 'El código debe tener una definición de \"program { ... }\".',\n 'errmsg:procedure-should-not-have-return': (name) => `El procedimiento \"${name}\" no debería tener un comando \"return\".`,\n 'errmsg:function-should-have-return': (name) => 'La función \"' + name + '\" debería tener un comando \"return\".',\n 'errmsg:return-statement-not-allowed-here': 'El comando \"return\" solo puede aparecer como el último comando ' +\n 'de una función o como el último comando del programa.',\n 'errmsg:local-name-conflict': (name, oldCat, oldPos, newCat, newPos) => 'Conflicto de nombres: \"' +\n name +\n '\" se usa dos veces: ' +\n 'como ' +\n oldCat +\n ' en ' +\n oldPos +\n ', y ' +\n 'como ' +\n newCat +\n ' en ' +\n newPos +\n '.',\n 'errmsg:repeated-variable-in-tuple-assignment': (name) => `La variable \"${name}\" está repetida en la asignación de tuplas.`,\n 'errmsg:constructor-used-as-procedure': (name, type) => 'El procedimiento \"' +\n name +\n '\" no está definido. ' +\n 'El nombre \"' +\n name +\n '\" es el nombre de un constructor ' +\n 'del tipo \"' +\n type +\n '\".',\n 'errmsg:undefined-procedure': (name) => 'El procedimiento \"' + name + '\" no está definido.',\n 'errmsg:undefined-function': (name) => 'La función \"' + name + '\" no está definida.',\n 'errmsg:procedure-arity-mismatch': (name, expected, received) => '\"El procedimiento \"' +\n name +\n '\" espera recibir ' +\n toFunc$2(LOCALE_ES['<n>-parameters'])(expected) +\n ' pero se lo invoca con ' +\n toFunc$2(LOCALE_ES['<n>-arguments'])(received) +\n '.',\n 'errmsg:function-arity-mismatch': (name, expected, received) => 'La función \"' +\n name +\n '\" espera recibir ' +\n toFunc$2(LOCALE_ES['<n>-parameters'])(expected) +\n ' pero se la invoca con ' +\n toFunc$2(LOCALE_ES['<n>-arguments'])(received) +\n '.',\n 'errmsg:structure-pattern-arity-mismatch': (name, expected, received) => 'El constructor \"' +\n name +\n '\" tiene ' +\n toFunc$2(LOCALE_ES['<n>-fields'])(expected) +\n ' pero el patrón tiene ' +\n toFunc$2(LOCALE_ES['<n>-parameters'])(received) +\n '.',\n 'errmsg:type-used-as-constructor'(name, constructorNames) {\n let msg;\n if (constructorNames.length === 0) {\n msg = '(no tiene constructores).';\n }\n else if (constructorNames.length === 1) {\n msg = '(tiene un constructor: ' + constructorNames[0] + ').';\n }\n else {\n msg = '(sus constructores son: ' + constructorNames.join(', ') + ').';\n }\n return ('El constructor \"' +\n name +\n '\" no está definido. ' +\n 'El nombre \"' +\n name +\n '\" es el nombre de un tipo ' +\n msg);\n },\n 'errmsg:procedure-used-as-constructor': (name) => 'El constructor \"' +\n name +\n '\" no está definido. ' +\n 'El nombre \"' +\n name +\n '\" es el nombre de un procedimiento.',\n 'errmsg:undeclared-constructor': (name) => 'El constructor \"' + name + '\" no está definido.',\n 'errmsg:wildcard-pattern-should-be-last': 'El comodín \"_\" debe estar en la última rama.',\n 'errmsg:variable-pattern-should-be-last': (name) => 'El patrón variable \"' + name + '\" tiene debe estar en la última rama.',\n 'errmsg:numeric-pattern-repeats-number': (number) => 'Hay dos ramas distintas para el número \"' + number + '\".',\n 'errmsg:structure-pattern-repeats-constructor': (name) => 'Hay dos ramas distintas para el constructor \"' + name + '\".',\n 'errmsg:structure-pattern-repeats-tuple-arity': (arity) => 'Hay dos ramas distintas para las tuplas de ' + arity.toString() + ' componentes.',\n 'errmsg:structure-pattern-repeats-timeout': 'Hay dos ramas distintas para el TIMEOUT.',\n 'errmsg:pattern-does-not-match-type': (expectedType, patternType) => 'Los patrones tienen que ser todos del mismo tipo. ' +\n 'El patrón debería ser de tipo ' +\n expectedType +\n 'pero es de tipo ' +\n patternType +\n '.',\n 'errmsg:patterns-in-interactive-program-must-be-events': 'Los patrones de un \"interactive program\" deben ser eventos.',\n 'errmsg:patterns-in-interactive-program-cannot-be-variables': 'El patrón no puede ser una variable.',\n 'errmsg:patterns-in-switch-must-not-be-events': 'El patrón no puede ser un evento.',\n 'errmsg:structure-construction-repeated-field': (constructorName, fieldName) => 'El campo \"' +\n fieldName +\n '\" está repetido en ' +\n 'la instanciación del constructor \"' +\n constructorName +\n '\".',\n 'errmsg:structure-construction-invalid-field': (constructorName, fieldName) => 'El campo \"' +\n fieldName +\n '\" no es un campo válido ' +\n 'para el constructor \"' +\n constructorName +\n '\".',\n 'errmsg:structure-construction-missing-field': (constructorName, fieldName) => 'Falta darle valor al campo \"' +\n fieldName +\n '\" ' +\n 'del constructor \"' +\n constructorName +\n '\".',\n 'errmsg:structure-construction-cannot-be-an-event': (constructorName) => 'El constructor \"' +\n constructorName +\n '\" corresponde a un ' +\n 'evento, y solamente se puede manejar implícitamente ' +\n 'en un programa interactivo (el usuario no puede construir ' +\n 'instancias).',\n 'errmsg:forbidden-extension-destructuring-foreach': 'El índice de la repetición indexada debe ser un identificador.',\n ['errmsg:forbidden-extension-allow-recursion']: (cycle) => {\n const msg = [];\n for (const call of cycle) {\n msg.push(' ' +\n call.caller +\n ' llama a ' +\n call.callee +\n ' (' +\n call.location.startPos.filename.toString() +\n ':' +\n call.location.startPos.line.toString() +\n ':' +\n call.location.startPos.column.toString() +\n ')');\n }\n return ('La recursión está deshabilitada. ' +\n 'Hay un ciclo en las invocaciones:\\n' +\n msg.join('\\n'));\n },\n 'errmsg:patterns-in-foreach-must-not-be-events': 'El patrón de un foreach no puede ser un evento.',\n /* Runtime errors (virtual machine) */\n 'errmsg:ellipsis': 'El programa todavía no está completo.',\n 'errmsg:undefined-variable': (variableName) => 'La variable \"' + variableName + '\" no está definida.',\n 'errmsg:too-few-arguments': (routineName) => 'Faltan argumentos para \"' + routineName + '\".',\n 'errmsg:expected-structure-but-got': (constructorName, valueTag) => 'Se esperaba una estructura construida ' +\n 'con el constructor \"' +\n constructorName +\n '\", ' +\n 'pero se recibió ' +\n valueTag +\n '.',\n 'errmsg:expected-constructor-but-got': (constructorNameExpected, constructorNameReceived) => 'Se esperaba una estructura construida ' +\n 'con el constructor \"' +\n constructorNameExpected +\n '\", ' +\n 'pero el constructor recibido es ' +\n constructorNameReceived +\n '\".',\n 'errmsg:incompatible-types-on-assignment': (variableName, oldType, newType) => 'La variable \"' +\n variableName +\n '\" ' +\n 'contenía ' +\n typeAsNoun(oldType) +\n ', ' +\n 'no se le puede asignar ' +\n typeAsNoun(newType) +\n '\".',\n 'errmsg:incompatible-types-on-list-creation': (index, oldType, newType) => 'Todos los elementos de una lista deben ser del mismo tipo. ' +\n 'Los elementos son ' +\n typeAsQualifierPlural(oldType) +\n ', ' +\n 'pero el elemento en la posición ' +\n index.toString() +\n ' ' +\n 'es ' +\n typeAsQualifierSingular(newType) +\n '.',\n 'errmsg:incompatible-types-on-structure-update': (fieldName, oldType, newType) => 'El campo \"' +\n fieldName +\n '\" es ' +\n typeAsQualifierSingular(oldType) +\n '. ' +\n 'No se lo puede actualizar con ' +\n typeAsNoun(newType) +\n '.',\n 'errmsg:expected-tuple-value-but-got': (receivedType) => 'Se esperaba una tupla pero se recibió ' + typeAsNoun(receivedType) + '.',\n 'errmsg:tuple-component-out-of-bounds': (size, index) => 'Índice fuera de rango. ' +\n 'La tupla es de tamaño ' +\n size.toString() +\n ' y ' +\n 'el índice es ' +\n index.toString() +\n '.',\n 'errmsg:expected-structure-value-but-got': (receivedType) => 'Se esperaba una estructura pero se recibió ' + typeAsNoun(receivedType) + '.',\n 'errmsg:structure-field-not-present': (fieldNames, missingFieldName) => 'La estructura no tiene un campo \"' +\n missingFieldName +\n '\". ' +\n 'Los campos son: [' +\n fieldNames.join(', ') +\n '].',\n 'errmsg:primitive-does-not-exist': (primitiveName) => `La operación primitiva \"${primitiveName}\" no existe o no está disponible.`,\n 'errmsg:primitive-arity-mismatch': (name, expected, received) => 'La operación \"' +\n name +\n '\" espera recibir ' +\n toFunc$2(LOCALE_ES['<n>-parameters'])(expected) +\n ' pero se la invoca con ' +\n toFunc$2(LOCALE_ES['<n>-arguments'])(received) +\n '.',\n 'errmsg:primitive-argument-type-mismatch'(name, parameterIndex, numArgs, expectedType, receivedType) {\n let msg = 'El ';\n if (numArgs > 1) {\n msg += ordinalNumber(parameterIndex) + ' ';\n }\n msg += 'parámetro ';\n msg += 'de \"' + name + '\" ';\n msg += 'debería ser ' + typeAsQualifierSingular(expectedType) + ' ';\n msg += 'pero es ' + typeAsQualifierSingular(receivedType) + '.';\n return msg;\n },\n 'errmsg:expected-value-of-type-but-got': (expectedType, receivedType) => 'Se esperaba ' +\n typeAsNoun(expectedType) +\n ' ' +\n 'pero se recibió ' +\n typeAsNoun(receivedType) +\n '.',\n 'errmsg:expected-value-of-some-type-but-got': (expectedTypes, receivedType) => 'Se esperaba un valor de alguno de los siguientes tipos: ' +\n listOfTypes(expectedTypes) +\n '. ' +\n 'Pero se recibió ' +\n typeAsNoun(receivedType) +\n '.',\n 'errmsg:expected-values-to-have-compatible-types': (type1, type2) => 'Los tipos de las expresiones no coinciden: ' +\n 'la primera es ' +\n typeAsQualifierSingular(type1) +\n ' ' +\n 'y la segunda es ' +\n typeAsQualifierSingular(type2) +\n '.',\n 'errmsg:switch-does-not-match': 'El valor analizado no coincide con ninguna de las ramas del switch.',\n 'errmsg:foreach-pattern-does-not-match': 'El elemento no coincide con el patrón esperado por el foreach.',\n 'errmsg:cannot-divide-by-zero': 'No se puede dividir por cero.',\n 'errmsg:negative-exponent': 'El exponente de la potencia no puede ser negativo.',\n 'errmsg:list-cannot-be-empty': 'La lista no puede ser vacía.',\n 'errmsg:timeout': (millisecs) => 'La ejecución del programa demoró más de ' + millisecs.toString() + 'ms.',\n /* Typecheck */\n 'errmsg:typecheck-failed': (errorMessage, type1, type2) => formatTypes(errorMessage, type1, type2),\n /* Board operations */\n 'errmsg:cannot-move-to': (dirName) => 'No se puede mover hacia la dirección ' + dirName + ': cae afuera del tablero.',\n 'errmsg:cannot-remove-stone': (dirName) => 'No se puede sacar una bolita de color ' + dirName + ': no hay bolitas de ese color.',\n /* Runtime */\n 'TYPE:Integer': 'Number',\n 'TYPE:String': 'String',\n 'TYPE:Tuple': '',\n 'TYPE:List': 'List',\n 'TYPE:Event': 'Event',\n 'CONS:INIT': 'INIT',\n 'CONS:TIMEOUT': 'TIMEOUT',\n 'TYPE:Bool': 'Bool',\n 'CONS:False': 'False',\n 'CONS:True': 'True',\n 'TYPE:Color': 'Color',\n 'CONS:Color0': 'Azul',\n 'CONS:Color1': 'Negro',\n 'CONS:Color2': 'Rojo',\n 'CONS:Color3': 'Verde',\n 'TYPE:Dir': 'Dir',\n 'CONS:Dir0': 'Norte',\n 'CONS:Dir1': 'Este',\n 'CONS:Dir2': 'Sur',\n 'CONS:Dir3': 'Oeste',\n 'PRIM:TypeCheck': 'TypeCheck',\n 'PRIM:BOOM': 'BOOM',\n 'PRIM:boom': 'boom',\n 'PRIM:PutStone': 'Poner',\n 'PRIM:RemoveStone': 'Sacar',\n 'PRIM:Move