x-engine-c v0.2.31
The C engine for x-lang
Loading...
Searching...
No Matches
x-eval-slots.h File Reference

The base's slot vector – the engine's routines, each at a fixed position, called through the position. More...

#include "x-base.h"
#include "x-vector.h"

Go to the source code of this file.

Enumerations

Slot Positions
enum  x_eval_slot_enum {
  X_SLOT_EVAL = 0 , X_SLOT_EVAL_LIST , X_SLOT_EVAL_BODY , X_SLOT_EVAL_BODY_TCO ,
  X_SLOT_EVAL_TCO_TRAMPOLINE , X_SLOT_EVAL_OP_BODY , X_SLOT_CALLABLE_CALL , X_SLOT_CALLABLE_APPLY ,
  X_SLOT_OBJ_PRIM_CALL , X_SLOT_ENV_LOOKUP , X_SLOT_ENV_BIND , X_SLOT_ENV_EXTEND ,
  X_SLOT_ALIST_BST_LOOKUP , X_SLOT_TOKEN_READ , X_SLOT_TOKEN_ANALYSE , X_SLOT_TOKEN_DELIMIT ,
  X_SLOT_HEAP_MARK , X_SLOT_HEAP_SWEEP , X_SLOT_OBJ_ALLOC , X_SLOT_LEN
}
 

Slot Access

#define x_slot(V, I)   x_vectorfn((V), (I))
 
#define x_argrun(...)   ((x_obj_t[]){ __VA_ARGS__ })
 
#define x_eval_slots(B)   x_restobj((B))
 
#define x_eval_slot(B, I)   x_slot(x_eval_slots((B)), (I))
 
#define x_eval_slots_isset(B)    ((B) != NULL && x_eval_slots((B)) != NULL)
 
#define x_eval_call(B, I, A)   (x_eval_slot((B), (I))((B), (A)))
 
#define x_eval_call_or(B, I, FN, A)    ((x_eval_slots_isset((B)) ? x_eval_slot((B), (I)) : (FN))((B), (A)))
 
#define x_eval_slot_isset(B, I)    (x_eval_slots_isset((B)) && x_eval_slot((B), (I)) != NULL)
 
x_obj_t * x_slots_make (x_obj_t *p_base, x_int_t length)
 

Detailed Description

The base's slot vector – the engine's routines, each at a fixed position, called through the position.

A base holds a slot vector: a vector (see x-vector.h) whose elements are function pointers, one per slot. The engine reaches a routine by its position in the vector, so a routine can be replaced while the engine runs by storing another function pointer in its slot.

A slot holds a function pointer and nothing more. Every routine in a slot has the engine's one signature, x_fn_t:

x_obj_t *fn(x_obj_t *p_base, x_obj_t *p_args);
static void x_obj_t * p_args
Definition x-prim.h:56
Definition x-obj.h:214

and p_args is the routine's argument run: a run of datum words, one per argument, in the order the slot's row in the layout contract gives them. A word holds what the argument is: an object pointer, an integer, a string. The run has no header and no length; the contract says how many words there are and what each holds. The caller writes the words, in stack storage, and the routine reads them back:

x_obj_t args[2] = { { .p = p_env }, { .p = p_sym } };
p = x_eval_call(p_base, X_SLOT_ENV_LOOKUP, args);
...
p_env = x_obj(p_args[0]);
p_sym = x_obj(p_args[1]);
x_obj_t * p
Definition x-obj.h:215
#define x_eval_call(B, I, A)
Definition x-eval-slots.h:190
@ X_SLOT_ENV_LOOKUP
Definition x-eval-slots.h:110
#define x_obj(X)
Definition x-obj.h:392

A call through a slot allocates nothing. The elements of a heap vector are a run of words too, so a caller that holds its arguments in a vector passes the address of its first element.

The slot vector is the base object's second data unit. x-expr makes a base of one unit holding the tree; x_eval_make() makes the engine's base of two, the tree first, where x-expr reads it, and the vector second, so a call locates the vector in one load from the base. Each base has a vector of its own, filled from the engine's table when the base is made, and a slot replaced in one base is replaced there alone. The positions are part of the layout contract: they are listed in tools/contract/base-slots.x, which tools/check/base-slots.sh diffs against this header, and a language that replaces a routine reads its position from there. Each slot's comment gives its arguments and the type of the word each travels in: an object, an integer or a string. The collector is the engine's: the mark and sweep phases and the allocation of an object are routines in the vector, written over x-expr's chain, traversal, sweep and hooks, which the engine calls by name and which are never in a slot.

Author
Jon Ruttan (jonru.nosp@m.ttan.nosp@m.@gmai.nosp@m.l.co.nosp@m.m)

Macro Definition Documentation

◆ x_argrun

#define x_argrun (   ...)    ((x_obj_t[]){ __VA_ARGS__ })

An argument run written as an expression: the datum initializers of its words, in order. It lasts as long as the block the expression is in.

x_eval_call(p_base, X_SLOT_EVAL, x_argrun({ .p = p_expr }));
#define x_argrun(...)
Definition x-eval-slots.h:169
@ X_SLOT_EVAL
Definition x-eval-slots.h:83

◆ x_eval_call

#define x_eval_call (   B,
  I,
  A 
)    (x_eval_slot((B), (I))((B), (A)))

Call the function in slot I of base B with argument run A. The base must have a slot vector and the slot must hold a function: one load for the vector, one for the slot, and the call.

◆ x_eval_call_or

#define x_eval_call_or (   B,
  I,
  FN,
  A 
)     ((x_eval_slots_isset((B)) ? x_eval_slot((B), (I)) : (FN))((B), (A)))

Call the function in slot I of base B with argument run A, or the routine FN when there is no base or the base has no slot vector. For the engine's own calls, which may run before a base exists, or on a base x-expr made; a base x_eval_make() made always has its slots.

◆ x_eval_slot

#define x_eval_slot (   B,
  I 
)    x_slot(x_eval_slots((B)), (I))

The function pointer in slot I of base B (an lvalue).

◆ x_eval_slot_isset

#define x_eval_slot_isset (   B,
  I 
)     (x_eval_slots_isset((B)) && x_eval_slot((B), (I)) != NULL)

Test whether slot I of base B holds a function: the base has a slot vector and the slot is not empty.

◆ x_eval_slots

#define x_eval_slots (   B)    x_restobj((B))

The slot vector of base B (an lvalue): its second data unit.

◆ x_eval_slots_isset

#define x_eval_slots_isset (   B)     ((B) != NULL && x_eval_slots((B)) != NULL)

Test whether base B has a slot vector: one load. The base must have two units: an object standing as an allocation context is a pair with nothing in it, never an atom, since the second unit is read.

◆ x_slot

#define x_slot (   V,
  I 
)    x_vectorfn((V), (I))

The function pointer in slot I of slot vector V (an lvalue).

Enumeration Type Documentation

◆ x_eval_slot_enum

The positions in the slot vector.

Enumerator
X_SLOT_EVAL 

x_eval(). Arguments: (expression). Types: (object).

X_SLOT_EVAL_LIST 

x_eval_list(). Arguments: (args). Types: (object).

X_SLOT_EVAL_BODY 

x_eval_body(). Arguments: (body). Types: (object).

X_SLOT_EVAL_BODY_TCO 

x_eval_body_tco(). Arguments: (body). Types: (object).

X_SLOT_EVAL_TCO_TRAMPOLINE 

x_eval_tco_trampoline(). Arguments: (result). Types: (object).

X_SLOT_EVAL_OP_BODY 

x_eval_op_body(). Arguments: (body, caller). Types: (object, object).

X_SLOT_CALLABLE_CALL 

x_callable_call(). Arguments: (args). Types: (object).

X_SLOT_CALLABLE_APPLY 

x_callable_apply(). Arguments: (args). Types: (object).

X_SLOT_OBJ_PRIM_CALL 

x_obj_prim_call(). Arguments: (args). Types: (object).

X_SLOT_ENV_LOOKUP 

x_env_lookup(). Arguments: (env, symbol). Types: (object, object).

X_SLOT_ENV_BIND 

x_env_bind(). Arguments: (env, symbol, value). Types: (object, object, object).

X_SLOT_ENV_EXTEND 

x_env_extend(). Arguments: (parent, params, values). Types: (object, object, object).

X_SLOT_ALIST_BST_LOOKUP 

x_alist_bst_lookup(). Arguments: (tree, symbol). Types: (object, object).

X_SLOT_TOKEN_READ 

x_token_read(). Arguments: (args). Types: (object).

X_SLOT_TOKEN_ANALYSE 

x_token_analyse(). Arguments: (args, label). Types: (object, integer). The routine stores the label it declares in the second word.

X_SLOT_TOKEN_DELIMIT 

x_token_delimit(). Arguments: (args). Types: (object).

X_SLOT_HEAP_MARK 

x_heap_mark_phase(), the collector's mark phase. Arguments: (). Types: ().

X_SLOT_HEAP_SWEEP 

x_heap_sweep_phase(), the collector's sweep phase. Arguments: (). Types: ().

X_SLOT_OBJ_ALLOC 

x_eval_alloc(), allocate an object. Arguments: (type, flags, units). Types: (object, integer, integer).

X_SLOT_LEN 

The length of the slot vector.

Function Documentation

◆ x_slots_make()

x_obj_t * x_slots_make ( x_obj_t *  p_base,
x_int_t  length 
)

Make a slot vector of length slots, every one empty.

Make a slot vector of length slots, every one empty.

The slot vector is a vector: its first data unit holds its length, and its slots follow. It has no type, and must not be given one: the vector sits in the base's tree, where the collector's mark reaches it, and an object with no type is marked and not descended – its elements are function pointers, not objects. It is allocated with X_OBJ_FLAG_SHARED, so a sweep keeps it for as long as the base lives, and its length is a static atom or a SHARED one for the same reason.

Parameters
p_baseBase the vector belongs to (allocation context).
lengthThe number of slots.
Returns
The slot vector, or NULL when it could not be allocated.