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 signature", which is a specification of the numbers (arities) of its inputs and outputs, and some information about their "types". I.e. static signatures denote families of similar methods. Used for "dispatch on name of static signature" invocation of methods (following verfication that actual parameters conform to this method's "dynamic signature", 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 signatures themselves typically appear as a type declaration in some Cedar interface. Hence if some of this method's args are Cedar types (rather than Structures), that can automatically be expressed in a static signature.
Should the system be able to "verbalize" static signatures, so e.g. an external client can get them?
ApplyToObject: PROC [method: REF, structure: Object, argList: LIST OF Object, recast: BOOL] RETURNS[value: Object];
m: Method;
ok: BOOLTRUE;
IF NARROW[method, Method] THEN m ← method ELSE m ← LookupMethodInStructure[method, structure]; -- FALSE => method arg is actually an ATOM methodSelector; use it to lookup the method
IF recast THEN [ok, outArgs] ← RecastArgs[m, structure, argList] ELSE outArgs ← argList;
IF ok THEN
Using m.type, search global AList of method types and applicator functions; when found, pass m and outArgs to applicator; it will make appropriate extracts from outArgs, handling Cedar types and Objects appropriately in so doing, and pass the finalized input args to the dereferent of the appropriate narrowing of m.value.
ELSE ERROR;
attributes: Atom.PropList,
"constant" attributes stored e.g. as [$commutative, $commutative]; NIL value field would confuse with absence of attribute
dynamicType: REF UnaryToTwoListsOp ← NIL,
PROC [Structure] RETURNS [args: LIST OF arg Structures, results: LIST OF result Structures]
Dynamic 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 dynamic signatures 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 Dynamic Signatures, e.g. REF, ROPE, or INT. Perhaps can have something like CedarType[INT], or CedarType[REF], in Dynamic Signatures. 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" dynamic signatures, so e.g. an external client can get them?
value: REF -- REF Proc
The "impl" of the method
];
Method: TYPE ~ REF MethodRep; -- inside impl module, use rep
MethodDictionaryRep: TYPE = Atom.PropList;
MethodDictionary: TYPE = REF MethodDictionaryRep;
END.