-- 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