Emacs: This is English -*- Text -*-

Information on primitives:

 * Primitives are routines written in the interpreter implementation
language (C in this case) which accept Scheme objects as arguments and
return a Scheme object as their values.  Some of them (APPLY,
SCODE-EVAL, CATCH) are really entry points into the interpreter, and
in other languages or implementations would be special forms.  These
depend on the way the interpreter works and should not be modified.
Most (all?) of these hooks into the interpreter live in the file
hooks.c .

 * Most primitives are basic in some sense.  Their functionality
cannot easily be achieved with a procedure written in Scheme (e.g.
CAR, PRIMITIVE-TYPE, TTY-READ-CHARACTER, etc).  Some exist only for
efficiency - they are used very frequently, are easily written in the
interpreter implementation language, and this extra work is worth the
speed that they provide (eg LENGTH, MEMQ, etc).

 * The runtime system depends on many primitives (some are fossils and
others are used by specialized subsystems only).  Users may, however,
add new primitives to suit their applications (graphics, matrix
multiplication, etc.), and are encouraged to do so.

 * The system provides some facilities for declaring new primitives,
which can then be accessed from Scheme.  The linking of the C code
which implements these user-supplied (we call them "external")
primitives is done at interpreter (microcode) generation time (e.g.
when you use "make" to link a new version of scheme under Unix).
These externals are handled in such a way that Scheme programs which
use them can be loaded on any system, including systems that do not
have those primitives.  If you run a program which tries to apply one
of these undefined externals to arguments, you will, of course, get an
error.

 * The original primitives (provided with CScheme) must always exist,
and are not linked in the same way as user defined primitives for
historical reasons.  They will eventually be linked in the same way,
and then there will be no difference between both kinds.  As far as
linking is concerned, there are two relevant files in the microcode:
usrdef.c and bltdef.c .  usrdef.c contains the tables which describe
the user provided primitives.  The position of any primitive in the
tables is arbitrary, and can change witouth affecting the behavior of
the system.  bltdef.c contains the tables which describe the original
(or "built in") primitives.  The position of any primitive in the
table is fixed (in particular, it must match the position in the file
utabmd.scm).  Both of these C source files are generated by the
Findprim program, which assigns arbitrary numbers to user defined
primitives every time it generates the tables.

 * Primitives have 2 names: The C name (the name of the C routine that
implements them), and the Scheme linking name.  The latter is the name
which when given to MAKE-PRIMITIVE-PROCEDURE will return the
appropriate procedure object.  Note that this name is not usually
initially bound in Scheme, and it may be bound to anything at all,
though for some of the most common primitives it is bound to the
primitive object.  In other words, you must choose names for your
primitives so that neither the C name nor the linking name have
conflicts with other linked primitives, but you need not worry about
name conflicts with the Scheme environment.  Note also that the
linking name is currently ignored for "built in" primitives.

 * Define_Primitive is a macro used to declare a primitive to the
linking mechanism.  It is both a C macro (defined in primitive.h) and
a special token searched for by the Findprim program to generate the
file usrdef.c when a new scheme microcode is linked together.  See the
file README for information on how to generate a new microcode which
includes primitives you have defined.  You should not write built-in
primitives, since the numbers you allocate for them will probably
conflict with numbers chosen at MIT for other primitives.  You should
also avoid adding your primitives to system files.  Write your own new
files with user defined primitives.

 * Define_Primitive expects 3 arguments which are the C name, the
number of arguments that the primitive expects (currently primitives
cannot receive variable numbers of arguments), and the Scheme linking
name.  Original primitives make use of the Built_In_Primitive macro
instead, which takes a fourth argument declaring what position the
primitive occupies in the built-in primitive tables.  The position in
the table is used for linking, rather than the symbolic name.

 * One last note: Unless very special care is taken (and we do not
recommend it), primitives cannot call other primitives.  If you want
to share code between two primitives, write a third procedure which
implements the common work, and have both primitives call it as
appropriate.  The reason for this is that the primitive calling
convention may change without notice, and the way arguments are
accessed may therefore change.  As long as you only use
Primitive_N_Args to access them, your code will continue to work.  In
particular, if you write primitives which do not expect any arguments,
make sure to use Primitive_0_Args anyway since it will take care of
any initialization needed.  Define_Primitive, Built_In_Primitive,
Primitive_N_Args, and other utilities for primitives are defined in
the file primitive.h.

 * For examples of user defined primitives, look at the files
sample.c, xdebug.c, Sgraph.c, or Xgraph.scm in the microcode
subdirectory.  For an example on how to access these primitives from
scheme look at ngraph.scm or Xgraph.scm in the runtime subdirectory.


