UNPKG

mathjslab

Version:

MathJSLab - An interpreter with language syntax like MATLAB®/Octave, ISBN 978-65-00-82338-7.

1,425 lines 52.5 kB
import { CharString, StringQuoteCharacter } from './CharString'; import { ComplexType } from './Complex'; import { FunctionHandle } from './FunctionHandle'; import { type ElementType, MultiArray } from './MultiArray'; /** * Normalized AST and runtime node contracts used by parser, evaluator, * unparser, MathML rendering, and diagnostics. * * Parser actions should create nodes through `AST` factory methods whenever * possible. The factories encode parent-pointer conventions, output/answer * suppression flags, and MATLAB/Octave-specific structural choices such as * return lists, command-form calls, `arguments` blocks, and `classdef` sections. */ /** * Operators accepted by the normalized expression AST. * * Suffix/prefix encodings such as `+_`, `_++`, and `.'` disambiguate source * syntax that shares a token but has different precedence or operand position. */ type OperatorType = '+' | '-' | '.*' | '*' | './' | '/' | '.\\' | '\\' | '.^' | '^' | '.**' | '**' | '<' | '<=' | '==' | '>=' | '>' | '!=' | '~=' | '&' | '|' | '&&' | '||' | '=' | '+=' | '-=' | '*=' | '/=' | '\\=' | '^=' | '**=' | '.*=' | './=' | '.\\=' | '.^=' | '.**=' | '&=' | '|=' | '()' | '!' | '~' | '+_' | '-_' | '++_' | '--_' | ".'" | "'" | '_++' | '_--'; /** * Delimiter used by an index expression. * * Parentheses mean ordinary array/function indexing; braces mean cell-array * content indexing. */ type IndexingDelimiterType = '()' | '{}'; /** * Discriminant values for AST nodes and runtime objects that participate in * generic interpreter dispatch. * * Numeric runtime tags are used by value classes such as `Complex`, * `MultiArray`, and class infrastructure objects. String tags are reserved for * parser-created AST nodes. */ type NodeType = 'IDENT' | 'CMDWLIST' | 'IDX' | 'RANGE' | 'ENDRANGE' | 'LIST' | '.' | ':' | '<~>' | 'VOID' | 'RETLIST' | 'FCNDEF' | 'USERFCN' | 'BUILTIN' | 'ARGVALID' | 'ARGS' | 'GLOBAL' | 'PERSIST' | 'IMPORT' | 'RETURN' | 'BREAK' | 'CONTINUE' | 'IF' | 'ELSEIF' | 'ELSE' | 'SWITCH' | 'CASE' | 'WHILE' | 'DO_UNTIL' | 'FOR' | 'SPMD' | 'TRY' | 'UNWIND_PROTECT' | 'CLASSDEF' | 'CLASS_SECTION' | 'CLASS_PROPERTY' | 'CLASS_EVENT' | 'CLASS_ENUMERATION' | 'CLASS_ATTRIBUTE' | 'SUPERCLASS_CTOR' | 'METACLASS' | OperatorType; /** * Table of symbolic aliases recognized by the lexer/parser layer. */ type AliasNameTable = Record<string, RegExp>; type DefiningScope = unknown; /** * Common metadata carried by all AST nodes. * * `parent` and `index` are best-effort navigation aids; evaluation logic should * not require them for correctness. `omitOutput` models MATLAB/Octave semicolon * suppression, while `omitAnswer` prevents helper statements such as * declarations and function definitions from updating `ans`. */ interface NodeBase { /** Node discriminant. */ type: NodeType | number; /** Parent AST node or runtime wrapper, when known. */ parent?: NodeBase; /** Index inside a parent list, when the node belongs to a list. */ index?: number; /** Whether evaluation output should be suppressed. */ omitOutput?: boolean; /** Whether the result should avoid assignment to `ans`. */ omitAnswer?: boolean; /** Source start position, when supplied by the parser. */ start?: { line: number; column: number; }; /** Source stop position, when supplied by the parser. */ stop?: { line: number; column: number; }; } /** * Explicit "no value" node. */ interface NodeVoid extends NodeBase { type: 'VOID'; } /** * Executable statement nodes recognized by the interpreter. */ type NodeStatement = NodeDeclaration | NodeImport | NodeReturn | NodeBreak | NodeContinue | NodeIf | NodeSwitch | NodeWhile | NodeDoUntil | NodeFor | NodeSpmd | NodeTry | NodeUnwindProtect | NodeFunctionDefinition | NodeClassDef; /** * Class-body nodes that are parsed as members or section metadata. */ type NodeClassMember = NodeClassSection | NodeClassProperty | NodeClassEvent | NodeClassEnumeration | NodeClassAttribute; /** * Nodes accepted inside concrete classdef sections. */ type NodeClassSectionMember = NodeClassProperty | NodeFunctionDefinition | NodeClassEvent | NodeClassEnumeration; /** * Root forms that can appear as direct interpreter input. */ type NodeProgramElement = NodeExpr | NodeStatement | NodeClassMember; /** * Any AST node that can be used as an executable/evaluable input. */ type NodeInput = NodeProgramElement | NodeList; /** * AST node that can appear in expression position. * * Runtime value shape accepted by expression evaluation before it is wrapped * into parser-created AST containers. */ type RuntimeExpressionValue = Exclude<ElementType, null | undefined>; /** * AST node that can appear in expression position. * * Strict expression shape used by new code that can stay inside the typed AST * and runtime-value surface. */ type StrictNodeExpr = RuntimeExpressionValue | NodeVoid | NodeIdentifier | NodeCmdWList | NodeIndexExpr | NodeSuperclassConstructor | NodeMetaClass | NodeRange | NodeColon | NodeEndRange | NodeOperation | NodeIgnoredTarget | NodeIndirectRef | NodeImport | NodeReturnList; /** * Non-expression AST nodes that are stored in `NodeList` while a surrounding * builder assembles a larger statement node. */ type NodeListElement = NodeExpr | NodeElseIf | NodeElse | NodeSwitchCase | NodeFunctionDefinition | NodeArgumentValidation | NodeArguments | NodeClassSection | NodeClassProperty | NodeClassEvent | NodeClassEnumeration | NodeClassAttribute; /** * AST node that can appear in expression position. * * Generated ANTLR actions and a few evaluator reducers still route mixed AST * shapes through `NodeExpr`. This carrier keeps that migration boundary * explicit while stricter hand-written code uses `StrictNodeExpr`, * `ExpressionBoundaryValue`, and AST guards. */ type LegacyNodeExprCarrier = any; /** * AST node that can appear in expression position. * * The strict branch documents the intended expression domain. The legacy * carrier is a named migration boundary for generated parser actions and old * evaluator paths that still carry broader AST shapes through expression * slots. */ type NodeExpr = StrictNodeExpr | LegacyNodeExprCarrier; /** * Value accepted after an explicit expression-boundary validation. * * `NodeList` is included only as an execution-result carrier for paths such as * `eval`/`evalin` and lazy return lists. New ordinary expression slots should * prefer `StrictNodeExpr` when they do not need that carrier. */ type ExpressionBoundaryValue = StrictNodeExpr | NodeList; /** * Reserved node. */ interface NodeReserved extends NodeBase { } /** * Literal node. */ interface NodeLiteral extends NodeBase { } /** * Name node. */ interface NodeIdentifier extends NodeBase { type: 'IDENT'; id: string; } /** * Command word list node. */ interface NodeCmdWList extends NodeBase { type: 'CMDWLIST'; id: string; args: CharString[]; } /** * Expression and arguments node. */ interface NodeIndexExpr extends NodeBase { type: 'IDX'; expr: NodeExpr; exprEvaluated?: NodeExpr; args: ExpressionBoundaryValue[]; delim: IndexingDelimiterType; } /** * Explicit superclass constructor call, e.g. `obj@Base(args...)`. */ interface NodeSuperclassConstructor extends NodeBase { type: 'SUPERCLASS_CTOR'; instance: NodeExpr; superclass: NodeIdentifier; args: ExpressionBoundaryValue[]; } /** * Metaclass literal, e.g. `?ClassName`. */ interface NodeMetaClass extends NodeBase { type: 'METACLASS'; className: NodeIdentifier; } /** * Range node. */ interface NodeRange extends NodeBase { type: 'RANGE'; start_: NodeExpr; stop_: NodeExpr; stride_: NodeExpr | null; } /** * Colon token node used by ranges and indexing. */ interface NodeColon extends NodeBase { type: ':'; } /** * `end` token node used inside indexing ranges. */ interface NodeEndRange extends NodeBase { type: 'ENDRANGE'; } /** * Operation node. */ type NodeOperation = UnaryOperation | BinaryOperation; /** * Unary operation node. */ type UnaryOperation = UnaryOperationL | UnaryOperationR; /** * Prefix unary operation with its operand stored on `right`. */ type PrefixUnaryOperation = UnaryOperationR; /** * Postfix unary operation with its operand stored on `left`. */ type PostfixUnaryOperation = UnaryOperationL; /** * Right unary operation node. */ interface UnaryOperationR extends NodeBase { right: NodeExpr; } /** * Left unary operation node. */ interface UnaryOperationL extends NodeBase { left: NodeExpr; } /** * Binary operation. */ interface BinaryOperation extends NodeBase { left: NodeExpr; right: NodeExpr; } /** * Ignored return target (`~`) in a return or assignment list. */ interface NodeIgnoredTarget extends NodeBase { type: '<~>'; } /** * Return-list entry accepted by MATLAB/Octave function definitions. */ type NodeFunctionReturn = NodeIdentifier | NodeIgnoredTarget; /** * Declaration entry accepted by `global` and `persistent` declarations. */ type NodeDeclarationElement = NodeIdentifier | NodeDefaultedParameter; /** * Parameter-list entry accepted by MATLAB/Octave function definitions. */ type NodeFunctionParameter = NodeIdentifier | NodeIgnoredTarget | NodeOperation; /** * Defaulted parameter form accepted in MATLAB/Octave function headers. */ type NodeDefaultedParameter = BinaryOperation & { type: '='; left: NodeIdentifier; right: NodeExpr; }; /** * Left-hand-side expression forms accepted by assignment validation. */ type NodeAssignmentTarget = NodeIdentifier | NodeIgnoredTarget | NodeIndexExpr | NodeIndirectRef | MultiArray; /** * List node */ interface NodeList extends NodeBase { type: 'LIST'; list: NodeListElement[]; } /** * Dot-reference node for structures and chained field access. */ interface NodeIndirectRef extends NodeBase { type: '.'; obj: NodeExpr; field: (string | NodeExpr)[]; } /** * Lazily evaluated return values keyed by result name. * * `length` is metadata, while dynamic output fields hold expression values. */ type ReturnHandlerResult = { length: number; [name: string]: NodeExpr | number | undefined; }; /** * Select a single output from a realized return handler result. */ type ReturnSelector = (evaluated: ReturnHandlerResult, index: number) => NodeExpr; /** * Materialize the outputs requested by a caller. */ type ReturnHandler = (length: number) => ReturnHandlerResult; /** * Error callback used by AST helpers that should not depend on Interpreter. */ type ThrowError = (message: string) => never; /** * Callable implementation stored in built-in registration tables. * * The concrete built-ins use specialized parameter and return types, so the * registry keeps only the common "callable" shape and lets the interpreter * perform the runtime dispatch. */ type BuiltInFunctionImplementation = Function; /** * Lazy multi-output return-list node. */ interface NodeReturnList extends NodeBase { type: 'RETLIST'; /** Select one materialized output by zero-based index. */ selector: ReturnSelector; /** Materialize the caller-requested output arity. */ handler: ReturnHandler; /** Marks values that should expand as a MATLAB/Octave comma-separated list. */ commaSeparated?: boolean; /** Number of comma-separated elements available without forcing the handler. */ returnListLength?: number; } /** * Common fields shared by user-defined and built-in functions. */ interface NodeFunction extends NodeBase { type: 'FCNDEF' | 'BUILTIN'; id: string; mapper: boolean; ev: boolean[]; func: Function | null; definingScope?: DefiningScope; /** * Canonical virtual source name for function-file backed definitions. * * The browser runtime has no ambient filesystem, so this stores the * resolver-provided `.m` source identity used by `mfilename("fullpath")` * and stack/introspection helpers. */ sourceName?: string; attributes?: { /** * Per-function persistent variable storage. * * Values are copied into the call scope at function entry and copied * back after execution. The table lives on the function node so it * survives between calls while the definition remains registered. */ persistent?: Record<string, RuntimeExpressionValue>; /** * Marks function definitions registered from inside another function. * * Nested functions share selected parent-scope bindings and are reported * as nested by introspection helpers such as `which` and `functions`. */ nested?: boolean; /** * Marks a classdef method declaration without an inline function body. */ prototype?: boolean; /** * Marks a subfunction registered from a function-file source. * * Function-file subfunctions share the file function table with the * primary function, but they are not exported to the caller/base scope. */ subfunction?: boolean; }; } /** * AST node for a MATLAB/Octave-like user function definition. */ interface NodeFunctionDefinition extends NodeFunction { type: 'FCNDEF'; /** * Return variables (IDENT nodes) * Example: function [a,b] = f(x) */ return: NodeList; /** * Formal parameters (IDENT nodes) */ parameter: NodeList; /** * Argument validation blocks (MATLAB-style). * * These blocks are validated during definition registration and function * calls. They support Input, Output, Repeating, defaults, name-value * declarations, size/class declarations, and supported validator functions. */ arguments: NodeList; /** * Function body statements */ statements: NodeList; } /** * Declarative arity shape for built-ins. * * `arity < 0` denotes a variadic signature. The absolute value is the 1-based * position where variadic arguments begin, matching the convention used by * MATLAB/Octave `nargin`/`nargout` introspection. */ interface BuiltInFunctionArity { arity: number; min?: number; max?: number; } /** * Supported declarative validators for built-in function parameters. */ type BuiltInFunctionParameterValidator = 'numeric' | 'float' | 'numericOrLogical' | 'text' | 'textScalar' | 'nonzeroLengthText' | 'validVariableName' | 'scalar' | 'scalarOrEmpty' | 'scalarOrVector' | 'empty' | 'matrix2d' | 'squareMatrix' | 'vector' | 'rowVector' | 'columnVector' | 'twoElement' | 'oneOrTwoElement' | 'dimension' | 'dimensionGreaterThanOne' | 'dimensionVector' | 'reshapeDimension' | 'reshapeDimensionVector' | 'nonempty' | 'positive' | 'nonnegative' | 'negative' | 'nonpositive' | 'nonzero' | 'nonnan' | 'nonmissing' | 'nonsparse' | 'sparse' | 'zeroOrOne' | 'integer' | 'finite' | 'real'; /** * One declarative built-in parameter. * * The signature validator uses these records to replace ad hoc argument checks * inside individual built-ins. */ interface BuiltInFunctionParameter { name: string; classes?: string[]; validators?: BuiltInFunctionParameterValidator[]; allowedStrings?: string[]; identifier?: boolean; alternatives?: BuiltInFunctionParameter[]; variadicGroup?: BuiltInFunctionParameter[]; allowInfinity?: boolean; optional?: boolean; variadic?: boolean; } /** * One input overload for a built-in function. */ interface BuiltInFunctionInputSignature extends BuiltInFunctionArity { parameters?: BuiltInFunctionParameter[]; } /** * Declarative built-in signature metadata. */ interface BuiltInFunctionSignature { inputs?: BuiltInFunctionInputSignature | BuiltInFunctionInputSignature[]; outputs?: BuiltInFunctionArity | BuiltInFunctionArity[]; } interface FunctionSignatureEntry { func: BuiltInFunctionImplementation; signature: BuiltInFunctionSignature; } /** * Built-in function node registered by the runtime. */ interface NodeBuiltInFunction extends NodeFunction { type: 'BUILTIN'; /** Concrete implementation for the registered built-in. */ func: BuiltInFunctionImplementation; /** * Optional declarative call signature used by the shared validator. */ signature?: BuiltInFunctionSignature; UnparserMathML?: (tree: NodeInput) => string; } /** * `builtInFunctionTable` type. */ type BuiltInFunctionTable = Record<string, NodeBuiltInFunction>; /** * User-defined function table keyed by function name. */ type FunctionTable = Record<string, NodeFunctionDefinition>; /** * One variable binding in a scope name table. */ type NameEntry = { /** * Identifier that blocked evaluation when forward references are enabled. */ undefinedReference?: string; /** * Bound value, if the entry has been assigned. */ node?: NodeInput; /** * Marks shared entries created by `global`. */ global?: boolean; /** * Tracks whether an Octave-style `global name = value` declaration has * already initialized this global binding. */ globalInitialized?: boolean; /** * Marks function-local entries loaded from a function persistent table. */ persistent?: boolean; }; /** * Variable binding table keyed by identifier. */ type NameTable = Record<string, NameEntry>; /** * Forward-reference dependency table keyed by identifier. */ type UndefinedReferenceTable = Record<string, Set<string>>; /** * Command-form external function. * * Returning `undefined` leaves evaluation with the original command-word-list * node; returning a value supplies the evaluated result. Host integrations may * return primitive values, which the interpreter normalizes to runtime values. */ type CommandWordListFunction = (...args: string[]) => NodeInput | string | number | boolean | void; /** * `commandWordListTable` entry type. */ type CommandWordListEntry = { func: CommandWordListFunction; /** * Keep this command name as an ordinary identifier when it is followed by * an assignment operator. This is needed for built-ins such as `run` and * `source`, which support command-form calls but are also common variable * names in MATLAB/Octave code. */ preserveAssignment?: boolean; }; /** * `commandWordListTable` type. */ type CommandWordListTable = Record<string, CommandWordListEntry>; /** * One declaration inside an `arguments` block. */ interface NodeArgumentValidation extends NodeBase { type: 'ARGVALID'; /** * Identifier or name-value target such as `opts.Name`. */ name: NodeExpr; /** * Literal/symbolic size declaration. */ size: ExpressionBoundaryValue[]; /** * Class declaration. May be a single identifier or a list. */ class: NodeInput | null; /** * Validator function declarations. */ functions: ExpressionBoundaryValue[]; /** * Default expression, when declared for an input argument. */ default: NodeExpr | null; } /** * `arguments` block node. */ interface NodeArguments extends NodeBase { type: 'ARGS'; /** * First block attribute kept for compatibility with existing single-attribute code paths. */ attribute: NodeIdentifier | null; /** * Full MATLAB-like block attribute list, for example `Input,Repeating`. */ attributes: NodeIdentifier[]; validation: NodeArgumentValidation[]; } /** * Declaration node for `global` and `persistent`. */ interface NodeDeclaration extends NodeBase { type: 'GLOBAL' | 'PERSIST'; list: NodeExpr[]; } /** * MATLAB-style package/class import declaration or import-list query. */ interface NodeImport extends NodeBase { type: 'IMPORT'; /** * Fully qualified class/package imports. An empty list represents bare * `import`, which queries the currently visible imports. */ imports: NodeIdentifier[]; } /** * `return` statement node. */ interface NodeReturn extends NodeBase { type: 'RETURN'; } /** * `break` statement node. */ interface NodeBreak extends NodeBase { type: 'BREAK'; } /** * `continue` statement node. */ interface NodeContinue extends NodeBase { type: 'CONTINUE'; } /** * `if` statement node. */ interface NodeIf extends NodeBase { type: 'IF'; expression: NodeExpr[]; then: NodeList[]; else: NodeList | null; } /** * `elseif` clause node. */ interface NodeElseIf extends NodeBase { type: 'ELSEIF'; expression: NodeExpr; then: NodeList; } /** * `else` clause node. */ interface NodeElse extends NodeBase { type: 'ELSE'; else: NodeList; } /** * `case` clause node. */ interface NodeSwitchCase extends NodeBase { type: 'CASE'; expression: NodeExpr; then: NodeList; } /** * `switch` statement node. */ interface NodeSwitch extends NodeBase { type: 'SWITCH'; expression: NodeExpr; cases: NodeSwitchCase[]; otherwise: NodeList | null; } /** * `while` statement node. */ interface NodeWhile extends NodeBase { type: 'WHILE'; expression: NodeExpr; body: NodeList; } /** * `do ... until` statement node. */ interface NodeDoUntil extends NodeBase { type: 'DO_UNTIL'; body: NodeList; expression: NodeExpr; } /** * `for` statement node. */ interface NodeFor extends NodeBase { type: 'FOR'; target: NodeExpr; expression: NodeExpr; workers: NodeExpr | null; body: NodeList; parallel: boolean; } /** * `spmd` statement node. */ interface NodeSpmd extends NodeBase { type: 'SPMD'; workers: NodeList | null; body: NodeList; } /** * `try ... catch` statement node. */ interface NodeTry extends NodeBase { type: 'TRY'; body: NodeList; catchIdentifier: NodeIdentifier | null; catchBody: NodeList | null; } /** * `unwind_protect ... unwind_protect_cleanup` statement node. */ interface NodeUnwindProtect extends NodeBase { type: 'UNWIND_PROTECT'; body: NodeList; cleanup: NodeList; } /** * Supported `classdef` section kinds. */ type ClassSectionKind = 'PROPERTIES' | 'METHODS' | 'EVENTS' | 'ENUMERATION'; /** * Duplicate-preserving class attribute table keyed by attribute name. * * MATLAB/Octave diagnostics need to distinguish a repeated attribute from an * effective attribute value, so the AST keeps the full list for each key. */ type ClassAttributeTable = Record<string, NodeClassAttribute[]>; /** * `classdef` declaration node. */ interface NodeClassDef extends NodeBase { type: 'CLASSDEF'; /** Class name declared after `classdef`. */ id: string; /** Attribute nodes declared in the class header. */ attributes: NodeClassAttribute[]; /** Attribute nodes grouped by name while preserving duplicates. */ attributeTable: ClassAttributeTable; /** Direct superclass identifiers from the `< A & B` clause. */ superclasses: NodeIdentifier[]; /** Ordered `properties`, `methods`, `events`, and `enumeration` sections. */ sections: NodeClassSection[]; } /** * Section inside a `classdef` block. */ interface NodeClassSection extends NodeBase { type: 'CLASS_SECTION'; /** Section kind, normalized independently from the concrete end keyword. */ kind: ClassSectionKind; /** Section-level attributes such as `Access`, `Static`, or `Hidden`. */ attributes: NodeClassAttribute[]; /** Section attributes grouped by name while preserving duplicates. */ attributeTable: ClassAttributeTable; /** Member list for this section. */ members: NodeList; } /** * Property declaration inside a `properties` section. */ interface NodeClassProperty extends NodeBase { type: 'CLASS_PROPERTY'; /** Property name as source text. */ id: string; /** * Canonical argument-validation-shaped declaration. * * Class property declarations reuse MATLAB's `arguments` validation syntax, * so downstream code can validate size, class, and `mustBe*` functions * through the same infrastructure used for function arguments. */ validation: NodeArgumentValidation; /** Identifier node for diagnostics and metadata construction. */ name: NodeIdentifier; /** Literal/symbolic size validation list. */ size: ExpressionBoundaryValue[]; /** Class validation node, or an empty list/null when absent. */ class: NodeInput | null; /** Validator function declarations. */ functions: ExpressionBoundaryValue[]; /** Default value expression, when declared. */ defaultValue: NodeExpr | null; } /** * Event declaration inside an `events` section. */ interface NodeClassEvent extends NodeBase { type: 'CLASS_EVENT'; /** Event name. */ id: string; } /** * Enumeration declaration inside an `enumeration` section. */ interface NodeClassEnumeration extends NodeBase { type: 'CLASS_ENUMERATION'; /** Enumeration member name. */ id: string; /** Constructor-like arguments attached to the member declaration. */ args: ExpressionBoundaryValue[]; } /** * Attribute declaration for `classdef`, `properties`, and `methods`. */ interface NodeClassAttribute extends NodeBase { type: 'CLASS_ATTRIBUTE'; /** Attribute name as declared in source. */ id: string; /** Optional attribute value, including identifiers, strings, cells, or negated markers. */ value: NodeExpr | null; } /** * AST (Abstract Syntax Tree) node factory methods. */ declare abstract class AST { /** * External node factory methods. */ static nodeString: (str: string, quote?: StringQuoteCharacter) => CharString; /** * External number factory, rebound by `reload`. */ static nodeNumber: (value: string) => ComplexType; /** * External first-row matrix factory, rebound by `reload`. */ static firstRow: <ELEMENT>(row: ElementType<ELEMENT>[], iscell?: boolean) => MultiArray<ELEMENT>; /** * External row-append matrix factory, rebound by `reload`. */ static appendRow: <ELEMENT>(M: MultiArray<ELEMENT>, row: ElementType<ELEMENT>[]) => MultiArray<ELEMENT>; /** * External empty-array factory, rebound by `reload`. */ static emptyArray: <ELEMENT>(iscell?: boolean | undefined) => MultiArray<ELEMENT>; /** * Reload external node factory methods. */ static readonly reload: () => void; /** * It makes a shallow copy of the node. * @param node AST node to copy. * @returns Shallow copy of `node`. */ static readonly nodeCopy: <T = object>(node: T) => T; /** * Test whether an unknown value has the common AST/runtime node shape. */ static readonly isNodeBase: (value: unknown) => value is NodeBase; /** * Test whether an unknown value is an identifier node. */ static readonly isNodeIdentifier: (value: unknown) => value is NodeIdentifier; /** * Test whether an unknown value is a list node. */ static readonly isNodeList: (value: unknown) => value is NodeList; /** * Test whether an unknown value is a command-form call node. */ static readonly isNodeCmdWList: (value: unknown) => value is NodeCmdWList; /** * Test whether an unknown value is an index expression node. */ static readonly isNodeIndexExpr: (value: unknown) => value is NodeIndexExpr; /** * Test whether an unknown value is an explicit superclass constructor call. */ static readonly isNodeSuperclassConstructor: (value: unknown) => value is NodeSuperclassConstructor; /** * Test whether an unknown value is a range expression node. */ static readonly isNodeRange: (value: unknown) => value is NodeRange; /** * Test whether an unknown value is a colon token node. */ static readonly isNodeColon: (value: unknown) => value is NodeColon; /** * Test whether an unknown value is an `end` token node for indexing ranges. */ static readonly isNodeEndRange: (value: unknown) => value is NodeEndRange; /** * Test whether an unknown value is a dot-reference node. */ static readonly isNodeIndirectRef: (value: unknown) => value is NodeIndirectRef; /** * Test whether an unknown value is a lazy return-list node. */ static readonly isNodeReturnList: (value: unknown) => value is NodeReturnList; /** * Test whether an unknown value is an ignored target (`~`) node. */ static readonly isNodeIgnoredTarget: (value: unknown) => value is NodeIgnoredTarget; /** * Test whether an unknown value is an operator expression node. */ static readonly isNodeOperation: (value: unknown) => value is NodeOperation; /** * Test whether an unknown value is a binary operator expression. */ static readonly isNodeBinaryOperation: (value: unknown) => value is BinaryOperation; /** * Test whether an unknown value is a prefix unary operator expression. */ static readonly isNodePrefixOperation: (value: unknown) => value is PrefixUnaryOperation; /** * Test whether an unknown value is a postfix unary operator expression. */ static readonly isNodePostfixOperation: (value: unknown) => value is PostfixUnaryOperation; /** * Test whether an unknown value is a function return-list entry. */ static readonly isNodeFunctionReturn: (value: unknown) => value is NodeFunctionReturn; /** * Test whether an unknown value is a declaration-list entry. */ static readonly isNodeDeclarationElement: (value: unknown) => value is NodeDeclarationElement; /** * Test whether an unknown value is a defaulted function parameter. */ static readonly isNodeDefaultedParameter: (value: unknown) => value is NodeDefaultedParameter; /** * Test whether an unknown value is a function parameter-list entry. */ static readonly isNodeFunctionParameter: (value: unknown) => value is NodeFunctionParameter; /** * Test whether an unknown value is an assignment target expression. */ static readonly isNodeAssignmentTarget: (value: unknown) => value is NodeAssignmentTarget; /** * Test whether an unknown value is a declaration statement. */ static readonly isNodeDeclaration: (value: unknown) => value is NodeDeclaration; /** * Test whether an unknown value is an import declaration. */ static readonly isNodeImport: (value: unknown) => value is NodeImport; /** * Test whether an unknown value is a control-flow or block statement. */ static readonly isNodeStatement: (value: unknown) => value is NodeStatement; /** * Test whether an unknown value is a parsed class body member. */ static readonly isNodeClassMember: (value: unknown) => value is NodeClassMember; /** * Test whether an unknown value can appear as a top-level or block body element. */ static readonly isNodeProgramElement: (value: unknown) => value is NodeProgramElement; /** * Test whether an unknown value is a function definition node. */ static readonly isNodeFunctionDefinition: (value: unknown) => value is NodeFunctionDefinition; /** * Test whether an unknown value is a class definition node. */ static readonly isNodeClassDef: (value: unknown) => value is NodeClassDef; /** * Test whether an unknown value is a metaclass literal node. */ static readonly isNodeMetaClass: (value: unknown) => value is NodeMetaClass; /** * Test whether an unknown value is a runtime value allowed in expression position. */ static readonly isRuntimeExpressionValue: (value: unknown) => value is RuntimeExpressionValue; /** * Test whether an unknown value belongs to the strict expression contract. */ static readonly isStrictNodeExpr: (value: unknown) => value is StrictNodeExpr; /** * Test whether an unknown value has passed an expression-boundary shape. * * This accepts strict expression values plus `NodeList` execution-result * carriers used by `eval`/`evalin` and comma-separated return paths. */ static readonly isExpressionBoundaryValue: (value: unknown) => value is ExpressionBoundaryValue; /** * Validate and narrow an unknown parser/runtime value to the strict expression shape. * * @param value Candidate expression value. * @param role Human-readable role used in diagnostics. * @returns The same value narrowed to `StrictNodeExpr`. * @throws TypeError When `value` is a statement, list, or other non-expression carrier. */ static readonly requireStrictNodeExpr: (value: unknown, role?: string) => StrictNodeExpr; /** * Test whether an unknown value is an `arguments` block node. */ static readonly isNodeArguments: (value: unknown) => value is NodeArguments; /** * Test whether an unknown value is one declaration inside an `arguments` block. */ static readonly isNodeArgumentValidation: (value: unknown) => value is NodeArgumentValidation; /** * Test whether an unknown value is a `case` clause node. */ static readonly isNodeSwitchCase: (value: unknown) => value is NodeSwitchCase; /** * Test whether an unknown value is a class section node. */ static readonly isNodeClassSection: (value: unknown) => value is NodeClassSection; /** * Test whether an unknown value is a class attribute node. */ static readonly isNodeClassAttribute: (value: unknown) => value is NodeClassAttribute; /** * Test whether an unknown value is a class property member node. */ static readonly isNodeClassProperty: (value: unknown) => value is NodeClassProperty; /** * Test whether an unknown value is a class event member node. */ static readonly isNodeClassEvent: (value: unknown) => value is NodeClassEvent; /** * Test whether an unknown value is a class enumeration member node. */ static readonly isNodeClassEnumeration: (value: unknown) => value is NodeClassEnumeration; /** * Create an explicit no-value node. */ static readonly nodeVoid: () => NodeVoid; /** * Create name node. * @param nodeid * @returns */ static readonly nodeIdentifier: (id: string) => NodeIdentifier; /** * Create a metaclass literal node (`?ClassName`). */ static readonly nodeMetaClass: (className: NodeIdentifier) => NodeMetaClass; /** * Validate one value before storing it in an AST expression slot. * * Parser actions still type several intermediate values as `NodeExpr`; this * guard keeps hand-written factories from preserving control-flow or block * nodes in expression-only fields. */ private static readonly factoryExpression; /** * Validate a parser list before storing it as expression arguments. */ private static readonly factoryExpressionList; /** * Validate a parser list before storing it as command-word arguments. */ private static readonly factoryCommandWordList; /** * Validate a parser list before storing it as a typed AST child array. */ private static readonly factoryNodeList; /** * Validate a statement/body list without changing the list object stored by the parser. */ private static readonly factoryProgramElementList; /** * Validate matrix/cell row elements while preserving the existing delayed-evaluation carrier. */ private static readonly factoryArrayElementList; /** * Validate an optional class declaration in `arguments` and class property syntax. */ private static readonly factoryArgumentClass; /** * Create a command-form call node. * * Word-list commands pass their arguments as literal character strings, * preserving the command-line spelling rather than evaluating them as * expressions. * * @param nodename Registered command name. * @param nodelist Raw command argument words. * @returns Command-form AST node. */ static readonly nodeCmdWList: (nodename: NodeIdentifier, nodelist: NodeList) => NodeCmdWList; /** * Create expression and arguments node. * @param nodeexpr * @param nodelist * @returns */ static readonly nodeIndexExpr: (nodeexpr: NodeExpr, nodelist?: NodeList | null, delimiter?: IndexingDelimiterType) => NodeIndexExpr; /** * Create an explicit superclass constructor call node. */ static readonly nodeSuperclassConstructor: (instance: NodeExpr, superclass: NodeIdentifier, args?: NodeList | null) => NodeSuperclassConstructor; /** * Create range node. * @param start_ * @param stop_ * @param stride_ * @returns NodeRange. */ static readonly nodeRange: (start_: NodeExpr, stop_: NodeExpr, stride_?: NodeExpr) => NodeRange; /** * Create a colon token node. */ static readonly nodeColon: () => NodeColon; /** * Create an `end` token node for indexing ranges. */ static readonly nodeEndRange: () => NodeEndRange; /** * Node types that, by definition, should omit writing to the `ans` * variable. */ private static readonly omitAnswerNodeOperation; /** * Assignment-like operations whose right side may temporarily carry a * `NodeList` execution-result value produced by `eval`/`evalin`. */ private static readonly assignmentNodeOperation; /** * Operations that MATLAB/Octave reject inside anonymous function bodies. */ private static readonly anonymousFunctionForbiddenOperation; /** * Validate the complete expression subtree of an anonymous function body. */ private static readonly assertAnonymousFunctionExpression; /** * Validate anonymous function parameters at the AST construction boundary. */ private static readonly assertFunctionSignatureList; /** * Validate anonymous function parameters at the AST construction boundary. */ private static readonly assertAnonymousFunctionParameters; /** * Create operator node. * @param op * @param data1 * @param data2 * @returns */ static readonly nodeOperation: (op: OperatorType, data1: NodeExpr, data2?: NodeExpr) => NodeOperation; /** * Create a defaulted declaration/parameter entry. * * MATLAB/Octave use the assignment token in function parameter lists and * persistent declarations. This helper preserves the regular binary * operation shape while exposing the narrower AST contract consumed by * declaration and parameter-list factories. * * @param id Declared identifier. * @param value Default expression. * @returns Defaulted parameter/declaration node. */ static readonly nodeDefaultedParameter: (id: NodeIdentifier, value: NodeExpr) => NodeDefaultedParameter; /** * Create an ignored return/assignment target node. */ static readonly nodeIgnoredTarget: () => NodeIgnoredTarget; /** * Create first element of list node. * @param node First element of list node. * @returns A NodeList. */ static readonly nodeListFirst: (node?: NodeListElement) => NodeList; /** * Append node to list node. * @param lnode NodeList. * @param node Element to append to list. * @returns NodeList with element appended. */ static readonly appendNodeList: (lnode: NodeList, node: NodeListElement) => NodeList; /** * * @param list * @returns */ static readonly nodeList: (list: NodeListElement[]) => NodeList; /** * Create first row of a MultiArray. * @param row * @returns */ static readonly nodeFirstRow: (row?: NodeList | null, iscell?: boolean) => MultiArray<ExpressionBoundaryValue>; /** * Append row to MultiArray. * @param M * @param row * @returns */ static readonly nodeAppendRow: (M: MultiArray<ExpressionBoundaryValue>, row?: NodeList | null) => MultiArray<ExpressionBoundaryValue>; /** * * @param left * @param right * @returns */ static readonly nodeIndirectRef: (left: NodeExpr, right: string | NodeExpr) => NodeIndirectRef; /** * Creates NodeReturnList (multiple assignment) * @param selector Left side selector function. * @param handler A handler that returns an object containing the length * of the multiple assignment and the values evaluated by the function in * a single execution. The `selector` function uses these values. * @returns Return list node. */ static readonly nodeReturnList: (selector: ReturnSelector, handler?: ReturnHandler) => NodeReturnList; /** * Create a return-list node that represents a comma-separated list. * * Runtime producers such as brace indexing, structure field expansion, and * built-ins like `deal` use this marker so callers can distinguish ordinary * lazy multi-output values from values that should expand across argument or * assignment positions. * * @param returnListLength Number of elements available in the comma-separated list. * @param selector Output selector for materialized handler results. * @param handler Optional materializer for requested output counts. * @returns Comma-separated lazy return-list node. */ static readonly nodeCommaSeparatedReturnList: (returnListLength: number, selector: ReturnSelector, handler?: ReturnHandler) => NodeReturnList; /** * Create a return-list node with a fixed maximum output count. * * Many MATLAB/Octave built-ins return a lazy list whose values are only * computed after the caller-selected arity is known. This helper keeps the * standard "element number N undefined in return list" diagnostic in one * place for those bounded return lists. * * @param maxLength Maximum number of outputs supported by the list. * @param selector Output selector for valid indexes. * @param handler Optional materializer for valid output counts. * @param throwError Optional callback used to rethrow through interpreter diagnostics. * @returns Bounded lazy return-list node. */ static readonly nodeBoundedReturnList: (maxLength: number, selector: ReturnSelector, handler?: ReturnHandler, throwError?: ThrowError) => NodeReturnList; /** * Ensures that the node is of type `NodeReturnList`. * @param node A `NodeExpr` * @returns A lazy return-list wrapper for `node`. */ static readonly ensureReturnList: (node: NodeExpr) => NodeReturnList; /** * Throws error if left hand side length of multiple assignment greater * than maximum length (to be used in ReturnSelector functions). * @param maxLength Maximum length of return list. * @param currentLength Requested length of return list. */ static readonly throwErrorIfGreaterThanReturnList: (maxLength: number, currentLength: number, throwError?: ThrowError) => void | never; /** * Tests if it is a NodeReturnList and if so reduces it to its first * element. * @param value A node. * @returns Reduced node if `tree` is a NodeReturnList. */ static readonly reduceToFirstIfReturnList: (tree: NodeInput) => NodeInput; /** * Throw invalid call error if (optional) test is true. * @param name */ static readonly throwInvalidCallError: (name: string, test?: boolean, throwError?: ThrowError) => void | never; /** * * @param id * @param parameter_list * @param expression * @returns */ static readonly nodeFunctionHandle: (id?: NodeIdentifier | null, parameter_list?: NodeList | null, expression?: NodeExpr | null) => FunctionHandle; /** * * @param id * @param return_list * @param parameter_list * @param arguments_list * @param statements_list * @returns */ static readonly nodeFunctionDefinition: (id: NodeIdentifier, return_list: NodeList, parameter_list: NodeList, arguments_list: NodeList, statements_list: NodeList) => NodeFunctionDefinition; /** * Build a name-keyed view of class attributes while preserving duplicates. */ private static readonly nodeClassAttributeTable; /** * Select the member guard required by each concrete classdef section. */ private static readonly nodeClassSectionMemberGuard; /** * Create one `arguments` block declaration. * * @param name Identifier or name-value field target. * @param size Size declaration list. * @param cl Class declaration node. * @param functions Validator function list. * @param dflt Default expression. * @returns Argument validation node. */ static readonly nodeArgumentValidation: (name: NodeExpr, size: NodeList, cl: (NodeInput | null) | undefined, functions: NodeList, dflt?: NodeExpr | null) => NodeArgumentValidation; /** * Create an `arguments` block. * * @param attribute Optional block attribute or attribute list (`Input`, `Output`, `Repeating`). * @param validationList Declaration list. * @returns Arguments block node. */ static readonly nodeArguments: (attribute: NodeIdentifier | NodeList | null, validationList: NodeList) => NodeArguments; /** * Create the first node for a `global` or `persistent` declaration list. */ static readonly nodeDeclarationFirst: (type: "GLOBAL" | "PERSIST") => NodeDeclaration; /** * Create a `return` statement node. */ static readonly nodeReturn: () => NodeReturn; /** * Create a `break` statement node. */ static readonly nodeBreak: () => NodeBreak; /** * Create a `continue` statement node. */ static readonly nodeContinue: () => NodeContinue; /** * Normalize declaration list entries. * * Older generated parser code may append the parser context instead of * the AST node itself; in that case the actual node is stored in `.node`. * * @param declaration Declaration list entry. * @returns AST node for the declaration entry. */ static readonly getDeclarationNode: (declaration: NodeExpr | { node: NodeExpr; }) => NodeExpr; /** * * @param node * @param declaration * @returns */ static readonly nodeAppendDeclaration: (node: NodeDeclaration, declaration: NodeExpr) => NodeDeclaration; /** * Create a bare MATLAB-style `import` query node. * * @returns Import node with no declared names. */ static readonly nodeImport: () => NodeImport; /** * Create the first node for a MATLAB-style `import` declaration. * * @param importName Fully qualified class/package name, optionally ending in `.*`. * @returns Import declaration node. */ static readonly nodeImportFirst: (importName: NodeIdentifier) => NodeImport; /** * Append one fully qualified import name to an `import` declaration. * * @param node Import declaration to extend. * @param importName Fully qualified class/package name. * @returns The same import declaration node. */ static readonly nodeAppendImport: (node: NodeImport, importName: NodeIdentifier) => NodeImport; /** * * @param expression * @param then * @returns */ static readonly nodeIfBegin: (expression: NodeExpr, then: NodeList) => NodeIf; /** * * @param nodeIf * @param nodeElse * @returns */ static readonly nodeIfAppendElse: (nodeIf: NodeIf, nodeElse: NodeElse) => NodeIf; /** * * @param nodeIf * @param nodeElseIf * @returns */ static readonly nodeIfAppendElseIf: (nodeIf: NodeIf, nodeElseIf: NodeElseIf) => NodeIf; /** * * @param expression * @param then * @returns */ static readonly nodeElseIf: (expression: NodeExpr, then: NodeList) => NodeElseIf; /** * * @param elseStmt * @returns */ static readonly nodeElse: (elseStmt: NodeList) => NodeElse; /** * Create a `switch` statement node. */ static readonly nodeSwitch: (expression: NodeExpr, cases: NodeList, otherwise?: NodeList | null) => NodeSwitch; /** * Create a `case` clause node. */ static readonly nodeSwitchCase: (expression: NodeExpr, then: NodeList) => NodeSwitchCase; /** * Create a `while` statement node. */ static readonly nodeWhile: (expression: NodeExpr, body: NodeList) => NodeWhile; /** * Create a `do ... until` statement node. */ static readonly nodeDoUntil: (body: NodeList, expression: NodeExpr) => NodeDoUntil; /** * Create a `for` statement node. */ static readonly nodeFor: (target: NodeExpr, expression: NodeExpr, body: NodeList, parallel?: boolean, workers?: NodeExpr | null) => NodeFor; /** * Create an `spmd` statement node. */ static readonly nodeSpmd: (body: NodeList, workers?: NodeList | null) => NodeSpmd; /** * Create a `try ... catch` statement node. */ static readonly nodeTry: (body: NodeList, catchBody?: NodeList | null, catchIdentifier?: NodeIdentifier | null) => NodeTry; /** * Create an `unwind_protect ... unwind_protect_cleanup` statement node. */ static readonly nodeUnwindProtect: (body: NodeList, cleanup: NodeList) => NodeUnwindProtect; /** * Create a minimal `classdef` node. */ static readonly nodeClassDef: (id: NodeIdentifier, sections: NodeList, attributes?: NodeList, superclasses?: NodeList) => NodeClassDef; /** * Create a `properties` or `methods` section. *