.rm CM
.nr PS 12
.ps 12
.nr VS 14
.vs 14
.de (C
.nr PS -2
.nr VS -2
.nr LL 5.5i
.IP
..
.de )C
.sp .5c
.nr PS +2
.nr VS +2
.nr LL 6i
..
.DS C
.LG
.LG
.sp |2c
\fBMagic Tutorial #S-1: The scheme command-line interpreter
.ds LH Magic Tutorial #S-1
.ds RH \*(DY
.ds CF - % -
.sp 1c
.NL
\fIRajit Manohar\fR
.sp 1c
Department of Computer Science
California Institute of Technology
Pasadena, CA 91125

.SM
This tutorial corresponds to Magic version 6.5-scm.


.DE
.SM
.LP
\fBTutorials to read first:\fR
.IP
Read reference [1].
.br
.LP
\fBCommands introduced in this tutorial:\fR
.IP
lots of scheme functions
.LP
\fBMacros introduced in this tutorial:\fR
.IP
none
.br
.NL
.sp 1c
.NH 1
Introduction
.PP
Magic's original command-line interpreter has some limitations. Some of 
these include the absence of definitions with arguments, block structure,
the ability to define complex functions. We describe an extension which
is almost completely backward compatible with the existing magic
command-line syntax, but permits the use of Scheme on the command-line.
.NH 1
Backward compatibility
.PP
To permit existing magic source files to work within the scheme interpreter,
we have had to sacrifice one feature of the magic command-line syntax. Single
quotes can only be used to quote a single character. The reason for this
limitation is that \fIunmatched\fR quotes are used by scheme to stop
evaluation of the next input symbol.

Parentheses are used by the scheme interpreter. If you use parentheses
outside single or double quotes in your magic source files, you might
find that the source files don't work properly. To circumvent this
problem, simply put your parentheses in double quotes. You can also
use backslashes to quote parentheses as in:
.DS I
\fB:macro \\( "echo hello"
.DE
 Another thing
you may notice is that floating-point numbers are parsed as such, and
therefore a command such as
.DS I
\fB:echo 5.3
.DE
would display the string \fB5.300000\fR. If you really want the string
\fB5.3\fR, use:
.DS I
\fB:echo "5.3"
.DE

If this difference is undesirable, the scheme interpreter can be
turned off at compile-time. Talk to your local magic maintainer if you
want this done. We feel that the minor trouble taken in modifying
existing magic source files will be outweighed by the advantage of
using a more powerful layout language.

.NH 1
The scheme interpreter
.PP
The interpreter supports a subset of the scheme language. The features
of scheme that are missing include character types,
vector types, file input/output, complex numbers, the distinction
between exact and inexact arithmetic, quasi-quotations, and
continuations.

.NH 2
Command-line interaction
.PP
When
interacting with the command-line of magic, the interpreter implicitly
parenthesizes its input. For example, the command
.DS I
\fB:paint poly
.DE
would be interpreted as the scheme expression
.DS I
\fB(paint poly)
.DE
This has exactly the same effect as the original expression, because
all existing magic command-line functions are also scheme functions.
Since the valid magic commands vary from window to window, the return
value of the function is a boolean that indicates whether the command
was valid for the current window.

.PP
The boolean \fBscm-echo-result\fR controls whether or not the result
of the evaluation is displayed. If the variable does not exist, or the
variable is not boolean-valued, the result of evaluation is not
echoed. Since the input is implicitly parenthesized, typing in
.DS I
\fB:scm-echo-result
.DE
would not display the value of the variable, since it would be
evaluated as:
.DS I
\fB(scm-echo-result)
.DE
To display the value of a variable, use the built-in procedure
\fBeval\fR as follows:
.DS I
\fB:eval scm-echo-result
.DE
This would result in the expression:
.DS I
\fB(eval scm-echo-result)
.DE
which would have the desired effect. (Note that for this to actually
display anything, the value of \fBscm-echo-result\fR must be \fB#t\fR,
and so examining its value is really a futile exercise---which is why
it is an example, of course!)

.NH 2
Types of arguments
.PP
Since scheme expressions are typed, we may need to examine the
type of a particular expression. The following functions return
booleans, and can be used to determine the type of an object.

\fB#t\fR and \fB#f\fR are constants representing the booleans true and
false. A standard scheme convention is to name functions that return
booleans with a name ending with ``?''. The built-in functions conform
to this convention.

The expression \fIexpr\fR is evaluated, and the type of the result of
evaluation is checked.

.KF
.TS
center box;
l|l.
\fB(boolean? \fIexpr\fB)	\fB#t\fR if \fIexpr\fR is a boolean
_
\fB(symbol? \fIexpr\fB)	\fB#t\fR if \fIexpr\fR is a symbol
_
\fB(list? \fIexpr\fB)	\fB#t\fR if \fIexpr\fR is a list
_
\fB(pair? \fIexpr\fB)	\fB#t\fR if \fIexpr\fR is a pair
_
\fB(number? \fIexpr\fB)	\fB#t\fR if \fIexpr\fR is a number
_
\fB(string? \fIexpr\fB)	\fB#t\fR if \fIexpr\fR is a string
_
\fB(procedure? \fIexpr\fB)	\fB#t\fR if \fIexpr\fR is a procedure
.TE
For example,
.DS I
\fB(boolean? #t)\fI => #t
\fB(number? #t)\fI => #f
.DE
.KE



.NH 2
Lists and pairs
.PP
A pair is a record structure with two fields, called the car and cdr
fields (for historical reasons). Pairs are used primarily to represent
lists. A list can be defined recursively as either the empty list, or
a pair whose cdr field is a list. The following functions are used to
extract these fields and to construct new pairs and lists.
.KF
.TS
center box;
l|l.
\fB(car \fIpair\fB)\fR	the car field of \fIpair\fR
_
\fB(cdr \fIpair\fB)\fR	the cdr field \fIpair\fR
_
\fB(cons \fIobj1 obj2\fB)\fR	a new pair whose car field is
	\fIobj1\fR and cdr field is \fIobj2\fR
_
\fB(list \fIarg1 ...\fB)\fR	a new list consisting of its arguments
_
\fB(null? \fIlist\fB)\fR	\fB#t\fR if \fIlist\fR is the empty list
_
\fB(length \fIlist\fB)\fR	the number of elements in \fIlist\fR
.TE
.KE

For example,
.DS I
\fB(car '(a b c))\fI => a
\fB(cdr '(a b c))\fI => (b c)
\fB(cons 'a '(b c))\fI => (a b c)
\fB(list 'a 'b 'c)\fI => (a b c)
\fB(null? '(a b))\fI => #f
\fB(null? ())\fI => #t
.DE

The car field and cdr field of a pair can be set using the following two
functions.

.KF
.TS
center box;
l|l.
\fB(set-car!  \fIpair obj\fB)\fR	sets the car field of \fIpair\fR
	to \fIobj\fR. It returns the new pair
_
\fB(set-cdr!  \fIpair obj\fB)\fR	sets the cdr field of \fIpair\fR
	to \fIobj\fR. It returns the new pair
.TE
.KE

These two functions have \fIside-effects\fR, another feature that
distinguishes scheme from pure lisp. Another naming convention
followed is that functions that have side-effects end in ``!''.

Try the following sequence in magic:
.DS I
\fB(define x '(a b))\fI => (a b)
\fB(set-car! x 'c)\fI => (c b)
\fB(set-cdr! x '(q))\fI => (c q)
\fB(set-cdr! x 'q)\fI => (c . q)
.DE

After the last statement, the value of x is no longer a list but a
pair.

.NH 2
Arithmetic
.PP
The interpreter supports both floating-point and integer
arithmetic. The basic arithmetic functions are supported.

.KF
.TS
center box;
l|l.
\fB(+ \fInum1 num2\fB)\fR	the sum \fInum1\fR+\fInum2\fR
_
\fB(- \fInum1 num2\fB)\fR	the difference \fInum1\fR-\fInum2\fR
_
\fB(* \fInum1 num2\fB)\fR	the product \fInum1\fR*\fInum2\fR
_
\fB(/ \fInum1 num2\fB)\fR	the quotient \fInum1\fR/\fInum2\fR
_
\fB(truncate \fInum\fB)\fR	the integer part of \fInum\fR
.TE
.KE

The division operator checks for division by zero, and 	promotes
integers to floating-point if deemed necessary. Floating-point numbers
can be converted into integers by truncation. The range of a number
can be checked using the following predicates:

.KF
.TS
center box;
l|l.
\fB(zero? \fInum\fB)\fR	\fB#t\fR if \fInum\fR is zero
_
\fB(positive? \fInum\fB)\fR	\fB#t\fR if \fInum\fR is positive
_
\fB(negative? \fInum\fB)\fR	\fB#t\fR if \fInum\fR is negative
.TE
.KE

.NH 2
Strings
.PP
The interpreter supports string manipulation. String manipulation can
be useful for interaction with the user as well as constructing names
for labels.
.KF
.TS
center box;
l|l.
\fB(string-append \fIstr1 str2\fB)\fR	the string formed by concatenating
	\fIstr1\fR and \fIstr2\fR
_
\fB(string-length \fIstr\fB)\fR	the length of string \fIstr\fR
_
\fB(string-compare \fIstr1 str2\fB)\fR	a positive, zero, or negative number
	depending on whether \fIstr1\fR is lexicographically
	greater, equal to, or less than \fIstr2\fR
_
\fB(string-ref \fIstr int\fB)\fR	the numerical value of the character
	stored at position \fIint\fR in \fIstr\fR
	(The first character is at position 0.)
_
\fB(string-set! \fIstr int1 int2\fB)\fR	sets character in string \fIstr\fR
	at position \fIint1\fR to \fIint2\fR
_
\fB(substring \fIstr int1 int2\fB)\fR	returns substring of \fIstr\fR from position
	\fIint1\fR (inclusive) to \fIint2\fR (exclusive)
.TE
.KE

Strings can be used to convert to and from various types.

.KF
.TS
center box;
l|l.
\fB(number->string \fInum\fB)\fR	the string corresponding to the
	representation of \fInum\fR
_
\fB(string->number \fIstr\fB)\fR	the number corresponding to \fIstr\fR
_
\fB(string->symbol \fIstr\fB)\fR	a symbol named \fIstr\fR
_
\fB(symbol->string \fIsym\fB)\fR	the string corresponding to
	the name of \fIsym\fR
.TE
.KE

.NH 2
Bindings and functions
.PP
An object (more accurately, the \fIlocation\fR where the object is
stored)  can be bound to a symbol using the following two functions:

.KF
.TS
center box;
l|l.
\fB(define \fIsym expr\fB)\fR	bind \fIexpr\fR to \fIsym\fR, creating
	a new symbol if necessary
	and return \fIexpr\fR
_
\fB(set! \fIsym expr\fB)\fR	bind \fIexpr\fR to an existing symbol
	\fIsym\fR and return \fIexpr\fR
.TE
.(C
(Note: these functions do not evaluate their first argument.)
.)C
.KE

The difference between the two is that \fBdefine\fR introduces a new
binding, whereas \fBset!\fR modifies an existing binding. In both
cases, \fIexpr\fR is evaluated, and the result is bound to the symbol
\fIsym\fR. The result of the evaluation is also returned.

.DS I
\fB(define x 4)\fI  =>  4
.DE

Functions can be defined using lambda expressions. Typically a
function is bound to a variable. If required, a lambda expression or
built-in function can be applied to a list.

.KF
.TS
center box;
l|l.
\fB(lambda \fIlist obj\fB)\fR	a new function
.TE
.(C
(Note: a lambda does not evaluate its arguments.)
.)C
.KE

\fIlist\fR is a list of symbol names, and \fIobj\fR is the expression
that corresponds to the body of the function. For example,
.DS I
\fB(lambda (x y z) (+ (+ x y) z))\fI => #proc
.DE
is a function that takes three arguments and returns their sum. It can
be bound to a symbol using \fBdefine\fR.
.DS I
\fB(define sum3 (lambda (x y z) (+ (+ x y) z)))\fI => #proc
.DE
Now, we can use \fBsum3\fR like any other function.
.DS I
\fB(sum3 5 3 8)\fI => 16
.DE

A function can be applied to a list using \fBapply\fR.

.KF
.TS
center box;
l|l.
\fB(apply \fIproc list\fB)\fR	apply \fIproc\fR to \fIlist\fR
.TE
.(C
(Note: both \fIproc\fR and \fIlist\fR are evaluated before
application.)
.)C
.KE

\fIlist\fR is used as the list of arguments for the function. For
instance, an alternative way to sum the three numbers in the example
above is:
.DS I
\fB(apply sum3 '(3 5 8))\fI => 16
.DE

An alternative method for creating bindings is provided by the
\fBlet\fR mechanism.
.KF
.TS
center box;
l|l.
\fB(let \fIbinding-list expr\fB)\fR	evaluate \fIexpr\fR after the
	bindings have been performed
_
\fB(let* \fIbinding-list expr\fB)\fR	evaluate \fIexpr\fR after the
	bindings have been performed
_
\fB(letrec \fIbinding-list expr\fB)\fR	evaluate \fIexpr\fR after the
	bindings have been performed
.TE
.KE

The \fIbinding-list\fR is a list of bindings. Each binding is a list
containing a symbol and an expression. The expression is evaluated and
bound to the symbol. In the case of \fBlet\fR, all the expressions are
evaluated before binding them to any symbol; \fBlet*\fR, on the other
hand, evaluates an expression and binds it to the symbol before
evaluating the next expression. \fBletrec\fR permits bindings to refer
to each other, permitting mutually recursive function definitions.
The evaluation order is defined to be from left to right in all
cases. After performing the bindings, \fIexpr\fR is evaluated with the
new bindings in effect and the result is returned.

\fBlet\fR bindings can be used in interesting ways. An example of
their use is provided later.

Scheme is an eager language, and only a few functions do not evaluate
all their arguments (definitions and conditionals). Evaluation can be
controlled to some degree using the following two functions:

.TS
center box;
l|l.
\fB(quote \fIobj\fB)\fR	the unevaluated object \fIobj\fR
_
\fB(eval \fIobj\fB)\fR	evaluates object \fIobj\fR
.TE

.NH 2
Control structures
.PP
Since scheme is a functional programming language, functions that are
usually written using loops are written using recursion. Conditional
constructs are used to terminate the recursion. These constructs are
slightly different in that they do not evaluate all their arguments
(otherwise recursive functions would not terminate!). 

.TS
center box;
l|l.
\fB(if \fIexpr arg1 arg2\fB)	evaluate \fIexpr\fR and evaluate one
	of \fIarg1\fR or \fIarg2\fR
.TE

The \fBif\fR construct evaluates its first argument (which must result
in a boolean), and if the result is \fB#t\fR evaluates \fIarg1\fR and
returns the result; otherwise \fIarg2\fR is evaluated and returned.

For instance, the standard factorial function might be written as:

.DS I
\fB(define fact (lambda (x) (if (positive? x) (* x (fact (- x 1))) 1)))
.DE

A more complicated form of conditional behavior is provided by \fBcond\fR.

.TS
center box;
l|l.
\fB(cond \fIarg1 arg2 ...\fB)\fR	generalized conditional
.TE

Each argument consists of a list which contains two expressions. The
first expression is evaluated (and must evaluate to a boolean), and if
it is true the second expression is evaluated and returned as the
result of the entire expression. If the result was false, the next
argument is examined and the above procedure is repeated. If all
arguments evaluate to false, the result is undefined.

For instance if \fBx\fR was a list, the expression
.DS I
\fB(cond ((null? x) x) ((list? x) (car x)) (#t (echo "error")))\fI
.DE
would return the empty list if \fBx\fR was the empty list and the
first element from the list otherwise. When \fBx\fR is not a list, an
error message is displayed. Note that \fBecho\fR is a standard magic
command.


Often one needs to evaluate a number of expressions in
sequence (since the language has side-effects). The \fBbegin\fR
construct can be used for this purpose.

.TS
center box;
l|l.
\fB(begin \fIarg1 arg2 ...\fB)\fR	sequencing construct
.TE

\fBbegin\fR evaluates each of its arguments in sequence, and returns
the result of evaluating its last argument.


.NH 2
Interaction with layout
.PP
All standard magic commands are also scheme functions. This permits
one to write scheme functions that interact with the layout
directly. Apart from the standard magic commands, the following scheme
functions are provided so as to enable the user to edit layout.

.TS
center box;
l|l.
\fB(getbox)\fR	a list containing four members
	(llx lly urx ury)
_
\fB(getpaint \fIstr\fB)\fR	a list containing the boxes
	from layer \fIstr\fR under the current box that have
	paint in them
_
\fB(getlabel \fIstr\fB)\fR	a list containing the labels
	under the current box that match \fIstr\fR
_
\fB(magic \fIsym\fB)\fR	forces \fIsym\fR to be interpreted as
	a magic command
.TE

The pairs (llx,lly) and (urx,ury) correspond to magic coordinates for
the lower left and upper right corner of the current
box. \fBgetpaint\fR returns a list of boxes (llx lly urx ury), and
\fBgetlabel\fR returns a list of tagged boxes (label llx lly urx ury)
which contain the label string. \fBmagic\fR can be used to force the
scheme interpreter to interpret a symbol as a magic procedure. The
evaluation returns the specified magic command.

.NH 2
Miscellaneous
.PP
Some additional functions are provided to enable the user to debug
functions.

.TS
center box;
l|l.
\fB(showframe)\fR	display the current list of bindings
_
\fB(display-object \fIobj\fB)\fR	display the type and value
	of \fIobj\fR
_
\fB(error \fIstr\fB)\fR	display error message and abort evaluation
_
\fB(eqv? \fIobj1 obj2\fB)\fR	checks if two objects are equal
_
\fB(collect-garbage)\fR	force garbage collection
.TE

The following is a complete list of the built-in scheme variables that
can be used to control the interpreter.

.TS
center box;
l|l.
\fBscm-library-path\fR	a colon-separated path string
_
\fBscm-echo-result\fR	a boolean used to determine if the result
	of evaluation should be displayed
_
\fBscm-trace-magic\fR	controls display of actual magic commands
_
\fBscm-echo-parser-input\fR	controls display of the string sent
	to the scheme parser
_
\fBscm-echo-parser-output\fR	controls display of the result of
	parsing
_
\fBscm-stack-display-depth\fR	controls the number of frames displayed
	in the stack trace output when an
	error occurs during evaluation
_
\fBscm-gc-frequency\fR	controls the frequency of garbage collection
.TE


.NH 2
Libraries
.PP
The following function loads in a file and evaluates its contents in order.

.TS
center box;
l|l.
\fB(load-scm \fIstr\fB)\fR	reads scheme commands in from the named
	file
_
\fB(save-scm \fIstr obj\fB)\fR	appends \fIobj\fR to the file \fIstr\fR,
	creating a new file if necessary
.TE

The file can be in the current directory, or in any of the
locations specified by a string containing a colon-separated list of
directory names stored in \fBscm-library-path\fR.

The format of these files differs from standard magic source files
because the contents of a line are not implicitly
parenthesized. In addition, semicolons are used as a comment
character; everything following a semicolon to the end of the current
line is treated as a comment. 

For instance,

.DS I
\fBdefine f (lambda (x) x)
.DE

would define \fBf\fR to be the identity function when placed in a
magic source file (so as to provide backward compatibility). The same
definition would result in an error if placed in a scheme source
file. 

.DS I
\fB(define f (lambda (x) x))
.DE

The above expression should be used in the scheme file to achieve the
same effect.



.NH 1
References
.IP [1]
H. Abelson and G.J. Sussman, \fIStructure and Interpretation of Computer
Programs\fR.

.IP [2]
H. Abelson et al. \fIRevised Report on the Algorithmic Language Scheme\fR.
