UNPKG

mathjslab

Version:

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

133 lines (132 loc) 6.98 kB
import type { ExpressionBoundaryValue, FunctionTable, NameEntry, NameTable, NodeFunctionDefinition, NodeInput, RuntimeExpressionValue } from './AST'; import { CharString } from './CharString'; type WorkspaceScope = { parent?: WorkspaceScope; nameTable: NameTable; functionTable: FunctionTable; resolveParentNames: boolean; defineName(name: string, node: NodeInput): NameEntry; hasLocalName(name: string): boolean; }; type RuntimeNameWriter = { nameTable?: NameTable; defineName(name: string, node: RuntimeExpressionValue): NameEntry; }; type ThrowSyntaxError = (message: string) => never; type EvaluateInScope = (source: string, scope: WorkspaceScope) => NodeInput; type UnparseInputArgument = (arg: ExpressionBoundaryValue) => string; type IsCatchableError = (error: unknown) => boolean; type OnCatchError = (error: unknown) => void; /** * Workspace helpers shared by function calls and MATLAB/Octave workspace * built-ins. * * This module owns the non-parser parts of `persistent`, `global`, `inputname`, * `eval`, `evalin`, and `assignin`. Keeping these operations outside * `Interpreter.ts` makes the execution rules visible and testable without * requiring a full interpreter instance. */ declare class FunctionWorkspace { /** * Ensure that a function definition has its persistent-variable table. * * Persistent storage lives on the function definition node itself, matching * the lifetime of a parsed function definition. Call scopes receive copies * when the function is entered and write values back when it returns. */ static ensurePersistentTable(func: NodeFunctionDefinition): Record<string, RuntimeExpressionValue>; /** * Copy all variable/function entries visible from `source` into `target`. * * The copy walks from outermost to innermost scope so local entries shadow * parent entries. It stops when a scope disables parent-name resolution, * preserving detached closure snapshots. */ static copyVisibleScopeEntries(target: Pick<WorkspaceScope, 'nameTable' | 'functionTable'>, source?: WorkspaceScope): void; /** * Implement `inputname(n[, onlyVariableNames])`. * * With the default `onlyVariableNames = true`, MATLAB/Octave return an * empty string unless the selected argument is a plain variable name. When * `onlyVariableNames` is false, the original caller expression is returned * when an unparser is supplied. */ static inputName(inputArgs: ExpressionBoundaryValue[], indexNode: NodeInput, throwSyntaxError: ThrowSyntaxError, onlyVariableNames?: boolean, unparse?: UnparseInputArgument): CharString; /** * Resolve `base` and `caller` workspace names for `evalin` and `assignin`. * * External files are intentionally not handled here; the browser UI owns * external-file access, so this helper only models in-memory workspaces. */ static resolveWorkspace(name: string, baseScope: WorkspaceScope, callerScope: WorkspaceScope, throwSyntaxError: ThrowSyntaxError): WorkspaceScope; /** * Evaluate source in a target workspace, optionally running a catch string. * * This models the two-argument `eval`/three-argument `evalin` form while * leaving parsing and execution to the callback supplied by the interpreter. * The optional predicate lets the interpreter keep control-flow signals * such as `return`, `break`, and `continue` out of the catch string path. * The optional catch hook records the original error before catch source * execution so `lasterr`/`lasterror` see the same state as `try/catch`. */ static evaluateWithCatch(scope: WorkspaceScope, source: string, catchSource: string | undefined, evaluate: EvaluateInScope, isCatchableError?: IsCatchableError, onCatchError?: OnCatchError): NodeInput; /** * Implement `assignin` after the interpreter has resolved the workspace. * * Values are copied before storage to avoid aliasing the caller's AST node. * The result is `VOID` because assignment-by-side-effect should not display * an answer in the command UI. */ static assignIn(scope: RuntimeNameWriter, name: string, value: RuntimeExpressionValue): NodeInput; /** * Declare or initialize a persistent variable for a function call. * * A declaration without initializer creates an empty-array persistent value * on first use. A declaration with initializer only initializes the table if * the name has not been seen before, matching MATLAB/Octave persistent * semantics. */ static declarePersistent(name: string, value: RuntimeExpressionValue | undefined, func: NodeFunctionDefinition, scope: RuntimeNameWriter): void; /** * Load all persistent variables into a fresh function-call scope. */ static loadPersistentVariables(func: NodeFunctionDefinition, scope: RuntimeNameWriter): void; /** * Store changed persistent variables back into the function definition. * * Only names known to the persistent table are saved. This prevents ordinary * local variables from becoming persistent accidentally. */ static storePersistentVariables(func: NodeFunctionDefinition, scope: Pick<WorkspaceScope, 'hasLocalName' | 'nameTable'>): void; /** * Declare a global binding in the current scope. * * Local and global scopes share the same `NameEntry` object. Mutating one * side therefore updates the other, which is the behavior expected by * MATLAB/Octave-like `global` declarations. * * Octave-style `global name = value` initializes a global binding only once * through declaration syntax. Later global declarations for the same name * reattach the existing binding without overwriting user changes. */ static declareGlobal(name: string, value: RuntimeExpressionValue | undefined, globalNameSet: Set<string>, globalNameTable: NameTable, scopeNameTable: NameTable, globalInitializedNameSet?: Set<string>): void; /** * Clear global variables from global, active, and captured scopes. * * Function handles and nested functions can keep references to defining * scopes. The recursive walk follows those defining scopes so `clear global` * does not leave stale global aliases hidden in closures. * * @param globalNameSet Names currently declared as global. * @param globalScope Base global scope. * @param callScopes Active call scopes that may contain global aliases. * @param requestedNames Optional subset of global names to remove. */ static clearGlobalVariables(globalNameSet: Set<string>, globalScope: WorkspaceScope | undefined, callScopes: WorkspaceScope[], requestedNames?: string[]): void; } export type { WorkspaceScope }; export { FunctionWorkspace }; declare const _default: { FunctionWorkspace: typeof FunctionWorkspace; }; export default _default;