ASExprsImpl.mesa
Last Edited by: Arnon, July 19, 1985 2:54:46 pm PDT
DIRECTORY
Rope,
IO,
Basics,
MathExpr,
MathConstructors,
AlgebraClasses,
ASExprs;
ASExprsImpl: CEDAR PROGRAM
IMPORTS Rope, IO, MathConstructors, MathExpr, AlgebraClasses
EXPORTS ASExprs
= BEGIN OPEN ASExprs;
Types
ASExprsError: PUBLIC SIGNAL [reason: ATOM ← $Unspecified] = CODE;
ROPE: TYPE = Rope.ROPE;
Object: TYPE = AlgebraClasses.Object;
Method: TYPE = AlgebraClasses.Method;
EXPR: TYPE ~ MathExpr.EXPR;
MathExprRep: TYPE ~ MathExpr.MathExprRep;
AtomEXPR: TYPE ~ MathExpr.AtomEXPR;
CompoundEXPR: TYPE ~ MathExpr.CompoundEXPR;
MatrixEXPR: TYPE ~ MathExpr.MatrixEXPR;
TaggedMathExpr: TYPE ~ MathExpr.TaggedMathExpr;
ExprFlavors: TYPE ~ MathExpr.ExprFlavors;
AtomClass: TYPE ~ MathExpr.AtomClass;
AtomClassRep: TYPE ~ MathExpr.AtomClassRep;
AtomFlavor: TYPE ~ MathExpr.AtomFlavor;
CompoundClass: TYPE ~ MathExpr.CompoundClass;
CompoundClassRep: TYPE ~ MathExpr.CompoundClassRep;
MatrixClass: TYPE ~ MathExpr.MatrixClass;
MatrixClassRep: TYPE ~ MathExpr.MatrixClassRep;
Argument: TYPE ~ MathExpr.Argument;
Symbol: TYPE ~ MathExpr.Symbol;
Element Representation
ASExprDataRep: TYPE ~
RECORD [
SELECT type:* FROM
atomic => [
op: ATOM, -- type of entity, e.g. $integer, $real, $symbol (our notion of a symbol is essentially that of an "identifier", i.e. a legal "name" which is capable of having an associated value), $string, $char
value: ROPE -- atomic value, e.g. integer as rope. Any legal name (e.g. Greek letter, subscripted variable, etc.) should be an atomic Expr of type $symbol (or we can have types $greekSymbol, $decoratedSymbol, etc., or $name ...). Better to have just one type $symbol, and plan to parse it to determine possible subcomponents, and so the right display.
],
composite => [
op: ATOM, -- operator
args: LIST OF Object ← NIL -- operands
]
ENDCASE
];
ASExprData: TYPE ~ REF ASExprDataRep; -- inside impl module, use rep
Given our assumption of one or more EltToEXPR procs in all domains (see below), allowing arbitrary Objects as subExprs, rather than limiting to Exprs, is essentially just being flexible with regard to the amount of local type inference that has been done on subExprs of an Expr. E.g. if we required subExprs to be Exprs, a user could of course at any time select a subExpr and EltEval (type narrow) it, and indeed he may be imagining in his mind that this has in fact been done for a subExpr of interest. And, of course, application of a EltToEXPR proc can always undo the casting of any subObject as an element of a (narrower) domain. Hence it is appropriate to have a data representation that supports easily going back and forth between the two viewpoints.
Since we can have Expr Objects which are just an "outermost method" applied to Objects belonging to narrower domains, plus the assertion of membership of the whole in the Exprs domain, we make think of Exprs objecthood as a kind of "packaging", or "brush stroke", of collections of (other) Objects, that is tantamount to a declaration that we want to be relaxed, or insensitive, about the type of the total package. And, with EltToEXPR procs, we have always the possibility of propagating this relaxedness to args. And of course, by invoking eltEval$Exprs, we can always abrogate our relaxedness and try to limit the Object to a narrower domain.
Structure Operations
PrintName: PUBLIC AlgebraClasses.PrintNameProc = {
RETURN["ASExprs"];
};
ShortPrintName: PUBLIC AlgebraClasses.PrintNameProc = {
RETURN["ASExprs"];
};
IsExprs: PUBLIC AlgebraClasses.UnaryPredicate = {
RETURN[AlgebraClasses.StructureEqual[arg, ASExprs] ];
};
I/O and Conversion
Recast: PUBLIC AlgebraClasses.BinaryOp = {
RETURN[FromEXPR[AlgebraClasses.ApplyLkpNoRecastExpr[$toExpr, firstArg.class, LIST[firstArg] ], ASExprs ] ];
};
CanRecast: PUBLIC AlgebraClasses.BinaryPredicate = {
RETURN[TRUE];
};
ToEXPR: PUBLIC AlgebraClasses.ToEXPROp = {
RETURN[NARROW[in.data] ];
};
FromEXPR: PUBLIC AlgebraClasses.FromEXPROp = {
RETURN[NEW[AlgebraClasses.ObjectRec ← [
flavor: StructureElement,
class: ASExprs,
data: in
] ] ];
};
LegalFirstChar: PUBLIC AlgebraClasses.LegalFirstCharOp = {
RETURN[char='(];
};
Read: PUBLIC AlgebraClasses.ReadOp ~ {
RETURN[FromEXPR[MathExpr.ExprFromStream[in], ASExprs] ];
};
FromRope: PUBLIC AlgebraClasses.FromRopeOp = {
stream: IO.STREAMIO.RIS[in];
RETURN[ Read[stream, structure] ];
};
ToRope: PUBLIC AlgebraClasses.ToRopeOp = {
data: ASExprData ← NARROW[in.data];
RETURN[ MathExpr.RopeFromEXPR[data] ];
};
Write: PUBLIC AlgebraClasses.WriteOp = {
IO.PutRope[ stream, ToRope[in] ]
};
Arithmetic
Zero: PUBLIC AlgebraClasses.NullaryOp = {
RETURN[ FromEXPR[MathConstructors.MakeInt["0"], ASExprs ] ]
};
One: PUBLIC AlgebraClasses.NullaryOp = {
RETURN[ FromEXPR[MathConstructors.MakeInt["1"], ASExprs ] ]
};
Add: PUBLIC AlgebraClasses.BinaryOp ~ {
firstData: ASExprData ← NARROW[firstArg.data];
secondData: ASExprData ← NARROW[secondArg.data];
RETURN[FromEXPR[MathConstructors.MakeSum[firstData, secondData], ASExprs] ];
};
Negate: PUBLIC AlgebraClasses.UnaryOp ~ {
data: ASExprData ← NARROW[arg.data];
RETURN[FromEXPR[MathConstructors.MakeNegation[data], ASExprs] ];
};
Subtract: PUBLIC AlgebraClasses.BinaryOp ~ {
firstData: ASExprData ← NARROW[firstArg.data];
secondData: ASExprData ← NARROW[secondArg.data];
RETURN[FromEXPR[MathConstructors.MakeDifference[firstData, secondData], ASExprs] ];
};
Multiply: PUBLIC AlgebraClasses.BinaryOp ~ {
firstData: ASExprData ← NARROW[firstArg.data];
secondData: ASExprData ← NARROW[secondArg.data];
RETURN[FromEXPR[MathConstructors.MakeProduct[firstData, secondData], ASExprs] ];
};
Power: PUBLIC AlgebraClasses.BinaryOp ~ { -- this simple algorithm is Structure independent
firstData: ASExprData ← NARROW[firstArg.data];
secondData: ASExprData ← NARROW[secondArg.data];
RETURN[FromEXPR[MathConstructors.MakePow[firstData, secondData], ASExprs] ];
};
Divide: PUBLIC AlgebraClasses.BinaryOp ~ {
firstData: ASExprData ← NARROW[firstArg.data];
secondData: ASExprData ← NARROW[secondArg.data];
RETURN[FromEXPR[MathConstructors.MakeFraction[firstData, secondData], ASExprs] ];
};
Comparison
Equal: PUBLIC AlgebraClasses.BinaryPredicate ~ {
firstData: EXPRNARROW[firstArg.data];
secondData: EXPRNARROW[secondArg.data];
RETURN[EqualSubr[firstData, secondData] ];
};
EqualSubr: PROC [firstData, secondData: EXPR] RETURNS[BOOL] ~ {
WITH firstData SELECT FROM
a: AtomEXPR => {
b: AtomEXPR;
IF NOT ISTYPE[secondData, AtomEXPR] THEN RETURN[FALSE] ELSE b← NARROW[secondData];
IF a.class.name # b.class.name THEN RETURN[FALSE];
IF NOT Rope.Equal[a.value, b.value] THEN RETURN[FALSE];
RETURN[TRUE];
};
c: CompoundEXPR => {
d: CompoundEXPR;
IF NOT ISTYPE[secondData, CompoundEXPR] THEN RETURN[FALSE] ELSE d← NARROW[secondData];
IF c.class.name # d.class.name THEN RETURN[FALSE];
Recursively check for equality of arguments
FOR l: LIST OF Argument ← c.class.arguments, l.rest UNTIL l = NIL DO
cArg: EXPR← MathExpr.GetTaggedExpr[l.first.name, c.subExprs].expression;
dArg: EXPR← MathExpr.GetTaggedExpr[l.first.name, d.subExprs].expression;
IF NOT EqualSubr[cArg, dArg] THEN RETURN[FALSE];
ENDLOOP;
RETURN[TRUE];
};
m: MatrixEXPR => {
n: MatrixEXPR;
l: LIST OF TaggedMathExpr;
IF NOT ISTYPE[secondData, MatrixEXPR] THEN RETURN[FALSE] ELSE n← NARROW[secondData];
IF m.class.name # n.class.name THEN RETURN[FALSE];
Recursively evaluate arguments, find LUB of element Structures
l ← n.elements;
FOR k: LIST OF TaggedMathExpr ← m.elements, k.rest UNTIL k = NIL DO
IF NOT EqualSubr[k.first.expression, l.first.expression] THEN RETURN[FALSE];
l ← l.rest;
ENDLOOP;
RETURN[TRUE];
};
ENDCASE => ERROR;
};
Standard Desired Arg Structures
ASExprsDesired: PUBLIC AlgebraClasses.UnaryToListOp ~ {
Name ASExprs explicitly, instead of using AlgebraClasses.DefaultDesiredArgStructures, so that if a ASExprs method found by lookup from a subclasss, then will recast its args correctly (i.e. to ASExprs)
RETURN[ LIST[ASExprs] ];
};
Start Code
ASExprClass: PUBLIC Object ← AlgebraClasses.MakeClass["ASExprClass", NIL, NIL];
ASExprs: PUBLIC Object ← AlgebraClasses.MakeStructure["ASExprs", ASExprClass, NIL];
categoryMethod: Method ← AlgebraClasses.MakeMethod[Value, FALSE, NEW[AlgebraClasses.Category ← ring], NIL, "category"];
groundStructureMethod: Method ← AlgebraClasses.MakeMethod[Value, FALSE, NIL, NIL, "groundStructure"];
expressionStructureMethod: Method ← AlgebraClasses.MakeMethod[Value, FALSE, NIL, NIL, "expressionStructure"];
shortPrintNameMethod: Method ← AlgebraClasses.MakeMethod[ToRopeOp, FALSE, NEW[AlgebraClasses.ToRopeOp ← ShortPrintName], NIL, "shortPrintName"];
recastMethod: Method ← AlgebraClasses.MakeMethod[BinaryOp, TRUE, NEW[AlgebraClasses.BinaryOp ← Recast], NIL, "recast"];
canRecastMethod: Method ← AlgebraClasses.MakeMethod[BinaryPredicate, TRUE, NEW[AlgebraClasses.BinaryPredicate ← CanRecast], NIL, "canRecast"];
toExprMethod: Method ← AlgebraClasses.MakeMethod[ToEXPROp, FALSE, NEW[AlgebraClasses.ToEXPROp ← ToEXPR], NEW[AlgebraClasses.UnaryToListOp ← ASExprsDesired], "toExpr"];
fromExprMethod: Method ← AlgebraClasses.MakeMethod[FromEXPROp, FALSE, NEW[AlgebraClasses.FromEXPROp ← FromEXPR], NIL, "fromExpr"];
legalFirstCharMethod: Method ← AlgebraClasses.MakeMethod[LegalFirstCharOp, FALSE, NEW[AlgebraClasses.LegalFirstCharOp ← LegalFirstChar], NIL, "legalFirstChar"];
readMethod: Method ← AlgebraClasses.MakeMethod[ReadOp, FALSE, NEW[AlgebraClasses.ReadOp ← Read], NIL, "read"];
fromRopeMethod: Method ← AlgebraClasses.MakeMethod[FromRopeOp, TRUE, NEW[AlgebraClasses.FromRopeOp ← FromRope], NIL, "fromRope"];
toRopeMethod: Method ← AlgebraClasses.MakeMethod[ToRopeOp, FALSE, NEW[AlgebraClasses.ToRopeOp ← ToRope], NIL, "toRope"];
parenMethod: Method ← AlgebraClasses.MakeMethod[UnaryOp, FALSE, NEW[AlgebraClasses.UnaryOp ← AlgebraClasses.Copy], NIL, "paren"];
zeroMethod: Method ← AlgebraClasses.MakeMethod[NullaryOp, FALSE, NEW[AlgebraClasses.NullaryOp ← Zero], NIL, "zero"];
oneMethod: Method ← AlgebraClasses.MakeMethod[NullaryOp, FALSE, NEW[AlgebraClasses.NullaryOp ← One], NIL, "one"];
sumMethod: Method ← AlgebraClasses.MakeMethod[BinaryOp, TRUE, NEW[AlgebraClasses.BinaryOp ← Add], NEW[AlgebraClasses.UnaryToListOp ← ASExprsDesired], "sum"];
negationMethod: Method ← AlgebraClasses.MakeMethod[UnaryOp, TRUE, NEW[AlgebraClasses.UnaryOp ← Negate], NEW[AlgebraClasses.UnaryToListOp ← ASExprsDesired], "negation"];
differenceMethod: Method ← AlgebraClasses.MakeMethod[BinaryOp, TRUE, NEW[AlgebraClasses.BinaryOp ← Subtract], NEW[AlgebraClasses.UnaryToListOp ← ASExprsDesired], "difference"];
productMethod: Method ← AlgebraClasses.MakeMethod[BinaryOp, TRUE, NEW[AlgebraClasses.BinaryOp ← Multiply], NEW[AlgebraClasses.UnaryToListOp ← ASExprsDesired], "product"];
powerMethod: Method ← AlgebraClasses.MakeMethod[BinaryOp, TRUE, NEW[AlgebraClasses.BinaryOp ← Power], NEW[AlgebraClasses.UnaryToListOp ← ASExprsDesired], "power"];
fractionMethod: Method ← AlgebraClasses.MakeMethod[BinaryOp, TRUE, NEW[AlgebraClasses.BinaryOp ← Divide], NEW[AlgebraClasses.UnaryToListOp ← ASExprsDesired], "fraction"];
equalMethod: Method ← AlgebraClasses.MakeMethod[BinaryPredicate, TRUE, NEW[AlgebraClasses.BinaryPredicate ← Equal], NEW[AlgebraClasses.UnaryToListOp ← ASExprsDesired], "equals"];
AlgebraClasses.AddMethodToClass[$category, categoryMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$groundStructure, categoryMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$expressionStructure, expressionStructureMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$shortPrintName, shortPrintNameMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$recast, recastMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$canRecast, canRecastMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$toExpr, toExprMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$fromExpr, fromExprMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$legalFirstChar, legalFirstCharMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$read, readMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$fromRope, fromRopeMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$toRope, toRopeMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$paren, parenMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$zero, zeroMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$one, oneMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$sum, sumMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$negation, negationMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$difference, differenceMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$product, productMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$pow, powerMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$fraction, fractionMethod, ASExprClass];
AlgebraClasses.AddMethodToClass[$eqFormula, equalMethod, ASExprClass]; -- commented 9/27/89, to allow entry of expression with variables to be later evaluated in some environment
AlgebraClasses.InstallStructure[ASExprs]; -- do it later so methods from other structures found first (currently done in EvaluatorImpl)
END.