|
x-engine-c v0.2.13
The C engine for x-lang
|
The x-expr object system – atoms, pairs, flags, and type dispatch. More...
#include "x-lib.h"Go to the source code of this file.
Data Structures | |
| union | x_datum_union |
Macros | |
| #define | x_0(X) x_firstobj(X) |
| #define | x_1(X) x_restobj(X) |
| #define | x_00(X) x_0(x_0(X)) |
| #define | x_01(X) x_0(x_1(X)) |
| #define | x_10(X) x_1(x_0(X)) |
| #define | x_11(X) x_1(x_1(X)) |
| #define | x_000(X) x_0(x_00(X)) |
| #define | x_001(X) x_0(x_01(X)) |
| #define | x_010(X) x_0(x_10(X)) |
| #define | x_011(X) x_0(x_11(X)) |
| #define | x_100(X) x_1(x_00(X)) |
| #define | x_101(X) x_1(x_01(X)) |
| #define | x_110(X) x_1(x_10(X)) |
| #define | x_111(X) x_1(x_11(X)) |
| #define | x_0000(X) x_0(x_000(X)) |
| #define | x_0001(X) x_0(x_001(X)) |
| #define | x_0010(X) x_0(x_010(X)) |
| #define | x_0011(X) x_0(x_011(X)) |
| #define | x_0100(X) x_0(x_100(X)) |
| #define | x_0101(X) x_0(x_101(X)) |
| #define | x_0110(X) x_0(x_110(X)) |
| #define | x_0111(X) x_0(x_111(X)) |
| #define | x_1000(X) x_1(x_000(X)) |
| #define | x_1001(X) x_1(x_001(X)) |
| #define | x_1010(X) x_1(x_010(X)) |
| #define | x_1011(X) x_1(x_011(X)) |
| #define | x_1100(X) x_1(x_100(X)) |
| #define | x_1101(X) x_1(x_101(X)) |
| #define | x_1110(X) x_1(x_110(X)) |
| #define | x_1111(X) x_1(x_111(X)) |
Type Names and Literal Text | |
All of these are plain C strings; x-expr has no interned-symbol type (that concept lives in the embedding layer), so nothing here is a "symbol". | |
| #define | X_TYPE_NIL_NAME "NIL" |
| #define | X_TYPE_ATOM_NAME "ATOM" |
| #define | X_TYPE_PAIR_NAME "PAIR" |
| #define | X_OBJ_TRUE_TEXT "#t" |
| #define | X_OBJ_FALSE_TEXT "#f" |
Metadata Accessors | |
Read or assign an object's metadata slots and locate its data. Each macro is an lvalue, so it may appear on either side of an assignment. | |
| #define | x_obj_type(X) ((X)[X_OBJ_META_TYPE].p) |
| #define | x_obj_flags(X) ((X)[X_OBJ_META_FLAGS].i) |
| #define | x_obj_data_ptr(X) ((X) + X_OBJ_META_LEN) |
| #define | x_obj_data_i(X, I) (x_obj_data_ptr((X))[(I)]) |
| #define | x_obj_data(X) x_obj_data_i((X), 0) |
| #define | x_obj_meta_i(X, I) ((X)[-((I) + 1)]) |
| #define | x_obj_set(T, F, ...) { { .p = (T) }, { .i = (F) }, __VA_ARGS__ } |
Type Predicates and Constructors | |
The | |
| #define | x_obj_type_isnil(B, X) x_obj_isnil((B), x_obj_type(X)) |
| #define | x_obj_is_type(B, X, T) (x_lib_strcmp(x_obj_type_name((B), (X)), (T)) == 0) |
| #define | x_obj_type_issatom(X) (x_obj_type((X)) == x_type_atom_obj) |
| #define | x_obj_type_isspair(X) (x_obj_type((X)) == x_type_pair_obj) |
| #define | x_mksatom(B, F, X) x_obj_make((B), x_type_atom_obj, (F), X_OBJ_LENGTH_ATOM, (X)) |
| #define | x_mksatomown(B, F, X) x_obj_make((B), x_type_atom_obj, (F) | X_OBJ_FLAG_OWN, X_OBJ_LENGTH_ATOM, (X)) |
| #define | x_mkspair(B, F, X, Y) x_obj_make((B), x_type_pair_obj, (F), X_OBJ_LENGTH_PAIR, (X), (Y)) |
Datum Member Accessors | |
Reinterpret a single datum through the chosen union member. Each is an lvalue selecting one member of an x_datum_union. | |
| #define | x_obj(X) ((X).p) |
| #define | x_fn(X) ((X).fn) |
| #define | x_int(X) ((X).i) |
| #define | x_char(X) ((X).c) |
| #define | x_str(X) ((X).s) |
| #define | x_ptr(X) ((X).v) |
Data Unit Accessors | |
Read an object's data units, optionally typed. The prefix selects the unit – | |
| #define | x_first(X) x_obj_data_i((X),0) |
| #define | x_second(X) x_obj_data_i((X),1) |
| #define | x_rest(X) x_second((X)) |
| #define | x_firstptr(X) x_ptr(x_first((X))) |
| #define | x_firstobj(X) x_obj(x_first((X))) |
| #define | x_firstint(X) x_int(x_first((X))) |
| #define | x_firstchar(X) x_char(x_first((X))) |
| #define | x_firststr(X) x_str(x_first((X))) |
| #define | x_firstfn(X) x_fn(x_first((X))) |
| #define | x_secondptr(X) x_ptr(x_rest((X))) |
| #define | x_secondobj(X) x_obj(x_rest((X))) |
| #define | x_secondint(X) x_int(x_rest((X))) |
| #define | x_secondchar(X) x_char(x_rest((X))) |
| #define | x_secondstr(X) x_str(x_rest((X))) |
| #define | x_secondfn(X) x_fn(x_rest((X))) |
| #define | x_atomptr(X) x_firstptr((X)) |
| #define | x_atomobj(X) x_firstobj((X)) |
| #define | x_atomint(X) x_firstint((X)) |
| #define | x_atomchar(X) x_firstchar((X)) |
| #define | x_atomstr(X) x_firststr((X)) |
| #define | x_atomfn(X) x_firstfn((X)) |
| #define | x_restptr(X) x_secondptr((X)) |
| #define | x_restobj(X) x_secondobj((X)) |
| #define | x_restint(X) x_secondint((X)) |
| #define | x_restchar(X) x_secondchar((X)) |
| #define | x_reststr(X) x_secondstr((X)) |
| #define | x_restfn(X) x_secondfn((X)) |
Debug Utilities | |
Formatted debug output and object dumping (compiled only with DEBUG). | |
| #define | x_obj_debug_va(p_base, fmt, ap) ; |
| #define | x_obj_debug(p_base, fmt, ...) ; |
| #define | x_obj_dump(p_base, p_obj, msg) ; |
Typedefs | |
| typedef enum x_obj_flag_enum | x_obj_flag_t |
| typedef union x_datum_union | x_obj_t |
| typedef x_obj_t *(* | x_fn_t) (x_obj_t *p_base, x_obj_t *p_args) |
Enumerations | |
| enum | x_obj_flag_enum { X_OBJ_FLAG_NONE =0x0 , X_OBJ_FLAG_OBJ =0x0 , X_OBJ_FLAG_1 =0x1 , X_OBJ_FLAG_2 =0x2 , X_OBJ_FLAG_3 =0x4 , X_OBJ_FLAG_4 =0x8 , X_OBJ_FLAG_ATTR_MASK =0xF , X_OBJ_FLAG_SIMPLE_TYPE =0x10 , X_OBJ_FLAG_PRIM =0x10 , X_OBJ_FLAG_FN , X_OBJ_FLAG_INT , X_OBJ_FLAG_CHAR , X_OBJ_FLAG_STR , X_OBJ_FLAG_PTR , X_OBJ_FLAG_TYPE_MASK =0xF0 , X_OBJ_FLAG_OWN =0x20 , X_OBJ_FLAG_RO =0x40 , X_OBJ_FLAG_META =0x80 , X_OBJ_FLAG_MASK =0xFF } |
Functions | |
Object Functions | |
| |
| int | x_obj_isnil (x_obj_t *p_base, x_obj_t *p_obj) |
| x_obj_t * | x_obj_alloc (x_obj_t *p_base, x_obj_t *p_type, x_obj_flag_t flags, size_t units) |
| x_obj_t * | x_obj_make_va (x_obj_t *p_base, x_obj_t *p_type, x_obj_flag_t flags, size_t units, va_list ap) |
| x_obj_t * | x_obj_make (x_obj_t *p_base, x_obj_t *p_type, x_obj_flag_t flags, size_t units,...) |
| void | x_obj_free (x_obj_t *p_base, x_obj_t *p_obj) |
| x_obj_t * | x_obj_prim_type_name (x_obj_t *p_base, x_obj_t *p_args) |
| x_char_t * | x_obj_type_name (x_obj_t *p_base, x_obj_t *p_obj) |
| x_obj_t * | x_atom_prim_units (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_pair_prim_units (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_obj_prim_units (x_obj_t *p_base, x_obj_t *p_args) |
| x_int_t | x_obj_units (x_obj_t *p_base, x_obj_t *p_obj) |
| x_obj_t * | x_atom_prim_length (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_pair_prim_length (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_obj_prim_length (x_obj_t *p_base, x_obj_t *p_args) |
| x_int_t | x_obj_length (x_obj_t *p_base, x_obj_t *p_obj) |
| x_obj_t * | x_obj_push_field (x_obj_t *p_base, x_obj_t **p_field, x_obj_t *p_value, x_obj_flag_t flags) |
| x_obj_t * | x_obj_pop_field (x_obj_t *p_base, x_obj_t **p_field) |
| x_obj_t * | x_obj_push (x_obj_t *p_base, x_obj_t *p_args) |
| x_obj_t * | x_obj_pop (x_obj_t *p_base, x_obj_t *p_args) |
| void | x_obj_error (x_obj_t *p_base, x_char_t *message, x_obj_t *p_obj) |
Object Layout | |
Metadata sizing and the offsets of an object's data units. | |
| #define | X_OBJ_UNITS_HEAP 0 |
| #define | X_OBJ_UNITS_TYPE 1 |
| #define | X_OBJ_UNITS_FLAGS 1 |
| #define | X_OBJ_UNITS_META X_OBJ_META_LEN |
| #define | X_OBJ_UNITS_ATOM 1 |
| #define | X_OBJ_UNITS_PAIR 2 |
| #define | X_OBJ_LENGTH_ATOM X_OBJ_UNITS_ATOM |
| #define | X_OBJ_LENGTH_PAIR X_OBJ_UNITS_PAIR |
| enum | { X_OBJ_META_TYPE = X_OBJ_UNITS_HEAP , X_OBJ_META_FLAGS = (X_OBJ_UNITS_HEAP + X_OBJ_UNITS_TYPE) , X_OBJ_META_LEN = (X_OBJ_UNITS_HEAP + X_OBJ_UNITS_TYPE + X_OBJ_UNITS_FLAGS) } |
| typedef x_obj_t | x_satom_t[X_OBJ_META_LEN+X_OBJ_UNITS_ATOM] |
| typedef x_obj_t | x_spair_t[X_OBJ_META_LEN+X_OBJ_UNITS_PAIR] |
| x_satom_t | x_type_atom_obj |
| x_satom_t | x_type_pair_obj |
| x_satom_t | x_type_units_atom_obj |
| x_satom_t | x_type_units_pair_obj |
| x_satom_t | x_type_length_atom_obj |
| x_satom_t | x_type_length_pair_obj |
| x_satom_t | x_true_obj |
| x_satom_t | x_false_obj |
The x-expr object system – atoms, pairs, flags, and type dispatch.
Defines the universal object representation used throughout x-expr along with the macros and functions for creating, inspecting, and traversing objects.
Every value is an object: a contiguous array of x_obj_t units (a tagged-union datum, see x_datum_union) laid out as a small metadata header followed by one or more data units. A pointer to an object addresses the start of its metadata; the data units begin at offset X_OBJ_META_LEN, reached via the accessor macros x_obj_type(), x_obj_flags() and x_obj_data_ptr().
There are two fundamental shapes:
nil is represented by a NULL object pointer (see x_obj_isnil()).
When the base configures extra metadata units (see x_base_field_obj_meta_extra()), x_obj_alloc() prepends them before the standard header and advances the object pointer past them, so the layout above still holds; the extras sit at negative offsets reached via x_obj_meta_i() and the object is flagged X_OBJ_FLAG_META.
Type system. An object carries type information two ways:
Primitive vs. wrapper functions. Type-introspection operations come in two forms. The x_*_prim_* functions follow the x_fn_t calling convention – (p_base, p_args) where p_args is a pair whose first element is the subject object – so they can be stored and dispatched as callables (e.g. installed as base hooks). The matching non-prim wrappers (x_obj_type_name(), x_obj_units(), x_obj_length()) take a plain object pointer, build the argument pair, invoke the primitive, and unwrap the result for C callers.
cons/car/cdr aliases over these pair operations. ., .,
{O,O}
( )
" "
| #define x_atomchar | ( | X | ) | x_firstchar((X)) |
Atom value as a character.
| #define x_atomfn | ( | X | ) | x_firstfn((X)) |
Atom value as a function.
| #define x_atomint | ( | X | ) | x_firstint((X)) |
Atom value as an integer.
| #define x_atomobj | ( | X | ) | x_firstobj((X)) |
Atom value as an object.
| #define x_atomptr | ( | X | ) | x_firstptr((X)) |
Atom value as a pointer.
| #define x_atomstr | ( | X | ) | x_firststr((X)) |
Atom value as a string.
| #define x_char | ( | X | ) | ((X).c) |
Datum as a character.
| #define x_first | ( | X | ) | x_obj_data_i((X),0) |
Data unit 0 (raw datum, lvalue).
| #define x_fn | ( | X | ) | ((X).fn) |
Datum as a function pointer.
| #define x_int | ( | X | ) | ((X).i) |
Datum as an integer.
| #define x_mksatom | ( | B, | |
| F, | |||
| X | |||
| ) | x_obj_make((B), x_type_atom_obj, (F), X_OBJ_LENGTH_ATOM, (X)) |
Heap-allocate an atom of the built-in atom type with flags F holding datum X.
| #define x_mksatomown | ( | B, | |
| F, | |||
| X | |||
| ) | x_obj_make((B), x_type_atom_obj, (F) | X_OBJ_FLAG_OWN, X_OBJ_LENGTH_ATOM, (X)) |
Heap-allocate an atom of the built-in atom type that owns its datum X (adds X_OBJ_FLAG_OWN).
| #define x_mkspair | ( | B, | |
| F, | |||
| X, | |||
| Y | |||
| ) | x_obj_make((B), x_type_pair_obj, (F), X_OBJ_LENGTH_PAIR, (X), (Y)) |
Heap-allocate a pair of the built-in pair type with flags F holding first X and rest Y.
| #define x_obj | ( | X | ) | ((X).p) |
Datum as an object pointer.
| #define x_obj_data | ( | X | ) | x_obj_data_i((X), 0) |
The first data unit of object X.
| #define x_obj_data_i | ( | X, | |
| I | |||
| ) | (x_obj_data_ptr((X))[(I)]) |
The data unit at index I of object X.
| #define x_obj_data_ptr | ( | X | ) | ((X) + X_OBJ_META_LEN) |
Pointer to the first data unit of object X.
| #define x_obj_debug | ( | p_base, | |
| fmt, | |||
| ... | |||
| ) | ; |
| #define x_obj_debug_va | ( | p_base, | |
| fmt, | |||
| ap | |||
| ) | ; |
| #define x_obj_dump | ( | p_base, | |
| p_obj, | |||
| msg | |||
| ) | ; |
| #define X_OBJ_FALSE_TEXT "#f" |
Literal text of the canonical false atom (x_false_obj).
| #define x_obj_flags | ( | X | ) | ((X)[X_OBJ_META_FLAGS].i) |
The object's flags slot (an x_obj_flag_t bitfield held as an integer).
| #define x_obj_is_type | ( | B, | |
| X, | |||
| T | |||
| ) | (x_lib_strcmp(x_obj_type_name((B), (X)), (T)) == 0) |
True if the type name of object X equals the C string T.
| #define X_OBJ_LENGTH_ATOM X_OBJ_UNITS_ATOM |
Logical length of an atom.
| #define X_OBJ_LENGTH_PAIR X_OBJ_UNITS_PAIR |
Logical length of a pair.
| #define x_obj_meta_i | ( | X, | |
| I | |||
| ) | ((X)[-((I) + 1)]) |
The extra metadata unit at index I (negative offset before X).
| #define x_obj_set | ( | T, | |
| F, | |||
| ... | |||
| ) | { { .p = (T) }, { .i = (F) }, __VA_ARGS__ } |
Brace initializer for a static object: type T, flags F, then data.
| #define X_OBJ_TRUE_TEXT "#t" |
Literal text of the canonical true atom (x_true_obj).
| #define x_obj_type | ( | X | ) | ((X)[X_OBJ_META_TYPE].p) |
The object's type slot: a pointer to its type object, or NULL (nil).
| #define x_obj_type_isnil | ( | B, | |
| X | |||
| ) | x_obj_isnil((B), x_obj_type(X)) |
True if object X has a nil (NULL) type slot.
| #define x_obj_type_issatom | ( | X | ) | (x_obj_type((X)) == x_type_atom_obj) |
True if X is typed as the built-in atom type (by pointer identity).
| #define x_obj_type_isspair | ( | X | ) | (x_obj_type((X)) == x_type_pair_obj) |
True if X is typed as the built-in pair type (by pointer identity).
| #define X_OBJ_UNITS_ATOM 1 |
Number of data units in an atom.
| #define X_OBJ_UNITS_FLAGS 1 |
Metadata units consumed by the flags slot.
| #define X_OBJ_UNITS_HEAP 0 |
Metadata units consumed by the heap-chain link (1 when X_HEAP, else 0).
| #define X_OBJ_UNITS_META X_OBJ_META_LEN |
Total number of standard metadata units preceding an object's data.
| #define X_OBJ_UNITS_PAIR 2 |
Number of data units in a pair.
| #define X_OBJ_UNITS_TYPE 1 |
Metadata units consumed by the type slot.
| #define x_ptr | ( | X | ) | ((X).v) |
Datum as an opaque pointer.
| #define x_rest | ( | X | ) | x_second((X)) |
Alias for x_second(): data unit 1.
| #define x_restchar | ( | X | ) | x_secondchar((X)) |
Rest value as a character.
| #define x_restfn | ( | X | ) | x_secondfn((X)) |
Rest value as a function.
| #define x_restint | ( | X | ) | x_secondint((X)) |
Rest value as an integer.
| #define x_restobj | ( | X | ) | x_secondobj((X)) |
Rest value as an object.
| #define x_restptr | ( | X | ) | x_secondptr((X)) |
Rest value as a pointer.
| #define x_reststr | ( | X | ) | x_secondstr((X)) |
Rest value as a string.
| #define x_second | ( | X | ) | x_obj_data_i((X),1) |
Data unit 1 (raw datum, lvalue).
| #define x_str | ( | X | ) | ((X).s) |
Datum as a string.
| #define X_TYPE_ATOM_NAME "ATOM" |
Type-name string for the built-in atom type (x_type_atom_obj).
| #define X_TYPE_NIL_NAME "NIL" |
Type-name string returned for nil (untyped) objects.
| #define X_TYPE_PAIR_NAME "PAIR" |
Type-name string for the built-in pair type (x_type_pair_obj).
Calling convention for x-expr primitive functions.
| p_base | Base (execution context). |
| p_args | A pair list of arguments (nil when there are none). |
| typedef enum x_obj_flag_enum x_obj_flag_t |
Object flags – a bitfield stored in each object's flags metadata slot.
The low nibble (X_OBJ_FLAG_ATTR_MASK) holds general-purpose attribute bits. The high nibble (X_OBJ_FLAG_TYPE_MASK) encodes an optional "simple type" tag. The remaining bits are storage- and GC-related.
| typedef union x_datum_union x_obj_t |
A single object datum and the unit type from which objects are built.
| typedef x_obj_t x_satom_t[X_OBJ_META_LEN+X_OBJ_UNITS_ATOM] |
Fixed-size storage for a statically allocated atom (metadata + 1 unit).
s prefix carries two senses in this header. Here (and in x_spair_t) it is storage: room for an object in static or stack storage instead of the heap. In x_obj_type_issatom() / x_obj_type_isspair() and in the x_mksatom() / x_mkspair() constructor family it is the built-in static type (x_type_atom_obj / x_type_pair_obj) – a property of the type slot, independent of where the object lives. | typedef x_obj_t x_spair_t[X_OBJ_META_LEN+X_OBJ_UNITS_PAIR] |
Fixed-size storage for a statically allocated pair (metadata + 2 units; see the s-prefix note at x_satom_t).
| anonymous enum |
| enum x_obj_flag_enum |
Object flags – a bitfield stored in each object's flags metadata slot.
The low nibble (X_OBJ_FLAG_ATTR_MASK) holds general-purpose attribute bits. The high nibble (X_OBJ_FLAG_TYPE_MASK) encodes an optional "simple type" tag. The remaining bits are storage- and GC-related.
| Enumerator | |
|---|---|
| X_OBJ_FLAG_NONE | No flags set. |
| X_OBJ_FLAG_OBJ | Full object typed via the type pointer; the default kind. |
| X_OBJ_FLAG_1 | General-purpose attribute bit 1 (application defined). |
| X_OBJ_FLAG_2 | General-purpose attribute bit 2 (application defined). |
| X_OBJ_FLAG_3 | General-purpose attribute bit 3 (application defined). |
| X_OBJ_FLAG_4 | General-purpose attribute bit 4 (application defined). |
| X_OBJ_FLAG_ATTR_MASK | Mask selecting the four attribute bits. |
| X_OBJ_FLAG_SIMPLE_TYPE | Base value of the simple-type enumeration. |
| X_OBJ_FLAG_PRIM | Simple type: primitive / special form. |
| X_OBJ_FLAG_FN | Simple type: function pointer (x_fn_t). |
| X_OBJ_FLAG_INT | Simple type: integer (x_int_t). |
| X_OBJ_FLAG_CHAR | Simple type: character (x_char_t). |
| X_OBJ_FLAG_STR | Simple type: string (x_char_t *). |
| X_OBJ_FLAG_PTR | Simple type: opaque pointer (void *). |
| X_OBJ_FLAG_TYPE_MASK | Mask selecting the simple-type nibble. |
| X_OBJ_FLAG_OWN | Object owns the allocation in its first datum; x_obj_free() releases it. |
| X_OBJ_FLAG_RO | Read-only attribute (advisory; not enforced by the core). |
| X_OBJ_FLAG_META | Object has extra metadata units prepended (see x_obj_meta_i()). |
| X_OBJ_FLAG_MASK | Mask of all defined flag bits. |
Primitive: logical length of an atom (x_fn_t convention).
Primitive: the logical length of an atom.
| p_base | Base (execution context; unused). |
| p_args | Argument pair (unused). |
Primitive: data-unit count of an atom (x_fn_t convention).
Primitive: the data-unit count of an atom.
| p_base | Base (execution context; unused). |
| p_args | Argument pair (unused). |
| x_obj_t * x_obj_alloc | ( | x_obj_t * | p_base, |
| x_obj_t * | p_type, | ||
| x_obj_flag_t | flags, | ||
| size_t | units | ||
| ) |
Allocate an uninitialized object with units data units.
Allocate an uninitialized object.
Allocates space for units data units plus the standard metadata header. When the base configures extra metadata units (see x_base_field_obj_meta_extra()), that many leading units are also reserved; the returned pointer is advanced past them and X_OBJ_FLAG_META is set so x_obj_free() can recover the original allocation. When X_HEAP is enabled the object is linked onto the base's heap chain (and, under X_PROFILE, the allocation counter is incremented). The type and flags slots are set; the data units are left uninitialized.
| p_base | Base (execution context), or NULL to allocate without a base. |
| p_type | The type object to assign, or NULL. |
| flags | Initial object flags. |
| units | Number of data units to allocate. |
Output an error message to stderr.
Output an error message to stderr.
If the error hook is set in the base, delegates to it via a cast to void (*)(x_obj_t *, x_char_t *, x_obj_t *) – this differs from x_fn_t because error handlers take raw arguments (not a pair list). Otherwise, extracts the object's string text (if it is a static atom) and calls x_error().
| p_base | Base (execution context). |
| message | Error message string. |
| p_obj | Related object for context, or NULL. |
Free an object, releasing any owned datum and extra metadata units.
Free an object and any resources it owns.
If the object has X_OBJ_FLAG_OWN set, the allocation referenced by its first datum is freed first. When X_HEAP is enabled and X_OBJ_FLAG_META is set, the original allocation address is recovered by stepping back over the extra metadata units before freeing. This does not unlink the object from the heap chain – x_heap_sweep() relinks the chain around freed objects.
| p_base | Base (execution context; used to size extra metadata units). |
| p_obj | The object to free. |
Test whether p_obj is nil (a NULL object pointer).
Test whether an object is nil.
nil is represented by a NULL object pointer. p_base is accepted for calling-convention uniformity but is not used.
| p_base | Base (execution context; unused). |
| p_obj | The object to test. |
p_obj is nil (NULL), zero otherwise. Get an object's logical length as an integer.
Get an object's logical length as an integer.
Builds the argument pair, calls x_obj_prim_length(), and unwraps the result.
| p_base | Base (execution context). |
| p_obj | The object to inspect. |
| x_obj_t * x_obj_make | ( | x_obj_t * | p_base, |
| x_obj_t * | p_type, | ||
| x_obj_flag_t | flags, | ||
| size_t | units, | ||
| ... | |||
| ) |
Allocate an object and initialize its data units from varargs.
Allocate an object and initialize its data units from varargs.
Variadic wrapper around x_obj_make_va(); the x_mksatom() and x_mkspair() macros build on it.
| p_base | Base (execution context), or NULL. |
| p_type | The type object to assign, or NULL. |
| flags | Initial object flags. |
| units | Number of data units, followed by that many x_obj_t * args. |
| x_obj_t * x_obj_make_va | ( | x_obj_t * | p_base, |
| x_obj_t * | p_type, | ||
| x_obj_flag_t | flags, | ||
| size_t | units, | ||
| va_list | ap | ||
| ) |
Allocate an object and initialize its data units from a va_list.
Allocate an object and initialize its data units from a va_list.
Calls x_obj_alloc(), then assigns units consecutive data units from ap (each consumed as an x_obj_t *).
| p_base | Base (execution context), or NULL. |
| p_type | The type object to assign, or NULL. |
| flags | Initial object flags. |
| units | Number of data units to allocate and initialize. |
| ap | Variable argument list supplying the data units. |
Callable wrapper for x_obj_pop_field() (x_fn_t convention).
Callable wrapper for x_obj_pop_field().
Follows the x_fn_t convention. p_args is (field-ptr) where field-ptr is an atom wrapping the x_obj_t ** field address.
| p_base | Base (execution context). |
| p_args | Argument pair whose first element wraps the field address. |
Pop and return the head value of the pair-list stack at *p_field.
Pop the head value from a pair-list stack.
Returns the current head (x_firstobj(*p_field)) and advances *p_field to its rest. The popped pair is not freed; under X_HEAP the collector reclaims it.
| p_base | Base (execution context; unused). |
| p_field | Address of the field to pop from (updated in place). |
Primitive: dispatch an object's logical length by type (x_fn_t convention).
Primitive: dispatch an object's logical length by type.
Returns x_pair_prim_length() for pairs and x_atom_prim_length() for atoms or nil-typed objects; for other types the base's length hook (x_base_field_hook_length()) is consulted.
| p_base | Base (execution context). |
| p_args | Pair list whose first element is the subject object. |
Primitive: resolve an object's type object (x_fn_t convention).
Primitive: resolve an object's type object.
Follows the x_fn_t convention: p_args is a pair whose first element is the object to inspect. Built-in atoms and pairs, and any object with a nil type slot, return their type slot directly; for other types the base's type-name hook (x_base_field_hook_type_name()) is consulted.
| p_base | Base (execution context). |
| p_args | Pair list whose first element is the subject object. |
Primitive: dispatch an object's data-unit count by type (x_fn_t convention).
Primitive: dispatch an object's data-unit count by type.
Returns x_pair_prim_units() for pairs and x_atom_prim_units() for atoms or nil-typed objects; for other types the base's units hook (x_base_field_hook_units()) is consulted.
| p_base | Base (execution context). |
| p_args | Pair list whose first element is the subject object. |
Callable wrapper for x_obj_push_field() (x_fn_t convention).
Callable wrapper for x_obj_push_field().
Follows the x_fn_t convention. p_args is (field-ptr value [flags]) where field-ptr is an atom wrapping the x_obj_t ** field address, value is the object to push, and the optional third element is an integer atom of flags (default X_OBJ_FLAG_NONE).
| p_base | Base (execution context). |
| p_args | Argument pair list as described above. |
| x_obj_t * x_obj_push_field | ( | x_obj_t * | p_base, |
| x_obj_t ** | p_field, | ||
| x_obj_t * | p_value, | ||
| x_obj_flag_t | flags | ||
| ) |
Push p_value onto the pair-list stack rooted at *p_field.
Push a value onto a pair-list stack.
Replaces *p_field with a new pair (p_value . old), so the field becomes a stack whose head is p_value. Used to save and restore base fields and to grow the heap hook/root lists.
| p_base | Base (execution context) for allocation. |
| p_field | Address of the field to push onto (updated in place). |
| p_value | The value to push. |
| flags | Flags for the new pair. |
p_value). Get an object's type name as a C string (X_TYPE_NIL_NAME if nil).
Get an object's type name as a C string.
Builds the argument pair, calls x_obj_prim_type_name(), and unwraps the resulting type object's string value.
| p_base | Base (execution context). |
| p_obj | The object to inspect. |
Get an object's data-unit count as an integer.
Get an object's data-unit count as an integer.
Builds the argument pair, calls x_obj_prim_units(), and unwraps the result.
| p_base | Base (execution context). |
| p_obj | The object to inspect. |
Primitive: logical length of a pair (x_fn_t convention).
Primitive: the logical length of a pair.
| p_base | Base (execution context; unused). |
| p_args | Argument pair (unused). |
Primitive: data-unit count of a pair (x_fn_t convention).
Primitive: the data-unit count of a pair.
| p_base | Base (execution context; unused). |
| p_args | Argument pair (unused). |
|
extern |
Canonical false atom (value X_OBJ_FALSE_TEXT).
|
extern |
Canonical true atom (value X_OBJ_TRUE_TEXT).
|
extern |
Built-in static atom type; its value is the "ATOM" type-name string.
|
extern |
Static atom holding the atom length, returned by x_atom_prim_length().
|
extern |
Static atom holding the pair length, returned by x_pair_prim_length().
|
extern |
Built-in static pair type; its value is the "PAIR" type-name string.
|
extern |
Static atom holding the atom data-unit count, returned by x_atom_prim_units().
|
extern |
Static atom holding the pair data-unit count, returned by x_pair_prim_units().