UNPKG

mathjslab

Version:

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

1,244 lines 89 kB
/** * MATLAB®/Octave like syntax parser/interpreter/compiler. */ import type { NodeInput, NodeExpr, NodeFunctionDefinition, NodeBuiltInFunction, AliasNameTable, BuiltInFunctionTable, CommandWordListTable, ExpressionBoundaryValue } from './AST'; import { ClassDefinition } from './ClassDefinition'; import { ClassInstance } from './ClassInstance'; import { ClassStaticMethod } from './ClassStaticMethod'; import { Scope } from './Scope'; import { CallFrame } from './CallFrame'; import type { SourceEntry, SourceProvider, SourceResolver, SourceTable } from './SourceResolver'; import { Context } from './Context'; import { CircularReferenceError, EvalError, InterpreterError, ReferenceError, SyntaxError, UndefinedReferenceError } from './InterpreterError'; import type { CallArgumentValue } from './FunctionCall'; /** * Numeric exit status used by the public `exitStatus` property. */ type ExitStatus = number; /** Named exit status table. */ type ExitStatusValues = Record<string, ExitStatus>; /** Host-provided class source entry. */ type ClassSource = SourceEntry; /** Host-provided function-file source entry. */ type FunctionSource = SourceEntry; /** Host-provided script-file source entry. */ type ScriptSource = SourceEntry; /** Callback used to provide classdef source for a class name. */ type ClassSourceProvider = SourceProvider; /** Table of host-provided class sources keyed by class name. */ type ClassSourceTable = SourceTable; /** Callback used to provide function-file source for a function name. */ type FunctionSourceProvider = SourceProvider; /** Table of host-provided function-file sources keyed by primary function name. */ type FunctionSourceTable = SourceTable; /** Callback used to provide script-file source for a script name. */ type ScriptSourceProvider = SourceProvider; /** Table of host-provided script-file sources keyed by script name. */ type ScriptSourceTable = SourceTable; /** * Interpreter construction options. * * All extension points are explicit so the engine remains browser-compatible: * callers can inject aliases, built-ins, command-form functions, and class * sources without requiring ambient filesystem or module loading. */ type InterpreterConfig = { /** Lexer/parser alias table for symbolic names. */ aliasNameTable?: AliasNameTable; /** Additional built-in functions registered at startup. */ externalFunctionTable?: BuiltInFunctionTable; /** Additional command-form functions registered at startup. */ externalCmdWListTable?: CommandWordListTable; /** Unified virtual `.m` source resolver. */ sourceResolver?: SourceResolver; /** Host predicate used by `mustBeFile` argument/property validation. */ fileExists?: (path: string) => boolean; /** Host predicate used by `mustBeFolder` argument/property validation. */ folderExists?: (path: string) => boolean; /** Host-provided function-file source strings. */ functionSourceTable?: FunctionSourceTable; /** Lazy host-provided function-file source callback. */ functionSourceProvider?: FunctionSourceProvider; /** Host-provided script-file source strings. */ scriptSourceTable?: ScriptSourceTable; /** Lazy host-provided script-file source callback. */ scriptSourceProvider?: ScriptSourceProvider; /** Host-provided class source strings. */ classSourceTable?: ClassSourceTable; /** Lazy host-provided class source callback. */ classSourceProvider?: ClassSourceProvider; /** * Compatibility alias for early class-loader experiments. Prefer * `classSourceTable` for browser/host-provided class sources. */ externalClassSourceTable?: Record<string, string>; /** * Compatibility alias for early function-loader experiments. Prefer * `functionSourceTable` for browser/host-provided function sources. */ externalFunctionSourceTable?: Record<string, string>; /** * Compatibility alias for early script-loader experiments. Prefer * `scriptSourceTable` for browser/host-provided script sources. */ externalScriptSourceTable?: Record<string, string>; }; /** * Increment and decrement operator handler type. */ type IncDecOperator = (tree: NodeExpr, scope: Scope) => NodeInput; /** * Full parse/evaluate/unparse bundle returned by `Interprets`. */ type InterpretsResult = { /** Original input string. */ input: string; /** AST produced from the original input. */ inputParsed: NodeInput; /** Textual unparse of the evaluated input. */ inputUnparsed: string; /** MathML rendering of the evaluated input. */ inputUnparsedMathML: string; /** Evaluated runtime value or AST result. */ evaluated: NodeInput; /** Textual unparse of the evaluated result. */ evaluatedUnparsed: string; /** MathML rendering of the evaluated result. */ evaluatedUnparsedMathML: string; }; /** * Interpreter instance interface. */ interface InterpreterInterface { /** Whether debug diagnostics and fallback tracing are enabled. */ debug: boolean; /** Runtime context owned by this interpreter. */ context: Context; /** Last public execution status. */ exitStatus: ExitStatus; /** Operator precedence table used by unparsers. */ precedenceTable: { [key: string]: number; }; /** Parse source text into an AST/runtime node. */ Parse(input: string): NodeInput; /** Reset runtime state while preserving constructor-level configuration defaults. */ Restart(): void; /** Clear variables/functions, or reset the interpreter when no names are supplied. */ Clear(...names: string[]): void; /** Evaluate one AST/runtime node in a scope. */ Evaluator(tree: NodeInput, scope?: Scope): NodeInput; /** Evaluate one parsed AST from the public top-level entry point. */ Evaluate(tree: NodeInput): NodeInput; /** Parse and evaluate source text in one call. */ Execute(input: string): NodeInput; /** Convert a runtime/AST node back to normalized source-like text. */ Unparse(tree: NodeInput, parentPrecedence?: number): string; /** Convert a runtime/AST node to a MathML fragment. */ UnparserMathML(tree: NodeInput, parentPrecedence: number): string; /** Convert a runtime/AST node to a complete MathML string. */ UnparseMathML(tree: NodeInput, display: 'inline' | 'block' | 'none'): string; /** Parse source text and render its AST as MathML. */ ToMathML(input: string, display: 'inline' | 'block' | 'none'): string; /** Return parsed/evaluated/unparsed forms for host diagnostics and demos. */ Interprets(input: string, display: 'inline' | 'block' | 'none'): InterpretsResult; } /** * MATLAB/Octave-like parser, evaluator, unparser, and host integration point. * * `Interpreter` owns the ANTLR parser pipeline, runtime context, built-in * tables, command-form functions, class loading contracts, and display * unparsers. Most semantic helpers are delegated to smaller modules; this * class coordinates them around one active `Context`. */ declare class Interpreter implements InterpreterInterface { /** MATLAB-compatible maximum identifier length exposed by `namelengthmax`. */ private static readonly nameLengthMax; /** Sorted language keywords as recognized by the lexer. */ private static readonly keywordNames; /** Keyword lookup set used by `iskeyword` and `isvarname`. */ private static readonly keywordNameSet; /** Public MATLAB validator functions backed by the `arguments` validator engine. */ private static readonly publicArgumentValidators; /** * After run `Evaluate` method, the `exitStatus` property will contains * exit state of evaluation. */ static readonly response: ExitStatusValues; /** * Private debug flag. */ private _debug; /** * `debug` getter. */ get debug(): boolean; /** * `debug` setter. */ set debug(value: boolean); /** * Interpreter context. */ context: Context; /** * Command word list table. */ private commandWordListTable; private commandWordListNameSet; private assignmentSensitiveCommandNameSet; /** * Unified virtual source resolver for browser/host-provided `.m` files. */ private sourceResolver; /** Host path predicates used by MATLAB-style file/folder validators. */ private pathValidationCallbacks; /** * Refresh lexer-facing command-name sets after command table changes. */ private refreshCommandWordListNames; /** * Function names currently being loaded, used to avoid recursive loader loops. */ private loadingFunctionNames; /** * Class names currently being loaded, used to avoid recursive loader loops. */ private loadingClassNames; /** * Class method names currently being loaded, used to avoid recursive loader loops. */ private loadingClassMethodNames; /** * Nesting level of host-provided script execution. * * A script is not a function frame, but MATLAB/Octave still allow `return` * to stop the current script. Keeping that state in the interpreter lets * interactive/top-level `return` remain invalid while scripts loaded * through the browser-safe source APIs can exit early. */ private scriptExecutionDepth; /** * Virtual source identities for currently executing scripts. * * Script-local functions are ordinary function definitions registered * temporarily in the caller workspace; this stack lets that registration * attach the surrounding script's browser-hosted source identity. */ private scriptSourceNameStack; /** * Interpreter exit status. */ private _exitStatus; /** * Last uncaught public evaluation error, exposed through `lasterror`. */ private lastError?; /** * Last warning state exposed through `lastwarn`. * * Warning emission is still intentionally conservative, but keeping the * state here gives the public API a stable MATLAB/Octave-like contract. */ private lastWarning; /** * Global warning state used by `warning("on"|"off"|"error")`. */ private globalWarningState; /** * Per-identifier warning emission overrides. */ private warningIdentifierStates; /** * Interpreter exit status getter. */ get exitStatus(): ExitStatus; /** * Increment and decrement operator * @param pre `true` if prefixed. `false` if postfixed. * @param operation Operation (`'plus'` or `'minus'`). * @returns Operator function that updates an assignable expression. */ private incDecOpFactory; /** * Operator table. */ private readonly opTable; private static readonly binaryOperatorMethodTable; private static readonly unaryOperatorMethodTable; /** * Precedence definitions. */ private static readonly precedence; /** * Operator precedence table. */ precedenceTable: { [key: string]: number; }; /** * Get tree node precedence. * @param tree Tree node. * @returns Node precedence. */ private nodePrecedence; /** * User functions. */ private functionArityCallable; private functionArgumentArity; private functionOutputArity; /** * Parse or resolve a textual function-handle source. */ private functionHandleFromString; /** * Resolve a runtime symbol through the interpreter-owned lookup facade. * * Keeping this indirection inside `Interpreter` prevents parser/evaluator * code from depending directly on the exact `Context.resolveSymbol` option * shape and gives lookup-sensitive features one place to evolve. * * @param name Name requested by source text. * @param scope Lookup scope. * @param options Resolution switches. * @returns Structured symbol resolution, if any. */ private resolveRuntimeSymbol; /** Resolve a function-like runtime symbol without considering variables or classes. */ private resolveRuntimeFunction; /** Resolve a class runtime symbol without considering variables or functions. */ private resolveRuntimeClass; /** * Create a named function handle using the current structured lookup layer. * * Qualified names and aliases are normalized to their runtime spelling. * Simple imported names keep their source spelling and rely on the captured * import table, matching MATLAB/Octave display behavior for `@name`. * When requested, user-function handles keep a lexical overlay so returned * handles remain bound to local/nested functions and in-scope imports. * * @param name Function name supplied by source text or a character string. * @param scope Lookup scope used to resolve imports and local functions. * @param parent Optional AST parent for the new handle. * @param captureLexical Whether to capture a lexical overlay for user functions. * @returns Named function handle. */ private createResolvedFunctionHandle; private localFunctionHandles; /** * Copy and validate one captured workspace value before exposing it through * the MATLAB/Octave `functions(handle).workspace` metadata struct. */ private functionHandleWorkspaceValue; private functionHandleWorkspaceInfo; private staticMethodInfo; private dbstackResult; /** * Return the MATLAB/Octave `mfilename` value for the current function. * * When a browser-hosted source provides a virtual path, plain `mfilename` * reports the file basename without the `.m` suffix while * `mfilename("fullpath")` keeps the complete virtual identity. */ private currentMFilename; /** * Return the MATLAB/Octave `mfilename("fullpath")` identity. * * For browser-hosted code, "fullpath" means the complete virtual source * identity supplied by the host resolver. Unlike plain `mfilename`, this * intentionally keeps the configured `.m`-like suffix because source * metadata, `functions`, and stack display share that identity. */ private currentMFilenameFullPath; /** * Return the best virtual source identity for a handle created now. */ private currentHandleSourceName; /** * Return the class context that should be captured by a handle created now. */ private currentHandleClassName; /** * Convert a native or interpreter error into the struct shape used by * MATLAB/Octave-style `catch ME` and `lasterror`. * * `InterpreterError.stackFrames` stores the most recent frame first, while * `dbstackResult` expects the live call-stack order and reverses it during * formatting. The local reversal preserves the captured thrown stack instead * of rebuilding it from the current catch/evaluation context. * * @param error Error object or thrown value. * @returns Structure with `message`, `identifier`, and `stack` fields. */ private exceptionToStruct; /** * Return the current `lasterror` value. * * MATLAB/Octave keep the last uncaught error until it is replaced or the * interpreter state is reset. When no error has escaped yet, the empty * structure uses the same fields so callers can index it without special * casing the initial state. * * @returns MATLAB-like last-error structure. */ private lastErrorStruct; /** * Return the default `lasterror` structure. */ private emptyLastErrorStruct; /** * Reset `lasterror` to its initial state. */ private resetLastError; /** * Store an error as the current MATLAB/Octave last-error state. * * Caught errors must be visible to `lasterr`/`lasterror` while the `catch` * block executes, matching Octave's documented try/catch behavior and the * legacy MATLAB diagnostic APIs. */ private rememberLastError; /** * Normalize a user-provided error structure for storage in `lasterror`. * * MATLAB/Octave accept structures with any subset of the public fields and * fill missing fields with defaults. Present `message` and `identifier` * fields must still be character values because they are consumed by * `rethrow` and catch-state introspection. */ private normalizeLastErrorStruct; /** * Implement `lasterror`, `lasterror("reset")`, and `lasterror(err)`. */ private lastErrorResult; /** * Implement `lasterr`, the message/id companion to `lasterror`. */ private lastErrorMessageResult; /** * Store the warning state returned by `lastwarn`. * * @param message Warning message. * @param identifier Optional warning identifier. */ private setLastWarning; /** * Reset warning state to the MATLAB/Octave default. */ private resetWarningState; /** * Return the effective warning state for an identifier. */ private warningState; /** * Test whether a string is a supported warning state. */ private isWarningState; /** * Build the structure returned by `warning("query", id)`. */ private warningStateStruct; /** * Build a MATLAB/Octave warning-state snapshot. * * The first element always represents the global `all` state. Additional * entries record warning identifiers that differ from the global default or * that were explicitly modified during this interpreter session, matching * the save/restore workflow of `s = warning; warning(s)`. */ private warningStateSnapshot; /** * Read a MATLAB/Octave warning-state structure. */ private warningStateStructParts; /** * Restore one warning state entry. */ private restoreWarningState; /** * Restore warning state from a MATLAB/Octave-style structure scalar or array. */ private restoreWarningStateStruct; /** * Apply `warning` state/query commands when the argument pattern matches. */ private warningControlResult; /** * Split diagnostic arguments into optional identifier, format, and values. * * A leading string containing `:` is treated as a message identifier when a * second string is present. Otherwise the first string is the message format. */ private diagnosticMessageParts; /** * Convert command-form diagnostic words to function-form arguments. * * `warning id:tag message words` and `error id:tag message words` map to * identifier/message calls, while ordinary words map to one message string. */ private diagnosticCommandArguments; /** * Implement the public `warning` built-in subset. * * The current browser-first runtime records warning state instead of * writing to a console or warning manager. This supports the common message * and identifier/message forms, a small diagnostic formatting subset, and * the common `on`/`off`/`query` state controls. * * @param args Evaluated built-in arguments. * @returns Void node because warnings do not produce expression output. */ private warningResult; /** * Implement the public `error` built-in subset. * * Supported MATLAB/Octave forms are `error(message)`, * `error(identifier, message)`, and formatted variants of those forms. The * thrown error keeps the current call stack through `Context.throwEvalError`, * and the optional identifier is attached for `catch ME` and `lasterror`. * * @param args Evaluated error arguments. */ private errorResult; /** * Decide whether an `assert` call is the condition/message form. */ private assertUsesDiagnosticForm; /** * Extract numeric elements for tolerance-based `assert` comparison. */ private assertNumericElements; /** * Test numerical equality using Octave-style absolute/relative tolerance. */ private assertValuesEqualWithinTolerance; /** * Split comparison-form `assert` arguments into comparison and diagnostic * parts. */ private assertComparisonParts; /** * Implement `assert(actual, expected[, tolerance][, message...])`. */ private assertComparisonResult; /** * Implement the public `assert` built-in subset. * * MATLAB/Octave treat a false condition as an error and pass the remaining * arguments through the same identifier/format pipeline used by `error`. */ private assertResult; /** * Extract MATLAB text-list arguments accepted by validation functions. * * The documented APIs accept a character vector, string scalar, string * array, or cell array of character vectors. The interpreter stores each as * `CharString` elements, so this helper normalizes the public forms without * losing order. */ private validationTextList; /** * Extract one text item from a mixed MATLAB validation cell array. */ private validationTextItem; /** * Return raw validation-list items, preserving non-text parameters. */ private validationListItems; /** * Implement MATLAB's unique-prefix, case-insensitive `validatestring`. */ private validatestringResult; /** * Build the optional function/variable context used by `validatestring`. */ private validatestringDiagnosticPrefix; /** * Map public `validateattributes` attribute names to shared validator keys. */ private validateattributesValidator; /** * Return dimensions as `validateattributes` should see them. * * The runtime stores both character vectors and string scalars in * `CharString`; MATLAB treats string scalars as `1x1`, while character * vectors remain `1xN`. */ private validateattributesDimensions; /** * Return real numeric elements for attributes that inspect values directly. */ private validateattributesRealNumericElements; /** * Extract a real numeric scalar used as a `validateattributes` parameter. */ private validateattributesNumericScalar; /** * Extract a real numeric vector used by `validateattributes('size', ...)`. */ private validateattributesNumericVector; /** * Test all numeric elements of a value against a scalar comparison. */ private validateattributesNumericComparison; /** * Test MATLAB/Octave monotonic attributes independently for each stored * column. `MultiArray` stacks pages in the physical row axis, so each * page-stride row group represents the rows of one logical page. */ private validateattributesMonotonicColumns; /** * Test non-parameterized `validateattributes` attributes not covered by the * shared validator table. */ private validateattributesSpecialAttribute; /** * Test one shared `validateattributes` validator with public string-scalar * shape semantics. */ private validateattributesMatchesValidator; /** * Apply one parameterized `validateattributes` attribute. */ private validateattributesParameterizedAttribute; /** * Build the subject text used by `validateattributes` diagnostics. */ private validateattributesSubject; /** * Test a `validateattributes` class constraint against runtime values. */ private validateattributesMatchesClass; /** * Implement the common MATLAB/Octave `validateattributes` forms. * * The browser runtime has no sparse storage type; sparse-compatible APIs are * kept explicit through the shared validator, where `sparse` always fails * and `nonsparse` always succeeds. */ private validateattributesResult; /** * Return supported public `mustBe*` call arity limits. */ private mustBeArity; /** * Implement public MATLAB `mustBe*` validator functions. */ private mustBeResult; /** * Build registry entries for public `mustBe*` validators. */ private mustBeFunctionEntries; /** * Normalize command-form results returned by host-provided integrations. * * External command handlers often return plain JavaScript primitives. The * interpreter boundary converts those values into ordinary runtime nodes so * command-form parsing can be used safely by browser-hosted commands such * as `help`. */ private commandWordListResult; /** * Implement `rethrow(ME)` for MATLAB/Octave-style caught error structs. * * The current runtime represents `catch ME` as a structure with `message`, * `identifier`, and `stack` fields. `rethrow` validates that shape and * raises a new evaluation error while preserving the public message and * identifier fields used by subsequent `catch` blocks and `lasterror`. * * @param errorStruct Error structure captured by a `catch` identifier. */ private rethrowResult; /** * Implement `lastwarn` getter/setter behavior. * * With no arguments it returns the current message and identifier. With one * or two string arguments it updates the stored warning state before * returning it, matching the MATLAB/Octave convention used by tests and * user code. * * @param args Optional message and identifier setter arguments. * @returns Comma-separated return list `[message, identifier]`. */ private lastWarningResult; /** * Implement MATLAB/Octave `deal` output distribution. * * With one input, every requested output receives that value. With multiple * inputs, a scalar-output call returns the first value; multiple-output * calls must match the input count and distribute values positionally. */ private dealResult; /** * Read one positive integer index for output-selection helpers. */ private positiveIntegerIndex; /** * Read scalar or vector output indexes for `nthargout`. */ private nthargoutIndexes; /** * Resolve the callable argument accepted by `nthargout`. */ private nthargoutCallable; /** * Implement Octave-compatible `nthargout`. */ private nthargoutResult; /** * Validate one evaluated value before exposing it as an ordinary expression. */ private expressionValue; /** * Validate an evaluated value that must be stored in runtime data * containers such as structures. */ private runtimeExpressionValue; /** * Evaluate an expression, reduce return-list carriers, and validate the * resulting value before it crosses an interpreter expression boundary. */ private evaluatedExpressionValue; /** * Evaluate one executable AST node and normalize lazy return-list carriers. * * This is intentionally broader than `evaluatedExpressionValue`: block and * top-level execution may legitimately produce `LIST`, `VOID`, or control * carrier nodes that are not ordinary expression values. */ private evaluatedExecutionResult; /** * Read a scope entry and validate it before reusing it as an expression. */ private scopedExpressionValue; /** * Read a scope entry that must contain a native array value. */ private scopedMultiArrayValue; /** * Validate evaluated variadic call arguments before forwarding them. * * @param values Runtime arguments after ordinary evaluator reduction. * @param prefix Diagnostic prefix used to identify the failing argument. * @returns Arguments narrowed to expression values. */ private callArgumentValues; /** * Validate a built-in control argument that must be a character string. * * @param value Candidate argument. * @param name Diagnostic role name. * @returns Validated character string. */ private charControlArgument; /** * Validate a list whose elements must all be character strings. * * MATLAB Set/Get APIs accept property-name cell arrays. This helper keeps * the cell-content validation explicit after `MultiArray.linearize`. * * @param values Candidate cell contents. * @param name Diagnostic role name. * @returns The same values narrowed to character strings. */ private charStringList; /** * Validate a built-in control argument that must be a function handle. * * @param value Candidate argument. * @param name Diagnostic role name. * @returns Validated function handle. */ private functionHandleControlArgument; /** * Validate an optional boolean-like control argument. * * @param value Candidate argument. * @param name Diagnostic role name. * @returns JavaScript boolean following MATLAB/Octave truthiness. */ private booleanControlArgument; /** * Validate worker-count expressions accepted by sequential parallel fallbacks. * * MATLAB requires `parfor(..., M)` to use a nonnegative integer worker * limit. `spmd(n)` and `spmd(m,n)` use the same numeric count shape, with * zero selecting local execution in environments without workers. * * @param value Evaluated worker-count expression. * @param name Diagnostic role name. * @returns Validated worker count. */ private workerCountControlArgument; /** * Validate runtime values before forwarding them to user-defined class methods. */ private classMethodArgumentValues; /** * Invoke one class instance method and reduce lazy return-list carriers at * the class-dispatch boundary. */ private reducedClassMethodResult; /** * Invoke one class method with an explicit output count and reduce the * scalar result expected by helper protocols such as `numArgumentsFromSubscript`. */ private reducedClassMethodResultWithOutputCount; /** * Validate the object returned by class `subsasgn` overloads. */ private classSubsasgnResult; /** * Normalize a value produced by assignment RHS evaluation before storing it * into a name, field, or object property. */ private reducedAssignmentValue; /** * Normalize and validate an assignment RHS before storing it in a runtime * structure field. */ private structureAssignmentValue; /** * Store a field-assignment value, scattering compound structure-array * results when the operation produced one value per target element. */ private assignStructureFieldValue; /** * Reduce values produced by scalar indexing/dispatch paths before checking * their runtime shape or class. */ private reducedIndexingResult; /** * Validate and linearize values before assigning them to object arrays. */ private assignmentValues; /** * Validate a sequence before storing it in an AST expression list. */ private expressionList; /** * Validate and linearize an expression value without crossing the generic * `MathObject` operation surface. */ private linearExpressionValues; /** * Validate and copy one expression value through the runtime copy protocol. */ private copyExpressionValue; /** * Expand a `for` loop expression into the sequence assigned to the target. * * MATLAB/Octave `for` assignment iterates over columns. Numeric row vectors * and scalars produce scalar loop values, while matrices and cell arrays * produce one column value per iteration. Cell columns remain cell arrays; * their contents are not unwrapped by the loop assignment. * * @param value Evaluated loop expression. * @param target Loop assignment target. * @returns Values assigned on each loop iteration. */ private forLoopValues; /** * Build the value assigned by one `for` iteration. * * Scalar targets receive a copied expression value. Row-vector targets use * a lazy return list so multi-target loop assignments can request each * element independently, matching the same comma-separated-list machinery * used elsewhere in the interpreter. * * @param target Loop assignment target. * @param value Iteration value to assign. * @returns Scalar assignment value or lazy return-list carrier. */ private forLoopAssignmentValue; /** * Validate the subset of MATLAB `parfor` semantics that remains meaningful * for the browser's sequential fallback execution. * * Unlike ordinary `for`, MATLAB `parfor` uses a simple loop variable and a * consecutive integer iteration vector. The runtime still executes * sequentially, but it rejects shapes that would not be valid parallel loop * headers. * * @param target Loop assignment target from the parser. * @param value Evaluated loop expression. */ private validateParforHeader; /** * Validate `parfor` body restrictions that can be checked from the AST. * * The sequential browser fallback keeps execution deterministic, but the * accepted source must still respect MATLAB `parfor` structural rules so * code does not become valid here and invalid in MATLAB/Octave-compatible * environments. * * @param body Loop body to inspect. * @param loopVariable Simple loop variable name. */ private validateParforBody; /** * Validate `spmd` body restrictions that remain relevant for the browser's * single-worker fallback. * * MATLAB rejects several control-flow and parallel constructs inside * `spmd` blocks because workers execute separately from the client * workspace. MathJSLab executes the block sequentially, but preserving the * structural restrictions prevents non-portable code from being accepted. * * @param body SPMD body to inspect before execution. */ private validateSpmdBody; /** * Clone an assignment target while preserving only expression-compatible shapes. * * Assignment lowering can duplicate identifiers, indexing chains, indirect * references, and runtime values before the actual write occurs. Every * cloned branch is routed back through the expression boundary so malformed * statement/control-flow nodes cannot enter the assignment pipeline. * * @param target Assignment target or runtime value to clone. * @returns Copied target constrained to expression position. */ private cloneAssignmentTarget; /** * Validate values before exposing them through an interpreter-owned comma * separated return list. */ private returnListValue; /** * Create a lazy comma-separated return list from already evaluated values. * * Values are validated only when selected so the return list can honor the * caller-requested output count while still rejecting non-expression values * before they cross an expression boundary. * * @param values Candidate output values. * @returns Lazy comma-separated return list. */ private valueReturnList; /** * Convert comma-separated values into a row vector for scalar operations. * * Native brace and structure-field descriptor chains may return a lazy * comma-separated list. Compound assignments need an expression value that * can participate in `+`, `-`, etc., so the selected list is materialized in * the same row-vector shape used by explicit concatenation contexts. */ private compoundAssignmentOperand; /** * Read the assigned value from an internal assignment-result list. */ private nestedAssignmentValue; /** * Parse and evaluate source text in a specific scope. * * This is shared by `eval`/`evalin` and deliberately creates a transient * call-stack frame so introspection and argument helpers observe the scope * in which the string is evaluated. * * @param source Source code to parse. * @param scope Scope used for evaluation. * @returns Evaluated result tree or runtime value. */ private evalStringInScope; /** * Determine whether an error can be handled by an `eval` catch string. * * MATLAB/Octave control-flow signals must propagate through `eval`; only * ordinary runtime errors are catchable by the optional catch source. * * @param error Error or control-flow signal thrown by evaluation. * @returns `true` when the catch string may handle the error. */ private isEvalCatchableError; /** * Evaluate source like `eval` while returning captured display text first. * * MATLAB `evalc` returns command-window output in the first result and the * evaluated expression outputs in subsequent result slots. The engine has * no separate command-window stream, so capture uses the same textual * representation that top-level evaluation would expose through `Unparse`. * * @param source Source code to parse and evaluate. * @param catchSource Optional catch source evaluated after ordinary errors. * @returns Captured output string, optionally followed by evaluated outputs. */ private evalcResult; /** * Extract top-level class definitions from a parsed source tree. * * Host-provided class sources are parsed as ordinary snippets; this helper * isolates classdef nodes without executing unrelated statements. * * @param tree Parsed source tree. * @returns Top-level class definitions in source order. */ private topLevelClassDefinitions; /** * Extract top-level function definitions from a parsed source tree. * * This is used by function-file loading and script-local function * pre-registration, keeping MATLAB/Octave function discovery separate from * statement execution. * * @param tree Parsed source tree. * @returns Top-level function definitions in source order. */ private topLevelFunctionDefinitions; /** * Parse a host-provided function-file source. * * The selected primary function is renamed to the requested canonical name * so package/import aliases can load source supplied under a fully * qualified runtime name while preserving MATLAB/Octave function-file * lookup behavior. * * @param name Canonical function name requested by lookup. * @param source Source text containing one primary function and optional subfunctions. * @returns Primary function plus private subfunctions. */ private parseFunctionSource; /** * Resolve function-file source through the configured host tables/providers. * * @param name Canonical function name requested by lookup. * @returns Normalized source entry, if the host can supply one. */ private resolveFunctionSource; /** * Test whether a semantically valid host-provided function source exists. * * The probe parses and validates the source without registering it, so * introspection such as `exist` and `which` cannot mutate the runtime. * * @param name Function name requested by lookup. * @returns `true` when a loadable function source is available. */ private hasFunctionSource; /** * Resolve and validate a function source without registering it. * * This mirrors the static checks performed by lazy function loading: * primary-function matching, declaration placement, signature validation, * `arguments` blocks, and duplicate subfunction names. * * @param name Function name requested by lookup. * @returns Normalized source entry, or `undefined` when unavailable/invalid. */ private validFunctionSource; /** * Validate a parsed function file before it is reported or registered. * * Host probes and lazy loading both use this single gate so externally * supplied primary functions, subfunctions, and class method files obey the * same signature and `arguments`-block rules. * * @param primary Primary function selected from the file. * @param subfunctions Private top-level subfunctions from the same source. * @param duplicateContext Source label used in duplicate-function diagnostics. */ private validateFunctionFileDefinitions; /** * Register a parsed function-file definition in a target scope. * * The primary function is visible from the caller scope. Subfunctions are * stored in the primary function's file scope so they remain private to the * loaded function file, which matches MATLAB/Octave file scoping. * * @param primary Primary function definition. * @param subfunctions Private top-level subfunctions from the same source. * @param scope Scope receiving the primary function. * @returns Registered primary function definition. */ private registerFunctionFileDefinition; /** * Load a MATLAB/Octave-like function file from host-provided source text. * * The primary function is exported to the target scope. Additional * top-level function definitions become private subfunctions visible only * through the primary function's file scope. * * @param name Canonical primary function name. * @param source Source text containing the function file. * @param scope Scope that receives the primary function. * @returns Registered primary function definition. */ LoadFunctionFile(name: string, source: string, scope?: Scope, sourceName?: string): NodeFunctionDefinition; /** * Resolve and register a function definition through host-provided sources. * * @param name Function name requested by lookup. * @param scope Scope that should receive the loaded primary function. * @returns Registered function definition, or `undefined` when unavailable. */ loadFunctionDefinition(name: string, scope: Scope): NodeFunctionDefinition | undefined; /** * Resolve script source through the configured host tables/providers. * * @param name Script name requested by lookup. * @returns Normalized source entry, if the host can supply one. */ private resolveScriptSource; /** * Test whether a semantically valid host-provided script source exists. * * The script is parsed and checked for declaration-placement violations, * but it is not executed and script-local functions are not registered. * * @param name Script name requested by lookup. * @returns `true` when a runnable script source is available. */ private hasScriptSource; /** * Resolve and validate a script source without executing it. * * @param name Script name requested by lookup. * @returns Normalized source entry, or `undefined` when unavailable/invalid. */ private validScriptSource; /** * Execute a parsed script while temporarily exposing script-local functions. * * @param tree Parsed script source tree. * @param scope Workspace where script statements execute. * @returns Evaluated script result. */ private executeScriptTree; /** * Execute MATLAB/Octave-like script source in a workspace. * * Script-local functions are visible while the script executes and hidden * afterward. Function handles created by the script keep captured closures, * so they remain callable even after the temporary function table is * restored. * * @param name Script name used for diagnostics. * @param source Source text containing the script. * @param scope Workspace where script statements execute. * @param sourceName Optional virtual source identity for script-local functions. * @returns Evaluated script result. */ LoadScriptFile(name: string, source: string, scope?: Scope, sourceName?: string): NodeInput; /** * Resolve and execute a host-provided script file by name. * * @param name Script name or `.m` filename. * @param scope Workspace where script statements execute. * @returns Evaluated script result. */ RunScriptFile(name: string, scope?: Scope): NodeInput; /** * Parse a host-provided class source and select the requested classdef. * * @param name Canonical class name requested by lookup. * @param source Source text containing the classdef. * @returns Classdef AST node with canonical runtime name. */ private parseClassSource; /** * Parse a class source if it contains the requested classdef. * * @param name Canonical class name requested by lookup. * @param source Source text containing a possible classdef. * @returns Matching classdef AST node, or `undefined` when the source is not a classdef file. */ private tryParseClassSource; /** * Test whether source text looks like a function/method file rather than a classdef file. * * Class lookup probes can reach sibling `@Class/method.m` files while * resolving qualified member chains. Function-only sources should decline * class loading quietly so the shorter class prefix can be selected. * * @param source Source text to inspect. * @returns `true` when the source contains top-level functions and no classdef. */ private isFunctionOnlySource; /** * Parse a host-provided class method source selected by a classdef prototype. * * MATLAB/Octave allow classdef files to declare method signatures while * concrete bodies live in sibling `@Class/method.m` files. The primary * function is stored under the prototype method name so class metadata and * stack traces keep the source-level method spelling. * * @param className Canonical class name that owns the prototype. * @param methodName Method name declared in the classdef prototype. * @param sourceName Canonical source entry name resolved by the host. * @param source Source text containing one method function and optional private subfunctions. * @returns Primary method plus private subfunctions. */ private parseClassMethodSource; /** * Resolve class source through the configured host tables/providers. * * @param name Canonical class name requested by lookup. * @returns Normalized source entry, if the host can supply one. */ private resolveClassSource; /** * Test whether a host class source is available without parsing/registering it. * * Lookup helpers such as `exist` and `which` should report browser-provided * class sources without mutating the runtime class registry, otherwise a * metadata query can change later function/class precedence. * * @param name Canonical class name requested by lookup. * @returns `true` when the configured resolver can provide class source. */ private hasClassSource; /** * Resolve and validate a class source without registering it. * * The check is intentionally local: it rejects malformed classdef metadata * while avoiding superclass resolution, dependency loading, and mutations * to the class registry. * * @param name Class name requested by lookup. * @returns Normalized source entry, or `undefined` when unavailable/invalid. */ private validClassSource; /** * Attach a virtual source identity to methods declared inside a loaded classdef. * * External `@Class/method.m` files receive their own identity when they are * materialized. Inline methods in a host-provided classdef share the class * file identity, matching MATLAB/Octave source-level introspection. */ private attachClassDefinitionSourceName; /** * Resolve and register a class definition through host-provided sources. * * @param name Class name requested by lookup. * @param scope Scope used to resolve superclass dependencies. * @returns Loaded class definition, or `undefined` when unavailable. */ loadClassDefinition(name: string, scope: Scope): ClassDefinition | undefined; /** * Resolve a concrete method body for a classdef prototype. * * The lookup key is `ClassName.methodName`, which maps naturally to * browser-hosted paths such as `+pkg/@Class/method.m` through the shared * class-source resolver. * * @param className Canonical class name. * @param methodName Method prototype name. * @param scope Scope used as parent for the method-file private scope. * @returns Loaded method body, or `undefined` when no external method file exists. */ loadClassMethodDefinition(className: string, methodName: string, scope: Scope): NodeFunctionDefinition | undefined; /** * Convert a dotted identifier chain into name parts when it is purely symbolic. * * @param tree Dotted reference node. * @returns Qualified name parts, or `undefined` for dynamic field access. */ private qualifiedReferenceParts; /** * Resolve static class members, constants, and enumeration members. * * @param definition Class definition that matched the qualified prefix. * @param fields Remaining field chain after the class name. * @param scope Evaluation scope for constant defaults and enumeration arguments. * @returns Runtim