8.  The Anatomy of Scheme Objects  

      All Scheme objects, regarless of their Scheme type, are represented as instances of the type Object in C. Object is implemented as a small C struct in newer Elk releases and was an integral type earlier. However, code using Elk should not assume a specific representation, as it may change again in future revisions. An Object consists of three components:

      Elk defines a few macros to retrieve and modify the fields of an Object independent of its representation:

TYPE(obj)          ISCONST(obj)       SET(obj,t,ptr)
POINTER(obj)       SETCONST(obj)

      TYPE() returns the contents of the type field of an Object; POINTER() returns the contents of the pointer field as an unsigned long (different macros are provided for types which have their values stored directly in the Object rather than in the heap); ISCONST() returns the value of the const bit; and SETCONST() sets the const bit to 1 (it cannot be cleared once it has been set). ISCONST() and SETCONST() may only be applied to Objects that have their value stored on the heap (such as vectors, strings, etc.); all other types of Scheme objects are ipso facto read-only. Another macro, SET(), can be used to set both the type and pointer field of a new object.

      Two objects can be compared by means of the macro EQ(), which is also used as the basis for the Scheme predicate eq?:

EQ() expands to a non-zero value if the type fields and the pointer fields of the two objects are identical, else zero (regardless of whether the pointer field really holds a pointer or the object's actual value). As EQ() may evaluate its arguments twice, it should not be invoked with function calls or complex expressions.

8.1.  Type-specific Macros  

      For each predefined Scheme type, there exists a preprocessor symbol that expands to the integer value of that type (the contents of the type field of members of the type). The name of each such symbol is the name of the type with the prefix ``T_'':

T_Boolean     T_Pair     T_Vector     etc...
These symbols are typically used as case labels in switch-statements to discriminate the possible types of a given object, or in if-statements to check whether a Scheme object is of a given type:
if (TYPE(obj) == T_Vector)
In addition, each type defines a macro to extract the contents of an object of that type and to convert it to the correct C type. For example, the macro
is used to fetch the character value (a C int) from members of the Scheme type character, that is, from objects whose type field contains the value T_Character. Similarly, the macro
gets the heap pointer conveyed in objects of the Scheme type vector. For objects such as vectors, pairs, and procedures, the heap address is coerced to a pointer to a C struct defining the layout of the object. There exists one structure type declaration for each such Scheme type; their names are that of the type with ``S_'' prepended. For example, VECTOR() returns a pointer to a structure with the components size (the number of elements in the vector) and data (the elements as an array of Objects). These can be used from within C code like this:
int i, num = VECTOR(obj)->size;

for (i = 0; i < num; i++)
	VECTOR(obj)->data[i] = ...;
Similarly, the structure underlying the Scheme type pair is defined as:
struct S_Pair { Object car, cdr; };
and the macro PAIR() returns a (heap) pointer to a member of the structure S_Pair. Macros such as VECTOR() and PAIR() just convert the contents of the pointer field to a pointer of the correct type:
#define VECTOR(obj)   ((struct S_Vector *)POINTER(obj))
#define PAIR(obj)     ((struct S_Pair   *)POINTER(obj))

      Authors of Scheme extensions and Elk-based applications are encouraged to follow these conventions in their code and, for each new type xyz, store the new type value (which is allocated by the interpreter when the type is registered) in a variable T_Xyz, and define a structure or class S_Xyz, and a macro XYZ() that makes a pointer to this structure from a member of the type. Capitalization may vary according to personal preference.

Markup created by unroff 1.0,    September 24, 1996,    net@informatik.uni-bremen.de