diff options
Diffstat (limited to 'doc/ref/data-rep.texi')
-rw-r--r-- | doc/ref/data-rep.texi | 663 |
1 files changed, 663 insertions, 0 deletions
diff --git a/doc/ref/data-rep.texi b/doc/ref/data-rep.texi new file mode 100644 index 000000000..23a1bb4bf --- /dev/null +++ b/doc/ref/data-rep.texi @@ -0,0 +1,663 @@ +@c -*-texinfo-*- +@c This is part of the GNU Guile Reference Manual. +@c Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2010, 2015, 2018 +@c Free Software Foundation, Inc. +@c See the file guile.texi for copying conditions. + +@node Data Representation +@section Data Representation + +Scheme is a latently-typed language; this means that the system cannot, +in general, determine the type of a given expression at compile time. +Types only become apparent at run time. Variables do not have fixed +types; a variable may hold a pair at one point, an integer at the next, +and a thousand-element vector later. Instead, values, not variables, +have fixed types. + +In order to implement standard Scheme functions like @code{pair?} and +@code{string?} and provide garbage collection, the representation of +every value must contain enough information to accurately determine its +type at run time. Often, Scheme systems also use this information to +determine whether a program has attempted to apply an operation to an +inappropriately typed value (such as taking the @code{car} of a string). + +Because variables, pairs, and vectors may hold values of any type, +Scheme implementations use a uniform representation for values --- a +single type large enough to hold either a complete value or a pointer +to a complete value, along with the necessary typing information. + +The following sections will present a simple typing system, and then +make some refinements to correct its major weaknesses. We then conclude +with a discussion of specific choices that Guile has made regarding +garbage collection and data representation. + +@menu +* A Simple Representation:: +* Faster Integers:: +* Cheaper Pairs:: +* Conservative GC:: +* The SCM Type in Guile:: +@end menu + +@node A Simple Representation +@subsection A Simple Representation + +The simplest way to represent Scheme values in C would be to represent +each value as a pointer to a structure containing a type indicator, +followed by a union carrying the real value. Assuming that @code{SCM} is +the name of our universal type, we can write: + +@example +enum type @{ integer, pair, string, vector, ... @}; + +typedef struct value *SCM; + +struct value @{ + enum type type; + union @{ + int integer; + struct @{ SCM car, cdr; @} pair; + struct @{ int length; char *elts; @} string; + struct @{ int length; SCM *elts; @} vector; + ... + @} value; +@}; +@end example +with the ellipses replaced with code for the remaining Scheme types. + +This representation is sufficient to implement all of Scheme's +semantics. If @var{x} is an @code{SCM} value: +@itemize @bullet +@item + To test if @var{x} is an integer, we can write @code{@var{x}->type == integer}. +@item + To find its value, we can write @code{@var{x}->value.integer}. +@item + To test if @var{x} is a vector, we can write @code{@var{x}->type == vector}. +@item + If we know @var{x} is a vector, we can write + @code{@var{x}->value.vector.elts[0]} to refer to its first element. +@item + If we know @var{x} is a pair, we can write + @code{@var{x}->value.pair.car} to extract its car. +@end itemize + + +@node Faster Integers +@subsection Faster Integers + +Unfortunately, the above representation has a serious disadvantage. In +order to return an integer, an expression must allocate a @code{struct +value}, initialize it to represent that integer, and return a pointer to +it. Furthermore, fetching an integer's value requires a memory +reference, which is much slower than a register reference on most +processors. Since integers are extremely common, this representation is +too costly, in both time and space. Integers should be very cheap to +create and manipulate. + +One possible solution comes from the observation that, on many +architectures, heap-allocated data (i.e., what you get when you call +@code{malloc}) must be aligned on an eight-byte boundary. (Whether or +not the machine actually requires it, we can write our own allocator for +@code{struct value} objects that assures this is true.) In this case, +the lower three bits of the structure's address are known to be zero. + +This gives us the room we need to provide an improved representation +for integers. We make the following rules: +@itemize @bullet +@item +If the lower three bits of an @code{SCM} value are zero, then the SCM +value is a pointer to a @code{struct value}, and everything proceeds as +before. +@item +Otherwise, the @code{SCM} value represents an integer, whose value +appears in its upper bits. +@end itemize + +Here is C code implementing this convention: +@example +enum type @{ pair, string, vector, ... @}; + +typedef struct value *SCM; + +struct value @{ + enum type type; + union @{ + struct @{ SCM car, cdr; @} pair; + struct @{ int length; char *elts; @} string; + struct @{ int length; SCM *elts; @} vector; + ... + @} value; +@}; + +#define POINTER_P(x) (((int) (x) & 7) == 0) +#define INTEGER_P(x) (! POINTER_P (x)) + +#define GET_INTEGER(x) ((int) (x) >> 3) +#define MAKE_INTEGER(x) ((SCM) (((x) << 3) | 1)) +@end example + +Notice that @code{integer} no longer appears as an element of @code{enum +type}, and the union has lost its @code{integer} member. Instead, we +use the @code{POINTER_P} and @code{INTEGER_P} macros to make a coarse +classification of values into integers and non-integers, and do further +type testing as before. + +Here's how we would answer the questions posed above (again, assume +@var{x} is an @code{SCM} value): +@itemize @bullet +@item + To test if @var{x} is an integer, we can write @code{INTEGER_P (@var{x})}. +@item + To find its value, we can write @code{GET_INTEGER (@var{x})}. +@item + To test if @var{x} is a vector, we can write: +@example + @code{POINTER_P (@var{x}) && @var{x}->type == vector} +@end example + Given the new representation, we must make sure @var{x} is truly a + pointer before we dereference it to determine its complete type. +@item + If we know @var{x} is a vector, we can write + @code{@var{x}->value.vector.elts[0]} to refer to its first element, as + before. +@item + If we know @var{x} is a pair, we can write + @code{@var{x}->value.pair.car} to extract its car, just as before. +@end itemize + +This representation allows us to operate more efficiently on integers +than the first. For example, if @var{x} and @var{y} are known to be +integers, we can compute their sum as follows: +@example +MAKE_INTEGER (GET_INTEGER (@var{x}) + GET_INTEGER (@var{y})) +@end example +Now, integer math requires no allocation or memory references. Most real +Scheme systems actually implement addition and other operations using an +even more efficient algorithm, but this essay isn't about +bit-twiddling. (Hint: how do you decide when to overflow to a bignum? +How would you do it in assembly?) + + +@node Cheaper Pairs +@subsection Cheaper Pairs + +However, there is yet another issue to confront. Most Scheme heaps +contain more pairs than any other type of object; Jonathan Rees said at +one point that pairs occupy 45% of the heap in his Scheme +implementation, Scheme 48. However, our representation above spends +three @code{SCM}-sized words per pair --- one for the type, and two for +the @sc{car} and @sc{cdr}. Is there any way to represent pairs using +only two words? + +Let us refine the convention we established earlier. Let us assert +that: +@itemize @bullet +@item + If the bottom three bits of an @code{SCM} value are @code{#b000}, then + it is a pointer, as before. +@item + If the bottom three bits are @code{#b001}, then the upper bits are an + integer. This is a bit more restrictive than before. +@item + If the bottom two bits are @code{#b010}, then the value, with the bottom + three bits masked out, is the address of a pair. +@end itemize + +Here is the new C code: +@example +enum type @{ string, vector, ... @}; + +typedef struct value *SCM; + +struct value @{ + enum type type; + union @{ + struct @{ int length; char *elts; @} string; + struct @{ int length; SCM *elts; @} vector; + ... + @} value; +@}; + +struct pair @{ + SCM car, cdr; +@}; + +#define POINTER_P(x) (((int) (x) & 7) == 0) + +#define INTEGER_P(x) (((int) (x) & 7) == 1) +#define GET_INTEGER(x) ((int) (x) >> 3) +#define MAKE_INTEGER(x) ((SCM) (((x) << 3) | 1)) + +#define PAIR_P(x) (((int) (x) & 7) == 2) +#define GET_PAIR(x) ((struct pair *) ((int) (x) & ~7)) +@end example + +Notice that @code{enum type} and @code{struct value} now only contain +provisions for vectors and strings; both integers and pairs have become +special cases. The code above also assumes that an @code{int} is large +enough to hold a pointer, which isn't generally true. + + +Our list of examples is now as follows: +@itemize @bullet +@item + To test if @var{x} is an integer, we can write @code{INTEGER_P + (@var{x})}; this is as before. +@item + To find its value, we can write @code{GET_INTEGER (@var{x})}, as + before. +@item + To test if @var{x} is a vector, we can write: +@example + @code{POINTER_P (@var{x}) && @var{x}->type == vector} +@end example + We must still make sure that @var{x} is a pointer to a @code{struct + value} before dereferencing it to find its type. +@item + If we know @var{x} is a vector, we can write + @code{@var{x}->value.vector.elts[0]} to refer to its first element, as + before. +@item + We can write @code{PAIR_P (@var{x})} to determine if @var{x} is a + pair, and then write @code{GET_PAIR (@var{x})->car} to refer to its + car. +@end itemize + +This change in representation reduces our heap size by 15%. It also +makes it cheaper to decide if a value is a pair, because no memory +references are necessary; it suffices to check the bottom two bits of +the @code{SCM} value. This may be significant when traversing lists, a +common activity in a Scheme system. + +Again, most real Scheme systems use a slightly different implementation; +for example, if GET_PAIR subtracts off the low bits of @code{x}, instead +of masking them off, the optimizer will often be able to combine that +subtraction with the addition of the offset of the structure member we +are referencing, making a modified pointer as fast to use as an +unmodified pointer. + + +@node Conservative GC +@subsection Conservative Garbage Collection + +Aside from the latent typing, the major source of constraints on a +Scheme implementation's data representation is the garbage collector. +The collector must be able to traverse every live object in the heap, to +determine which objects are not live, and thus collectable. + +There are many ways to implement this. Guile's garbage collection is +built on a library, the Boehm-Demers-Weiser conservative garbage +collector (BDW-GC). The BDW-GC ``just works'', for the most part. But +since it is interesting to know how these things work, we include here a +high-level description of what the BDW-GC does. + +Garbage collection has two logical phases: a @dfn{mark} phase, in which +the set of live objects is enumerated, and a @dfn{sweep} phase, in which +objects not traversed in the mark phase are collected. Correct +functioning of the collector depends on being able to traverse the +entire set of live objects. + +In the mark phase, the collector scans the system's global variables and +the local variables on the stack to determine which objects are +immediately accessible by the C code. It then scans those objects to +find the objects they point to, and so on. The collector logically sets +a @dfn{mark bit} on each object it finds, so each object is traversed +only once. + +When the collector can find no unmarked objects pointed to by marked +objects, it assumes that any objects that are still unmarked will never +be used by the program (since there is no path of dereferences from any +global or local variable that reaches them) and deallocates them. + +In the above paragraphs, we did not specify how the garbage collector +finds the global and local variables; as usual, there are many different +approaches. Frequently, the programmer must maintain a list of pointers +to all global variables that refer to the heap, and another list +(adjusted upon entry to and exit from each function) of local variables, +for the collector's benefit. + +The list of global variables is usually not too difficult to maintain, +since global variables are relatively rare. However, an explicitly +maintained list of local variables (in the author's personal experience) +is a nightmare to maintain. Thus, the BDW-GC uses a technique called +@dfn{conservative garbage collection}, to make the local variable list +unnecessary. + +The trick to conservative collection is to treat the C stack as an +ordinary range of memory, and assume that @emph{every} word on the C +stack is a pointer into the heap. Thus, the collector marks all objects +whose addresses appear anywhere in the C stack, without knowing for sure +how that word is meant to be interpreted. + +In addition to the stack, the BDW-GC will also scan static data +sections. This means that global variables are also scanned when looking +for live Scheme objects. + +Obviously, such a system will occasionally retain objects that are +actually garbage, and should be freed. In practice, this is not a +problem, as the set of conservatively-scanned locations is fixed; the +Scheme stack is maintained apart from the C stack, and is scanned +precisely (as opposed to conservatively). The GC-managed heap is also +partitioned into parts that can contain pointers (such as vectors) and +parts that can't (such as bytevectors), limiting the potential for +confusing a raw integer with a pointer to a live object. + +Interested readers should see the BDW-GC web page at +@uref{http://www.hboehm.info/gc/}, for more information on conservative +GC in general and the BDW-GC implementation in particular. + +@node The SCM Type in Guile +@subsection The SCM Type in Guile + +Guile classifies Scheme objects into two kinds: those that fit entirely +within an @code{SCM}, and those that require heap storage. + +The former class are called @dfn{immediates}. The class of immediates +includes small integers, characters, boolean values, the empty list, the +mysterious end-of-file object, and some others. + +The remaining types are called, not surprisingly, @dfn{non-immediates}. +They include pairs, procedures, strings, vectors, and all other data +types in Guile. For non-immediates, the @code{SCM} word contains a +pointer to data on the heap, with further information about the object +in question is stored in that data. + +This section describes how the @code{SCM} type is actually represented +and used at the C level. Interested readers should see +@code{libguile/scm.h} for an exposition of how Guile stores type +information. + +In fact, there are two basic C data types to represent objects in +Guile: @code{SCM} and @code{scm_t_bits}. + +@menu +* Relationship Between SCM and scm_t_bits:: +* Immediate Objects:: +* Non-Immediate Objects:: +* Allocating Heap Objects:: +* Heap Object Type Information:: +* Accessing Heap Object Fields:: +@end menu + + +@node Relationship Between SCM and scm_t_bits +@subsubsection Relationship Between @code{SCM} and @code{scm_t_bits} + +A variable of type @code{SCM} is guaranteed to hold a valid Scheme +object. A variable of type @code{scm_t_bits}, on the other hand, may +hold a representation of a @code{SCM} value as a C integral type, but +may also hold any C value, even if it does not correspond to a valid +Scheme object. + +For a variable @var{x} of type @code{SCM}, the Scheme object's type +information is stored in a form that is not directly usable. To be able +to work on the type encoding of the scheme value, the @code{SCM} +variable has to be transformed into the corresponding representation as +a @code{scm_t_bits} variable @var{y} by using the @code{SCM_UNPACK} +macro. Once this has been done, the type of the scheme object @var{x} +can be derived from the content of the bits of the @code{scm_t_bits} +value @var{y}, in the way illustrated by the example earlier in this +chapter (@pxref{Cheaper Pairs}). Conversely, a valid bit encoding of a +Scheme value as a @code{scm_t_bits} variable can be transformed into the +corresponding @code{SCM} value using the @code{SCM_PACK} macro. + +@node Immediate Objects +@subsubsection Immediate Objects + +A Scheme object may either be an immediate, i.e.@: carrying all +necessary information by itself, or it may contain a reference to a +@dfn{heap object} which is, as the name implies, data on the heap. +Although in general it should be irrelevant for user code whether an +object is an immediate or not, within Guile's own code the distinction +is sometimes of importance. Thus, the following low level macro is +provided: + +@deftypefn Macro int SCM_IMP (SCM @var{x}) +A Scheme object is an immediate if it fulfills the @code{SCM_IMP} +predicate, otherwise it holds an encoded reference to a heap object. The +result of the predicate is delivered as a C style boolean value. User +code and code that extends Guile should normally not be required to use +this macro. +@end deftypefn + +@noindent +Summary: +@itemize @bullet +@item +Given a Scheme object @var{x} of unknown type, check first +with @code{SCM_IMP (@var{x})} if it is an immediate object. +@item +If so, all of the type and value information can be determined from the +@code{scm_t_bits} value that is delivered by @code{SCM_UNPACK +(@var{x})}. +@end itemize + +There are a number of special values in Scheme, most of them documented +elsewhere in this manual. It's not quite the right place to put them, +but for now, here's a list of the C names given to some of these values: + +@deftypefn Macro SCM SCM_EOL +The Scheme empty list object, or ``End Of List'' object, usually written +in Scheme as @code{'()}. +@end deftypefn + +@deftypefn Macro SCM SCM_EOF_VAL +The Scheme end-of-file value. It has no standard written +representation, for obvious reasons. +@end deftypefn + +@deftypefn Macro SCM SCM_UNSPECIFIED +The value returned by some (but not all) expressions that the Scheme +standard says return an ``unspecified'' value. + +This is sort of a weirdly literal way to take things, but the standard +read-eval-print loop prints nothing when the expression returns this +value, so it's not a bad idea to return this when you can't think of +anything else helpful. +@end deftypefn + +@deftypefn Macro SCM SCM_UNDEFINED +The ``undefined'' value. Its most important property is that is not +equal to any valid Scheme value. This is put to various internal uses +by C code interacting with Guile. + +For example, when you write a C function that is callable from Scheme +and which takes optional arguments, the interpreter passes +@code{SCM_UNDEFINED} for any arguments you did not receive. + +We also use this to mark unbound variables. +@end deftypefn + +@deftypefn Macro int SCM_UNBNDP (SCM @var{x}) +Return true if @var{x} is @code{SCM_UNDEFINED}. Note that this is not a +check to see if @var{x} is @code{SCM_UNBOUND}. History will not be kind +to us. +@end deftypefn + + +@node Non-Immediate Objects +@subsubsection Non-Immediate Objects + +A Scheme object of type @code{SCM} that does not fulfill the +@code{SCM_IMP} predicate holds an encoded reference to a heap object. +This reference can be decoded to a C pointer to a heap object using the +@code{SCM_UNPACK_POINTER} macro. The encoding of a pointer to a heap +object into a @code{SCM} value is done using the @code{SCM_PACK_POINTER} +macro. + +@cindex cells, deprecated concept +Before Guile 2.0, Guile had a custom garbage collector that allocated +heap objects in units of 2-word @dfn{cells}. With the move to the +BDW-GC collector in Guile 2.0, Guile can allocate heap objects of any +size, and the concept of a cell is now obsolete. Still, we mention +it here as the name still appears in various low-level interfaces. + +@deftypefn Macro {scm_t_bits *} SCM_UNPACK_POINTER (SCM @var{x}) +@deftypefnx Macro {scm_t_cell *} SCM2PTR (SCM @var{x}) +Extract and return the heap object pointer from a non-immediate +@code{SCM} object @var{x}. The name @code{SCM2PTR} is deprecated but +still common. +@end deftypefn + +@deftypefn Macro SCM_PACK_POINTER (scm_t_bits * @var{x}) +@deftypefnx Macro SCM PTR2SCM (scm_t_cell * @var{x}) +Return a @code{SCM} value that encodes a reference to the heap object +pointer @var{x}. The name @code{PTR2SCM} is deprecated but still +common. +@end deftypefn + +Note that it is also possible to transform a non-immediate @code{SCM} +value by using @code{SCM_UNPACK} into a @code{scm_t_bits} variable. +However, the result of @code{SCM_UNPACK} may not be used as a pointer to +a heap object: only @code{SCM_UNPACK_POINTER} is guaranteed to transform +a @code{SCM} object into a valid pointer to a heap object. Also, it is +not allowed to apply @code{SCM_PACK_POINTER} to anything that is not a +valid pointer to a heap object. + +@noindent +Summary: +@itemize @bullet +@item +Only use @code{SCM_UNPACK_POINTER} on @code{SCM} values for which +@code{SCM_IMP} is false! +@item +Don't use @code{(scm_t_cell *) SCM_UNPACK (@var{x})}! Use +@code{SCM_UNPACK_POINTER (@var{x})} instead! +@item +Don't use @code{SCM_PACK_POINTER} for anything but a heap object pointer! +@end itemize + +@node Allocating Heap Objects +@subsubsection Allocating Heap Objects + +Heap objects are heap-allocated data pointed to by non-immediate +@code{SCM} value. The first word of the heap object should contain a +type code. The object may be any number of words in length, and is +generally scanned by the garbage collector for additional unless the +object was allocated using a ``pointerless'' allocation function. + +You should generally not need these functions, unless you are +implementing a new data type, and thoroughly understand the code in +@code{<libguile/scm.h>}. + +If you just want to allocate pairs, use @code{scm_cons}. + +@deftypefn Function SCM scm_words (scm_t_bits word_0, uint32_t n_words) +Allocate a new heap object containing @var{n_words}, and initialize the +first slot to @var{word_0}, and return a non-immediate @code{SCM} value +encoding a pointer to the object. Typically @var{word_0} will contain +the type tag. +@end deftypefn + +There are also deprecated but common variants of @code{scm_words} that +use the term ``cell'' to indicate 2-word objects. + +@deftypefn Function SCM scm_cell (scm_t_bits word_0, scm_t_bits word_1) +Allocate a new 2-word heap object, initialize the two slots with +@var{word_0} and @var{word_1}, and return it. Just like calling +@code{scm_words (@var{word_0}, 2)}, then initializing the second slot to +@var{word_1}. + +Note that @var{word_0} and @var{word_1} are of type @code{scm_t_bits}. +If you want to pass a @code{SCM} object, you need to use +@code{SCM_UNPACK}. +@end deftypefn + +@deftypefn Function SCM scm_double_cell (scm_t_bits word_0, scm_t_bits word_1, scm_t_bits word_2, scm_t_bits word_3) +Like @code{scm_cell}, but allocates a 4-word heap object. +@end deftypefn + +@node Heap Object Type Information +@subsubsection Heap Object Type Information + +Heap objects contain a type tag and are followed by a number of +word-sized slots. The interpretation of the object contents depends on +the type of the object. + +@deftypefn Macro scm_t_bits SCM_CELL_TYPE (SCM @var{x}) +Extract the first word of the heap object pointed to by @var{x}. This +value holds the information about the cell type. +@end deftypefn + +@deftypefn Macro void SCM_SET_CELL_TYPE (SCM @var{x}, scm_t_bits @var{t}) +For a non-immediate Scheme object @var{x}, write the value @var{t} into +the first word of the heap object referenced by @var{x}. The value +@var{t} must hold a valid cell type. +@end deftypefn + + +@node Accessing Heap Object Fields +@subsubsection Accessing Heap Object Fields + +For a non-immediate Scheme object @var{x}, the object type can be +determined by using the @code{SCM_CELL_TYPE} macro described in the +previous section. For each different type of heap object it is known +which fields hold tagged Scheme objects and which fields hold untagged +raw data. To access the different fields appropriately, the following +macros are provided. + +@deftypefn Macro scm_t_bits SCM_CELL_WORD (SCM @var{x}, unsigned int @var{n}) +@deftypefnx Macro scm_t_bits SCM_CELL_WORD_0 (@var{x}) +@deftypefnx Macro scm_t_bits SCM_CELL_WORD_1 (@var{x}) +@deftypefnx Macro scm_t_bits SCM_CELL_WORD_2 (@var{x}) +@deftypefnx Macro scm_t_bits SCM_CELL_WORD_3 (@var{x}) +Deliver the field @var{n} of the heap object referenced by the +non-immediate Scheme object @var{x} as raw untagged data. Only use this +macro for fields containing untagged data; don't use it for fields +containing tagged @code{SCM} objects. +@end deftypefn + +@deftypefn Macro SCM SCM_CELL_OBJECT (SCM @var{x}, unsigned int @var{n}) +@deftypefnx Macro SCM SCM_CELL_OBJECT_0 (SCM @var{x}) +@deftypefnx Macro SCM SCM_CELL_OBJECT_1 (SCM @var{x}) +@deftypefnx Macro SCM SCM_CELL_OBJECT_2 (SCM @var{x}) +@deftypefnx Macro SCM SCM_CELL_OBJECT_3 (SCM @var{x}) +Deliver the field @var{n} of the heap object referenced by the +non-immediate Scheme object @var{x} as a Scheme object. Only use this +macro for fields containing tagged @code{SCM} objects; don't use it for +fields containing untagged data. +@end deftypefn + +@deftypefn Macro void SCM_SET_CELL_WORD (SCM @var{x}, unsigned int @var{n}, scm_t_bits @var{w}) +@deftypefnx Macro void SCM_SET_CELL_WORD_0 (@var{x}, @var{w}) +@deftypefnx Macro void SCM_SET_CELL_WORD_1 (@var{x}, @var{w}) +@deftypefnx Macro void SCM_SET_CELL_WORD_2 (@var{x}, @var{w}) +@deftypefnx Macro void SCM_SET_CELL_WORD_3 (@var{x}, @var{w}) +Write the raw value @var{w} into field number @var{n} of the heap object +referenced by the non-immediate Scheme value @var{x}. Values that are +written into heap objects as raw values should only be read later using +the @code{SCM_CELL_WORD} macros. +@end deftypefn + +@deftypefn Macro void SCM_SET_CELL_OBJECT (SCM @var{x}, unsigned int @var{n}, SCM @var{o}) +@deftypefnx Macro void SCM_SET_CELL_OBJECT_0 (SCM @var{x}, SCM @var{o}) +@deftypefnx Macro void SCM_SET_CELL_OBJECT_1 (SCM @var{x}, SCM @var{o}) +@deftypefnx Macro void SCM_SET_CELL_OBJECT_2 (SCM @var{x}, SCM @var{o}) +@deftypefnx Macro void SCM_SET_CELL_OBJECT_3 (SCM @var{x}, SCM @var{o}) +Write the Scheme object @var{o} into field number @var{n} of the heap +object referenced by the non-immediate Scheme value @var{x}. Values +that are written into heap objects as objects should only be read using +the @code{SCM_CELL_OBJECT} macros. +@end deftypefn + +@noindent +Summary: +@itemize @bullet +@item +For a non-immediate Scheme object @var{x} of unknown type, get the type +information by using @code{SCM_CELL_TYPE (@var{x})}. +@item +As soon as the type information is available, only use the appropriate +access methods to read and write data to the different heap object +fields. +@item +Note that field 0 stores the cell type information. Generally speaking, +other data associated with a heap object is stored starting from field +1. +@end itemize + + +@c Local Variables: +@c TeX-master: "guile.texi" +@c End: |