scsh-0.6/doc/user-guide.txt

710 lines
24 KiB
Plaintext

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.