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: BOOL ← IF 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: BOOL ← IF m.nRows = 1 THEN TRUE ELSE FALSE;
dimension: NAT ← IF 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
};