|
x-engine-c v0.2.13
The C engine for x-lang
|
Operative (fexpr / dynamic-scope combiner) type implementation. More...
Functions | |
| static x_obj_t * | x_type_operative_mark (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_make_operative (x_obj_t *p_base, x_obj_flag_t flags, x_obj_t *p_params, x_obj_t *p_envparam, x_obj_t *p_body, x_obj_t *p_env) |
| x_obj_t * | x_type_operative_save (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_type_operative_struct (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_type_operative_register (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_type_operative_make (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_type_operative_call (x_obj_t *p_base, x_obj_t *p_args) |
Variables | |
| static x_satom_t | x_type_operative_mark_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_mark }) |
| static x_satom_t | x_type_operative_units_obj = x_obj_set(NULL, X_OBJ_FLAG_NONE, { .i = 2 }) |
| x_satom_t | x_type_operative_name = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { .s = (x_char_t *)X_TYPE_OPERATIVE_NAME }) |
| x_satom_t | x_type_operative_make_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_make }) |
| x_satom_t | x_type_operative_call_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_call }) |
| x_satom_t | x_type_operative_struct_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_struct }) |
| x_satom_t | x_type_operative_save_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_save }) |
Operative (fexpr / dynamic-scope combiner) type implementation.
| x_obj_t * x_make_operative | ( | x_obj_t * | p_base, |
| x_obj_flag_t | flags, | ||
| x_obj_t * | p_params, | ||
| x_obj_t * | p_envparam, | ||
| x_obj_t * | p_body, | ||
| x_obj_t * | p_env | ||
| ) |
Allocate a new operative on the heap.
Builds the state list (params . (envparam . (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 |
| p_params | x_obj_t* – Formal parameter tree |
| p_envparam | x_obj_t* – Environment parameter name (or nil) |
| p_body | x_obj_t* – Body expression list |
| p_env | x_obj_t* – Captured environment |
Type-dispatch call callback: evaluate an operative application.
Operatives are lexically scoped: the body runs in the env captured at (op ...) creation time, extended with the formals bound to the UNEVALUATED arguments. The caller's environment is exposed only through the named env-param (when the op declares one), so that (eval expr e) or (tail-eval expr e) inside the body can reach back into the caller's scope explicitly. Caller-local names cannot silently shadow the globals the body relies on. Operatives do NOT get self-passing.
Implementation:
Body is run via x_eval_body (NOT a TCO body evaluator). Each body form is evaluated synchronously to completion – tail-eval inside a form still TCOs via x_eval's own trampoline, so common patterns like (tail-eval (...) e) work without growing the C stack. The op itself doesn't TCO into its caller, but lib ops typically dispatch the heavy work via tail-eval into the caller's env, so the op frame isn't on the recursion path.
After the body returns, the caller's environment is made current again, unconditionally. A (def ...) the body evaluated in the caller's environment is IN that environment, so restoring the pointer keeps it.
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – (operative . unevaluated-args) |
Type-dispatch make callback: construct an operative from x-lang args.
Expects args: (params envparam body env [flags]).
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – Construction arguments |
GC mark callback for operative objects.
Only marks slot 1 (state list), not slot 0 (fn ptr).
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – (object . (flags)) |
Register (or retrieve) the OPERATIVE type struct on p_base.
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – Unused |
Build the OPERATIVE type struct descriptor.
| p_base | x_obj_t* – Base (execution context) |
| p_args | x_obj_t* – Unused |
Build the OPERATIVE type struct descriptor.
| x_satom_t x_type_operative_call_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_call }) |
| x_satom_t x_type_operative_make_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_make }) |
|
static |
| x_satom_t x_type_operative_name = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { .s = (x_char_t *)X_TYPE_OPERATIVE_NAME }) |
| x_satom_t x_type_operative_save_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_save }) |
| x_satom_t x_type_operative_struct_prim = x_obj_set(x_type_atom_obj, X_OBJ_FLAG_NONE, { (x_obj_t *)&x_type_operative_struct }) |
|
static |