If you want to extend, fix or simply customize ECL for your own needs, you should understand how the implementation works.
In ECL a lisp object is represented by a type called cl_object
. This
type is a word which is long enough to host both an integer and a pointer. The
least significant bits of this word, also called the tag bits, determine
whether it is a pointer to a C structure representing a complex object, or
whether it is an immediate data, such as a fixnum or a character.
|-------------------|--| | Fixnum value |01| |-------------------|--| |------------|------|--| | Unused bits| char |10| |------------|------|--| |----------------------| |--------|--------|-----|--------| | Pointer to cell |---->| word-1 | word-2 | ... | word-n | |----------------------| |--------|--------|-----|--------| | ...................00| | actual data of the object | |----------------------| |--------------------------------|
The fixnums and characters are called immediate datatypes, because they require
no more than the cl_object
datatype to store all information. All other
ECL objects are non-immediate and they are represented by a pointer to a
cell that is allocated on the heap. Each cell consists of several words of
memory and contains all the information related to that object. By storing data
in multiples of a word size, we make sure that the least significant bits of a
pointer are zero, which distinguishes pointers from immediate data.
In an immediate datatype, the tag bits determine the type of the object. In non-immediate datatypes, the first byte in the cell contains the secondary type indicator, and distinguishes between different types of non immediate data. The use of the remaining bytes differs for each type of object. For instance, a cons cell consists of three words:
|---------|----------| |CONS| | | |---------|----------| | car-pointer | |--------------------| | cdr-pointer | |--------------------|
There is one important function which tells the type of an object, plus several macros which group several tests.
C type: cl_objectThis is the type of a lisp object. For your C/C++ program, a
cl_object
can be either a fixnum, a character, or a pointer to a union of structures (See the headerobject.h
). The actual interpretation of that object can be guessed with the macroecl_t_of
.For example, if
x
is of typecl_object
, and it is of type fixnum, we may retrieve its valueif (ecl_t_of(x) == t_fixnum) printf("Integer value: %d\n", fix(x));If
x
is of typecl_object
and it does not contain an immediate datatype, you may inspect the cell associated to the lisp object usingx
as a pointer. For example,if (ecl_t_of(x) == t_cons) printf("CAR = %x, CDR = %x\n", x->cons.car, x->cons.cdr); else if (ecl_t_of(x) == t_string) printf("String: %s\n", x->string.self);You should see the following sections and the header
object.h
to learn how to use the different fields of acl_object
pointer.
C type: cl_typeEnumeration type which distinguishes the different types of lisp objects. The most important values are t_cons, t_fixnum, t_character, t_bignum, t_ratio, t_singlefloat, t_doublefloat, t_complex, t_symbol, t_package, t_hashtable, t_array, t_vector, t_string, t_bitvector, t_stream, t_random, t_readtable, t_pathname, t_bytecodes, t_cfun, t_cclosure, t_gfun, t_instance, t_foreign and t_thread.
Function: cl_typeecl_t_of
(cl_objectO
)If
O
is a valid lisp object,ecl_t_of(
returns an integer denoting the type that lisp object. That integer is one of the values of the enumeration typeO
)cl_type
.
Function: boolFIXNUMP
(cl_objecto
)Function: boolCHARACTERP
(cl_objecto
)Function: boolCONSP
(cl_objecto
)Function: boolLISTP
(cl_objecto
)Function: boolATOM
(cl_objecto
)Function: boolARRAYP
(cl_objecto
)Function: boolVECTORP
(cl_objecto
)Function: boolSTRINGP
(cl_objecto
)Different macros that check whether
o
belongs to the specified type. These checks have been optimized, and are preferred over several calls toecl_t_of
.