-- File: [Thyme]<Thyme>System>CSIM01>spExpressions.mesa
-- Last editted:
-- by Barth, July 11, 1983 11:04 AM.
-- SChen April 19, 1983 1:00 PM.
-- Wilhelm March 23, 1982 3:41 PM, reformated by Barth and stored under
-- [Cherry]<Barth>Thyme>1.97> .
-- Details at end of file.
DIRECTORY spGlobals, AltoDefs, Real, RealFns;
spExpressions: PROGRAM
IMPORTS spGlobals, Real, RealFns
EXPORTS spGlobals =
BEGIN
OPEN spGlobals;
Types: TYPE = {real, name};
type: Types;
factor: PROCEDURE RETURNS[f: expressionPtr] =
BEGIN
n: namePtr;
SELECT item FROM
leftP =>
BEGIN
next[];
f ← expression[];
IF item = rightP THEN next[] ELSE error[211]
END;
name =>
BEGIN
f ← makeExpr[];
n ← variable[NIL];
type ← IF n # NIL THEN
IF n↑.nType = parmName THEN real ELSE name
ELSE real;
f↑.operands ← load[n, NIL]
END;
number =>
BEGIN
type ← real;
f ← makeExpr[];
f↑.operands ← num[value];
next[]
END;
string =>
BEGIN
type ← real;
f ← makeExpr[];
f↑.operands ← num[LOOPHOLE[newString, REAL]];
next[]
END
ENDCASE => error[209]
END;
unaryExpr: PROCEDURE RETURNS[u: expressionPtr] =
BEGIN
oldItem: itemType;
SELECT item FROM
minus, atSign, upArrow, backSlash, slash, squiggle, vertical =>
BEGIN
oldItem ← item;
next[];
u ← makeExpr[];
SELECT oldItem FROM
minus => u↑.operands ← neg[unaryExpr[]];
atSign => u↑.operands ← abs[unaryExpr[]];
slash => u↑.operands ← sqrt[unaryExpr[]];
squiggle => u↑.operands ← not[unaryExpr[]];
backSlash => u↑.operands ← log[unaryExpr[]];
upArrow => u↑.operands ← exp[unaryExpr[]];
vertical => u↑.operands ← int[unaryExpr[]]
ENDCASE;
IF type > real THEN error[270]
END
ENDCASE => u ← factor[]
END;
powerExpr: PROCEDURE RETURNS[p: expressionPtr] =
BEGIN
p2: expressionPtr;
p ← unaryExpr[];
IF item = upArrow THEN
BEGIN
IF type > real THEN error[270];
next[];
p2 ← makeExpr[];
p2↑.operands ← power[p, unaryExpr[]];
IF type > real THEN error[270];
p ← p2
END
END;
term: PROCEDURE RETURNS[t: expressionPtr] =
BEGIN
mulOp: BOOLEAN;
t2: expressionPtr;
t ← powerExpr[];
IF item = star OR item = slash THEN
IF type > real THEN error[270];
WHILE item = star OR item = slash DO
mulOp ← item = star;
next[];
t2 ← makeExpr[];
IF mulOp THEN t2↑.operands ← mul[t, powerExpr[]]
ELSE t2↑.operands ← div[t, powerExpr[]];
IF type > real THEN error[270];
t ← t2
ENDLOOP
END;
arithExpr: PROCEDURE RETURNS[e: expressionPtr] =
BEGIN
e2: expressionPtr;
e ← term[];
IF (item = plus OR item = minus) OR
(item = maximum OR item = minimum) THEN
IF type > real THEN error[270];
WHILE (item = plus OR item = minus) OR
(item = maximum OR item = minimum) DO
oldItem: itemType← item;
next[];
e2 ← makeExpr[];
SELECT oldItem FROM
plus => e2↑.operands← add[e, term[]];
minus => e2↑.operands← sub[e, term[]];
maximum => e2↑.operands← max[e, term[]];
ENDCASE => e2↑.operands← min[e, term[]];
IF type > real THEN error[270];
e ← e2
ENDLOOP
END;
relExpr: PROCEDURE RETURNS[r: expressionPtr] =
BEGIN
r2: expressionPtr;
oldItem: itemType;
nodeOK: BOOLEAN;
r ← arithExpr[];
SELECT item FROM
greater, less, equal, pound, greatEqual, lessEqual =>
BEGIN
oldItem ← item;
next[];
r2 ← makeExpr[];
nodeOK ← oldItem = equal OR oldItem = pound;
IF type > real AND ~nodeOK THEN error[270];
SELECT oldItem FROM
greater => r2↑.operands ← grt[r, arithExpr[]];
greatEqual => r2↑.operands ← geq[r, arithExpr[]];
less => r2↑.operands ← les[r, arithExpr[]];
lessEqual => r2↑.operands ← leq[r, arithExpr[]];
equal => r2↑.operands ← eq[r, arithExpr[]];
pound => r2↑.operands ← neq[r, arithExpr[]]
ENDCASE;
IF type > real AND ~nodeOK THEN error[270];
type ← real;
r ← r2
END
ENDCASE
END;
andExpr: PROCEDURE RETURNS[e: expressionPtr] =
BEGIN
e2: expressionPtr;
e ← relExpr[];
IF item = amperesand THEN
IF type > real THEN error[270];
WHILE item = amperesand DO
next[];
e2 ← makeExpr[];
e2↑.operands ← and[e, relExpr[]];
IF type > real THEN error[270];
e ← e2
ENDLOOP
END;
expression: PUBLIC PROCEDURE RETURNS[e: expressionPtr] =
BEGIN
e2: expressionPtr;
e ← andExpr[];
IF item = vertical THEN
IF type > real THEN error[270];
WHILE item = vertical DO
next[];
e2 ← makeExpr[];
e2↑.operands ← or[e, andExpr[]];
IF type > real THEN error[270];
e ← e2
ENDLOOP
END;
assignExpr: PUBLIC PROCEDURE[leftContext: circuitNamePtr]
RETURNS[a: expressionPtr] =
BEGIN
v: namePtr;
a ← makeExpr[];
v ← variable[leftContext];
IF v#NIL THEN IF v↑.nType # parmName THEN error[271];
IF item = leftArrow THEN next[] ELSE error[210];
a↑.operands ← store[v, expression[]];
IF type > real THEN error[270]
END;
eval: PUBLIC PROCEDURE[exp: expressionPtr] RETURNS[v: REAL] =
BEGIN
ENABLE
Real.RealException =>
BEGIN
errorCode: CARDINAL;
errorCode ← SELECT TRUE FROM
flags[divisionByZero] => 901,
flags[overflow] => 902,
flags[underflow] => 903,
flags[fixOverflow] => 904,
ENDCASE => 900;
ErrorSignal[errorCode, "?"]
END;
v ← ev[exp]
END;
ev: PROCEDURE[exp: expressionPtr] RETURNS[v: REAL] =
BEGIN
OPEN Real, RealFns;
x, y: REAL;
IF exp # NIL THEN
WITH e: exp↑ SELECT FROM
max => v ← MAX[ev[e.leftOp], ev[e.rightOp]];
min => v ← MIN[ev[e.leftOp], ev[e.rightOp]];
add => v ← ev[e.leftOp] + ev[e.rightOp];
sub => v ← ev[e.leftOp] - ev[e.rightOp];
mul => v ← ev[e.leftOp] * ev[e.rightOp];
div => v ← ev[e.leftOp] / ev[e.rightOp];
eq => v ← IF LOOPHOLE[ev[e.leftOp], LONG CARDINAL] =
LOOPHOLE[ev[e.rightOp], LONG CARDINAL]
THEN 1.0
ELSE 0.0;
neq => v ← IF LOOPHOLE[ev[e.leftOp], LONG CARDINAL] #
LOOPHOLE[ev[e.rightOp], LONG CARDINAL]
THEN 1.0
ELSE 0.0;
grt => v ← IF ev[e.leftOp] > ev[e.rightOp] THEN 1.0
ELSE 0.0;
les => v ← IF ev[e.leftOp] < ev[e.rightOp] THEN 1.0
ELSE 0.0;
geq => v ← IF ev[e.leftOp] >= ev[e.rightOp] THEN 1.0
ELSE 0.0;
leq => v ← IF ev[e.leftOp] <= ev[e.rightOp] THEN 1.0
ELSE 0.0;
and => v ← IF ev[e.leftOp]*ev[e.rightOp] # 0.0 THEN 1.0
ELSE 0.0;
or => v ← IF ev[e.leftOp] # 0.0 OR
ev[e.rightOp] # 0.0 THEN 1.0
ELSE 0.0;
power =>
BEGIN
x ← ev[e.leftOp];
y ← ev[e.rightOp];
IF ABS[y] < 100.0 AND y = FixI[y] THEN
BEGIN
v ← 1.0;
THROUGH[1..ABS[FixI[y]]] DO
v ← v*x
ENDLOOP;
IF y < 0.0 THEN v ← 1.0/v
END
ELSE v ← Power[ev[e.leftOp], ev[e.rightOp]]
END;
int => v ← Real.RoundLI[ev[e.unaryOp]];
abs => v ← ABS[ev[e.unaryOp]];
exp => v ← Exp[ev[e.unaryOp]];
log => v ← Ln[ev[e.unaryOp]];
sqrt => v ← SqRt[ev[e.unaryOp]];
neg => v ← -ev[e.unaryOp];
not => v ← IF ev[e.unaryOp] # 0.0 THEN 0.0 ELSE 1.0;
load => v ← getParmValue[e.var];
store => putParmValue[e.var, ev[e.expr]];
num => v ← e.v
ENDCASE => v ← 0.0
ELSE v ← 0.0
END;
END.
4/19/83:-
original: [Cherry]<Barth>Thyme>1.97>spExpressions.mesa
changes:
1. arithExpr - modified to allow item = minimum or maximum.
2. ev - added MAX and MIN operations.
July 11, 1983 11:04 AM, by Barth
checked for v=NIL in assignExpr