DIRECTORY SafeStorage, IO, Atom, Rope, Basics, Imager, MathExpr, MathObjects; MathObjectsImpl: CEDAR PROGRAM IMPORTS Rope EXPORTS MathObjects = BEGIN ROPE: TYPE = Rope.ROPE; STREAM: TYPE = IO.STREAM; ObjectRep: TYPE = RECORD [ class: Object _ NIL, data: REF _ NIL ]; 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. runtimeType: REF UnaryToTwoListsOp _ NIL, 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). proc: REF -- REF Proc The "impl" of the method attributes: Atom.PropList, ]; 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 StaticTypes: PUBLIC Atom.PropList _ NIL; ApplyMethod: PUBLIC PROC [method: REF, structure: Object, argList: LIST OF REF, recast: BOOL] RETURNS[value: REF] = m: Method; ok: BOOL _ TRUE; 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 ELSE ERROR; END; 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. Κ MathObjectsImpl.mesa Copyright c 1989 by Xerox Corporation. All rights reserved. Arnon, August 28, 1989 1:42:36 pm PDT Types From Other Interfaces Private Type Reps 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? 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). Should the system be able to "verbalize" runtime types, so e.g. an external client can get them? "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 Static Types and Method Application 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?) 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 ΚH•NewlineDelimiter ™codešœΟc™Kšœ Οmœ1™˜—šŸœŸ˜ Jšœ‘ œ“™Ί—JšŸœŸœ˜ JšŸœ˜—J˜Kš ‘ ™«šœ ŸœΟbœ„˜K˜—˜J™—K˜—K˜KšŸœ˜J˜—…— N`