MathObjectsImpl.mesa
Copyright © 1989 by Xerox Corporation. All rights reserved.
Arnon, August 28, 1989 1:42:36 pm PDT
DIRECTORY
SafeStorage,
IO,
Atom,
Rope,
Basics,
Imager,
MathExpr,
MathObjects;
MathObjectsImpl: CEDAR PROGRAM
IMPORTS Rope
EXPORTS MathObjects
= BEGIN
Types From Other Interfaces
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Private Type Reps
ObjectRep: TYPE = RECORD [
class: Object ← NIL,
data: REFNIL
];
Object: TYPE ~ REF ObjectRep; -- inside impl module, use rep
MethodRep: TYPE = RECORD [
staticType: ATOM,
name of method's "static type", which is a specification of the numbers (arities) of its inputs and outputs, and "some" information about their types. I.e. static types denote families of similar methods. Used for "dispatch on name of static type" invocation of methods (following check (and possible parameter recasting) that actual parameters conform to this method's "runtime type", which is computed afresh at each invocation of this method) via a global Alist of method types and corresponding method apply procs. The actual ATOM here is a selector into that global AList.
Static types themselves are generally defined (via type declarations) in some Cedar interface. Hence if some of a method's args are Cedar types (rather than MathStructures), this can be expressed in its static type.
Should the system be able to "verbalize" static types, so e.g. an external client can get them?
runtimeType: REF UnaryToTwoListsOp ← NIL,
PROC [Structure] RETURNS [LIST[args: LIST OF arg Structures, results: LIST OF result Structures] ]
Runtime type checking of Object args to this method; none done if = NIL.
Point of passing in a Structure (usually the Structure to which this method belongs) is that runtime types are typically (uniquely) parametrized by it.
Construed as "desired" arg Structures: assume, for example, that the args of this method are expected to be Elements (and not Structures). Here is the processing we will do to RecastArgs. Consider arg A with Structure S (S is either a Domain or View). If desired Structure Q is a Domain, and Q # S, we try to convert A into Q by first trying Q's Widen and Narrow procs (for direct Sub or Super Domain relations), then try to find a path from S to Q in the global Domain lattice. We may fail and exit. If Q is a Category, let C be S's Category. First check Q = C, or Q is a superCategory of C via "basic" inheritance, or via the global Category lattice. If success, create a (new Structure which is a) View V of S as Q, and create a new Object whose class is V and whose data is A.data. Suppose Q is a View, with underlying Domain D. Suppose S is a Domain. Then, as above, see if S can be converted to D; if so, then make the appropriate new Object in Q corresponding to A. If S is a View, then let D' be its underlying Domain, see if D' can be converted to D as above; if so, make the appropriate new Object in Q corresponding to A.
Note that there are two ways to "widen" or "narrow" a View: one is to change its Domain, the other to change its Category.
If one or more args are expected to be Domains or Views, then their desired Structures must be Categories.
Perhaps want some way to selectively turn off the check for individual args. Note that can pass Domains like "GeneralExpressions" or "DomainAndViewElements" to be very permissive about args.
Perhaps want some way to specify Cedar types in Runtime Types, e.g. REF, ROPE, or INT. Perhaps can have something like CedarType[INT], or CedarType[REF], in Runtime Types. Then can either do no checking of Cedar-typed args, or actually try to do some kind of checking for them (perhaps whatever checking Cedar Interpreter can do).
If output LIST OF arg Structures has i < n = (# args this method) Structures, then args i, i+1, ..., n expected to belong to last (ith) Structure of the list (useful e.g. for vector and matrix constructors).
Should the system be able to "verbalize" runtime types, so e.g. an external client can get them?
proc: REF -- REF Proc
The "impl" of the method
attributes: Atom.PropList,
"constant" attributes stored e.g. as [$commutative, $commutative] (NIL value field would confuse with absence of attribute)
can e.g. record alternative "keys" or "tags" or "names" for this method; perhaps all methods should have unique "primary" keys
Use Atom.PropList, not RefTab, since # attributes expected small
];
Method: TYPE ~ REF MethodRep; -- inside impl module, use rep
MethodDictionaryRep: TYPE = RefTab.Ref; -- ATOM keys; facilitates switch to Atom.PropList if desired
MethodDictionary: TYPE = REF MethodDictionaryRep; -- inside impl module, use rep
Static Types and Method Application
StaticTypes: PUBLIC Atom.PropList ← NIL;
ApplyMethod: PUBLIC PROC [method: REF, structure: Object, argList: LIST OF REF, recast: BOOL] RETURNS[value: REF] =
m: Method;
ok: BOOLTRUE;
IF NARROW[method, Method] THEN m ← method ELSE m ← LookupMethodInStructure[method, structure]; -- FALSE => method arg is actually an ATOM method key; use it to lookup the method
IF recast THEN [ok, outArgs] ← RecastArgs[m, structure, argList] ELSE outArgs ← argList; -- note that RecastArgs must handle argList as a list of REF's
IF ok THEN
Using m.type, search global StaticTypes AList of method types and applicator functions; when found, pass m and outArgs to applicator; it will make appropriately extract the successive elements of outArgs, handling Cedar types and Objects appropriately in so doing, pass the finalized input args to the dereferent of the appropriate narrowing of m.value, and return the result (narrowing it to an Object if possible, or caller should do that?)
ELSE ERROR;
END;
Impls of applicator procs for each of the following should be provided in the right places (e.g. FromINTOp in Ints), and then the [key, proc] pairs loaded into StaticTypes
MethodType: TYPE = {Value, SideEffect, TrueNullaryOp, NullaryOp, UnaryOp, BinaryOp, BinaryMixedOp, TernaryOp, TernaryMixedOp, QuaternaryOp, LegalFirstCharOp, ReadOp, FromRopeOp, ToRopeOp, ToExprOp, FromExprOp, FromBOOLOp, FromINTOp, UnaryPredicate, BinaryPredicate, CompareToZeroOp, BinaryCompareOp, StructuredToGroundOp, ElementRankOp, UnaryImbedOp, BinaryImbedOp, ListImbedOp, MatrixImbedOp, StructureFromSetConstructor, VectorStructureConstructor, SequenceStructureConstructor, MatrixStructureConstructor, PolynomialStructureConstructor};
END.