call (inputs... callable -- outputs...)
Inputs
inputs...: Objects required bycallable, already below it in its required stack order.callable: Already-selected object orRefwhose dereferenced schema isBlock,Code, callableDict, or knownText.
Outputs
outputs...: Zero or more objects left bycallable, according to its own stack effect.
Calls one already-selected stack callable. No name lookup or field selection happens inside the builtin.
call performs a call boundary. Locals created inside the called logic do not remain available afterward.
Behavior
- Stored Block, Code, and callable Dict objects are obtained via
.@NAMEor@NAMEwhen the stored callable itself must be pushed. Plain.NAMEorNAMEcalls the stored object at once, sorunner callcallsrunnerand then appliescallto what it leaves. Known Text locals differ: plain mention already pushes the Text object, sotextLocal callis valid. - For a callable Dict already on the data stack, its
CALLfield must haveBlockschema;callprocesses thatBlockdirectly. A Code-valued or other non-BlockCALLis rejected.PREis not used, because the Dict object is already selected beforecallruns. - Calling a Code that is not a known
NIL— known non-NILor unknown — is a run-time call; its outputs are unknown objects of the signature's output schema. - A known
NILCode is invalid. - Unknown Text is invalid.
- A known
NILText input is invalid.
When the input is a callable Dict, that callable Dict's fields are available for direct scope lookup during CALL. For a non-Meta non-static callable Dict supplied through a Ref — @NAME or .@NAME — call also introduces closure as a reference to that Dict with the same mutability, subject to normal name shadowing. A bare Dict supplies its fields but introduces no closure reference. Use @closure — for example, @closure.factor — because plain closure calls CALL again. There is no separate self name here, because no outer field-selection step occurs inside call.
Known Text inputs are interpreted as MPL code text and then called through the same call boundary.
Known issue: parsed Text bodies are cached by their contents. If identical Text is called from different modules, later processing can reuse the first call site's module for name lookup, so the result can depend on processing order. Use module-defined Blocks instead when names must resolve separately in each module.
Example
{} 0 {} [
"-- block uses stack values below it --" printCompilerMessage
5 [2 +] call printStack _:;
"-- call uses CALL directly on an already selected Dict --" printCompilerMessage
runner: {
factor: 3;
PRE: [FALSE];
CALL: [factor *];
};
7 @runner call printStack _:;
"-- read Code value first, then call it --" printCompilerMessage
codeLocal: {} 0 {} codeRef;
[42] !codeLocal # a non-NIL Code
@codeLocal call printStack _:;
"-- known text from stack --" printCompilerMessage
9 «1 +» call printStack _:;
"-- known text local may be mentioned plainly --" printCompilerMessage
textLocal: «2 +»;
8 textLocal call printStack _:;
0
] "main" exportFunction
Expected Output During Compilation
-- block uses stack values below it --
7
-- call uses CALL directly on an already selected Dict --
21
-- read Code value first, then call it --
Int32
-- known text from stack --
10
-- known text local may be mentioned plainly --
10
See also
callFieldbuiltin(inputs... dict name -- outputs...)Selects a Dict field by known Text name and then applies.NAME-style semantics. Callable fields are called; non-callable fields are read.ifbuiltin(inputs... condition trueCallable falseCallable -- outputs...)Selects between two already-selected Block branches by Cond. Unknown conditions require both branches to be compiled and merged.loopbuiltin(inputs... callable -- outputs...)Repeatedly calls one already-selected Block through a call boundary. The run-time repetition invariant is(A -- A Cond): each body call preserves the carried stack’s shape — the number of objects and their schemas — not necessarily their values, and leaves a final Cond; known-condition iterations may add items or change schemas.ucallbuiltin(inputs... callable -- outputs...)Processes an already-selected Block or known Text inline in the current scope.uifbuiltin(inputs... condition trueCallable falseCallable -- outputs...)Selects between two already-selected Block branches by a known Cond and processes the selected branch inline. No branch-output merge occurs.