   This file documents the use of MIT Scheme.

   Copyright (C) 1991-2002 Massachusetts Institute of Technology

   Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.1 or
any later version published by the Free Software Foundation; with no
Invariant Sections, with no Front-Cover Texts, and with no Back-Cover
Texts.  A copy of the license is included in the section entitled "GNU
Free Documentation License".

Environment Variables for OS/2
------------------------------

   These environment variables are specific to the OS/2 implementation.

`USER'
     Specifies the login name of the user running Scheme.  This is used
     for several different purposes.  If this variable is undefined, an
     error is signalled when the username is required.

`USERDIR'
     Specifies a directory that contains the home directories of users.
     One of the places in which Scheme looks for the user's home
     directory, by searching for a subdirectory with the user's login
     name.  This variable is used only when `HOME' is not defined; we
     recommend using `HOME' rather than `USERDIR'.

`COMSPEC'
     Specifies the command shell.  This is set in all versions of OS/2
     (and is required for proper operation of the operating system).
     Scheme uses this to determine the user's shell if the environment
     variable `SHELL' is not defined.

Starting Scheme from Microsoft Windows
======================================

   The Microsoft Windows version of MIT Scheme runs as a graphics-based
application.  Scheme is normally started using shortcuts; the installer
automatically generates several different predefined shortcuts for your
convenience.

   The rest of this section gives some tips on how to set up shortcuts
that run Scheme.  If you are unfamiliar with this concept you should
read about it in the system help.

   * Under Windows NT, Windows 2000, or Windows XP, shortcuts can be
     _common_ or _personal_.  When setting common shortcuts it is
     important to make the shortcut properties independent of the
     vagaries of the environment of the user who is running them.

   * Give the shortcut an accurate DESCRIPTION.

   * Include absolute pathnames to `scheme.exe' and `bchscheme.exe' in
     the shortcut COMMAND LINE.

   * If you specify the `-library' command-line option then you do not
     have to worry about the `MITSCHEME_LIBRARY_PATH' environment
     variable.

   * Set the shortcut's WORKING DIRECTORY to something sensible.  On
     Windows NT/2000/XP you can use `%HOMEDRIVE%%HOMEPATH%' to make
     Scheme start up in the user's home directory.  On Windows 9x/ME
     you can use `%HOME%' to achieve the same effect, provided that you
     have set the `HOME' environment variable as we recommend.

   * There are several icons available in the Scheme executable --
     choose one that best represents the options given on the command
     line.

   * Specifying a band that contains Edwin is not sufficient to invoke
     the editor.  You also have to put `-edit' at the end of the command
     line.

Leaving Scheme
==============

   There are several ways that you can leave Scheme: there are two
Scheme procedures that you can call; there are several Edwin commands
that you can execute; and there are are graphical-interface buttons
(and their associated keyboard accelerators) that you can activate.

   * _Two Scheme procedures that you can call._  The first is to
     evaluate

          (exit)

     which will halt the Scheme system, after first requesting
     confirmation.  Any information that was in the environment is
     lost, so this should not be done lightly.

     The second procedure suspends Scheme; when this is done you may
     later restart where you left off.  Unfortunately this is not
     possible in all operating systems; currently it works under unix
     versions that support job control (i.e. all of the unix versions
     for which we distribute Scheme).  To suspend Scheme, evaluate

          (quit)

     If your system supports suspension, this will cause Scheme to
     stop, and you will be returned to the shell.  Scheme remains
     stopped, and can be continued using the job-control commands of
     your shell.  If your system doesn't support suspension, this
     procedure does nothing.  (Calling the `quit' procedure is
     analogous to typing `C-z', but it allows Scheme to respond by
     typing a prompt when it is unsuspended.)

   * _Several Edwin commands that you can execute,_ including
     `save-buffers-kill-scheme', normally bound to `C-x C-c', and
     `suspend-scheme', normally bound to `C-x C-z'.  These two commands
     correspond to the procedures `exit' and `quit', respectively.

   * _Graphical-interface buttons that you can activate._  Under OS/2
     and Windows, closing the console window (Scheme's main window)
     causes Scheme to be terminated.  Under any operating system,
     closing an Edwin window causes that window to go away, and if it
     is the only Edwin window, it terminates Scheme as well.

     Under OS/2, there are two distinct ways to close the console
     window.  The first is to use any of the usual window-closing
     methods, such as the `Close' system-menu item or double-clicking
     on the system-menu icon.  When this is done, you will be presented
     with a dialog that gives you the option to close the window with
     or without termating Scheme.  The second way is to select the
     `Exit' item from the `File' menu, which terminates Scheme
     immediately with no dialog.

Using Scheme
************

   This chapter describes how to use Scheme to evaluate expressions and
load programs.  It also describes how to save custom "world images",
and how to control the garbage collector.  Subsequent chapters will
describe how to use the compiler, and how to debug your programs.

The Read-Eval-Print Loop
========================

   When you first start up Scheme from the command line, you will be
typing at a program called the "Read-Eval-Print Loop" (abbreviated
"REPL").  It displays a prompt at the left hand side of the screen
whenever it is waiting for input.  You then type an expression
(terminating it with <RET>).  Scheme evaluates the expression, prints
the result, and gives you another prompt.

The Prompt and Level Number
---------------------------

   The REPL "prompt" normally has the form

     1 ]=>

The `1' in the prompt is a "level number", which is always a positive
integer.  This number is incremented under certain circumstances, the
most common being an error.  For example, here is what you will see if
you type `f o o <RET>' after starting Scheme:

     ;Unbound variable: foo
     ;To continue, call RESTART with an option number:
     ; (RESTART 3) => Specify a value to use instead of foo.
     ; (RESTART 2) => Define foo to a given value.
     ; (RESTART 1) => Return to read-eval-print level 1.

     2 error>

In this case, the level number has been incremented to `2', which
indicates that a new REPL has been started (also the prompt string has
been changed to remind you that the REPL was started because of an
error).  The `2' means that this new REPL is "over" the old one.  The
original REPL still exists, and is waiting for you to return to it, for
example, by entering `(restart 1)'.  Furthermore, if an error occurs
while you are in this REPL, yet another REPL will be started, and the
level number will be increased to `3'.  This can continue ad infinitum,
but normally it is rare to use more than a few levels.

   The normal way to get out of an error REPL and back to the top level
REPL is to use the `C-g' interrupt.  This is a single-keystroke command
executed by holding down the <CTRL> key and pressing the <G> key.
`C-g' always terminates whatever is running and returns you to the top
level REPL immediately.

   Note: The appearance of the `error>' prompt does not mean that
Scheme is in some weird inconsistent state that you should avoid.  It is
merely a reminder that your program was in error: an illegal operation
was attempted, but it was detected and avoided.  Often the best way to
find out what is in error is to do some poking around in the error
REPL.  If you abort out of it, the context of the error will be
destroyed, and you may not be able to find out what happened.

Interrupting
------------

   Scheme has several interrupt keys, which vary depending on the
underlying operating system: under unix, `C-g' and `C-c'; under OS/2
and Windows, `C-g', `C-b', `C-x' and `C-u'.  The `C-g' key stops any
Scheme evaluation that is running and returns you to the top level
REPL.  `C-c' prompts you for another character and performs some action
based on that character.  It is not necessary to type <RET> after `C-g'
or `C-c', nor is it needed after the character that `C-c' will ask you
for.

   Here are the definitions of the more common interrupt keys; on unix,
type `C-c ?' for more possibilities.  Note that in any given
implementation, only a subset of the following keys is available.

`C-c C-c'
`C-g'
     Abort whatever Scheme evaluation is currently running and return
     to the top-level REPL.  If no evaluation is running, this is
     equivalent to evaluating

          (cmdl-interrupt/abort-top-level)

`C-c C-x'
`C-x'
     Abort whatever Scheme evaluation is currently running and return
     to the "current" REPL.  If no evaluation is running, this is
     equivalent to evaluating

          (cmdl-interrupt/abort-nearest)

`C-c C-u'
`C-u'
     Abort whatever Scheme evaluation is running and go up one level.
     If you are already at level number 1, the evaluation is aborted,
     leaving you at level 1.  If no evaluation is running, this is
     equivalent to evaluating

          (cmdl-interrupt/abort-previous)

`C-c C-b'
`C-b'
     Suspend whatever Scheme evaluation is running and start a
     "breakpoint" REPL.  The evaluation can be resumed by evaluating

          (continue)

     in that REPL at any time.

`C-c q'
     Similar to typing `(exit)' at the REPL, except that it works even
     if Scheme is running an evaluation, and does not request
     confirmation.

`C-c z'
     Similar to typing `(quit)' at the REPL, except that it works even
     if Scheme is running an evaluation.

`C-c i'
     Ignore the interrupt.  Type this if you made a mistake and didn't
     really mean to type `C-c'.

`C-c ?'
     Print help information.  This will describe any other options not
     documented here.

Restarting
----------

   Another way to exit a REPL is to use the `restart' procedure:

 - procedure+: restart [k]
     This procedure selects and invokes a "restart method".  The list of
     restart methods is different for each REPL and for each error; in
     the case of an error REPL, this list is printed when the REPL is
     started:

          ;Unbound variable: foo
          ;To continue, call RESTART with an option number:
          ; (RESTART 3) => Specify a value to use instead of foo.
          ; (RESTART 2) => Define foo to a given value.
          ; (RESTART 1) => Return to read-eval-print level 1.

          2 error>

     If the K argument is given, it must be a positive integer index
     into the list (in the example it must be between one and three
     inclusive).  The integer K selects an item from the list and
     invokes it.  If K is not given, `restart' prints the list and
     prompts for the integer index:

          2 error> (restart)
          ;Choose an option by number:
          ;  3: Specify a value to use instead of foo.
          ;  2: Define foo to a given value.
          ;  1: Return to read-eval-print level 1.

          Option number:

     The simplest restart methods just perform their actions.  For
     example:

          2 error> (restart 1)
          ;Abort!

          1 ]=>

     Other methods will prompt for more input before continuing:

          2 error> (restart)
          ;Choose an option by number:
          ;  3: Specify a value to use instead of foo.
          ;  2: Define foo to a given value.
          ;  1: Return to read-eval-print level 1.

          Option number: 3

          Value to use instead of foo: '(a b)
          ;Value: (a b)

          1 ]=>

The Current REPL Environment
----------------------------

   Every REPL has a "current environment", which is the place where
expressions are evaluated and definitions are stored.  When Scheme is
started, this environment is the value of the variable
`user-initial-environment'.  There are a number of other environments
in the system, for example `system-global-environment', where the
runtime system's bindings are stored.

   You can get the current REPL environment by evaluating

     (nearest-repl/environment)

   There are several other ways to obtain environments.  For example, if
you have a procedure object, you can get a pointer to the environment in
which it was closed by evaluating

     (procedure-environment PROCEDURE)

   Here is the procedure that changes the REPL's environment:

 - procedure+: ge environment
     Changes the current REPL environment to be ENVIRONMENT (`ge'
     stands for "Goto Environment").  ENVIRONMENT is allowed to be a
     procedure as well as an environment object.  If it is a procedure,
     then the closing environment of that procedure is used in its
     place.

 - procedure+: pe
     This procedure is useful for finding out which environment you are
     in (`pe' stands for "Print Environment").  If the current REPL
     environment belongs to a package, then `pe' returns the package
     name (a list of symbols).  If the current REPL environment does not
     belong to a package then the environment is returned.

Loading Files
=============

   To load files of Scheme code, use the procedure `load':

 - procedure: load filename [environment [syntax-table [purify?]]]
     FILENAME may be a string naming a file, or a list of strings
     naming multiple files.  ENVIRONMENT, if given, is the environment
     to evaluate the file in; if not given the current REPL environment
     is used.

     SYNTAX-TABLE is no longer used and if supplied will be ignored.

     The optional argument PURIFY? is a boolean that says whether to
     move the contents of the file into constant space after it is
     loaded but before it is evaluated.  This is performed by calling
     the procedure `purify' (see Garbage Collection).  If PURIFY?
     is given and true, this is done; otherwise it is not.

     `load' determines whether the file to be loaded is binary or source
     code, and performs the appropriate action.  By convention, files of
     source code have a pathname type of `"scm"', and files of binary
     SCode have pathname type `"bin"'.  Native-code binaries have
     pathname type `"com"'.  (See the description of `pathname-type' in
     Pathname Type (scheme).)

 - variable+: load-noisily?
     If `load-noisily?' is set to `#t', `load' will print the value of
     each expression in the file as it is evaluated.  Otherwise,
     nothing is printed except for the value of the last expression in
     the file.  (Note: the noisy loading feature is implemented for
     source-code files only.)

 - variable+: load/default-types
     When load is given a pathname without a type, it uses the value of
     this variable to determine what pathname types to look for and how
     to load the file.  `load/default-types' is a list of associations
     that maps pathname types (strings) to loader procedures.  `load'
     tries the pathname types in the order that they appear in the
     list.  The initial value of this variable has pathname types in
     this order:

          "com" "so" "sl" "bin" "scm"

     This means that, for example, `(load "foo")' will try to load
     `foo.com' first, and `foo.scm' only after looking for and failing
     to find the other pathname types.

   All pathnames are interpreted relative to a working directory, which
is initialized when Scheme is started.  The working directory can be
obtained by calling the procedure `pwd' or modified by calling the
procedure `cd'; see Working Directory (scheme).
Files may be loaded when Scheme first starts; see the `-load'
command-line option for details.

 - procedure+: load-option symbol [no-error?]
     Loads the option specified by SYMBOL; if already loaded, does
     nothing.  Returns SYMBOL; if there is no such option, an error is
     signalled.  However, if NO-ERROR? is specified and true, no error
     is signalled in this case, and `#f' is returned.

     A number of built-in options are defined:

    `compress'
          Support to compress and uncompress files.  Undocumented; see
          the source file `runtime/cpress.scm'.  Used by the runtime
          system for compression of compiled-code debugging information.

    `format'
          The `format' procedure.  See Format (scheme).

    `gdbm'
          Support to access `gdbm' databases.  Undocumented; see the
          source files `runtime/gdbm.scm' and `microcode/prgdbm.c'.

    `hash-table'
          The hash-table data type.  See Hash Tables (scheme).

    `ordered-vector'
          Support to search and do completion on vectors of ordered
          elements.  Undocumented; see the source file
          `runtime/ordvec.scm'.

    `rb-tree'
          The red-black tree data type.  See Red-Black Trees (scheme).

    `regular-expression'
          Support to search and match strings for regular expressions.
          See Regular Expressions (scheme).

    `stepper'
          Support to step through the evaluation of Scheme expressions.
          Undocumented; see the source file `runtime/ystep.scm'.  Used
          by the Edwin command `step-expression'.

    `subprocess'
          Support to run other programs as subprocesses of the Scheme
          process.  Undocumented; see the source file
          `runtime/process.scm'.  Used extensively by Edwin.

    `synchronous-subprocess'
          Support to run synchronous subprocesses.  See Subprocesses (scheme).

    `wt-tree'
          The weight-balanced tree data type.  See Weight-Balanced Trees (scheme).

   In addition to the built-in options, you may define other options to
be loaded by `load-options' by modifying the file `optiondb.scm' on the
library path.  An example file is included with the distribution;
normally this file consists of a series of calls to the procedure
`define-load-option', terminated by the expression

     (further-load-options standard-load-options)

 - procedure+: define-load-option symbol thunk ...
     Each THUNK must be a procedure of no arguments.  Defines the load
     option named SYMBOL.  When the procedure `load-option' is called
     with SYMBOL as an argument, the THUNK arguments are executed in
     order from left to right.

World Images
============

   A "world image", also called a "band", is a file that contains a
complete Scheme system, perhaps additionally including user application
code.  Scheme provides a method for saving and restoring world images.
The method writes a file containing all of the Scheme code and data in
the running process.  The file `runtime.com' that is loaded by the
microcode is just such a band.  To make your own band, use the procedure
`disk-save'.

 - procedure+: disk-save filename [identify]
     Causes a band to be written to the file specified by FILENAME.
     The optional argument IDENTIFY controls what happens when that
     band is restored, as follows:

    not specified
          Start up in the top-level REPL, identifying the world in the
          normal way.

    a string
          Do the same thing except print that string instead of
          `Scheme' when restarting.

    the constant `#t'
          Restart exactly where you were when the call to `disk-save'
          was performed.  This is especially useful for saving your
          state when an error has occurred and you are not in the
          top-level REPL.

    the constant `#f'
          Just like `#t', except that the runtime system will not
          perform normal restart initializations; in particular, it
          will not load your init file.

   To restore a saved band, give the `-band' option when starting
Scheme.  Alternatively, evaluate `(disk-restore FILENAME)', which will
destroy the current world, replacing it with the saved world.  The
argument to `disk-restore' may be omitted, in which case it defaults to
the filename from which the current world was last restored.

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

   This section describes procedures that control garbage collection.
See Memory Usage, for a discussion of how MIT Scheme uses memory.

 - procedure+: gc-flip [safety-margin]
     Forces a garbage collection to occur.  Returns the number of words
     of storage available after collection, an exact non-negative
     integer.

     SAFETY-MARGIN determines the number of words of storage available
     to system tasks after the need for a garbage collection is
     detected and before the garbage collector is started.  (An example
     of such a system task is changing the run-light to show "gc" when
     scheme is running under Emacs.)  See well*.
     If you
     specify a value that is too small, you can put Scheme in an
     unusable state.

 - procedure+: purify object [pure-space? [queue?]]
     Moves OBJECT from the heap into constant space.  Has no effect if
     OBJECT is already stored in constant space.  OBJECT is moved in
     its entirety; if it is a compound object such as a list, a vector,
     or a record, then all of the objects that OBJECT points to are also
     moved to constant space.

     There are three important effects associated with moving an object
     to constant space.  The first and most important effect is that
     the object takes up half as much space, because when in the heap,
     the system must reserve space for the object in both the active
     heap and the inactive heap; if the object is in constant space it
     is not copied and therefore no extra space is required.  The
     second effect is that garbage collection will take less time,
     because OBJECT will no longer be copied.  The third effect is that
     the space allocated to OBJECT is permanently allocated, because
     constant space is never cleaned; any unreachable objects in
     constant space remain there until the Scheme process is terminated.

     The optional argument PURE-SPACE? is obsolete; it defaults to `#t'
     and when explicitly specified should always be `#t'.

     The optional argument QUEUE?, if `#f', specifies that OBJECT
     should be moved to constant space immediately; otherwise OBJECT is
     queued to be moved during the next garbage collection.  This
     argument defaults to `#t'.  The reason for queuing these requests
     is that moving an object to constant space requires a garbage
     collection to occur, a relatively slow process.  By queuing the
     requests, this overhead is avoided, because moving an object
     during a garbage collection has no effect on the time of the
     garbage collection.  Furthermore, if several requests are queued,
     they can all be processed together in one garbage collection,
     while if done separately they would each require their own garbage
     collection.

 - procedure+: flush-purification-queue!
     Forces any pending queued purification requests to be processed.
     This examines the `purify' queue, and if it contains any requests,
     forces a garbage collection to process them.  If the queue is
     empty, does nothing.

 - procedure+: print-gc-statistics
     Prints out information about memory allocation and the garbage
     collector.  The information is printed to the current output port.
     Shows how much space is "in use" and how much is "free", separately
     for the heap and constant space.  The amounts are shown in words,
     and also in 1024-word blocks; the block figures make it convenient
     to use these numbers to adjust the arguments given to the `-heap'
     and `-constant' command-line options.  Following the allocation
     figures, information about the most recent 8 garbage collections is
     shown, in the same format as a GC notification.

     Note that these numbers are accurate at the time that
     `print-gc-statistics' is called.  In the case of the heap, the "in
     use" figure shows how much memory has been used since the last
     garbage collection, and includes all live objects as well as any
     uncollected garbage that has accumulated since then.  The only
     accurate way to determine the size of live storage is to subtract
     the value of `(gc-flip)' from the size of the heap.  The size of
     the heap can be determined by adding the "in use" and "free"
     figures reported by `print-gc-statistics'.

     (print-gc-statistics)
     constant in use:   534121 words =   521 blocks +  617 words
     constant free:        128 words =     0 blocks +  128 words
     heap in use:        34845 words =    34 blocks +   29 words
     heap free:         205530 words =   200 blocks +  730 words
     GC #1: took: 0.13 (81%) CPU time, 0.15 (1%) real time; free: 207210
     ;No value

 - procedure+: set-gc-notification! [on?]
     Controls whether the user is notified of garbage collections.  If
     ON? is true, notification is enabled; otherwise notification is
     disabled.  If ON? is not given, it defaults to `#t'.  When Scheme
     starts, notification is disabled.

     The notification appears as a single line like the following,
     showing how many garbage collections have occurred, the time taken
     to perform the garbage collection and the free storage remaining
     (in words) after collection.

          GC #5: took: 0.50 (8%) CPU time, 0.70 (2%) real time; free: 364346

     To operate comfortably, the amount of free storage after garbage
     collection should be a substantial proportion of the heap size.
     If the CPU time percentage is consistently high (over 20%), you
     should consider running with a larger heap.  A rough rule of thumb
     to halve the GC overhead is to take the amount of free storage,
     divide by 1000, and add this figure to the current value used for
     the `-heap' command-line option.  Unfortunately there is no way to
     adjust the heap size without restarting Scheme.

 - procedure+: toggle-gc-notification!
     Toggles GC notification on and off.  If GC notification is turned
     on, turns it off; otherwise turns it on.

Compiling Programs
******************

   Note: the procedures described in this section are only available
when the `-compiler' command-line option is specified.

Compilation Procedures
======================

 - procedure+: cf filename [destination]
     This is the program that transforms a source-code file into
     native-code binary form.  If DESTINATION is not given, as in

          (cf "foo")

     `cf' compiles the file `foo.scm', producing the file `foo.com'
     (incidentally it will also produce `foo.bin', `foo.bci', and
     possibly `foo.ext').  If you later evaluate

          (load "foo")

     `foo.com' will be loaded rather than `foo.scm'.

     If DESTINATION is given, it says where the output files should go.
     If this argument is a directory, they go in that directory, e.g.:

          (cf "foo" "../bar/")

     will take `foo.scm' and generate the file `../bar/foo.com'.  If
     DESTINATION is not a directory, it is the root name of the output:

          (cf "foo" "bar")

     takes `foo.scm' and generates `bar.com'.

   About the `.bci' files: these files contain the debugging
information that Scheme uses when you call `debug' to examine compiled
code.  When you load a `.com' file, Scheme remembers where it was
loaded from, and when the debugger (or `pp') looks at the compiled code
from that file, it attempts to find the `.bci' file in the same
directory from which the `.com' file was loaded.  Thus it is a good
idea to leave these files together.

   `.bci' files are stored in a compressed format.  The debugger has to
uncompress the files when it looks at them, and on a slow machine this
can take a noticeable time.  The system takes steps to reduce the
impact of this behavior: debugging information is cached in memory, and
uncompressed versions of `.bci' files are kept around.  The default
behavior is that a temporary file is created and the `.bci' file is
uncompressed into it.  The temporary file is kept around for a while
afterwards, and during that time if the uncompressed `.bci' file is
needed the temporary file is used.  Each such reference updates an
`access time' that is associated with the temporary file.  The garbage
collector checks the access times of all such temporary files, and
deletes any that have not been accessed in five minutes or more.  All of
the temporaries are deleted automatically when the Scheme process is
killed.

   Two other behaviors are available.  One of them uncompresses the
`.bci' file each time it is referenced, and the other uncompresses the
`.bci' file and writes it back out as a `.bif' file.  The `.bif' file
remains after Scheme exits.  The time interval and the behavior are
controlled by the following variables.

 - variable+: *save-uncompressed-files?*
     This variable affects what happens when `.bci' files are
     uncompressed.  It allows a trade-off between performance and disk
     space.  There are three possible values:

    `#f'
          The uncompressed versions of `.bci' files are never saved.
          Each time the information is needed the `.bci' file is
          uncompressed.  This option requires the minimum amount of
          disk space and is the slowest.

    `automatic'
          Uncompressed versions of `.bci' files are kept as temporary
          files.  The temporary files are deleted when Scheme exits, or
          if they have not been used for a while.  This is the default.

    `#t'
          The `.bci' files are uncompressed to permanent `.bif' files.
          These files remain on disk after Scheme exits, and are rather
          large - about twice the size of the corresponding `.bci'
          files.  If you choose this option and you are running out of
          disk space you may delete the `.bif' files.  They will be
          regenerated as needed.

 - variable+: *uncompressed-file-lifetime*
     The minimum length of time that a temporary uncompressed version of
     a `.bci' file will stay on disk after it is last used.  The time
     is in milliseconds; the default is `300000' (five minutes).

 - variable+: load-debugging-info-on-demand?
     If this variable is `#f', then printing a compiled procedure will
     print the procedure's name only if the debugging information for
     that procedure is already loaded.  Otherwise, it will force
     loading of the debugging information.  The default value is `#f'.

 - procedure+: sf filename [destination]
     `sf' is the program that transforms a source-code file into binary
     SCode form; it is used on machines that do not support native-code
     compilation.  It performs numerous optimizations that can make your
     programs run considerably faster than unoptimized interpreted code.
     Also, the binary files that it generates load very quickly
     compared to source-code files.

     The simplest way to use `sf' is just to say:

          (sf FILENAME)

     This will cause your file to be transformed, and the resulting
     binary file to be written out with the same name, but with
     pathname type `"bin"'.  If you do not specify a pathname type on
     the input file, `"scm"' is assumed.

     Like `load', the first argument to `sf' may be a list of filenames
     rather than a single filename.

     `sf' takes an optional second argument, which is the filename of
     the output file.  If this argument is a directory, then the output
     file has its normal name but is put in that directory instead.

Declarations
============

   Several declarations can be added to your programs to help `cf' and
`sf' make them more efficient.

Standard Names
--------------

   Normally, all files have a line

     (declare (usual-integrations))

near their beginning, which tells the compiler that free variables whose
names are defined in `system-global-environment' will not be shadowed
by other definitions when the program is loaded.  If you redefine some
global name in your code, for example `car', `cdr', and `cons', you
should indicate it in the declaration:

     (declare (usual-integrations car cdr cons))

   You can obtain an alphabetically-sorted list of the names that the
`usual-integrations' declaration affects by evaluating the following
expression:

     (eval '(sort (append usual-integrations/constant-names
                          usual-integrations/expansion-names)
                  (lambda (x y)
                    (string<=? (symbol->string x)
                               (symbol->string y))))
           (->environment '(scode-optimizer)))

In-line Coding
--------------

   Another useful facility is the ability to in-line code procedure
definitions.  In fact, the compiler will perform full beta conversion,
with automatic renaming, if you request it.  Here are the relevant
declarations:

 - declaration+: integrate name ...
     The variables NAMEs must be defined in the same file as this
     declaration.  Any reference to one of the named variables that
     appears in the same block as the declaration, or one of its
     descendant blocks, will be replaced by the corresponding binding's
     value expression.

 - declaration+: integrate-operator name ...
     Similar to the `integrate' declaration, except that it only
     substitutes for references that appear in the operator position of
     a combination.  All other references are ignored.

 - declaration+: integrate-external filename
     Causes the compiler to use the top-level integrations provided by
     FILENAME.  FILENAME should not specify a file type, and the
     source-code file that it names must have been previously processed
     by the compiler.

     If FILENAME is a relative filename (the normal case), it is
     interpreted as being relative to the file in which the declaration
     appears.  Thus if the declaration appears in file
     `/usr/cph/foo.scm', then the compiler looks for a file called
     `/usr/cph/FILENAME.ext'.

     Note: When the compiler finds top-level integrations, it collects
     them and outputs them into an auxiliary file with extension `.ext'.
     This `.ext' file is what the `integrate-external' declaration
     refers to.

   Note that the most common use of this facility, in-line coding of
procedure definitions, requires a somewhat complicated use of these
declarations.  Because this is so common, there is a special form,
`define-integrable', which is like `define' but performs the
appropriate declarations.  For example:

     (define-integrable (foo-bar foo bar)
       (vector-ref (vector-ref foo bar) 3))

   Here is how you do the same thing without this special form: there
should be an `integrate-operator' declaration for the procedure's name,
and (internal to the procedure's definition) an `integrate' declaration
for each of the procedure's parameters, like this:

     (declare (integrate-operator foo-bar))

     (define foo-bar
       (lambda (foo bar)
         (declare (integrate foo bar))
         (vector-ref (vector-ref foo bar) 3)))

   The reason for this complication is as follows: the
`integrate-operator' declaration finds all the references to `foo-bar'
and replaces them with the lambda expression from the definition.
Then, the `integrate' declarations take effect because the combination
in which the reference to `foo-bar' occurred supplies code that is
substituted throughout the body of the procedure definition.  For
example:

     (foo-bar (car baz) (cdr baz))

First use the `integrate-operator' declaration:

     ((lambda (foo bar)
        (declare (integrate foo bar))
        (vector-ref (vector-ref foo bar) 3))
      (car baz)
      (cdr baz))

Next use the internal `integrate' declaration:

     ((lambda (foo bar)
        (vector-ref (vector-ref (car baz) (cdr baz)) 3))
      (car baz)
      (cdr baz))

Next notice that the variables `foo' and `bar' are not used, and
eliminate them:

     ((lambda ()
        (vector-ref (vector-ref (car baz) (cdr baz)) 3)))

Finally, remove the `((lambda () ...))' to produce

     (vector-ref (vector-ref (car baz) (cdr baz)) 3)

Useful tip
..........

   To see the effect of integration declarations (and of macros) on a
source file, pretty-print the `.bin' file like this (be prepared for a
lot of output).

     (sf "foo.scm")
     (pp (fasload "foo.bin"))

Operator Replacement
--------------------

   The `replace-operator' declaration is provided to inform the
compiler that certain operators may be replaced by other operators
depending on the number of arguments.  For example:

Declaration:

     (declare (replace-operator (map (2 map-2) (3 map-3))))

Replacements:

     (map F X Y Z) ==> (map F X Y Z)
     (map F X Y) ==> (map-3 F X Y)
     (map F X) ==> (map-2 F X)
     (map F) ==> (map F)
     (map) ==> (map)

Presumably `map-2' and `map-3' are efficient versions of `map' that are
written for exactly two and three arguments respectively.  All the
other cases are not expanded but are handled by the original, general
`map' procedure, which is less efficient because it must handle a
variable number of arguments.

 - declaration+: replace-operator name ...
     The syntax of this declaration is

          (replace-operator
            (NAME
              (NARGS1 VALUE1)
              (NARGS2 VALUE2)
              ...))

     where

        * NAME is a symbol.

        * NARGS1, NARGS2 etc. are non-negative integers, or one of the
          following symbols:  `any', `else' or `otherwise'.

        * VALUE1, VALUE2 etc. are simple expressions in one of these
          forms:

         `'CONSTANT'
               A constant.

         `VARIABLE'
               A variable.

         `(primitive PRIMITIVE-NAME [ARITY])'
               The primitive procedure named PRIMITIVE-NAME.  The
               optional element ARITY, a non-negative integer,
               specifies the number of arguments that the primitive
               accepts.

         `(global VAR)'
               A global variable.

     The meanings of these fields are:

        * NAME is the name of the operator to be reduced.  If is is not
          shadowed (for example, by a let) then it may be replaced
          according to the following rules.

        * If the operator has NARGSN arguments then it is replaced with
          a call to VALUEN with the same arguments.

        * If the number of arguments is not listed, and one of the
          NARGSN is `any', `else' or `otherwise', then the operation is
          replaced with a call to the corresponding VALUEN.  Only one
          of the NARGSN may be of this form.

        * If the number of arguments is not listed and none of the
          NARGSN is `any', `else' or `otherwise', then the operation is
          not replaced.

Operator Reduction
------------------

   The `reduce-operator' declaration is provided to inform the compiler
that certain names are n-ary versions of binary operators.  Here are
some examples:

Declaration:

     (declare (reduce-operator (cons* cons)))

Replacements:

     (cons* X Y Z W) ==> (cons X (cons Y (cons Z W))),
     (cons* X Y) ==> (cons X Y)
     (cons* X) ==> X
     (cons*) error--> too few arguments

Declaration:

     (declare (reduce-operator (list cons (null-value '() any))))

Replacements:

     (list X Y Z W) ==> (cons X (cons Y (cons Z (cons W '()))))
     (list X Y) ==> (cons X (cons Y '()))
     (list X) ==> (cons X '())
     (list) ==> '()

Declaration:

     (declare (reduce-operator (- %- (null-value 0 single) (group left))))

Replacements:

     (- X Y Z W) ==> (%- (%- (%- X Y) Z) W)
     (- X Y) ==> (%- X Y)
     (- X) ==> (%- 0 X)
     (-) ==> 0

Declaration:

     (declare (reduce-operator (+ %+ (null-value 0 none) (group right))))

Replacements:

     (+ X Y Z W) ==> (%+ X (%+ Y (%+ Z W)))
     (+ X Y) ==> (%+ X Y)
     (+ X) ==> X
     (+) ==> 0

   Note: This declaration does not cause an appropriate definition of
`%+' (in the last example) to appear in your code.  It merely informs
the compiler that certain optimizations can be performed on calls to
`+' by replacing them with calls to `%+'.  You should provide a
definition of `%+' as well, although it is not required.

Declaration:

     (declare (reduce-operator (apply (primitive cons)
                                      (group right)
                                      (wrapper (global apply) 1))))

Replacements:

     (apply F X Y Z W)
        ==> ((access apply ()) F (cons X (cons Y (cons Z W))))
     (apply F X Y)
        ==> ((access apply ()) F (cons X Y))
     (apply F X) ==> (apply F X)
     (apply F) ==> (apply F)
     (apply) ==> (apply)

 - declaration+: reduce-operator name ...
     The general format of the declaration is (brackets denote optional
     elements):

          (reduce-operator
            (NAME
              BINOP
              [(group ORDERING)]
              [(null-value VALUE NULL-OPTION)]
              [(singleton UNOP)]
              [(wrapper WRAP [n])]
              [(maximum M)]
            ))

     where

        * N and M are non-negative integers.

        * NAME is a symbol.

        * BINOP, VALUE, UNOP, and WRAP are simple expressions in one of
          these forms:

         `'CONSTANT'
               A constant.

         `VARIABLE'
               A variable.

         `(primitive PRIMITIVE-NAME [ARITY])'
               The primitive procedure named PRIMITIVE-NAME.  The
               optional element ARITY specifies the number of arguments
               that the primitive accepts.

         `(global VAR)'
               A global variable.

        * NULL-OPTION is either `always', `any', `one', `single',
          `none', or `empty'.

        * ORDERING is either `left', `right', or `associative'.

     The meaning of these fields is:

        * NAME is the name of the n-ary operation to be reduced.

        * BINOP is the binary operation into which the n-ary operation
          is to be reduced.

        * The `group' option specifies whether NAME associates to the
          right or left.

        * The `null-value' option specifies a value to use in the
          following cases:

         `none'
         `empty'
               When no arguments are supplied to NAME, VALUE is
               returned.

         `one'
         `single'
               When a single argument is provided to NAME, VALUE becomes
               the second argument to BINOP.

         `any'
         `always'
               BINOP is used on the "last" argument, and VALUE provides
               the remaining argument to BINOP.

          In the above options, when VALUE is supplied to BINOP, it is
          supplied on the left if grouping to the left, otherwise it is
          supplied on the right.

        * The `singleton' option specifies a function, UNOP, to be
          invoked on the single argument given.  This option supersedes
          the `null-value' option, which can only take the value `none'.

        * The `wrapper' option specifies a function, WRAP, to be
          invoked on the result of the outermost call to BINOP after the
          expansion.  If N is provided it must be a non-negative
          integer indicating a number of arguments that are transferred
          verbatim from the original call to the wrapper.  They are
          passed to the left of the reduction.

        * The maximum option specifies that calls with more than M
          arguments should not be reduced.

Efficiency Tips
===============

   How you write your programs can have a large impact on how
efficiently the compiled program runs.  The most important thing to do,
after choosing suitable data structures, is to put the following
declaration near the beginning of the file.

     (declare (usual-integrations))

   Without this declaration the compiler cannot recognize any of the
common operators and compile them efficiently.

   The `usual-integrations' declaration is usually sufficient to get
good quality compiled code.

   If you really need to squeeze more performance out of your code then
we hope that you find the following grab-bag of tips, hints and
explanations useful.