EvaluatorImpl.mesa
Last Edited by: Arnon, June 10, 1987 8:38:29 am PDT
DIRECTORY
Rope,
Convert,
MathExpr,
MathDisplayExpr,
MathConstructors,
AlgebraClasses,
Structures,
Variables,
Expressions,
Ints,
Matrices,
Sets,
Vectors,
Sequences,
VariableSequences,
Polynomials,
Environment,
Evaluator;
EvaluatorImpl: CEDAR PROGRAM
IMPORTS MathExpr, MathDisplayExpr, MathConstructors, Convert, AlgebraClasses, Structures, Variables, Expressions, Ints, Matrices, Sets, Sequences, VariableSequences, Polynomials, Environment
EXPORTS Evaluator =
BEGIN OPEN AC: AlgebraClasses, SEQ: Sequences, MAT: Matrices, POL: Polynomials, ENV: Environment;
Type and Variable Abbreviations from Imported Interfaces
ROPE: TYPE ~ Rope.ROPE;
Object: TYPE ~ AlgebraClasses.Object;
Method: TYPE ~ AlgebraClasses.Method;
TaggedMathExpr: TYPE ~ MathExpr.TaggedMathExpr;
Argument: TYPE ~ MathExpr.Argument;
EXPR: TYPE ~ MathExpr.EXPR;
AtomEXPR: TYPE ~ MathExpr.AtomEXPR;
CompoundEXPR: TYPE ~ MathExpr.CompoundEXPR;
MatrixEXPR: TYPE ~ MathExpr.MatrixEXPR;
MeddleExprs: AC.Object ~ Expressions.MeddleExprs;
Procedure Abbreviations from Imported Interfaces
LookupMethodInStructure: PROC [methodSelector: ATOM, structure: Object] RETURNS[Method] ~ AlgebraClasses.LookupMethodInStructure;
LookupMethodInAllStructures: PROC [methodSelector: ATOM] RETURNS[method: Method, structure: Object] ~ AlgebraClasses.LookupMethodInAllStructures;
ApplyFromExprMethod: PROC [method: Method, in: EXPR, structure: Object] RETURNS[Object] ~ AlgebraClasses.ApplyFromExprMethod;
ApplyNoLkpNoRecastRef: PROC [method: Method, argList: LIST OF Object] RETURNS[value: REF] ~ AlgebraClasses.ApplyNoLkpNoRecastRef;
ApplyNoLkpNoRecastObject: PROC [method: Method, argList: LIST OF Object] RETURNS[value: Object] ~ AlgebraClasses.ApplyNoLkpNoRecastObject;
GetMethodAndRecastArgs: PROC [methodSelector: ATOM, structure: Object, inArgs: LIST OF Object] RETURNS [ok: BOOL, method: Method, outArgs: LIST OF Object ← NIL] ~ AlgebraClasses.GetMethodAndRecastArgs;
ApplyLkpNoRecastExpr: PROC [methodSelector: ATOM, structure: Object, argList: LIST OF Object] RETURNS[value: EXPR] ~ AlgebraClasses.ApplyLkpNoRecastExpr;
ApplyPredNoLkpNoRecast: PROC [method: Method, argList: LIST OF Object] RETURNS[BOOL] ~ AlgebraClasses.ApplyPredNoLkpNoRecast;
ApplyFromRopeMethod: PROC [method: Method, in: ROPE, structure: Object] ~ AlgebraClasses.ApplyFromRopeMethod; -- why does compiler complain about this?
IsExprs: AC.UnaryPredicate ~ Expressions.IsExprs;
Evaluator
EvalAtom: PROC [a: AtomEXPR, quote: BOOLFALSE, sourceStructureForMethod: Object ← NIL] RETURNS [result: Object] ~ {
Determine some Object value for an AtomEXPR
method: Method;
structure: Object;
IF a.class.name=$variable AND NOT quote THEN { -- if this is an unquoted variable with an assigned value, return that value.
value: EXPRENV.LookupVariable[Convert.AtomFromRope[a.value] ];
IF value#NIL THEN RETURN[Eval[value] ]; -- do one Eval and return
};
method ← IF sourceStructureForMethod # NIL THEN LookupMethodInStructure[a.class.name, sourceStructureForMethod] ELSE NIL; -- try to find method a.class.name, i.e. a constructor named a.class.name, in sourceStructureForMethod; there may or may not be such.
structure ← IF method#NIL THEN sourceStructureForMethod ELSE NIL;
IF method = NIL THEN
[method, structure] ← LookupMethodInAllStructures[a.class.name]; -- look for it anywhere
IF method # NIL THEN {
result ← AC.ApplyFromRopeMethod[method, a.value, structure]; -- a constructor that works on an atom is assumed to be FromRopeOp
RETURN[result];
};
No constructor found for this class of Atoms, so just return the given Atom unevaluated. Thus e.g. a placeholder evaluates to itself.
[method, structure] ← LookupMethodInAllStructures[$fromExpr]; -- we assume that we find this method in the Structure "Expressions", i.e. general expressions
RETURN[ ApplyFromExprMethod[method, a, structure] ];
};
VariableName: PROC [var: EXPR] RETURNS [ROPE] ~ {
WITH var SELECT FROM
a: AtomEXPR => RETURN[a.value];
c: CompoundEXPR => {
methodName: ATOM ← c.class.name;
SELECT methodName FROM -- a functional variable whose EXPR representation is a CompoundEXPR must be a VARIABLE decorated with either subscript, superscript, hat, prime
$subscript, $superscript, $hat, $prime => { -- args assumed to be atoms
atomName: ROPE ← MathDisplayExpr.ASRopeFromDisplayExpr[MathDisplayExpr.DisplayExprFromExpr[c] ]; -- makes a variable name like "aSuperb"
RETURN[atomName];
};
ENDCASE => ERROR;
};
ENDCASE => ERROR;
};
EvalVariable: PROC [var: EXPR, quote: BOOLFALSE, sourceStructureForMethod: Object ← NIL] RETURNS [result: Object] ~ {
Evaluate something which is functionally a variable
WITH var SELECT FROM
a: AtomEXPR => RETURN[EvalAtom[a, quote, sourceStructureForMethod] ];
c: CompoundEXPR => {
methodName: ATOM ← c.class.name;
SELECT methodName FROM -- a functional variable whose EXPR representation is a CompoundEXPR must be a decorated VARIABLE
$subscript, $superscript, $hat, $prime => { -- args assumed to be atoms
atomName: ROPE ← VariableName[c];
tempAtom: AtomEXPR ← NARROW[MathConstructors.MakeVariable[atomName] ];
RETURN[EvalAtom[tempAtom, quote, sourceStructureForMethod] ];
};
ENDCASE => ERROR;
};
ENDCASE => ERROR;
};
Eval: PUBLIC PROC[expr: EXPR, sourceStructureForMethod: Object ← NIL] RETURNS[result: Object] ~ {
effects: Evaluates the input, looking first for (outermost) method in sourceStructureForMethod if nonNIL.
ok: BOOL;
outArgs, outArgsPointer: LIST OF Object;
argObject: Object;
argObjects, argObjectsPointer: LIST OF Object ← NIL; -- cons up list of argument subexprs
WITH expr SELECT FROM
a: AtomEXPR => RETURN[EvalAtom[a, FALSE, sourceStructureForMethod] ];
c: CompoundEXPR => {
methodName: ATOM ← c.class.name;
method, toExprMethod: Method;
argStructure, argLubStructure, structure: Object;
outExpr: EXPR;
newSubExprs, trailer: LIST OF TaggedMathExpr ← NIL;
isVarThisArg: BOOL;
variableArgPresent: BOOL;
fArg: Object;
fName, varName: ROPE;
Check for decorated item; currently anything decorated with subscript, superscript, hat, or prime, assumed to be a functional variable
SELECT methodName FROM
$subscript, $superscript, $hat, $prime =>
RETURN[EvalVariable[expr, FALSE, sourceStructureForMethod] ];
ENDCASE;
Check for quote method
IF methodName=$quote THEN {
argExpr: EXPR ← MathExpr.GetTaggedExpr[c.class.arguments.first.name, c.subExprs].expression;
RETURN[Expressions.FromExpr[argExpr, Expressions.MeddleExprs] ];
};
Check for assignment method (note: assignment is being viewed as a special case of Eval, rather than as a method belonging to some Structure)
IF methodName=$assign THEN {
lhsArg, rhsArg: Object;
rhsExpr: EXPR;
lhsArg ← EvalVariable[
var: NARROW[MathExpr.GetTaggedExpr[c.class.arguments.first.name, c.subExprs].expression],
quote: TRUE, -- don't evaluate variable being assigned to
sourceStructureForMethod: NIL
]; -- left hand side is expected to be a functional variable
varName ← NARROW[lhsArg.data];
rhsArg ← Eval[MathExpr.GetTaggedExpr[c.class.arguments.rest.first.name, c.subExprs].expression];
toExprMethod ← AC.LookupMethodInStructure[$toExpr, rhsArg.class];
rhsExpr ← NARROW[AC.ApplyNoLkpNoRecastRef[toExprMethod, LIST[rhsArg] ] ];
ENV.InstallVariable[Convert.AtomFromRope[varName], rhsExpr];
RETURN[rhsArg];
};
Recursively evaluate arguments
FOR l: LIST OF Argument ← c.class.arguments, l.rest UNTIL l = NIL DO
argObject: Object ← Eval[MathExpr.GetTaggedExpr[l.first.name, c.subExprs].expression];
IF argObjects = NIL THEN argObjects ← argObjectsPointer ← LIST[argObject] ELSE argObjectsPointer ← argObjectsPointer.rest ← LIST[argObject];
ENDLOOP;
Check for function method; if so then reset method and argList
SELECT methodName FROM
$nullaryFunction, $unaryFunction, $binaryFunction, $ternaryFunction, $quaternaryFunction => {
fArg ← argObjects.first;
fName ← NARROW[fArg.data];
argObjects ← argObjects.rest;
methodName ← Convert.AtomFromRope[fName];
};
ENDCASE;
Look for method in suggested structure, if any
IF sourceStructureForMethod # NIL THEN {
[ok, method, outArgs] ← GetMethodAndRecastArgs[methodName, sourceStructureForMethod, argObjects];
IF ok THEN RETURN[NARROW[ApplyNoLkpNoRecastRef[method, outArgs] ] ];
};
Look for method in argument structures (if any)
FOR l: LIST OF Object ← argObjects, l.rest UNTIL l = NIL DO
argObject ← l.first;
[ok, method, outArgs] ← GetMethodAndRecastArgs[methodName, argObject.class, argObjects];
IF ok THEN RETURN[ApplyNoLkpNoRecastObject[method, outArgs] ];
ENDLOOP;
Next look for method in LUB of argument Structures, if any, using Z[var] instead of Variables.Variables as their Structure for any arguments that are variables
IF argObjects # NIL THEN {
variableArgPresent ← isVarThisArg ← Sets.IsVariable[argObjects.first];
IF isVarThisArg THEN
argLubStructure ← argStructure ← SimplePolyStructureForVar[argObjects.first]
ELSE
argLubStructure ← argStructure ← argObjects.first.class;
FOR l: LIST OF Object ← argObjects.rest, l.rest UNTIL l = NIL DO
argObject ← l.first;
isVarThisArg ← Sets.IsVariable[argObject];
variableArgPresent ← variableArgPresent OR isVarThisArg;
IF isVarThisArg THEN argStructure ← SimplePolyStructureForVar[argObject] ELSE argStructure ← argObject.class;
argLubStructure ← BinaryStructureLUB[argLubStructure, argStructure];
ENDLOOP;
[ok, method, outArgs] ← GetMethodAndRecastArgs[methodName, argLubStructure, argObjects];
IF ok THEN RETURN[ApplyNoLkpNoRecastObject[method, outArgs] ];
If some args are variables, then try again to find method in LUB of argument Structures, using their actual Structures for any arguments that are variables
IF variableArgPresent THEN {
argLubStructure ← argObjects.first.class;
FOR l: LIST OF Object ← argObjects.rest, l.rest UNTIL l = NIL DO
argObject ← l.first;
argLubStructure ← BinaryStructureLUB[argLubStructure, argObject.class];
ENDLOOP;
[ok, method, outArgs] ← GetMethodAndRecastArgs[methodName, argLubStructure, argObjects];
IF ok THEN RETURN[ApplyNoLkpNoRecastObject[method, outArgs] ];
};
};
Next look for method in any structure
[method, structure] ← LookupMethodInAllStructures[methodName];
IF method # NIL THEN {
[ok, method, outArgs] ← GetMethodAndRecastArgs[methodName, structure, argObjects]; -- the Exprs recast proc will ToExpr the evaluated args
IF ok THEN RETURN[ApplyNoLkpNoRecastObject[method, outArgs] ];
};
Treat method as a noun function and return the GeneralExpression MethodName(Eval'd args).
For a function, begin by restoring function name
SELECT c.class.name FROM
$nullaryFunction, $unaryFunction, $binaryFunction, $ternaryFunction, $quaternaryFunction => argObjects ← CONS[fArg, argObjects];
ENDCASE;
Replace evaluated arguments.
FOR l: LIST OF Argument ← c.class.arguments, l.rest UNTIL l = NIL DO
taggedExpr: TaggedMathExpr ← MathExpr.GetTaggedExpr[l.first.name, c.subExprs];
argObject: Object ← argObjects.first;
taggedExpr.expression ← ApplyLkpNoRecastExpr[$toExpr, argObject.class, LIST[argObject] ];
IF newSubExprs = NIL THEN newSubExprs ← trailer ← LIST[taggedExpr] ELSE trailer ← trailer.rest ← LIST[taggedExpr];
argObjects ← argObjects.rest;
ENDLOOP;
outExpr ← MathExpr.MakeCompoundExpr[c.class.name, newSubExprs]; -- use c.class.name instead of methodName since latter will have been reset if function
[method, structure] ← LookupMethodInAllStructures[$expressionStructure]; -- avoid having to explicitly name the Structure GeneralExpressions
RETURN[NEW[AC.ObjectRec ← [
flavor: StructureElement,
class: structure,
data: outExpr
] ] ];
};
m: MatrixEXPR => {
className: ATOM ← m.class.name;
elementStructure, matrixStructure, structure: Object ← NIL;
matrixStructureConstructorMethod, vectorStructureConstructorMethod, sequenceStructureConstructorMethod: Method;
matrixStructureConstructor: REF AC.MatrixStructureConstructor;
vectorStructureConstructor: REF AC.VectorStructureConstructor;
sequenceStructureConstructor: REF AC.SequenceStructureConstructor;
recastMethod, matrixMethod: Method;
isVarThisArg: BOOL;
argStructure: Object;
argObject: Object;
Recursively evaluate arguments, find LUB of element Structures, using Z[var] instead of Variables.Variables as their Structure for any arguments that are variables
FOR l: LIST OF TaggedMathExpr ← m.elements, l.rest UNTIL l = NIL DO
argObject ← Eval[l.first.expression];
isVarThisArg ← Sets.IsVariable[argObject];
IF isVarThisArg THEN argStructure ← SimplePolyStructureForVar[argObject] ELSE argStructure ← argObject.class;
elementStructure ← BinaryStructureLUB[elementStructure, argStructure];
IF argObjects = NIL THEN argObjects ← argObjectsPointer ← LIST[argObject] ELSE argObjectsPointer ← argObjectsPointer.rest ← LIST[argObject];
ENDLOOP;
For block, return last element
SELECT className FROM
$point => RETURN[argObject];
ENDCASE;
Recast elements into LUBStructure
recastMethod ← LookupMethodInStructure[$recast, elementStructure];
outArgs ← outArgsPointer ← NIL;
FOR l: LIST OF Object ← argObjects, l.rest UNTIL l = NIL DO
recastArg: Object ← ApplyNoLkpNoRecastObject[recastMethod, LIST[l.first, elementStructure] ];
IF outArgs = NIL THEN outArgs ← outArgsPointer ← LIST[recastArg] ELSE outArgsPointer ← outArgsPointer.rest ← LIST[recastArg];
ENDLOOP;
Create matrix or vector Structure, then element of it
SELECT className FROM
$set => {
[sequenceStructureConstructorMethod, structure] ← LookupMethodInAllStructures[$makeFamilyOfSetsStructure];
sequenceStructureConstructor ← NARROW[sequenceStructureConstructorMethod.value];
matrixStructure ← sequenceStructureConstructor^[elementStructure];
matrixMethod ← LookupMethodInStructure[$set, matrixStructure];
};
$sequence => {
row: BOOLIF m.nRows = 1 THEN TRUE ELSE FALSE;
[sequenceStructureConstructorMethod, structure] ← LookupMethodInAllStructures[$makeSequenceStructure];
sequenceStructureConstructor ← NARROW[sequenceStructureConstructorMethod.value];
matrixStructure ← sequenceStructureConstructor^[elementStructure, row];
matrixMethod ← LookupMethodInStructure[$sequence, matrixStructure];
};
$vector => {
row: BOOLIF m.nRows = 1 THEN TRUE ELSE FALSE;
dimension: NATIF row THEN m.nCols ELSE m.nRows;
[vectorStructureConstructorMethod, structure] ← LookupMethodInAllStructures[$makeVectorStructure];
vectorStructureConstructor ← NARROW[vectorStructureConstructorMethod.value];
matrixStructure ← vectorStructureConstructor^[elementStructure, dimension, row];
matrixMethod ← LookupMethodInStructure[$vector, matrixStructure];
};
$matrix => {
[matrixStructureConstructorMethod, structure] ← LookupMethodInAllStructures[$makeMatrixStructure];
matrixStructureConstructor ← NARROW[matrixStructureConstructorMethod.value];
matrixStructure ← matrixStructureConstructor^[elementStructure, m.nRows, m.nCols];
matrixMethod ← LookupMethodInStructure[$matrix, matrixStructure];
};
ENDCASE => ERROR;
RETURN[ApplyNoLkpNoRecastObject[matrixMethod, CONS[matrixStructure, outArgs] ] ]; -- make Structure arg the first Arg here; this is what Apply procs expect
};
ENDCASE => ERROR;
};
SimplePolyStructureForVar: PUBLIC AC.UnaryOp ~ {
assumes that arg is a variable represented as an element of a SingleSetStructure
coeffRing: AC.Object ← Ints.Ints;
one: AC.Object ← Ints.One[Ints.Ints];
variableSeq: VariableSequences.VariableSequence;
variable: Object ← Sets.UnderlyingSetUniverseEltFromSSSElt[arg];
variableSeq ← SEQ.MakeSequence[LIST[variable], VariableSequences.VariableSequences];
RETURN[POL.MakePolynomialStructure[Ints.Ints, variableSeq] ];
};
SimpleBinaryStructureLUB: PUBLIC AC.BinaryStructureLUBOp ~ {
canRecastMethod: Method;
canRecast: BOOL;
Trivial cases
IF firstStructure = NIL THEN RETURN[secondStructure];
IF secondStructure = NIL THEN RETURN[firstStructure];
IF IsExprs[firstStructure] OR IsExprs[secondStructure] THEN RETURN[MeddleExprs];
IF AC.StructureEqual[firstStructure, secondStructure] THEN RETURN[firstStructure];
If canRecast elts of secondStructure to firstStructure, then call firstStructure the LUB
canRecastMethod ← LookupMethodInStructure[$canRecast, firstStructure];
canRecast 𡤊pplyPredNoLkpNoRecast[canRecastMethod, LIST[secondStructure, firstStructure] ];
IF canRecast THEN RETURN[firstStructure];
If canRecast elts of firstStructure to secondStructure, then call secondStructure the LUB
canRecastMethod ← LookupMethodInStructure[$canRecast, secondStructure];
canRecast 𡤊pplyPredNoLkpNoRecast[canRecastMethod, LIST[firstStructure, secondStructure] ];
IF canRecast THEN RETURN[secondStructure];
RETURN[NIL]; -- give up
};
BinaryStructureLUB: PUBLIC AC.BinaryStructureLUBOp ~ {
Favors matrices over polynomials, i.e. tries to make matrices of polynomials before making polynomials with matrix coefficients.
firstArgGround, firstArgMatrix, firstArgPolynomial: BOOL;
secondArgGround, secondArgMatrix, secondArgPolynomial: BOOL;
lub: AC.Object;
Try SimpleBinaryStructureLUB
lub ← SimpleBinaryStructureLUB[firstStructure, secondStructure];
IF lub#NIL THEN RETURN[lub];
firstArgGround ← AC.LookupMethodInStructure[$groundStructure, firstStructure]#NIL;
firstArgMatrix ← ( AC.LookupMethodInStructure[$matrixStructure, firstStructure]#NIL );
firstArgPolynomial ← ( AC.LookupMethodInStructure[$polynomialStructure, firstStructure]#NIL );
secondArgGround ← ( AC.LookupMethodInStructure[$groundStructure, secondStructure]#NIL );
secondArgMatrix ← ( AC.LookupMethodInStructure[$matrixStructure, secondStructure]#NIL );
secondArgPolynomial ← ( AC.LookupMethodInStructure[$polynomialStructure, secondStructure]#NIL );
IF firstArgGround AND secondArgGround THEN RETURN[MeddleExprs]; -- SimpleBinaryStructureLUB failed
IF firstArgPolynomial THEN {
baseCoeffLub: Object;
firstData: Polynomials.PolynomialRingData ← NARROW[firstStructure.data];
baseCoeffRing: Object ← firstData.baseCoeffRing;
SELECT TRUE FROM
secondArgGround => {
baseCoeffLub ← BinaryStructureLUB[baseCoeffRing, secondStructure];
RETURN[Polynomials.MakePolynomialStructure[baseCoeffLub, firstData.allVariables] ];
};
secondArgPolynomial => {
secondData: Polynomials.PolynomialRingData ← NARROW[secondStructure.data];
mergedAllVariableList: VariableSequences.VariableSequence;
baseCoeffLub ← BinaryStructureLUB[baseCoeffRing, secondData.baseCoeffRing];
mergedAllVariableList ← VariableSequences.MergeVariableSequences[firstData.allVariables, secondData.allVariables];
RETURN[Polynomials.MakePolynomialStructure[baseCoeffLub, mergedAllVariableList] ];
};
secondArgMatrix => {
matrixStructureData: MAT.MatrixStructureData ← NARROW[secondStructure.data];
elementStructure: Object ← matrixStructureData.elementStructure;
lub: Object;
If either matrix elementStructure, or polynomial baseCoeffRing, are GeneralExpressions, we know what to do. Favor Matrices(GeneralExpressions) to Polynomials(GeneralExpressions)
IF Expressions.IsExprs[elementStructure] THEN RETURN[secondStructure];
IF Expressions.IsExprs[baseCoeffRing] THEN RETURN[firstStructure];
Try to make matrices of polynomials, rather than polynomials with matrix coefficients, i.e. first check if can join polynomial Structure with matrix elementStructure
lub ← BinaryStructureLUB[firstStructure, elementStructure];
IF NOT Expressions.IsExprs[lub] THEN RETURN[MAT.MakeMatrixStructure[lub, matrixStructureData.nRows, matrixStructureData.nCols] ];
Next see if matrices can be joined with poly base coeffs
baseCoeffLub ← BinaryStructureLUB[baseCoeffRing, secondStructure];
IF NOT Expressions.IsExprs[baseCoeffLub] THEN RETURN[POL.MakePolynomialStructure[baseCoeffLub, firstData.allVariables] ];
Return matrices of GeneralExpressions
RETURN[MAT.MakeMatrixStructure[MeddleExprs, matrixStructureData.nRows, matrixStructureData.nCols] ];
};
ENDCASE;
};
IF secondArgPolynomial THEN {
baseCoeffLub: Object;
secondData: Polynomials.PolynomialRingData ← NARROW[secondStructure.data];
baseCoeffRing: Object ← secondData.baseCoeffRing;
SELECT TRUE FROM
firstArgGround => {
baseCoeffLub ← BinaryStructureLUB[firstStructure, baseCoeffRing];
RETURN[Polynomials.MakePolynomialStructure[baseCoeffLub, secondData.allVariables] ];
};
firstArgMatrix => {
matrixStructureData: MAT.MatrixStructureData ← NARROW[firstStructure.data];
elementStructure: Object ← matrixStructureData.elementStructure;
lub: Object;
If either matrix elementStructure, or polynomial baseCoeffRing, are GeneralExpressions, we know what to do. Favor Matrices(GeneralExpressions) to Polynomials(GeneralExpressions)
IF Expressions.IsExprs[elementStructure] THEN RETURN[firstStructure];
IF Expressions.IsExprs[baseCoeffRing] THEN RETURN[secondStructure];
Try to make matrices of polynomials, rather than polynomials with matrix coefficients, i.e. first check if can join polynomial Structure with matrix elementStructure
lub ← BinaryStructureLUB[elementStructure, secondStructure];
IF NOT Expressions.IsExprs[lub] THEN RETURN[MAT.MakeMatrixStructure[lub, matrixStructureData.nRows, matrixStructureData.nCols] ];
Next see if matrices can be joined with poly base coeffs
baseCoeffLub ← BinaryStructureLUB[firstStructure, baseCoeffRing];
IF NOT Expressions.IsExprs[baseCoeffLub] THEN RETURN[POL.MakePolynomialStructure[baseCoeffLub, secondData.allVariables] ];
Return matrices of GeneralExpressions
RETURN[MAT.MakeMatrixStructure[MeddleExprs, matrixStructureData.nRows, matrixStructureData.nCols] ];
};
ENDCASE;
};
IF firstArgMatrix THEN {
elementLub: Object;
matrixStructureData: MAT.MatrixStructureData ← NARROW[firstStructure.data];
elementStructure: Object ← matrixStructureData.elementStructure;
SELECT TRUE FROM
secondArgGround => {
elementLub ← BinaryStructureLUB[elementStructure, secondStructure];
RETURN[MAT.MakeMatrixStructure[elementLub, matrixStructureData.nRows, matrixStructureData.nCols] ];
};
secondArgMatrix => {
secondMatrixStructureData: MAT.MatrixStructureData ← NARROW[secondStructure.data];
secondElementStructure: Object ← secondMatrixStructureData.elementStructure;
lub: Object;
IF matrixStructureData.nRows#secondMatrixStructureData.nRows THEN RETURN[MeddleExprs];
IF matrixStructureData.nCols#secondMatrixStructureData.nCols THEN RETURN[MeddleExprs];
If either matrix elementStructure is GeneralExpressions, return Matrices(GeneralExpressions)
IF Expressions.IsExprs[elementStructure] THEN RETURN[firstStructure];
IF Expressions.IsExprs[secondElementStructure] THEN RETURN[secondStructure];
Join element Structures
lub ← BinaryStructureLUB[elementStructure, secondElementStructure];
RETURN[MAT.MakeMatrixStructure[lub, matrixStructureData.nRows, matrixStructureData.nCols] ];
};
ENDCASE;
};
IF secondArgMatrix THEN {
elementLub: Object;
matrixStructureData: MAT.MatrixStructureData ← NARROW[secondStructure.data];
elementStructure: Object ← matrixStructureData.elementStructure;
SELECT TRUE FROM
firstArgGround => {
elementLub ← BinaryStructureLUB[firstStructure, elementStructure];
RETURN[MAT.MakeMatrixStructure[elementLub, matrixStructureData.nRows, matrixStructureData.nCols] ];
};
ENDCASE;
};
RETURN[MeddleExprs]; -- Catchall; currently (4/27/87) never should reach here
};
KillAll: PUBLIC AC.TrueNullaryOp ~ {
effects: Resets (i.e. destroys) the Environment
Environment.ResetEnvironment[];
RETURN[Variables.FromRope["done"] ];
};
KillVariable: PUBLIC AlgebraClasses.UnaryOp ~ {
effects: delete the value, if any, associated with (possibly decorated) Environment variable arg. Only needed if want to delete the name arg from the Environment, not if want to give arg a new value.
argStructure: Object ← arg.class;
argExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, argStructure, LIST[arg] ] ];
Environment.RemoveVariable[Convert.AtomFromRope[VariableName[argExpr] ] ];
RETURN[Variables.FromRope["done"] ];
};
Hacks
SquareMatrixFromFunction: PUBLIC AlgebraClasses.QuaternaryOp ~ {
SquareMatrixFromFunction[function, rowIndex, colIndex, size]; Result is a size x size matrix of general expressions. prior values of rowIndex and colIndex are destroyed; at exit they have value size
funExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, firstArg.class, LIST[firstArg] ] ];
rowIndexExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, secondArg.class, LIST[secondArg] ] ];
colIndexExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, thirdArg.class, LIST[thirdArg] ] ];
size: NAT ← Ints.ToINT[fourthArg];
matrixStructure: Object ← Matrices.MakeMatrixStructure[Expressions.MeddleExprs, size, size];
elements, trailer: LIST OF Object ← NIL;
i, j: NAT ← 1;
FOR i IN [1..size] DO
[] ← Eval[MathExpr.MakeCompoundExpr[$assign, LIST[ [$lhs, rowIndexExpr], [$rhs, MathConstructors.MakeInt[Convert.RopeFromInt[i]]] ] ] ];
FOR j IN [1..size] DO
element, elementExprObject: Object;
elementExpr: EXPR;
[] ← Eval[MathExpr.MakeCompoundExpr[$assign, LIST[ [$lhs, colIndexExpr], [$rhs, MathConstructors.MakeInt[Convert.RopeFromInt[j]]] ] ] ];
element ← Eval[funExpr];
elementExpr ← NARROW[AC.ApplyLkpNoRecastRef[$toExpr, element.class, LIST[element] ] ];
elementExprObject ← Expressions.FromExpr[elementExpr, Expressions.MeddleExprs];
IF elements=NIL THEN elements ← trailer ← LIST[elementExprObject] ELSE trailer ← trailer.rest ← LIST[elementExprObject];
ENDLOOP;
ENDLOOP;
RETURN[Matrices.MakeMatrix[elements, matrixStructure] ];
};
MatrixFromRowSequence: PUBLIC AlgebraClasses.UnaryOp ~ {
MatrixFromRowSequence[rowSequence]; rowSequence is a Sequence of Vectors over any Domain(s), all of same dimension; Result is a nRows x nCols matrix of general expressions, where nRows is length of rowSequence, and nCols is dimension of each row. The elements of the output matrix are obtained by evaluation of (the Exprs obtained) from the appropriate vector elements.
rowSequenceData: Sequences.SequenceData ← NARROW[arg.data];
nRows: NAT ← rowSequenceData.lengthPlus1 - 1;
firstRow: Object ← rowSequenceData[1];
firstRowStructureData: Vectors.VectorStructureData ← NARROW[firstRow.class.data];
nCols: NAT ← firstRowStructureData.dimension;
matrixStructure: Object ← Matrices.MakeMatrixStructure[Expressions.MeddleExprs, nRows, nCols];
elements, trailer: LIST OF Object ← NIL;
FOR i:NAT IN [1..nRows] DO
row: Object ← rowSequenceData[i];
rowData: Vectors.VectorData ← NARROW[row.data];
FOR j:NAT IN [1..nCols] DO
funExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, rowData[j].class, LIST[rowData[j]] ] ];
element: Object ← Eval[funExpr];
elementExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, element.class, LIST[element] ] ];
elementExprObject: Object ← Expressions.FromExpr[elementExpr, Expressions.MeddleExprs];
IF elements=NIL THEN elements ← trailer ← LIST[elementExprObject] ELSE trailer ← trailer.rest ← LIST[elementExprObject];
ENDLOOP;
ENDLOOP;
RETURN[Matrices.MakeMatrix[elements, matrixStructure] ];
};
SequenceFromIteration: PUBLIC AlgebraClasses.QuaternaryOp ~ {
SequenceFromIteration[function, variable, start, finish]; Result is a sequence of general expressions. prior value of variable is destroyed; at exit has value finish
funExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, firstArg.class, LIST[firstArg] ] ];
variableExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, secondArg.class, LIST[secondArg] ] ];
start: NAT ← Ints.ToINT[thirdArg];
finish: NAT ← Ints.ToINT[fourthArg];
sequenceStructure: Object ← Sequences.MakeSequenceStructure[elementStructure: Expressions.MeddleExprs, row: TRUE];
elements, trailer: LIST OF Object ← NIL;
FOR i: NAT IN [start..finish] DO
element, elementExprObject: Object;
elementExpr: EXPR;
[] ← Eval[MathExpr.MakeCompoundExpr[$assign, LIST[ [$lhs, variableExpr], [$rhs, MathConstructors.MakeInt[Convert.RopeFromInt[i]]] ] ] ];
element ← Eval[funExpr];
elementExpr ← NARROW[AC.ApplyLkpNoRecastRef[$toExpr, element.class, LIST[element] ] ];
elementExprObject ← Expressions.FromExpr[elementExpr, Expressions.MeddleExprs];
IF elements=NIL THEN elements ← trailer ← LIST[elementExprObject] ELSE trailer ← trailer.rest ← LIST[elementExprObject];
ENDLOOP;
RETURN[Sequences.MakeSequence[elements, sequenceStructure] ];
};
Iteration: PUBLIC AlgebraClasses.QuaternaryOp ~ {
Iteration[function, variable, start, finish]; Result is value of last iteration. prior value of variable is destroyed; at exit has value finish
funExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, firstArg.class, LIST[firstArg] ] ];
variableExpr: EXPRNARROW[AC.ApplyLkpNoRecastRef[$toExpr, secondArg.class, LIST[secondArg] ] ];
start: NAT ← Ints.ToINT[thirdArg];
finish: NAT ← Ints.ToINT[fourthArg];
element: Object;
FOR i: NAT IN [start..finish] DO
[] ← Eval[MathExpr.MakeCompoundExpr[$assign, LIST[ [$lhs, variableExpr], [$rhs, MathConstructors.MakeInt[Convert.RopeFromInt[i]]] ] ] ];
element ← Eval[funExpr];
ENDLOOP;
RETURN[element];
};
Start Code
killVariableMethod: Method ← AC.MakeMethod[UnaryOp, TRUE, NEW[AC.UnaryOp ← KillVariable], NIL, "killVariable"];
killAllMethod: Method ← AC.MakeMethod[TrueNullaryOp, TRUE, NEW[AC.TrueNullaryOp ← KillAll], NIL, "killAll"];
squareMatrixFromFunctionMethod: Method ← AC.MakeMethod[QuaternaryOp, TRUE, NEW[AC.QuaternaryOp ← SquareMatrixFromFunction], NIL, "squareMatrixFromFunction"];
iterationMethod: Method ← AC.MakeMethod[QuaternaryOp, TRUE, NEW[AC.QuaternaryOp ← Iteration], NIL, "iteration"];
sequenceFromIterationMethod: Method ← AC.MakeMethod[QuaternaryOp, TRUE, NEW[AC.QuaternaryOp ← SequenceFromIteration], NIL, "sequenceFromIteration"];
matrixFromRowSequenceMethod: Method ← AC.MakeMethod[UnaryOp, TRUE, NEW[AC.UnaryOp ← MatrixFromRowSequence], NIL, "matrixFromRowSequenceMethod"];
AC.AddMethodToClass[$killVariable, killVariableMethod, Structures.StructuresClass];
AC.AddMethodToClass[$killAll, killAllMethod, Structures.StructuresClass];
AC.AddMethodToClass[$squareMatrixFromFunction, squareMatrixFromFunctionMethod, Structures.StructuresClass];
AC.AddMethodToClass[$squareMatrixFunction, squareMatrixFromFunctionMethod, Structures.StructuresClass];
AC.AddMethodToClass[$sMFF, squareMatrixFromFunctionMethod, Structures.StructuresClass];
AC.AddMethodToClass[$iteration, iterationMethod, Structures.StructuresClass];
AC.AddMethodToClass[$it, iterationMethod, Structures.StructuresClass];
AC.AddMethodToClass[$sequenceFromIteration, sequenceFromIterationMethod, Structures.StructuresClass];
AC.AddMethodToClass[$sFI, sequenceFromIterationMethod, Structures.StructuresClass];
AC.AddMethodToClass[$matrixFromRowSequence, matrixFromRowSequenceMethod, Structures.StructuresClass];
AC.AddMethodToClass[$mFRS, matrixFromRowSequenceMethod, Structures.StructuresClass];
AC.InstallStructure[Expressions.MeddleExprs]; -- do it now so methods from other structures found first by LookupMethodInAllStructures
END.