UNPKG

mathjslab

Version:

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

302 lines (301 loc) 12.4 kB
import type { ExpressionBoundaryValue, NodeExpr, NodeFunctionDefinition, NodeFunctionParameter, NodeFunctionReturn, NodeInput, NameTable } from './AST'; import { MultiArray } from './MultiArray'; /** * Interpreter error callback used by pure call helpers. */ type ThrowEvalError = (message: string) => never; type ReturnName = NodeFunctionReturn; type FunctionParameter = NodeFunctionParameter; type EvaluatedArgumentValue = ExpressionBoundaryValue | DefaultArgumentMarker; type CallArgumentValue = ExpressionBoundaryValue; /** * Internal placeholder for Octave's `:` default-argument marker. */ type DefaultArgumentMarker = { /** Discriminator for default-marker values. */ useDefaultArgument: true; }; /** * Workspace binding callback used while wiring evaluated inputs and outputs. */ type DefineName = (name: string, value: ExpressionBoundaryValue) => void; /** * Expression evaluator callback supplied by the interpreter. */ type EvaluateExpression = (expression: NodeExpr) => NodeInput; /** * Default-argument evaluator callback. * * The parameter name is passed so interpreter diagnostics can report which * default expression failed. */ type EvaluateDefault = (name: string, expression: NodeExpr) => NodeInput; /** * Static input layout derived from a function definition. */ type FunctionInputLayout = { /** * All declared parameters, including name-value-only parameters and `varargin`. */ params: FunctionParameter[]; /** * Whether the final declared parameter is `varargin`. */ hasVarargin: boolean; /** * Number of parameters before `varargin`, if any. */ fixedParamCount: number; /** * Parameters that accept positional arguments after name-value filtering. */ positionalParams: FunctionParameter[]; /** * Number of positional parameters after name-value filtering. */ positionalParamCount: number; }; /** * Static output layout derived from a function definition. */ type FunctionReturnLayout = { /** * All declared return identifiers, including `varargout`. */ returnNames: ReturnName[]; /** * Whether the final declared return identifier is `varargout`. */ hasVarargout: boolean; /** * Return variable that behaves as a variable-length output cell. * * This is usually `varargout`, but MATLAB `arguments (Output,Repeating)` * also allows an ordinary output name to back a repeating output list. */ variableOutputName?: string; /** * Number of fixed return identifiers before `varargout`, if any. */ fixedReturnCount: number; /** * Return names as strings for workspace lookup. */ names: string[]; }; /** * Call-site arguments after positional and name-value splitting. */ type FunctionCallArguments = { /** * Positional argument expressions in call order. */ positional: CallArgumentValue[]; /** * Positional argument count before comma-separated-list expansion. */ rawPositionalCount?: number; /** * Name-value argument expressions keyed by option name. */ named: Map<string, CallArgumentValue>; }; /** * Complete metadata needed to enter a user-function call. */ type PreparedFunctionCall = { /** * Prepared input layout. */ inputLayout: FunctionInputLayout; /** * Prepared output layout. */ returnLayout: FunctionReturnLayout; /** * Split call-site arguments. */ callArguments: FunctionCallArguments; /** * Default expressions keyed by parameter name. */ inputDefaults: Map<string, NodeExpr>; /** * Minimum number of positional arguments required after trailing defaults. */ minFixedParamCount: number; }; /** * Interpreter services required while preparing a function call. */ type FunctionCallPreparationCallbacks = { /** * Return the parameters that are bound exclusively through name-value input. */ nameValueParameters: (func: NodeFunctionDefinition) => Set<string>; /** * Split raw call arguments into positional and named groups. */ splitCallArguments: (func: NodeFunctionDefinition, args: CallArgumentValue[]) => FunctionCallArguments; /** * Expand comma-separated-list expressions in positional call arguments. */ expandPositionalArguments?: (args: CallArgumentValue[]) => CallArgumentValue[]; /** * Return default expressions keyed by input parameter name. */ inputDefaults: (func: NodeFunctionDefinition) => Map<string, NodeExpr>; /** * Return the `arguments (Output,Repeating)` output name, when present. */ outputRepeatingName?: (func: NodeFunctionDefinition) => string | undefined; /** * Raise an interpreter evaluation error. */ throwEvalError: ThrowEvalError; }; /** * Mechanics for calling MATLAB/Octave-like user functions and lambdas. * * The interpreter remains responsible for parsing, expression evaluation, and * error construction. This class is deliberately a pure helper around layouts, * arity checks, argument binding, `varargin`, `varargout`, default arguments, * and lazy return-list construction. */ declare class FunctionCall { private static readonly defaultArgumentMarker; private static isIdentifier; private static isDefaultedIdentifier; private static parameterName; private static isNamed; /** * Validate function header metadata that should already be guaranteed by AST factories. */ private static checkedList; /** * Ensure a workspace value can be exposed through a lazy return list. * * `eval`/`evalin` can legitimately hand back a `NodeList` execution result, * so the return channel accepts strict expression values plus that explicit * carrier while still rejecting control-flow statements. */ private static returnExpression; /** * Ensure an evaluated input can be bound to a function workspace. */ private static evaluatedArgument; private static isDefaultArgumentMarker; private static callArgumentRequestsDefault; private static requireEvaluatedArgument; /** * Convert evaluated argument values back to ordinary expression values. * * This is used after fixed positional defaults have consumed any `:` * markers, before forwarding remaining inputs to `varargin` or repeating * argument validation. */ static expressionArgumentValues(values: EvaluatedArgumentValue[], role: string, throwEvalError: ThrowEvalError): ExpressionBoundaryValue[]; /** * Compute the input layout of a user-defined function. * * Name-value option structs declared through `arguments` are excluded from * the positional parameter list. `varargin` still participates as the final * catch-all parameter. */ static inputLayout(func: NodeFunctionDefinition, nameValueParameters: Set<string>): FunctionInputLayout; /** * Compute the fixed/variadic input layout of an anonymous function handle. */ static lambdaInputLayout(params: FunctionParameter[]): Pick<FunctionInputLayout, 'hasVarargin' | 'fixedParamCount'>; /** * Compute the return layout, including `varargout`. */ static returnLayout(func: NodeFunctionDefinition, repeatingOutputName?: string): FunctionReturnLayout; /** * Determine the minimum required positional count after trailing defaults. */ static minimumPositionalCount(positionalParams: FunctionParameter[], inputDefaults: Map<string, NodeExpr>): number; /** * Check anonymous-function input arity. */ static validateLambdaInputArity(argsLength: number, hasVarargin: boolean, fixedParamCount: number, throwEvalError: ThrowEvalError): void; /** * Check user-function input arity after name-value splitting and defaults. */ static validateFunctionInputArity(func: NodeFunctionDefinition, positionalLength: number, hasVarargin: boolean, positionalParamCount: number, minFixedParamCount: number, throwEvalError: ThrowEvalError): void; /** * Check requested output count before entering the function body. */ static validateFunctionOutputArity(returnNames: ReturnName[], hasVarargout: boolean, requestedOutputCount: number, throwEvalError: ThrowEvalError): void; /** * Build all static call metadata needed before evaluating arguments. */ static prepareFunctionCall(func: NodeFunctionDefinition, args: CallArgumentValue[], requestedOutputCount: number, callbacks: FunctionCallPreparationCallbacks): PreparedFunctionCall; /** * Create a cell row for `varargin`. */ static vararginCell(values: EvaluatedArgumentValue[]): MultiArray<ExpressionBoundaryValue>; /** * Create the initial `varargout` cell array. * * MATLAB permits assigning elements later. The placeholder length is at * least one so the variable exists even when no extra output is requested. */ static emptyVarargoutCell(requestedOutputCount: number, fixedReturnCount: number): MultiArray; /** * Predeclare fixed return names in the function workspace. * * An empty entry lets the return-list builder distinguish "declared but not * assigned" from "not a return variable" and produce MATLAB-like undefined * return errors. */ static initializeFixedReturnSlots(returnNames: ReturnName[], nameTable: NameTable): void; /** * Attach call-site metadata and evaluate positional arguments. */ static evaluateCallArguments(args: CallArgumentValue[], parent: NodeInput, evaluate: EvaluateExpression, throwEvalError: ThrowEvalError, indexOffset?: number, allowDefaultMarkers?: boolean): EvaluatedArgumentValue[]; /** * Evaluate already-split name-value arguments. */ static evaluateNameValueArguments(named: Map<string, CallArgumentValue>, parent: NodeInput, evaluate: EvaluateExpression, throwEvalError: ThrowEvalError): Map<string, ExpressionBoundaryValue>; /** * Bind anonymous-function inputs, including `varargin`. */ static bindLambdaInputs(params: FunctionParameter[], args: CallArgumentValue[], parent: NodeInput, hasVarargin: boolean, fixedParamCount: number, defineName: DefineName, evaluate: EvaluateExpression, throwEvalError: ThrowEvalError): void; /** * Bind evaluated positional arguments and default values to function inputs. */ static bindPositionalInputs(func: NodeFunctionDefinition, inputLayout: FunctionInputLayout, evaluatedArgs: EvaluatedArgumentValue[], inputDefaults: Map<string, NodeExpr>, defineName: DefineName, evaluateDefault: EvaluateDefault, throwEvalError: ThrowEvalError): void; /** * Bind the remaining evaluated inputs to `varargin`. */ static bindVarargin(inputLayout: FunctionInputLayout, evaluatedArgs: EvaluatedArgumentValue[], defineName: DefineName): void; /** * Initialize `varargout` in the function workspace. */ static bindVarargout(returnLayout: FunctionReturnLayout, requestedOutputCount: number, defineName: DefineName): void; private static variableReturnKey; /** * Runtime placeholder returned when a function declares an ignored output. * * MATLAB/Octave permit `~` in a function output list. The function body has * no variable to assign for that position, but callers that request the * corresponding output still receive an ordinary empty array. */ private static ignoredReturnValue; /** * Create the lazy return list read by assignment and display code. * * Values are pulled from the function workspace only when requested. This is * important for MATLAB/Octave compatibility: requesting one output should * not force validation of later outputs, while requesting an unassigned * output must raise an error. */ static createReturnList(returnLayout: FunctionReturnLayout, nameTable: NameTable, throwEvalError: ThrowEvalError, outputMask?: boolean[]): NodeExpr; } export type { CallArgumentValue, FunctionInputLayout, FunctionReturnLayout, FunctionCallArguments, PreparedFunctionCall, FunctionParameter }; export { FunctionCall }; declare const _default: { FunctionCall: typeof FunctionCall; }; export default _default;