JunoAlgebra.mesa
Written July, 1982 by Donna M. Auguste and Greg Nelson
Edited September 7, 1982 10:58 pm
Edited September 8, 1982 10:59 pm
Last Edited by: Gnelson, October 11, 1983 4:15 pm
Last Edited by: Stolfi, May 31, 1984 4:22:02 pm PDT

This module is concerned with the interpretation of Juno symbolic expressions. It defines the semantics of the Juno language.

DIRECTORY

JunoStorage USING [Point, Coords],
Rope USING [ROPE];

JunoAlgebra: DEFINITIONS =

BEGIN OPEN Stor: JunoStorage;

- - - - SYMBOLIC EXPRESSIONS

Se: TYPE = REF ANY; -- Symbolic Expression. Either:

ATOM (variable, operator, or function name)
REF REAL, REF INT
ROPE
LIST OF Se of the form (operator arg) or (operator arg arg)

- - - - VALUES

Value: TYPE = REF ANY; -- the result of evaluating a Symbolic Expression. Either:

REF REAL, REF INT
ROPE
Point (see JunoStorage)
LIST OF Value

ValueList: TYPE = LIST OF Value;

- - - - IMPORTED TYPES

Point: TYPE = Stor.Point;

Coords: TYPE = Stor.Coords;

- - - - RESERVED ATOMS
and: READONLY ATOM;
approx: READONLY ATOM; -- '~' symbol (hint/initial value for local variable)
assign: READONLY ATOM; -- ':=' symbol
at: READONLY ATOM; -- 'at' constraint
ccw: READONLY ATOM;
colon: READONLY ATOM; -- ':' infix operator (lambda expression)
comma: READONLY ATOM; -- ',' (concatenate sequences of values)
cong: READONLY ATOM;
dec: READONLY ATOM; -- decrement by 1
do: READONLY ATOM;
draw: READONLY ATOM;
ends: READONLY ATOM;
face: READONLY ATOM; -- infix; sets face (bold, italic, etc) for folowing prints
fill: READONLY ATOM;
font: READONLY ATOM; -- infix; sets font for following prints
hor: READONLY ATOM;
if: READONLY ATOM;
inc: READONLY ATOM; -- increment by one
justified: READONLY ATOM; -- infix; sets justification (left, center, right) for folowing prints.
lambda: READONLY ATOM; -- infix; separates parm list from body in lambdas (faked for now).
leftPren: READONLY ATOM;
minus: READONLY ATOM; -- '-' operator (unary or binary)
obox: READONLY ATOM; -- "or" ("else if") box to separate alternatives in if/do statements
paint: READONLY ATOM;
para: READONLY ATOM;
perp: READONLY ATOM;
print: READONLY ATOM;
rel: READONLY ATOM;
rightArrow: READONLY ATOM; -- '->' ("then") operator for if/do sataements
semicolon: READONLY ATOM;
size: READONLY ATOM; -- infix; sets font size for folowing prints
skip: READONLY ATOM; -- 'skip' ("do nothing") statement
stroke: READONLY ATOM;
suchThat: READONLY ATOM; -- '|' (separates declaations from constraints)
true: READONLY ATOM; -- 'true' atom (for empty constraint lists)
ver: READONLY ATOM;
width: READONLY ATOM;

- - - - ALISTS

AList: TYPE = LIST OF REF ANY; -- Association list.

Of the form (atom value atom value ... atom value)

GetDef: PROC [name: ATOM, alist: AList] RETURNS [value: Value];
Returns NIL if not found.

AddDef: PROC [name: ATOM, value: Value, alist: AList]
RETURNS [newAlist: AList];
Prepends name-value pair to the alist. Gets storage from pool if available.

- - - - EXPRESSION EVALUATION

Comand mode vs. eval mode:

The cmd flag in Eval and Apply specifies that the given Se should be interpreted as an executable command, rather than a value -returning expression.

If cmd = false, an atomic expr is looked up in the varable alist, and the result returned without further evaluations. If cmd=FALSE, atomic exprs are looked up in the proc file alist; the result must be a parameterless lambda, that is evaluated again (In juno, a call to a parameterless procedure Foo is written ``Foo'' instead of "Foo()").

Some operations (like print and draw) are allowed only if cmd=TRUE; conversely, others (such as unary minus) are allowed only when cmd=FALSE. Note that function arguments are always evaluated with cmd=FALSE, and the left part of "A; B" is always evaluated with cmd=TRUE.

Eval: PROC [expr: Se, alist: AList, cmd: BOOLFALSE] RETURNS [value: Value];
Evaluates expr using the given alist for variables, and the current proc file for functions.

Apply: PROC[op: Se, args: ValueList, cmd: BOOLFALSE] RETURNS [value: Value];
Applies the given operation to the given arguments.
Both op and args are assumed to be evaluated; op is NOT looked up in the proc file.
The op may be a lambda expression: (lambda (comma <parm> ...) <body>).

EvalError: SIGNAL [what: Rope.ROPE] RETURNS [value: Value];
Raised by Eval and Apply on run-time errors.

- - - - PROCEDURE CALL

Call: PROC[func: ATOM, args: ValueList];
Similar to Apply, but evaluates op first (i.e., uses op if intrinsic function, else uses its current definition obtained from proc file). The args are assumed to be already evaluated.

- - - - MISCELLANEOUS SUPPORT ROUTINES

Car: PROC [r: Se] RETURNS [Se];

Cdr: PROC [r: Se] RETURNS [Se];

Cadr: PROC [r: Se] RETURNS [Se];

Caddr: PROC [r: Se] RETURNS [Se];

Cddr: PROC [r: Se] RETURNS [Se];

END.

- - - - JUNK

Shouldn't this be in the parser world?

VerdictAndCulprit: TYPE = RECORD [verdict: Verdict, culprit: Se];
Culprit relevant only if verdict is No or OfCourseNot

Verdict: TYPE = {Yes, No, OfCourseNot}; -- Yes == innocent

WellFormedDef: PUBLIC PROC [f: Se] RETURNS [VerdictAndCulprit];