mathjslab
Version:
MathJSLab - An interpreter with language syntax like MATLAB®/Octave, ISBN 978-65-00-82338-7.
302 lines (301 loc) • 12.4 kB
TypeScript
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;