

		     A User's Guide to Scheme 48



    A line may take us hours, yet if it does not seem a moment's thought
    All our stitching and unstitching has been as nought.

    						Yeats
    						Adam's Curse


Introduction

Scheme 48 is an implementation of the Scheme programming language as
described in the Revised^4 Report on the Algorithmic Language Scheme.
It is based on a compiler and interpreter for a virtual Scheme
machine.  The name derives from our desire to have an implementation
that is simple and lucid enough that it looks as if it were written in
just 48 hours.  We don't claim to have reached that stage yet; much
more simplification is necessary.

Scheme 48 tries to be faithful to the upcoming Revised^5 Scheme
Report, providing neither more nor less in the initial user
environment.  (This is not to say that more isn't available in other
environments; see below.)  Support for numbers is weak: bignums are
slow and floating point is almost nonexistent (see description of
floatnums, below).  DEFINE-SYNTAX, LET-SYNTAX, LETREC-SYNTAX, and
SYNTAX-RULES are supported, but not the rest of the Revised^4 Scheme
macro proposal.

The Revised^5 Report hasn't been published yet, but it will be very
similar to the Revised^4 Report.  For a list of differences, see
doc/meeting.tex.

This is what might be called an alpha release.  Please report bugs,
especially in the VM, especially core dumps, to
scheme-48-bugs@altdorf.ai.mit.edu.  Include the version number x.yy
from the "Welcome to Scheme 48 x.yy" greeting message in your bug
report.  It is a goal of this project to produce a bullet-proof
system; we want no bugs and, especially, no crashes.  (There are a few
known bugs, listed in the TODO file that comes with the distribution.)

Send mail to scheme-48-request@altdorf.ai.mit.edu to be put on a
mailing list for announcements, discussion, bug reports, and bug
fixes.

-----

Command line arguments

A few command line arguments are processed by the virtual machine as
it starts up.

    scheme48 [-i image] [-h heapsize] [-o filename] [-s stacksize]
          [-a argument ...]

-i image
    specifies a heap image file to resume.  This defaults to a heap
    image that runs a Scheme command processor.  Heap images are
    created by the ,dump and ,build commands, for which see below.

-h heapsize
    specifies how much space should be reserved for allocation.
    Heapsize is in words (where one word = 4 bytes), and covers both
    semispaces, only one of which is in use at any given time (except
    during garbage collection).  Cons cells are currently 3 words, so
    if you want to make sure you can allocate a million cons cells,
    you should specify -h 6000000 (actually somewhat more than this,
    to account for the initial heap image and breathing room).

-s stacksize
    specifies how much space should be reserved for the continuation
    and environment stack.  If this space is exhausted, continuations
    and environments are copied to the heap.  stacksize is in words
    and defaults to 2500.

-o filename
    This specifies an executable file in which foreign identifiers can be
    looked up for the foreign function interface.  Filename should be the
    file that contains the scheme48vm executable image.  See
    doc/external.txt.

-a argument ...
    is only useful with images built using ,build.  The arguments are
    passed as a list to the procedure specified in the ,build command.
    E.g.

        > ,build (lambda (a) (for-each display a) (newline) 0) foo.image
	> ,exit
	% scheme48vm -i foo.image -a mumble "foo x"
	mumblefoo x
	% 

The usual definition of the "s48" or "scheme48" command is actually a
shell script that starts up the virtual machine with a -i argument
specifying the development environment heap image, and a -o argument
specifying the location of the virtual machine.

-----

Command processor

When you invoke the default heap image, a command processor starts
running.  At the > prompt, you can type either a Scheme form
(expression or definition), or a command beginning with a comma.

Logistical commands:

 ,load <filename> ...                load Scheme source file(s)
    Easier to type than (load "filename") because you don't have to
    shift to type the parentheses or quote marks.  Also, it works in
    any package, unlike (load "filename"), which will work only work
    in packages in which the variable LOAD is defined properly.

 ,exit [<exp>]			     leave
    Exit back out to shell (or executive or whatever invoked Scheme 48
    in the first place).  <exp> should evaluate to an integer.  The
    integer is returned to the calling program.  (On Unix, 0 is
    generally interpreted as success, nonzero as failure.)


Command levels:

  If an errors occurs, you are put in a command loop at the dynamic
  point at which the error occurred.  The prompt will then be "n >"
  where n is the command level nesting depth.
  
 <eof> 
    Pop out one level (running any dynamic-wind "after" thunks), and
    resumes running all non-broken threads.  EOF after a keyboard
    interrupt resumes running the interrupted thread.  <eof> is usually
    control-D at a Unix shell or using the Emacs "cmuscheme48" library.

 ,reset                              top level
    Unwind all the way back out to top level.

 ,level <number>                     go to command level
    Unwind out to a given level.  ,level 0 is the same as ,reset.

 ,push
    Go to a deeper command level.  (See ,levels, below.)


Debugging commands:

 ,preview
    Sort of like a backtrace, but because of tail recursion you see
    less than you might in debuggers for some other languages.

 ,threads
    Invoke the inspector on the threads running on the next level out.

 ,proceed <exp> ...
    Proceed after an interrupt or error, delivering the values of <exp>
    ... to the continuation.

 ,trace <name> ...
    Start tracing calls to the named procedure or procedures.
    With no arguments, displays all procedures currently traced.
    This affects the binding of <name>, not the behavior of the
    procedure that's it's current value.  The effect is similar to
	(define <name> (make-traced <name>))
    where make-traced is a procedure-returning procedure.

 ,untrace <name> ...
    Stop tracing calls to the named procedure or procedures.
    With no argument, stop tracing all calls to all procedures.

 ,condition
    The ,condition command selects and displays the condition object
    describing the error or interrupt that initiated the current
    command level.  This is particularly useful in conjunction with
    the inspector.  E.g. if a procedure is passed the wrong number of
    arguments, do ,condition followed by ,inspect ## to inspect the
    procedure and its arguments.

 ,bound? <name>
    Display the binding of <name>, if there is one.
 
 ,expand <form>
    Show macro expansion of <form>, if any.

 ,where <procedure>
    Display name of source file in which <procedure> is defined.


Building images:

 ,dump <filename> [<identification>]
    This writes out the current heap.  When the new image is resumed,
    it starts in the command processor.  If present, <identification>
    should be a string (written with double quotes); this string will
    be part of the greeting message as the image starts up.

 ,build <exp> <filename>
    <exp> should evaluate to a procedure of one argument.  When
    <filename> is resumed, that procedure will be invoked on the VM's
    -a arguments, which are passed as a list of strings.  The
    procedure should return an integer (as for ,exit).  The command
    processor and debugging system are not included in the image
    (unless you go to some effort to preserve them, such as retaining
    a continuation).

    Doing ",flush" before building an image will make for smaller
    images, but if an error occurs, the error message may be less
    helpful.  Doing ",flush source maps" before loading any programs
    will make the image still smaller.
    


Modes:

When given no argument, all of these commands toggle the corresponding
mode.  With the argument ?, the current setting is displayed.
Otherwise the argument should be ON or OFF.

 ,batch [on | off | ?]
    In "batch mode," any error or interrupt that comes up will cause
    Scheme 48 to exit immediately with a non-zero exit status.  Also,
    the command processor doesn't print prompts.  The default is
    interactive mode.

 ,form-preferred [on | off | ?]
    Enable or disable "form preferred" mode.  In this mode, command
    processor commands needn't be prefixed by comma.  To see the value
    of a variable (or number - this should be fixed), do (begin
    <name>).  "Command preferred" mode is the default.

 ,levels [on | off | ?]
    Enable or disable command levels.  With levels enabled (the
    default), errors "push" a new command level, and <eof> (see above)
    or ,reset is required to return to top level.  The effects of
    pushed command levels include:
      - a longer prompt
      - retention of the continuation in effect at the point of errors
      - longer ,previews
      - confusion among some newcomers
    With levels disabled, one must issue a ,push command immediately
    following an error in order to retain the error continuation for
    debugging purposes; otherwise the continuation is lost after the
    next evaluation request.  If you don't know anything about the
    available debugging tools, then levels might as well be disabled.

    This is an experimental feature inspired by gripes about how
    confusing recursive command loop levels are to newcomers to
    Scheme.  Let me know (jar@ai.mit.edu) if you like it; otherwise it
    might get flushed.

    Each level has its own set of threads, so pushing a new level stops
    all threads running at the current level.
    
 ,break-on-warnings [on | off | ?]
    When a warning is produced, enter a new command level, just as
    when an error occurs.


Resource query and control:

 ,time <exp>
    Measure execution time.

 ,collect
    Invoke the garbage collector.  Ordinarily this happens
    automatically, but the command tells how much space is available
    before and after the collection.

 ,keep <kind>
 ,flush <kind>
    These control the amount of debugging information retained after
    compiling procedures.  This information can consume a fair amount
    of space.  <kind> is one of the following:
     . maps - environment maps (local variable names, for inspector)
     . source - source code for continuations (displayed by inspector)
     . names - procedure names (as displayed by WRITE and in error
       messages)
     . files  - source file names
    These commands refer to future compilations only, not to procedures
    that already exist.  To have any effect, they must be done before
    programs are loaded.

 ,flush
    The flush command with no argument deletes the database of names
    of initial procedures.  Doing ",flush" before a ,build or ,dump
    will make the resulting image significantly smaller (by up to 200K
    bytes), but will compromise the information content of many error
    messages.


Quite obscure:

 ,go <exp>
    This is like ,exit <exp> except that the evaluation of <exp>
    is tail-recursive with respect to the command processor.  This
    means that the command processor itself can probably be GC'ed,
    should a garbage collection occur in the execution of <exp>.
    Any errors will be treated as in batch mode.

 ,translate <from> <to>
    For LOAD and the ,load command (but not for OPEN-xxPUT-FILE), file
    names beginning with the string <from> will be changed so that the
    initial <from> is replaced by the string <to>.  E.g.

        ,translate /usr/gjc/ /zu/gjc/

    will cause (load "/usr/gjc/foo.scm") to have the same effect as
    (load "/zu/gjc/foo.scm").

 ,from-file <filename> <form> ... ,end
    This is used by the cmuscheme48 Emacs library.

Other commands are (or should be) described in the module system
document.

-----

Editing

We recommend running Scheme 48 under Gnu Emacs using the cmuscheme48
command package.  This is in the Scheme 48 distribution's emacs/
subdirectory.  It is a variant of the "cmuscheme" library, which
comes to us courtesy of Olin Shivers, formerly of CMU.  You might want
to put the following in your emacs init file (.emacs):

    (setq scheme-program-name "scheme48")
    (autoload 'run-scheme  "cmuscheme48" "Run an inferior Scheme process." t)

To make the autoload and (require ...) forms work, you will also need
to put the directory containing cmuscheme and related files in your
emacs load-path:

    (setq load-path (append load-path '("<scheme-48-directory>/emacs")))

For further documentation see emacs/cmuscheme48.el and emacs/comint.el.

-----

Performance

If you want to generally have your code run faster than it normally
would, enter "benchmark mode" before loading anything.  Otherwise
calls to primitives (like + and cons) and in-line procedures (like not
and cadr) won't be open-coded, and programs will run more slowly.
Enter benchmark mode by issuing the ,bench command to the command
processor.

The system doesn't start in benchmark mode by default because the
Scheme report permits redefinitions of built-in procedures.  In
benchmark mode, such redefinitions don't work according to the report,
because previously compiled calls may have in-lined the old
definition, leaving no opportunity to call the new definition.

",bench" toggles benchmark mode.  ",bench on" and ",bench off" turn it
on and off.

-----

Inspector

There is a low-tech inspector available via the ,inspect and ,debug
commands.  The ,inspect command starts an inspector command loop.
There is a focus object (the same as the command processor's ##), for
which a menu of selectable components is displayed.  To inspect a
particular component, just type the corresponding number in the menu.
For example:

	,inspect '(a (b c) d)
	(a (b c) d)

	[0] a
	[1] (b c)
	[2] d
	inspect: 1
	(b c)

	[0] b
	[1] c
	inspect: 

When a new object is selected, the previous one is pushed onto a
stack.  You can pop the stack, reverting to the previous object, with
the U command.

The inspector is particularly useful with procedures, continuations,
and records.

Other inspector commands:
	u	pop object stack
	d	down stack (current object must be a continuation)
	m	print more of a long menu
	(...)   evaluate a form and select result
	t	select a closure or continuation's template
	q       quit

## is always the object currently being inspected.  After a Q command,
or an error in the inspector, ## is the last object that was being
inspected.

The inspector also accepts arbitrary command processor commands, e.g.
the ,dis command (see below).  The leading comma is optional.

After an error occurs, ,debug invokes the inspector on the
continuation at the point of the error.  The U and D (up and down)
commands then make the inspector look like a conventional stack
debugger, with continuations playing the role of stack frames.  D goes
to older or deeper continuations (frames), and U goes back up to more
recent ones.

Templates are the static components of procedures; these are found
inside of procedures and continuations, and contain the quoted
constants and top-level variables referred to by byte-compiled code.

-----

Disassembler

The ,dis command disassembles procedures.

	> ,dis cons
	cons
	  0 (check-nargs= 2)
	  2 (pop)
	  3 (make-stored-object 2 pair)
	  6 (return)
	> 

The command argument is optional; if unsupplied it defaults to the
current focus object (##).

The disassembler can also be invoked on continuations and templates.

-----

Module system

For information on the module (package) system, see doc/module.tex.

-----

Library

A number of useful utilities are either built in to Scheme 48 or can
be loaded from an external library.  These utilities are not visible
in the user environment by default, but can be made available with the
,open command.  For example, to use the tables structure, do

    > ,open tables
    > 

If the utility is not already loaded, then the ,open command will
offer to load it:

    > ,open queues
    Load structure queues (y/n)? 

Or, you can load something explicitly (without opening it) using the
load-package command:

    > ,load-package queues
    ...
    > ,open queues

When loading a utility, the message "Note: optional optimizer not
invoked" is innocuous.  Feel free to ignore it.

See also the package system documentation, doc/module.tex.

Unfortunately, few of these wonderful things are documented.  They are
listed, however, in files rts-packages.scm, comp-packages.scm, and
more-packages.scm in the distribution directory, and the bindings they
export are listed in interfaces.scm and more-interfaces.scm.  Here is
a little information on the more generally useful structures.

architecture
    Information about the virtual machine.  E.g.
      (enum op eq?) => the integer opcode of the EQ? instruction

arrays
    Arrays.  See comments at the top of file big/array.scm.

ascii
    CHAR->ASCII and ASCII->CHAR.  Similar to CHAR->INTEGER and
    INTEGER->CHAR except that ASCII encoding is guaranteed.

big-scheme
    Many generally useful features.  See doc/big-scheme.txt.

bigbit
    Extensions to the bitwise logical operators (exported by
    the BITWISE structure) so that they operate on bignums.
    To use these you should do

        ,load-package bigbit
	,open bitwise

bitwise
    Bitwise logical operators.  See doc/big-scheme.txt.

conditions
    Part of the condition system: DEFINE-CONDITION-PREDICATE and
    routines for examining condition objects.  (See also handle,
    signals.)

define-record-types
    A DEFINE-RECORD-TYPE macro, providing a concise front end to the
    record package.  (Richard and Jonathan favor different
    record type defining macros; this one is Jonathan's.)

    The general syntax is:
      (define-record-type <tag> <type-name>
        (<constructor-name> <field-tag>*)
	<predicate-name>
	(<field-tag> <accessor-name> [<modifier-name>])*)

    Example:
      (define-record-type pare :pare
        (kons x y)
	pare?
	(x kar set-kar!)
	(y kdr))
    This defines KONS to be a constructor, KAR and KDR to be
    accessors, SET-KAR! to be a modifier, and PARE? to be a predicate
    for a new type of object.  The type itself is named :PARE.
    PARE is a tag used in printing the new objects.
    The field tags X and Y are used in the inspector and to match
    constructor arguments with fields.

    By default, the new objects print as #{Pare}.  The print method
    can be modified using DEFINE-RECORD-DISCLOSER:
      (define-record-discloser :pare
        (lambda (p) `(pare ,(kar p) ,(kdr p))))

defpackage
    The module system: DEFINE-STRUCTURE and DEFINE-INTERFACE.

defrecord
    A define-record-type macro, providing more concise use of the
    record package.  (Richard and Jonathan favor different
    record type defining macros; this one is Richard's.)

destructuring
    DESTRUCTURE macro.  See doc/big-scheme.txt.

display-conditions
    Displaying condition objects.
        (DISPLAY-CONDITION condition port) => unspecific
	  Display condition in an easily readable form.  E.g.
	  > ,open display-conditions handle conditions
	  > (display-condition
	     (call-with-current-continuation
	       (lambda (k)
		 (with-handler (lambda (c punt)
				 (if (error? c)
				     (k c)
				     (punt)))
		   (lambda () (+ 1 'a)))))
	     (current-output-port))

	  Error: exception
		 (+ 1 'a)
	  > 

enumerated
    Enumerated types.  See doc/big-scheme.txt.

extended-ports
    Ports for reading from and writing to strings, and related things.
    See doc/big-scheme.txt.

externals
    Rudimentary external function interface.  See doc/external.txt.

filenames
    Rudimentary file name parsing and synthesis.  E.g.
    file-name-directory and file-name-nondirectory are as in Gnu emacs.

floatnums
    Floating point numbers.  These are in a very crude state; use at
    your own risk.  They are slow and do not read or print correctly.

fluids
    Dynamically bound "variables."
      (MAKE-FLUID top-level-value) => a "fluid" object
      (FLUID fluid) => current value of fluid object
      (SET-FLUID! fluid value) => unspecific; changes current value of
        fluid object
      (LET-FLUID fluid value thunk) => whatever thunk returns
        Within the dynamic extent of execution of (thunk), the fluid
        object has value as its binding (unless changed by SET-FLUID!
        or overridden by another LET-FLUID).
    E.g.
      (define f (make-fluid 7))
      (define (baz) (+ (fluid f) 1))
      (baz)   ;=> 8
      (let-fluid f 4 (lambda () (+ (baz) 1)))  ;=> 6

formats
    A simple FORMAT procedure, similar to Common Lisp's or T's.
    See doc/big-scheme.txt for documentation.

general-tables
    An extended version of TABLES; supports tables keyed by strings.
    See doc/big-scheme.txt.

handle
    Part of the condition system.
      (WITH-HANDLER handler thunk) => whatever thunk returns.
        handler is a procedure of two arguments.  The first argument
	is a condition object, and the second is a "punt" procedure.
	The handler should examine the condition object (using ERROR?,
	etc. from the CONDITIONS structure).  If it decides not to do
	anything special, it should tail-call the "punt" procedure.
	Otherwise it should take appropriate action and perform a
	non-local exit.  It should not just return unless it knows
	damn well what it's doing; returns in certain situations can
	cause VM crashes.

interrupts
    Interrupt system

ports
    A few extra port-related operations, notably FORCE-OUTPUT.

pp
    A pretty-printer.  (p <exp>) will pretty-print the result of <exp>,
    which must be an S-expression.  (Source code for procedures is not
    retained or reconstructed.)  You can also do (p <exp> <port>) to
    print to a specific port.

    The procedure pretty-print takes three arguments: the object to be
    printed, a port to write to, and the current horizontal cursor
    position.  If you've just done a newline, then pass in zero for
    the position argument.

    The algorithm is very peculiar, and sometimes buggy.

queues
    FIFO queues.

random
    Not-very-random random number generator.  The <seed> should be between
    0 and 2^28 exclusive.

        > (define random (make-random <seed>))
	> (random)  =>  a pseudo-random number between 0 and 2^28

receiving
    Convenient interface to the call-with-values procedure, like
    Common Lisp's multiple-value-bind macro.  See doc/big-scheme.txt.

records
    MAKE-RECORD-TYPE and friends.  See the Scheme of Things column in
    Lisp Pointers, volume 4, number 1, for documentation.

recnums
    Complex numbers.  This should be loaded (e.g. with ,load-package)
    but needn't be opened.

search-trees
    Balanced binary search trees.  See comments at top of
    big/search-tree.scm. 

signals
    ERROR, WARN, and related procedures.

sort
    Online merge sort (see comment at top of file big/sort.scm).

        (sort-list <list> <pred>)
	(sort-list! <list> <pred>)

sicp
    Compatibility package for the Scheme dialect used in the book
    "Structure and Interpretation of Computer Programs."

sockets
    Interface to Unix BSD sockets.  See comments at top of file
    misc/socket.scm.

tables
    Hashed association tables.  Keys are compared using EQ?.
    See doc/big-scheme.txt.

threads
    Multitasking.  See doc/threads.txt.

util
    SUBLIST, ANY, REDUCE, FILTER, and some other useful things.

weak
    Weak pointers and populations.
        (MAKE-WEAK-POINTER thing) => weak-pointer
	(WEAK-POINTER-REF weak-pointer) => thing or #F
	  #F if the thing has been gc'ed.

writing
        (RECURRING-WRITE thing port recur) => unspecific
	  This is the same as WRITE except that recursive calls invoke
	  the recur argument instead of WRITE.  For an example, see
	  the definition of LIMITED-WRITE in env/dispcond.scm, which
	  implements processing similar to common Lisp's *print-level*
	  and *print-length*.

-----

Acknowledgment

Thanks to Deborah Tatar for providing the Yeats quotation.
