Here is a read-eval-print-loop which, given an eval, evaluates forms.
read
s, repl:eval
s and write
s expressions from
(current-input-port)
to (current-output-port)
until an
end-of-file is encountered. load
, slib:eval
,
slib:error
, and repl:quit
dynamically bound during
repl:top-level
.
repl:top-level
.
The repl:
procedures establish, as much as is possible to do
portably, a top level environment supporting macros.
repl:top-level
uses dynamic-wind
to catch error conditions
and interrupts. If your implementation supports this you are all set.
Otherwise, if there is some way your implementation can catch error
conditions and interrupts, then have them call slib:error
. It
will display its arguments and reenter repl:top-level
.
slib:error
dynamically bound by repl:top-level
.
To have your top level loop always use macros, add any interrupt catching lines and the following lines to your Scheme init file:
(require 'macro) (require 'repl) (repl:top-level macro:eval)
When displaying error messages and warnings, it is paramount that the output generated for circular lists and large data structures be limited. This section supplies a procedure to do this. It could be much improved.
Notice that the neccessity for truncating output eliminates Common-Lisp's See section Format from consideration; even when variables
*print-level*
and*print-level*
are set, huge strings and bit-vectors are not limited.
qp
writes its arguments, separated by spaces, to
(current-output-port)
. qp
compresses printing by
substituting `...' for substructure it does not have sufficient
room to print. qpn
is like qp
but outputs a newline
before returning. qpr
is like qpn
except that it returns
its last argument.
*qp-width*
is the largest number of characters that qp
should use.
Requiring debug
automatically requires trace
and
break
.
An application with its own datatypes may want to substitute its own
printer for qp
. This example shows how to do this:
(define qpn (lambda args) ...) (provide 'qp) (require 'debug)
define
d at top-level in
file `file'.
define
d at
top-level in file `file'.
break
or
abort
, a message will appear when you (require 'break)
or
(require 'debug)
telling you to type (init-debug)
. This
is in order to establish a top-level continuation. Typing
(init-debug)
at top level sets up a continuation for
break
.
breakpoint
is called before calling proc1 ....
The following routines are the procedures which actually do the tracing when this module is supplied by SLIB, rather than natively. If defmacros are not natively supported by your implementation, these might be more convenient to use.
(set! symbol (breakf symbol))
or
(set! symbol (breakf symbol 'symbol))
or
(define symbol (breakf function))
or
(define symbol (breakf function 'symbol))
(set! symbol (unbreakf symbol))
The following routines are the procedures which actually do the tracing when this module is supplied by SLIB, rather than natively. If defmacros are not natively supported by your implementation, these might be more convenient to use.
(set! symbol (tracef symbol))
or
(set! symbol (tracef symbol 'symbol))
or
(define symbol (tracef function))
or
(define symbol (tracef function 'symbol))
(set! symbol (untracef symbol))
This routine implements Posix command line argument parsing. Notice
that returning values through global variables means that getopt
is not reentrant.
(vector-ref argv *optind*)
) that matches a letter in
optstring. argv is a vector or list of strings, the 0th of
which getopt usually ignores. argc is the argument count, usually
the length of argv. optstring is a string of recognized
option characters; if a character is followed by a colon, the option
takes an argument which may be immediately following it in the string or
in the next element of argv.
*optind* is the index of the next element of the argv vector
to be processed. It is initialized to 1 by `getopt.scm', and
getopt
updates it when it finishes with each element of
argv.
getopt
returns the next option character from argv that
matches a character in optstring, if there is one that matches.
If the option takes an argument, getopt
sets the variable
*optarg* to the option-argument as follows:
getopt
returns an error
indication.
If, when getopt
is called, the string (vector-ref argv
*optind*)
either does not begin with the character #\-
or is
just "-"
, getopt
returns #f
without changing
*optind*. If (vector-ref argv *optind*)
is the string
"--"
, getopt
returns #f
after incrementing
*optind*.
If getopt
encounters an option character that is not contained in
optstring, it returns the question-mark #\?
character. If
it detects a missing option argument, it returns the colon character
#\:
if the first character of optstring was a colon, or a
question-mark character otherwise. In either case, getopt
sets
the variable getopt:opt to the option character that caused the
error.
The special option "--"
can be used to delimit the end of the
options; #f
is returned, and "--"
is skipped.
RETURN VALUE
getopt
returns the next option character specified on the command
line. A colon #\:
is returned if getopt
detects a missing argument
and the first character of optstring was a colon #\:
.
A question-mark #\?
is returned if getopt
encounters an option
character not in optstring or detects a missing argument and the first
character of optstring was not a colon #\:
.
Otherwise, getopt
returns #f
when all command line options have been
parsed.
Example:
#! /usr/local/bin/scm ;;;This code is SCM specific. (define argv (program-arguments)) (require 'getopt) (define opts ":a:b:cd") (let loop ((opt (getopt (length argv) argv opts))) (case opt ((#\a) (print "option a: " *optarg*)) ((#\b) (print "option b: " *optarg*)) ((#\c) (print "option c")) ((#\d) (print "option d")) ((#\?) (print "error" getopt:opt)) ((#\:) (print "missing arg" getopt:opt)) ((#f) (if (< *optind* (length argv)) (print "argv[" *optind* "]=" (list-ref argv *optind*))) (set! *optind* (+ *optind* 1)))) (if (< *optind* (length argv)) (loop (getopt (length argv) argv opts)))) (slib:exit)
getopt--
is an extended version of getopt
which parses long option names of the form
`--hold-the-onions' and `--verbosity-level=extreme'.
Getopt--
behaves as getopt
except for non-empty
options beginning with `--'.
Options beginning with `--' are returned as strings rather than
characters. If a value is assigned (using `=') to a long option,
*optarg*
is set to the value. The `=' and value are
not returned as part of the option string.
No information is passed to getopt--
concerning which long
options should be accepted or whether such options can take arguments.
If a long option did not have an argument, *optarg
will be set to
#f
. The caller is responsible for detecting and reporting
errors.
(define opts ":-:b:") (define argc 5) (define argv '("foo" "-b9" "--f1" "--2=" "--g3=35234.342" "--")) (define *optind* 1) (define *optarg* #f) (require 'qp) (do ((i 5 (+ -1 i))) ((zero? i)) (define opt (getopt-- argc argv opts)) (print *optind* opt *optarg*))) -| 2 #\b "9" 3 "f1" #f 4 "2" "" 5 "g3" "35234.342" 5 #f "35234.342"
read-command
converts a command line into a list of strings
suitable for parsing by getopt
. The syntax of command lines
supported resembles that of popular shells. read-command
updates port to point to the first character past the command
delimiter.
If an end of file is encountered in the input before any characters are found that can begin an object or comment, then an end of file object is returned.
The port argument may be omitted, in which case it defaults to the
value returned by current-input-port
.
The fields into which the command line is split are delimited by
whitespace as defined by char-whitespace?
. The end of a command
is delimited by end-of-file or unescaped semicolon (;) or
newline. Any character can be literally included in a field by
escaping it with a backslach (\).
The initial character and types of fields recognized are:
read
starting with this character. The
read
expression is evaluated, converted to a string
(using display
), and replaces the expression in the returned
field.
The comment field differs from the previous fields in that it must be
the first character of a command or appear after whitespace in order to
be recognized. # can be part of fields if these conditions are
not met. For instance, ab#c
is just the field ab#c.
read-dommand-line
and backslashes before newlines in
comments are also ignored.
If (provided? 'getenv)
:
#f
is returned.
If (provided? 'system)
:
These variables and procedures are provided by all implementations.
source
, or compiled
. The cdr of the pathname
should be either a string or a list.
In the following three functions if feature is not a symbol it is assumed to be a pathname.
#t
if feature is a member of *features*
or
*modules*
or if feature is supported by a file already
loaded and #f
otherwise.
(not (provided? feature))
it is loaded if feature
is a pathname or if (assq feature *catalog*)
. Otherwise an
error is signaled.
*features*
if
feature is a symbol and *modules*
otherwise.
#t
if feature is a member of *features*
or
*modules*
or if feature is supported by a file already
loaded. Returns a path if one was found in *catalog*
under the
feature name, and #f
otherwise. The path can either be a string
suitable as an argument to load or a pair as described above for
*catalog*.
Below is a list of features that are automatically determined by
require
. For each item, (provided? 'feature)
will
return #t
if that feature is available, and #f
if
not.
A vicinity is a descriptor for a place in the file system. Vicinities hide from the programmer the concepts of host, volume, directory, and version. Vicinities express only the concept of a file environment where a file name can be resolved to a file in a system independent manner. Vicinities can even be used on flat file systems (which have no directory structure) by having the vicinity express constraints on the file name. On most systems a vicinity would be a string. All of these procedures are file system dependent.
These procedures are provided by all implementations.
in-vicinity
.
program-vicinity
can
return incorrectl values if your program escapes back into a
load
.
slib:load
,
slib:load-source
, slib:load-compiled
,
open-input-file
, open-output-file
, etc. The returned
filename is filename in vicinity. in-vicinity
should
allow filename to override vicinity when filename is
an absolute pathname and vicinity is equal to the value of
(user-vicinity)
. The behavior of in-vicinity
when
filename is absolute and vicinity is not equal to the value
of (user-vicinity)
is unspecified. For most systems
in-vicinity
can be string-append
.
sub-vicinity
will
return a pathname of the subdirectory name of
vicinity.These constants and procedures describe characteristics of the Scheme and underlying operating system. They are provided by all implementations.
char->integer
.
unix
, vms
, macos
, amiga
, or
ms-dos
.
(slib:report-version) => slib "2a3" on scm "4e1" on unix
(slib:report-version)
followed by
almost all the information neccessary for submitting a problem report.
An unspecified value is returned.
(slib:report) => slib "2a3" on scm "4e1" on unix (implementation-vicinity) is "/usr/local/src/scm/" (library-vicinity) is "/usr/local/lib/slib/" (scheme-file-suffix) is ".scm" implementation *features* : bignum complex real rational inexact vicinity ed getenv tmpnam system abort transcript with-file ieee-p1178 rev4-report rev4-optional-procedures hash object-hash delay eval dynamic-wind multiarg-apply multiarg/and- logical defmacro string-port source array-for-each array full-continuation char-ready? line-i/o i/o-extensions pipe implementation *catalog* : (rev4-optional-procedures . "/usr/local/lib/slib/sc4opt") ...
These procedures are provided by all implementations.
#t
if the specified file exists. Otherwise, returns
#f
. If the underlying implementation does not support this
feature then #f
is always returned.
#f
is returned. Otherwise, #t
is
returned.
(tmpnam)
will return different
pathnames.
(current-output-port)
.
Returns the width of port, which defaults to
(current-output-port)
if absent. If the width cannot be
determined 79 is returned.
Returns the height of port, which defaults to
(current-output-port)
if absent. If the height cannot be
determined 24 is returned.
Example:
(identity 3) => 3 (identity '(foo bar)) => (foo bar) (map identity lst) == (copy-list lst)
These were present in Scheme until R4RS (see section `Language changes' in Revised(4) Scheme).
#t
.
#f
.
(last-pair (cons 1 2)) => (1 . 2) (last-pair '(1 2)) => (2) == (cons 2 '())
These procedures are provided by all implementations.
(slib:load-source "foo")
will
load from file `foo.scm'.
If an implementation does not support compiled code then
slib:load
will be identical to slib:load-source
.
eval
returns the value of obj evaluated in the current top
level environment.
slib:eval-load
procedure does not affect the values returned by
current-input-port
and current-output-port
.
#t
, a success status is returned to the
system (if possible). If n is #f
a failure is returned to
the system (if possible). If n is an integer, then n is
returned to the system (if possible). If the Scheme session cannot exit
an unspecified value is returned from slib:exit
.
Go to the first, previous, next, last section, table of contents.