|
x-engine-c v0.2.13
The C engine for x-lang
|
Procedure (applicative closure) type for x-lang. More...
Go to the source code of this file.
Macros | |
| #define | X_TYPE_PROCEDURE_NAME "PROCEDURE" |
| #define | X_OBJ_FLAG_WRAP X_OBJ_FLAG_1 |
Type predicates | |
| #define | x_obj_type_isprocedure(B, X) x_obj_is_type((B), (X), X_TYPE_PROCEDURE_NAME) |
State accessors | |
Procedure state list: (params . (body . env)). Stored in x_callable_state (slot 1) of [fn-ptr][state] layout. GC traverses via the p_units=2 fallback in x_type_heap_mark. The environment is the one the closure was made in, and a call makes a child of it. It reaches the root through its parents, so a closure carries no separate copy of the global tree the way it once did; the root is an environment like any other. | |
| #define | x_procstate(X) x_callable_state((X)) |
| #define | x_procparams(X) x_firstobj(x_procstate((X))) |
| #define | x_procbody(X) x_firstobj(x_restobj(x_procstate((X)))) |
| #define | x_procenv(X) x_restobj(x_restobj(x_procstate((X)))) |
Convenience constructors | |
| #define | x_mkproc(B, P, BD, E) x_make_procedure((B), X_OBJ_FLAG_NONE, (P), (BD), (E)) |
| #define | x_mkfproc(B, F, P, BD, E) x_make_procedure((B), (F), (P), (BD), (E)) |
| #define | x_mkwrap(B, C) x_make_procedure((B), X_OBJ_FLAG_WRAP, NULL, NULL, (C)) |
Functions | |
| x_obj_t * | x_make_procedure (x_obj_t *p_base, x_obj_flag_t flags, x_obj_t *p_params, x_obj_t *p_body, x_obj_t *p_env) |
| x_obj_t * | x_type_procedure_register (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_type_procedure_struct (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_type_procedure_make (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_type_procedure_call (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_type_procedure_apply (x_obj_t *p_base, x_obj_t *p_args) |
Variables | |
Static primitive atoms for the type struct. | |
| x_satom_t | x_type_procedure_name |
| x_satom_t | x_type_procedure_make_prim |
| x_satom_t | x_type_procedure_call_prim |
| x_satom_t | x_type_procedure_struct_prim |
Procedure (applicative closure) type for x-lang.
A procedure is a two-unit heap object with callable layout:
When X_OBJ_FLAG_WRAP is set, the procedure is a wrapped applicative: env holds the underlying combiner instead of a closure environment, and call dispatches to that combiner after evaluating args.
| #define x_mkfproc | ( | B, | |
| F, | |||
| P, | |||
| BD, | |||
| E | |||
| ) | x_make_procedure((B), (F), (P), (BD), (E)) |
Make procedure with flags.
| #define x_mkproc | ( | B, | |
| P, | |||
| BD, | |||
| E | |||
| ) | x_make_procedure((B), X_OBJ_FLAG_NONE, (P), (BD), (E)) |
Make unwrapped procedure.
| #define x_mkwrap | ( | B, | |
| C | |||
| ) | x_make_procedure((B), X_OBJ_FLAG_WRAP, NULL, NULL, (C)) |
Wrap a combiner as applicative.
| #define X_OBJ_FLAG_WRAP X_OBJ_FLAG_1 |
Flag marking a wrapped applicative combiner.
| #define x_obj_type_isprocedure | ( | B, | |
| X | |||
| ) | x_obj_is_type((B), (X), X_TYPE_PROCEDURE_NAME) |
Test if object is a procedure.
| #define x_procbody | ( | X | ) | x_firstobj(x_restobj(x_procstate((X)))) |
Body expression list.
| #define x_procenv | ( | X | ) | x_restobj(x_restobj(x_procstate((X)))) |
Captured environment.
| #define x_procparams | ( | X | ) | x_firstobj(x_procstate((X))) |
Parameter tree.
| #define x_procstate | ( | X | ) | x_callable_state((X)) |
Full state list.
| #define X_TYPE_PROCEDURE_NAME "PROCEDURE" |
Type name string.
| x_obj_t * x_make_procedure | ( | x_obj_t * | p_base, |
| x_obj_flag_t | flags, | ||
| x_obj_t * | p_params, | ||
| x_obj_t * | p_body, | ||
| x_obj_t * | p_env | ||
| ) |
Allocate a new procedure object on the heap.
Allocate a new procedure (closure) on the heap.
Builds the state list (params . (body . env)) and stores it in slot 1 of the two-unit callable layout.
| p_base | x_obj_t* – Base (execution context) |
| flags | x_obj_flag_t – Object flags (e.g. X_OBJ_FLAG_WRAP) |
| p_params | x_obj_t* – Formal parameter tree |
| p_body | x_obj_t* – Body expression list |
| p_env | x_obj_t* – Captured lexical environment |
Non-TCO apply path for (apply f args).
Non-TCO apply path for (apply f args).
Arguments are already evaluated. Saves and restores the full environment state around body evaluation.
Unlike x_type_procedure_call, this path does NOT use the TCO trampoline. It calls x_eval_body (not x_eval_body_tco), which means the C call stack grows with each nested apply. This is necessary because apply is called from contexts where the caller needs the result immediately (e.g. map, fold, for-each).
The current environment is saved to a local before body evaluation and made current again afterward.
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – (procedure . evaluated-args) |
Type-dispatch call callback – evaluate a procedure application.
Type-dispatch call callback: evaluate a procedure application (TCO).
For wrapped combiners (applicatives), dispatches to the underlying combiner with evaluated arguments. For plain closures, extends the environment, pushes a save-stack frame, and enters the body via TCO.
Two dispatch paths based on X_OBJ_FLAG_WRAP:
Wrapped applicative (WRAP flag set): The procedure is a thin wrapper around another combiner stored in the env slot. Args are evaluated, then the underlying combiner is called via x_obj_prim_call. This is how (wrap op) creates an applicative from an operative.
Plain closure (no WRAP flag): Pushes the caller's environment onto the save-stack, makes a child of the closure's environment with the parameters bound current, and enters the body via x_eval_body_tco for tail-call optimization – the trampoline loop in x_eval makes the saved environment current again when the TCO chain completes.
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – (procedure . unevaluated-args) |
Type-dispatch make callback for PROCEDURE.
Type-dispatch make callback: construct a procedure from x-lang args.
Expects args: (params body env [flags]).
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – Construction arguments |
Register (or retrieve) the PROCEDURE type struct on p_base.
Register (or retrieve) the PROCEDURE type struct on p_base.
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – Unused |
Build the PROCEDURE type struct descriptor.
| x_satom_t x_type_procedure_call_prim |
| x_satom_t x_type_procedure_make_prim |
|
extern |
| x_satom_t x_type_procedure_struct_prim |