Single-callable wrapper schemas with stored callable context and one declared call signature.


Use

"Function" use exposes the module's public names. Name-specific imports such as "Function.Function" use, "Function.Function2" use, or "Function.makeFunction" use expose only selected names.


Dispatch keys

FUNCTION_ASSIGN_KEY

(-- key) Returns Int32 key 0 for the vtable's context-copy operation.

FUNCTION_CALL_KEY

(-- key) Returns Int32 key 1 for invocation.

FUNCTION_DIE_KEY

(-- key) Returns Int32 key 2 for destruction.

FUNCTION_INIT_KEY

(-- key) Returns Int32 key 3 for initialization.

FUNCTION_INVALID_KEY

(-- key) Returns Int32 key 4 for the installed-context query.

Construction forms


Function2

Function2

(signature dataSize -- function) Constructs an empty Function object with dataSize bytes of embedded callable storage.
  • signature is the three-part descriptor (inputs output options) used to form a codeRef signature, not a Code reference. The input and option descriptors follow codeRef's rules.
  • dataSize is a known Int32 of at least 8; smaller sizes fail compilation with The [Function] data size is less than 8 bytes.
  • The result is an initialized, managed, non-Meta object.
  • DATA_SIZE counts embedded callable bytes, not the vtable or whole-object padding. Callable storage starts at 8-byte alignment.

Fields

Methods

assign

(callable --) Stores one callable in the wrapper.
  • A callable matching Signature is required. A sized runtime callable is stored in the wrapper: an immutable source is copied, and a mutable source is moved.
  • A sized callable context must fit DATA_SIZE; an oversized context fails compilation with The object is too large to be encapsulated in a [Function]. The callable must also match Signature's input and output schemas.
  • Reference fields remain borrowed. A Code reference is retained independently of later rebinding of the source Code variable.
  • For runtime storage, use a callable Dict with explicit fields; stored reference fields remain borrowed.
  • A Function of the same wrapper schema uses the assignment rules above; a different Function schema is encapsulated as a callable context and must fit DATA_SIZE.
  • A callable that cannot be copied may still be moved into the wrapper. Copying such an installed context reports Non-assignable callable and terminates the process.

CALL

(arguments... -- result...) Invokes the stored callable according to Signature.
  • The input and output stacks are specified by Signature. Push the first declared input last, so it is on top. A void output produces no item; a reference output returns the declared reference.
  • Calling an empty wrapper reports Invalid function called and terminates the process. The hidden context address is not a caller argument.
  • Output values and references follow Signature. A reference into stored callable state remains valid only while that state stays alive at the same address; replacement, release, movement, or destruction can invalidate it.
  • References to external objects retain those objects' lifetime requirements; storing a reference does not keep its target alive.
  • Calling through an immutable Function view can still mutate the stored callable and return mutable references. An installed Code reference must be non-NIL and valid; hasContext does not validate it.

hasContext

(-- cond) Returns Cond indicating whether the wrapper has an installed callable dispatch.
  • Returns FALSE after construction or release, and after assigning an empty Function of the same schema.
  • TRUE does not validate a stored Code reference or the state of a nested Function.

release

(--) Destroys the stored callable and resets the wrapper.

Example: explicit context size

"Function.Function2" use
"control"            use

{} () {} [
  ({value: Int32;} () {}) 48 Function2 .DATA_SIZE printStack _:;
] "main" exportFunction

Expected Output During Compilation

48

Runtime example: call through one explicit-size wrapper

"Function.Function2" use
"String"             use
"control"            use

{} Int32 {} [
  code: {value1: Int64; value0: Int32;} Real32 {} codeRef;
  [swap drop Int32 cast 5 + Real32 cast] !code
  function: ({value1: Int64; value0: Int32;} Real32 {}) 48 Function2;
  @code @function.assign
  ("has=" @function.hasContext LF
    "call=" 7 11i64 function 16.0r32 = LF) printList
  0
] "main" exportFunction

Expected Output

has=TRUE
call=TRUE

Stored state and call validity

Known issue: Lifetime hooks on Meta callable objects can run extra times during assignment, invocation, and release with the current compiler. Avoid side-effecting lifetime hooks on Meta callables here; use a callable with runtime storage instead.

For a Meta callable, diagnostic-only INIT and DIE fields are enough to expose the extra calls when the callable is assigned to a Function, invoked, and released.

c: {
  CALL: [7];
  INIT: ["meta-init\n" print];
  DIE: ["meta-die\n" print];
};
f: ({} Int32 {}) Function;
@c @f.assign
f
@f.release

Function

Function

(signature -- function) Constructs an empty Function object with 32 bytes of embedded callable storage.
  • Function has the same fields and operations as Function2, with that default size.
  • The result is an initialized, managed, non-Meta object.

Lifecycle and call result

"Function.Function"     use
"Function.makeFunction" use
"String"                use
"control"               use

{} Int32 {} [
  code: {value1: Int64; value0: Int32;} Real32 {} codeRef;
  [swap drop Int32 cast 11 + Real32 cast] !code

  function: ({value1: Int64; value0: Int32;} Real32 {}) Function;
  ("has0=" @function.hasContext LF) printList
  @code @function.assign
  ("has1=" @function.hasContext LF
    "call1=" 17 19i64 function 30.0r32 = LF) printList
  @function.release
  ("has2=" @function.hasContext LF) printList

  function2: @code ({value1: Int64; value0: Int32;} Real32 {}) makeFunction;
  ("has3=" @function2.hasContext LF
    "call2=" 23 29i64 function2 40.0r32 = LF) printList
  0
] "main" exportFunction

Expected Output

has0=FALSE
has1=TRUE
call1=TRUE
has2=FALSE
has3=TRUE
call2=TRUE

Copy from another wrapper

"Function.Function" use
"String"            use
"control"           use

{} Int32 {} [
  function0: ({value1: Int64; value0: Int32;} Real32 {}) Function;
  function1: ({value1: Int64; value0: Int32;} Real32 {}) Function;

  code0: {value1: Int64; value0: Int32;} Real32 {} codeRef;
  [swap drop Int32 cast 11 + Real32 cast] !code0
  @code0 @function0.assign

  code1: {value1: Int64; value0: Int32;} Real32 {} codeRef;
  [swap drop Int32 cast 13 + Real32 cast] !code1
  @code1 @function1.assign

  @function0 const @function1 set
  ("call0=" 17 19i64 function0 30.0r32 = LF
    "call1=" 23 29i64 function1 40.0r32 = LF
    "has0=" @function0.hasContext LF
    "has1=" @function1.hasContext LF) printList
  0
] "main" exportFunction

Expected Output

call0=TRUE
call1=TRUE
has0=TRUE
has1=TRUE

makeFunction

makeFunction

(callable signature -- function) Constructs and initializes one Function object.
  • Uses Function's 32-byte capacity and the same input, storage, and copy/move rules as assign.

See also