This is sizzle-embed.info, produced by makeinfo version 4.0 from
sizzle-embed.texi.

INFO-DIR-SECTION Sizzle Scheme Interpreter
START-INFO-DIR-ENTRY
* sizzle-embed: (sizzle-embed).     Embedding Sizzle
END-INFO-DIR-ENTRY

   This file documents embedding of the Sizzle Scheme interpreter.

   Copyright (C) 1999, 2000 Martin Grabmueller

   Permission is granted to make and distribute verbatim copies of this
manual provided the copyright notice and this permission notice are
preserved on all copies.


File: sizzle-embed.info,  Node: Accessor functions,  Next: Port Functions,  Prev: Type predicates,  Up: Embedding API

Accessor functions
==================

   The macros and functions in this section are used to query the
properties of Scheme objects.  Before applying them to any object, you
have to check whether the object is of the correct type, because the
accessor macros and functions will not check for validity.

 - Macro: car (C)
 - Macro: cdr (C)
     Return the car or cdr of C, which must be a pair.

 - Macro: set_car (C, VALUE)
 - Macro: set_cdr (C, VALUE)
     Set the car or cdr of C to VALUE.

 - Macro: car_addr (C)
 - Macro: cdr_addr (C)
     Return the address of the car or cdr of C.

 - Macro: tagged_type (C)
     Return the type of the tagged object C.

 - Macro: tagged_info (C)
     Return the tagged info field of the tagged object C.  The result
     will be one of the `tagged_info_*' constants.

 - Macro: tagged_data0 (C)
 - Macro: tagged_data1 (C)
 - Macro: tagged_data2 (C)
     Returns the values of the data slots of the tagged object C.  The
     results are of type `void *' and must be casted before being used.

 - Macro: immediate_val (C)
     Returns the value of the immediate form C.

 - Macro: fixnum_val (C)
     Returns the value of the fixnum C.

 - Macro: integer_val (C)
     Returns the integer value of C, which must be either a fixnum or a
     long object.

 - Macro: string_val (C)
     Returns a pointer to the string contents of C.

 - Macro: string_len (C)
     Returns the length of the string C.

 - Macro: bool_val (C)
     Returns the value of the boolean object C.

 - Macro: char_val (C)
     Returns the value of the character object C.

 - Macro: float_val (C)
     Returns the value of the real number object C.

 - Macro: symbol_name (C)
     Returns the name of the symbol C.

 - Macro: symbol_value (C)
     Returns the global value of the symbol C.

 - Macro: symbol_name_addr (C)
     Returns the address of the name field of the symbol C.

 - Macro: symbol_value_addr (C)
     Returns the address of the value field of the symbol C.

 - Macro: set_symbol_name (C, S)
     Set the name of the symbol C to S.

 - Macro: set_symbol_value (C, S)
     Set the global value of the symbol C to S.

 - Macro: func_ptr (C)
     Returns the address of the C function which handles the primitive
     procedure or syntactic form C.

 - Macro: func_name (C)
     Returns the name of the primitive procedure or syntactic form C.

 - Macro: func_form_p (C)
     Returns true if the primitive procedure or syntactic form C is
     actually a syntactic form.

 - Macro: func_param (C)
     Returns the parameter specification of the primitive procedure or
     syntactic form C.

 - Macro: lambda_name (C)
     Returns the name of the lambda expression C, or `NULL' if the
     closure is anonymous.

 - Macro: lambda_args (C)
     Returns the formal argument list of the closure C.

 - Macro: lambda_body (C)
     Returns the closure body of C

 - Macro: lambda_env (C)
     Returns the environment the lambda expression C is closed over.

 - Macro: lambda_file (C)
     The file name in which the closure was defined, or NULL if not
     available.

 - Macro: lambda_line (C)
     Returns the line number in the file where the closure was defined,
     or NULL if not available.

 - Macro: long_val (C)
     Returns the value of the long integer object C.

 - Macro: env_val (C)
     Returns the environment vector of the environment C.

 - Macro: location_address (C)
     Returns the address the location object C refers to.

 - Macro: lloc_val (C)
     Returns the lloc list containing access data for memoized lloc
     objects.

 - Macro: gloc_name (C)
     Returns the name of the gloc C.

 - Macro: gloc_val (C)
     Returns the address the gloc C refers to.

 - Macro: constant_val (C)
     Returns the value of the constant value object C.

 - Macro: keyword_name (C)
     Returns the name of the keyword C.

 - Macro: vector_val (C)
     Returns a pointer to the array of vector elements of vector C,
     which are all of type `zzz_scm_t'.

 - Macro: vector_len (C)
     Returns the length of the vector C.

 - Macro: zzz_vector_put (VECTOR, INDEX, VALUE)
     Store the object VALUE at index INDEX into VECTOR.  Make sure that
     INDEX is valid before calling this macro.

 - Macro: zzz_vector_get (VECTOR, INDEX)
     Fetch the object at index INDEX from VECTOR.  Make sure that INDEX
     is valid before calling this macro.

 - Macro: values_val (C)
     Returns the value list of the muliple value object C.

 - Macro: int_var_addr (C)
     Returns the address of the integer variable the integer variable
     wrapper C refers to.

 - Macro: bool_var_addr (C)
     Returns the address of the boolean variable the boolean variable
     wrapper C refers to.

 - Macro: str_var_val (C)
     Returns the address of the string variable the string variable
     wrapper C refers to.

 - Macro: str_var_len (C)
     Returns the length of the string variable the string variable
     wrapper C refers to.

 - Macro: str_var_size (C)
     Returns the maximum size of the string variable the string variable
     wrapper C refers to.

 - Macro: regexp_valid (C)
     Returns true if the regular expression object C was compiled
     successfully.

 - Macro: regexp_string (C)
     Returns the string pattern which was compiled into the regular
     expression object C as a Scheme string object.

 - Macro: regexp_regex (C)
     Returns the regular expression structure of type `regex_t', into
     which the regular expression was compiled.

 - Macro: promise_env (C)
     Returns the environment in which the promise C will be evaluated.

 - Macro: promise_result (C)
     Returns the result of the promise C.  Only a valid field if the
     promise was already forced.

 - Macro: promise_expr (C)
     Returns the expression which was delayed in the promise C.

 - Macro: promise_thawed (C)
     Returns a true value if the promise C was already forced, false
     otherwise.

 - Macro: macro_code (C)
     Returns the macro code of the macro object C.

 - Macro: syntax_rules (C)
     Returns the syntax rules of the syntax object C.

 - Macro: port_ptype (C)
     Returns the port type of the port object C.

 - Macro: port_open_p (C)
     Returns true if the port object C is open.

 - Macro: port_write_p (C)
     Returns true if the port object C is for output.

 - Macro: port_read_p (C)
     Returns true if the port object C is for input.

 - Macro: port_line_number (C)
     Returns the current line number of the port object C.

 - Macro: port_col_number (C)
     Returns the current column number of the port object C.

 - Macro: port_saved_col (C)
     Returns the last column number of the port object C.  This is
     remembered to restore column numbers after a `port_ungetc()'
     operation.

 - Macro: fport_file (C)
     Returns the file pointer of the standard IO file port C.

 - Macro: fdport_fd (C)
     Returns the file descriptor of the file descriptor port C.

 - Macro: fdport_has_unget (C)
     Returns true if the file descriptor port C has pushed back data.

 - Macro: fdport_unget (C)
     Returns the pushed back character of the file descriptor port C.

 - Macro: sport_val (C)
     Returns a pointer to the character buffer of the string port C.

 - Macro: sport_len (C)
     Returns the current length of valid data in the character buffer
     of the string port C.

 - Macro: sport_size (C)
     Returns the allocated size of the character buffer of the string
     port C.

 - Macro: sport_pos (C)
     Returns the current file pointer of the string port C.

 - Macro: TAGvector_val (C)
     Returns a pointer to the array of vector elements of the homogenous
     numeric vector C, which are all of the type indicated by TAG.

     TAG in the constructor name may be replaced by `s8', `u8', `s16',
     `u16', `s32', `u32', `s64', `u64', `f32' or `f64', depending on
     the needed datatype.  So there are actually ten of these accessor
     macros.

 - Macro: TAGvector_len (C)
     Returns the length of the homogenous numeric vector C.

     TAG in the constructor name may be replaced by `s8', `u8', `s16',
     `u16', `s32', `u32', `s64', `u64', `f32' or `f64', depending on
     the needed datatype.  So there are actually ten of these accessor
     macros.


File: sizzle-embed.info,  Node: Port Functions,  Next: Defining Scheme Types,  Prev: Accessor functions,  Up: Embedding API

Port Functions
==============

 - Function: unsigned zzz_define_port_type (port_getc_t PORT_GETC,
          port_ungetc_t PORT_UNGETC, port_putc_t PORT_PUTC, port_puts_t
          PORT_PUTS, port_flush_t PORT_FLUSH, port_close_t PORT_CLOSE,
          port_seek_t PORT_SEEK, port_tell_t PORT_TELL,
          port_char_ready_p_t PORT_CHAR_READY_P, port_free_t PORT_FREE,
          port_mark_t PORT_MARK)
     Define a new port type.  Must be given functions for all supported
     port operations.

 - Function: result_t zzz_port_puts (zzz_scm_t PORT, char * BUF, int
          LEN, zzz_scm_t * RESULT);
     Put the string BUF of length LEN onto the port PORT.  Returns
     `RESULT_SUCCESS' on success or an error code and an error object
     in the location pointed to by RESULT if an error occurs.

 - Function: result_t zzz_port_putc (int CH, zzz_scm_t PORT, zzz_scm_t
          * RESULT)
     Put the character CH to port PORT.  Returns `RESULT_SUCCESS' on
     success or an error code and an error object in the location
     pointed to by RESULT if an error occurs.

 - Function: result_t zzz_port_print (zzz_scm_t PORT, zzz_scm_t CELL,
          zzz_print_state_t STATE, zzz_scm_t * RESULT)
     Print the Scheme object CELL to the port PORT.  Formatting is
     specified via the passed STATE structure.  Returns
     `RESULT_SUCCESS' on success or an error code and an error object in
     the location pointed to by RESULT if an error occurs.

 - Function: result_t zzz_port_getc (zzz_scm_t PORT, int * CH,
          zzz_scm_t * RESULT)
     Read a character from the port PORT and return it in the location
     pointed to by CH.  Returns `RESULT_SUCCESS' on success or an error
     code and an error object in the location pointed to by RESULT if
     an error occurs.

 - Function: result_t zzz_port_ungetc (int CH, zzz_scm_t PORT,
          zzz_scm_t * RESULT)
     Return the character CH back to the stream of characters from port
     PORT.  Returns `RESULT_SUCCESS' on success or an error code and an
     error object in the location pointed to by RESULT if an error
     occurs.

 - Function: result_t zzz_port_close (zzz_scm_t PORT, zzz_scm_t *
          RESULT)
     Close the port PORT.  After using this function, no more data can
     be written to or read from PORT.  Returns `RESULT_SUCCESS' on
     success or an error code and an error object in the location
     pointed to by RESULT if an error occurs.

 - Function: result_t zzz_port_seek (zzz_scm_t PORT, long OFS, int
          WHENCE, long * RES_OFS, zzz_scm_t * RESULT)
     Move the file pointer of port PORT to position OFS.
     Interpretation of OFS depends on the parameter WHENCE, which is
     the same as in th C library function `fseek()'.  The new offset
     after repositioning is returned in the location pointed to by
     RES_OFS.  Returns `RESULT_SUCCESS' on success or an error code and
     an error object in the location pointed to by RESULT if an error
     occurs.

 - Function: result_t zzz_port_tell (zzz_scm_t PORT, long * RES_OFS,
          zzz_scm_t * RESULT)
     Return the position of PORT's file pointer in the location pointed
     to by RES_OFS.  Returns `RESULT_SUCCESS' on success or an error
     code and an error object in the location pointed to by RESULT if
     an error occurs.

 - Function: result_t zzz_port_flush (zzz_scm_t PORT, zzz_scm_t *
          RESULT);
     Flushes all pending output of the port PORT which has not yet been
     written to the underlying file.  Returns `RESULT_SUCCESS' on
     success or an error code and an error object in the location
     pointed to by RESULT if an error occurs.

 - Function: result_t zzz_port_char_ready_p (zzz_scm_t PORT, int *
          READY, zzz_scm_t * RESULT);
     Checks whether data is available for reading on the input port
     PORT.  A flag indicating the availability of data is returned in
     the location pointed to by READY.  Returns `RESULT_SUCCESS' on
     success or an error code and an error object in the location
     pointed to by RESULT if an error occurs.


File: sizzle-embed.info,  Node: Defining Scheme Types,  Next: Misc C API Functions,  Prev: Port Functions,  Up: Embedding API

Defining Scheme Types
=====================

 - Function: unsigned long zzz_define_tagged_type (void * (*
          CONSTRUCTOR_FUNC) (zzz_tagged_t tagged, const void * data0,
          const void * data1, const void * data2), void (*
          PRINT_FUNC)(zzz_scm_t port, zzz_tagged_t tagged,
          zzz_print_state_t state), void (* FREE_FUNC) (zzz_tagged_t
          tagged), void (* MARK_FUNC) (zzz_tagged_t tagged), int (*
          EQUAL_FUNC) (zzz_tagged_t tagged0, zzz_tagged_t tagged1))
     This function defines a new Scheme type.  The functions
     CONSTRUCTOR_FUNC, PRINT_FUNC, FREE_FUNC, MARK_FUNC and EQUAL_FUNC
     are stored internally and are used for all objects of the new
     type.  `zzz_define_tagged_type()' returns a type tag for the new
     type.

   The following two functions can be given as arguments to
`zzz_define_tagged_type()', if the data fields of the tagged type
contain variables of type `zzz_scm_t'.

 - Function: void * zzz_simple_constructor (zzz_tagged_t TAGGED, const
          void * DATA0, const void * DATA1, const void * DATA2)
     Constructor for simple types which store complete value state in
     the data fields of the tagged cell.  Returns its argument TAGGED.

 - Function: void zzz_simple_mark (zzz_tagged_t TAGGED);
     Mark function for types which hold zzz_scm_t values in their data
     slots which should be protected from being GC'ed.

 - Function: void zzz_mark_cell (zzz_scm_t CELL);
     Use this functions from the marking function of your tagged type
     if you have to mark a variable of type `zzz_scm_t'.


File: sizzle-embed.info,  Node: Misc C API Functions,  Prev: Defining Scheme Types,  Up: Embedding API

Misc C API Functions
====================

   The following functions do not seem to fit into any of the previous
sections, but they may come in handy from time to time.

 - Function: void zzz_garbage_collect (void)
     Force immediate garbage collection.

 - Macro: zzz_eq (FIRST, SECOND)
     Returns 1 if FIRST and SECOND are equal in the sense of `eq?'.
     Returns 0 otherwise.

     This macro can be undefined in the file `node.h', which will cause
     a function with the same functionality, but more error checking,
     to be compiled in.

 - Function: int zzz_eqv (zzz_scm_t FIRST, zzz_scm_t SECOND)
     Returns 1 if FIRST and SECOND are equal in the sense of `eqv?'.
     Returns 0 otherwise.

 - Function: int zzz_equal (zzz_scm_t FIRST, zzz_scm_t SECOND)
     Returns 1 if FIRST and SECOND are equal in the sense of `equal?'.
     Returns 0 otherwise.

 - Function: int zzz_list_length (zzz_scm_t LIST);
     Returns the length of list LIST.  Returns -1 if LIST is not a
     proper list and returns -2 if LIST contains circular references.
     A proper list is a list terminated by the empty list `'()' and a
     circular list is a list which points to one of its own elements
     somewhere.


File: sizzle-embed.info,  Node: Memory Management,  Next: Creating Data Types,  Prev: Embedding API,  Up: Top

Memory Management
*****************

   In this section, we will see how Sizzle represents Scheme objects
internally and how the memory needed for storing these objects is
managed.

* Menu:

* Cell Representation::         How data cells are represented in core
* Garbage Collection::          How storage is reclaimed


File: sizzle-embed.info,  Node: Cell Representation,  Next: Garbage Collection,  Prev: Memory Management,  Up: Memory Management

Cell Representation
===================

   The Sizzle interpreter makes a difference between four types of
Scheme objects: immediate values, fixnums, cons cells and tagged cells.
These types are stored in memory differently, and we will look at the
representation of them in detail in the following section.

   Most functions use the opaque data type `zzz_scm_t', which is
defined as a pointer to `struct cell'.  A value of type `zzz_scm_t' can
represent four different kinds of data.  They are differentiated by
their two least significant bits.

   If these bits are zero, it is a pointer to a cons cell which in turn
holds two values of type `zzz_scm_t'.  Cons cells are used to build the
normal Scheme lists from.  Environments, procedures, hash tables etc.
are all build using lists, so objects of this type are quite common.

   Should the two least significant bits be 1, it represents an 29-bit,
two-complement integer value, a so-called fixnum; in order to get the
real value, the value must be right-shifted by three bits.

   The third kind, encoded by a 2 in the two least significant bits is a
so-called tagged cell where the first word of the object pointed to is
the a combination of the "tagged data type" (a 16 bit unsigned int) and
additional 13 information bits.  The usage of the info bits depends on
the particular object type.  Function objects, for example, encode the
expected parameter formet in these bits; and read-only strings and
vectors have a bit set in the info field.  The next three words of the
tagged cell object (as you can calculate, a tagged object is at least 4
words long) are data words and the values stored there depend on the
data type.  Some types store a pointer to additional storage there,
others use the three words to hold values larger than one word (floating
point values, for example, store their 2-word value in the last two
words of the object).

   A value of 3 in the two least significant bits of the "car" of a
cell means that the cell represents a so-called immediate value.
Immediate values do not point to any heap-allocated object, but stand
for themselves.  The immediate forms, into which most syntactic forms
are transformed on evaluation, are examples of this type of object.

   Bit two is used to implement a marking garbage collector.  Cells
which have been seen during the scan phase of collection have this bit
set in the "car".

   Cons cells and tagged cells are allocated on two different heaps,
because they have a different size.

Pointer Layout
..............

   General layout of a variable of type `zzz_scm_t':

      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |               |               |               |         | | | |
     +---------------+---------------+---------------+---------+-+-+-+
                                                                | | |
                                      garbage collection mark --+ | |
                                                                  | |
                                                    node type ----+-+
                                                    0 = cons cell,
                                                        '(),
                                                        immediate code
                                                    1 = integer (shifted)
                                                    2 = tagged cell
                                                    3 = immediate value

   Cons cell pointers have zeros in their least significant bits.  They
can be used as pointers to structures of type `struct cell' without
further modification.  Note: when dealing with values of this type while
garbage collection is running is dangerous, because you have to mask out
bit #2 before dereferencing the pointer.

      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|0|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _________________________^___/
                                     \/                         |
                  32-bit pointer to value of type `struct cell' |
                                        Might be set during gc -+

   The null pointer (which is the representation of the empty list) is a
word of only zero bits.  Only during garbage collection the third bit
may be set and must be masked off.

      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0|x|0|0|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _________________________^___/
                                     \/                         |
                  32-bit pointer to value of type `struct cell' |
                                        Might be set during gc -+

   Integer values, aka fixnums, have the following layout.  The value
of any fixnum value can be obtained by arithmetically right-shifting
the value by three bits.

      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|1|
     +---------------+---------------+---------------+---------+-+-+-+
      \___________________________  __________________________/ ^
                                  \/                            |
                      Two-complement 29-bit-value               |
                                        Might be set during gc -+

   Tagged cells hold the value 2 in their two least significant bits
and a pointer to a tagged cell structure can be obtained by masking the
lower 4 bits off.

      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x 0|x|1|0|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _______________________^_^___/
                                     \/                       | |
                  32-bit pointer to tagged object             | |
                                                              | |
         Zero, because tagged objects are aligned to 16 bytes + |
                                                                |
                                        Might be set during gc -+

   Immediate codes have their least significant two bits set and their
value encoded in the upper 29 bits.

      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|1|1|
     +---------------+---------------+---------------+---------+-+-+-+
      \___________________________  __________________________/ ^
                                  \/                            |
               any value, depending of the immediate value      |
                                        Might be set during gc -+

Heap Cell Layout
................

   When looking at any cell on one of the heaps, the values defined in
the following paragraphs are valid.

   On the cons heap, any cell can be either free or in use.

   Free cells carry a pointer to the next entry in the free list in the
cdr and the value `2' in the car.

      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0|0|1|0|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _____________________________/
                                     \/
                          Pointer to next free cell

   Used cons cells can be in one of the following four states.

   The car of a cons cell either contains a cons cell pointer (or
NULL), a tagged cell pointer, a fixnum or an immediate value.  During
garbage collection, bit #2 of the car may be set.

                            Pointer to cons cell
       ______________________________/\____________________________
      /                                                            \
      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|0|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|0|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _____________________________/
                                     \/
                     Any possible value of type zzz_scm_t

                           Pointer to tagged cell
       ______________________________/\____________________________
      /                                                            \
      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|1|0|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|0|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _____________________________/
                                     \/
                    Any possible value of type zzz_scm_t

                               Integer value
       _____________________________/\_______________________
      /                                                      \
      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|1|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|0|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _____________________________/
                                     \/
                     Any possible value of type zzz_scm_t

                              Immediate value
       _____________________________/\_______________________
      /                                                      \
      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|1|1|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|0|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _____________________________/
                                     \/
                     Any possible value of type zzz_scm_t

   The first word of a tagged cell always containes a type tag (and
maybe information in the upper bits); the tag 0 stands for an unused
cell.  The following three words may hold any value, they are not
interpreted by the memory manager.

   Free tagged cell:

      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0 0 0 0|0 0 0 0 0|0|1|0|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
     .\______________________________  _____________________________/.
     .                               \/                              .
     .                    Pointer to next free cell                  .
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _____________________________/
                                     \/
                                   Garbage

   A use tagged cell looks like this.  Note that the third bit of the
first word may be set during garbage collection, just like for cons
cells.

           Type information                Type tag
       ___________/\__________   _____________/\_____________
      /                       \ /                            \
      7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|0|0|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
     |x x x x x x x x|x x x x x x x x|x x x x x x x x|x x x x x|x|x|x|
     +---------------+---------------+---------------+---------+-+-+-+
      \______________________________  _____________________________/
                                     \/
                   Pointer(s) to cell data / immediate data


File: sizzle-embed.info,  Node: Garbage Collection,  Prev: Cell Representation,  Up: Memory Management

Garbage Collection
==================

   In order to free the programmer from the burden of memory management,
the Scheme runtime environment must reclaim storage when it is no longer
accessible by the running program.  This process is called "Garbage
Collection", or GC for short.

   Memory allocation in Sizzle works as follows: functions creating data
objects call either the function `zzz_alloc_tagged_cell()' or
`zzz_cons()' (which in turn calls `zzz_alloc_cons_cell()').  After a
certain number of calls to one of these functions, the garbage
collection is invoked.  When not enough free memory is reserved for
fulfilling the allocation request, more memory is requested from the
operating system and the space needed is reserved.  Note that Sizzle
does not invoke the garbage collector when the freelists are empty,
because it tries to avoid garbage collection when memory is nearly full.

   The garbage collector uses a simple mark-and-sweep algorithm.  That
means, that garbage collection starts by marking all directly and
indirectly reachable objects as referenced.  In the second step, all
objects which are not marked are returned to the freelists of their
respective types.

   For marking all referenced objects it is necessary to find the "root
pointers" through which all used objects can be reached.  Sizzle
performs "conservative marking", that is, it marks all data objects
which are pointed to by values on the stack of the C program it runs in
and by marking all objects in locations which have been explicitly made
known to the interpreter.  This mechanism requires that the interpreter
knows how to find the beginning and the end of the stack.

   Two methods are provided to make these addresses available: The
first is to make the embedding application calling a library function
which calls back to the procedure doing the applications work.  With
this method, the library can calculate the end of the stack
automatically, but it takes over the main control function of the
program.  The Sizzle command line interpreter uses this method.

   The other method is to make the client code call explicitly a library
function and tell it where the end of the stack is by passing the
address of a local variable.  The tutorial in this manual is an example
for this procedure (*note Parsing initialization files::).

Object Marking
..............

   The marking phase is performed by traversing all objects pointed by
the root pointers.  Immediate objects do not need to get marked, because
they do not use heap memory at all.  What happens to other objects,
depends on their type.  Cons cells are directly known to the mark
function, and the funtion tries to reduce the needed stack space by
avoiding deep recursion.  Therefore, the spine of lists is marked in a
loop, marking recursively only the list elements.  Because lists in
Scheme are normally long and shallow, this speeds up marking a lot.

   Tagged objects are marked by calling the mark function for the type
of the object.  The mark function is responsible for calling the mark
function recursively for all Scheme objects referenced by the object.


File: sizzle-embed.info,  Node: Creating Data Types,  Next: Creating Port Types,  Prev: Memory Management,  Up: Top

Creating Data Types
*******************

   Sizzle has been designed in a way that it is easy to add additional
data types.  For now, this section only crudely documents the method for
defining data types, so for details, please refer to the source code to
find out how to do it.  Start by reading the files `node.h' and
`node.c' where all builtin data types are defined.

   The internal representation of all data is documented in *Note Cell
Representation::.

   The API functions for handling tagged types are documented briefly in
*Note Defining Scheme Types::.

   New data types in Sizzle are introduced by defining so-called
"tagged types".  Objects of tagged types occupy at least one tagged
cell on the heap, but they may allocate additional memory and store
pointers to those allocated areas into the heap cells.  For every tagged
type, a bunch of function must be defined which tell the memory manager
to handle objects of these types without actually knowing the memory
layout of the types.

* Menu:

* Type Functions::              How to define type functions
* Defining Tagged Types::       Register the new type with Sizzle


File: sizzle-embed.info,  Node: Type Functions,  Next: Defining Tagged Types,  Prev: Creating Data Types,  Up: Creating Data Types

Type Functions
==============

   This section documents what type functions are, and how to write
them.  First, I will summarize what functions are required, then I will
describe each function type in detail, giving examples as I go.

   The following type functions are defined:
Constructor function
     This function gets called when an object is created.  May allocate
     memory which may be needed to store an object, and must initialize
     the object from data passed to the constructor.

Print function
     This gets called by primitives like `display' or `write', and is
     responsible for printing a textual representation of the object to
     a port.

Free function
     Destructor function, which must free all memory which has been
     allocated by the constructor.

Mark function
     Called by the garbage collector during the mark phase for
     traversing all reachable objects.

Equal function
     Equality predicate called by `equal?' to determine whether two
     objects of the same type have the same structure.

* Menu:

* Constructor Function::        Function for initializing objects
* Print Function::              Function for printing objects
* Free Function::               Function for freeing object memory
* Equal Function::              Testing for object equality
* Mark Function::               Marking reachable objects


File: sizzle-embed.info,  Node: Constructor Function,  Next: Print Function,  Prev: Type Functions,  Up: Type Functions

Constructor Function
--------------------

   The constructor function is responsible for initializing a tagged
object.  When it is called, a tagged cell is already allocated on the
heap and has been initialized with the tagged type tag for the object.
The constructor has three formal arguments: The address of the allocated
cell, and three void pointer, which are used to pass arguments to the
constructor function.  The actual type and value of these arguments
depend on the object type the cosntructor function was defined for.

   The prototype for constructor functions looks like this:
     typedef void * (* constructor_func_t) (zzz_tagged_t tagged, void * data0,
                                            void * data1, void * data2);

   Often, types only need to store their three pointer arguments in the
three data slots of a tagged cell.  These types can use the library
function `zzz_simple_constructor()', which does this cell
initialization.  User types are free to use this pre-defined constructor
functions for their types, if its specification suits their needs.

   The constructor function for the string datatype is given below, to
serve as a non-trivial example.
     static void *
     string_constructor (zzz_tagged_t tagged, void * data0,
                         void * data1, void * data2)
     {
       char * p = (char *) data0;
       int len =  (int) ((long) data1);
       void * ret;
     
       ret = zzz_malloc (len + 1);   /* +1 for terminating '\0'.  */
       if (p)
         memmove ((char *) ret, p, len);
       ((char *) ret)[len] = '\0';
       tagged->fill[1] = (unsigned long) ret;
       tagged->fill[2] = (unsigned long) len;
       return tagged;
     }


File: sizzle-embed.info,  Node: Print Function,  Next: Free Function,  Prev: Constructor Function,  Up: Type Functions

Print Function
--------------

   Print functions must print a textual representation of an object to a
Scheme port.  They must match the following protoype:

     typedef void (* print_func_t) (zzz_scm_t port, zzz_tagged_t tagged,
                                    zzz_print_state_t state);

   The argument PORT specifies the Scheme port to print to, TAGGED is
the object, and STATE specifies the current state for printing.
`zzz_print_state_t' is defined as a pointer to the following structure,
which currently includes only one field.  This field is a bitset for
which the `PRINT_*' macros have been defined.
     struct zzz_print_state
     {
       int flags;
     };
     
     #define PRINT_NEWLINE 0x01
     #define PRINT_QUOTE   0x02
     #define PRINT_ESCAPE  0x04

   `PRINT_NEWLINE' is currently unused.  `PRINT_QUOTE' means, that the
print function should do all necessary quoting for making the textual
representation suitable for reading the object back in using `read'.
`PRINT_ESCAPE' means that special characters must be escaped in a way
compatible with `read'.  `write' for example, calls the print functions
with both `PRINT_QUOTE' and `PRINT_ESCAPE' set, `display' calls the
function without these flags.

   The print function for strings is rather complicated, but because it
interprets the print flags, it makes a good example.
     static void
     string_print (zzz_scm_t port, zzz_tagged_t tagged, zzz_print_state_t state)
     {
       zzz_scm_t result;
       char * p = tagged_data0 (tagged);
       int len = (long) tagged_data1 (tagged);
     
       assert (len >= 0);
       if (!(state->flags & (PRINT_ESCAPE | PRINT_QUOTE)))
         zzz_port_puts (port, p, len, &result); /* Fast path for `display'.  */
       else
         {
           if (state->flags & PRINT_QUOTE)
             zzz_port_putc ('"', port, &result);
           while (len-- > 0)
             {
               if ((state->flags & PRINT_ESCAPE) && (*p == '\\' || *p == '"'))
                 zzz_port_putc ('\\', port, &result);
               zzz_port_putc (*p, port, &result);
               p++;
             }
           if (state->flags & PRINT_QUOTE)
             zzz_port_putc ('"', port, &result);
         }
     }


File: sizzle-embed.info,  Node: Free Function,  Next: Equal Function,  Prev: Print Function,  Up: Type Functions

Free Function
-------------

   The free function must free all memory which might have been
allocated in the constructor.  As an example, here is the string type
free function.
     static void
     string_free (zzz_tagged_t tagged)
     {
       int len =  (long) tagged_data1 (tagged);
       zzz_free (tagged_data0 (tagged), len + 1); /* + 1 for terminating '\0' */
     }


File: sizzle-embed.info,  Node: Equal Function,  Next: Mark Function,  Prev: Free Function,  Up: Type Functions

Equal Function
--------------

   The equal function must determine whether two objects of the same
type have the same structure in the sense of `equal?'.  For strings,
that means that the strings must be tested whether they have the same
length and the same character contents.
     static int
     string_equal (zzz_tagged_t tagged0, zzz_tagged_t tagged1)
     {
       char * p1 = tagged_data0 (tagged0);
       char * p2 = tagged_data0 (tagged1);
       int len1 = (long) tagged_data1 (tagged0);
       int len2 = (long) tagged_data1 (tagged1);
     
       if (len1 != len2)
         return 0;
       if (len1 == 0)
         return 1;
       len1 = memcmp (p1, p2, len1);
       if (len1)
         return 0;
       else
         return 1;
     }


File: sizzle-embed.info,  Node: Mark Function,  Prev: Equal Function,  Up: Type Functions

Mark Function
-------------

   The mark function for strings is empty, because no other Scheme
objects are referenced.  It would be possible to pass a null pointer to
the type definition function also, if no mark function is required.
     static void
     string_mark (zzz_tagged_t tagged)
     {
     }

   Here is a second example, the mark function for vector objects.  It
calls the library mark function for every vector element.

     static int
     vector_equal (zzz_tagged_t tagged0, zzz_tagged_t tagged1)
     {
       zzz_scm_t * vec1   = vector_val (tagged0);
       unsigned long len1 = vector_len (tagged0);
       zzz_scm_t * vec2   = vector_val (tagged1);
       unsigned long len2 = vector_len (tagged1);
       unsigned long x;
     
       if (len1 != len2)
         return 0;
       for (x = 0; x < len1; x++)
         {
           if (!zzz_equal (vec1[x], vec2[x]))
             return 0;
         }
       return 1;
     }

   Like for the constructor function, a library function exists to be
used as a mark function when your tagged type has a certain structure.
Whenever a tagged type is to be created which should hold Scheme values
in the data slots of the tagged cells, you can use the function
`zzz_simple_mark()'.  This function simply calls the system's mark
function for all three data slots.


File: sizzle-embed.info,  Node: Defining Tagged Types,  Prev: Type Functions,  Up: Creating Data Types

Defining Tagged Types
=====================

   After writing the type functions, you have to register the new type
with the library.  This is done by calling the type definition function
`zzz_define_tagged_type()', which has this protoype:

     unsigned long zzz_define_tagged_type
               (constructor_func_t constructor_func,
                print_func_t print_func,
                free_func_t free_func,
                mark_func_t mark_func,
                equal_func_t equal_func);

   The return value of this function is the type tagged, which can then
be used to create objects of the given type.  It is used in calls to the
tagged typ creation function `zzz_create_tagged_type()'.  It is called
with the type tag obtained by the call to the register function and
three opaque pointers, which will be passed to the type's constructor
function.

     zzz_scm_t zzz_create_tagged_cell (unsigned long tag, void * data0,
                                       void * data1, void * data2);


File: sizzle-embed.info,  Node: Creating Port Types,  Next: Adding Primitives,  Prev: Creating Data Types,  Up: Top

Creating Port Types
*******************

   New port types can be created on the C as well as on the Scheme
level.  For now, refer to the files `sport.c' and `sport.h', which
define string ports and which will be instructive if you want to build
your own port types in C.  The other port types are implemented in the
files `fport.[ch]', `fdport.[ch]' and `scmport.[ch]'.

   On the Scheme level, the procedure `make-soft-port' can be used to
create ports which handle in- and output in a special way.  Refer to the
Reference Manual for more information.  Scheme ports are implemented in
the files `scmport.c' and `scmport.h'.


File: sizzle-embed.info,  Node: Adding Primitives,  Next: sizzle-gen-if,  Prev: Creating Port Types,  Up: Top

Adding Primitives
*****************

   It is easy to add primitive procedures to the interpreter.  The
process involves two steps.  You have to write a C function which
handles the primitive procedure calls and you must tell the interpreter
under which name your function wants to be called.

* Menu:

* The C Function::                   How to write a primitive in C
* Adding the Function to the Core::  How to register the primitive


File: sizzle-embed.info,  Node: The C Function,  Next: Adding the Function to the Core,  Prev: Adding Primitives,  Up: Adding Primitives

The C Function
==============

   This is a small example for writing a C primitive.  The code is
actually taken from the code of the Sizzle library, it implements the
primitive function `eval'.

     /*:doc
       eval
       (eval expr [environment]) => value(s)
       Evaluate the expression EXPR in the environment specified by
       ENVIRONMENT and return the resulting value(s).  ENVIRONMENT
       defaults to the current top-level environment.
       doc:*/
     #define FUNC_NAME "eval"
     static result_t
     eval_func (zzz_scm_t env, zzz_scm_t form, zzz_scm_t new_env,
                zzz_scm_t * result)
     {
       static char * s_func_name = FUNC_NAME;
       zzz_scm_t res;
     
       if (zzz_eq (new_env, zzz_undefined))
         new_env = zzz_current_environment;
       else
         CHECK_TYPE (2, env_p (new_env), zzz_environment_type_name);
       return zzz_evaluate (new_env, form, result);
     }
     #undef FUNC_NAME

   The first thing to notice is the definition of the CPP macro
`FUNC_NAME'.  This macro must always be defined to be the name of the
Scheme primitive this function stands for, because it is used in error
messages produced by several support macros.  `s_func_name' must be
declared always for the same reason, and in exactly the same way.

   `eval' takes an optional second parameter.  Therefore, the code must
check whether any value was given for that parameter, if not the value
of the parameter will be `zzz_undefined'.  Depending on this check,
`eval' either provides a default value or checks the given value's
type.  The macro `CHECK_TYPE' will produce an error message and return
from the function if it is not.  The first argument to `CHECK_TYPE' is
the parameter number to include in error messages, the second is an
expression which must evaluate to true in order to proceed, and the
last parameter is a string telling which parameter type was expected.
When the test for the second argument fails, `CHECK_TYPE' will generate
an appropriate error message including the error message from the last
parameter and return immediately from the current function.

   When the parameters have been verified, the function
`zzz_evaluate()' is called to evaluate the first parameter.  The return
value if that call is simply returned, an the result pointer is passed
to the evaluation function, which will store the result value in the
given location.


File: sizzle-embed.info,  Node: Adding the Function to the Core,  Prev: The C Function,  Up: Adding Primitives

Adding the Function to the Core
===============================

   After writing the C function for a primitive, we have to announce to
the library what we have laborously achieved.  This is done using the
API function `zzz_define_function()', like in the following example.

     zzz_define_function ("eval", eval_func, argv_1_1_0);

   Here, `"eval"' is the name of the Schme primitive we want to bind
the function to, EVAL_FUNC is the C function we have defined in the
previous section and `argv_1_1_0' is a descriptor of the argument
format our function expects.  There are several of those `argv_*_*_*'
macros defined in `node.h'.  The first number stands for the number of
fixed arguments the procedure expects, the second number for the number
of optional arguments and the last number is 1 if a rest parameter will
be accepted, to which a list of all remaining arguments will be bound;
and 0 if no rest argument is acceptable.

