MathStructures.mesa
Copyright © 1989 by Xerox Corporation. All rights reserved.
Arnon, August 28, 1989 1:42:36 pm PDT
DIRECTORY
SafeStorage,
IO,
Atom,
Rope,
Basics,
MathObjects;
MathStructures: CEDAR DEFINITIONS
= BEGIN
Types From Referenced Interfaces
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Object: TYPE = MathObjects.Object;
MethodDictionary: TYPE = MathObjects.MethodDictionary;
Structure Types
By a "(Math)Structure:" we mean a Domain, View, or Category. Domains and Views are presumed to correspond to families of "mathematical values", i.e. to denote certain "underlying sets". Category. We call an element of a Domain or View a "(Math)Element". Categories are presumed to correspond to families of Domains and Views.
Category: TYPE = Object;
Domain: TYPE = Object;
View: TYPE = Object;
Structure: TYPE = Object;
Element: TYPE = Object;
CategoryData: TYPE = REF StructureDataRep;
DomainData: TYPE = REF StructureDataRep;
ViewData: TYPE = REF StructureDataRep;
StructureDataRep: TYPE; -- internal concrete rep; we expect and intend it to be the same for Domains, Views, and Categories
In general, we want a (Math)Object's .class field to express the "isAnElementOf", i.e. the "is an instance of", relation. The .class of an "Element" is a Domain or View. The .class of a Domain, View, or Category is the SystemObject Domains,Views, or Categories. We rely on the global Domains and Categories lattices to record the (possibly multiple) "isAnElementOf" relations existing between Domains and Views, and Categories.
We expect that the methods of any Domain, View, Category, or suitable SystemObject will include an $eltFlavor method to report the "flavor" (e.g. $Element, $Domain, $View, $Category, $Package, $Environment) of its consituent elements.
Structure-Related System Objects
Domains: Object; -- SystemObject; .class of any Domain
DomainsData: TYPE ~ REF DomainsDataRep;
DomainsDataRep: TYPE; -- includes the system (global) lattice of currently instantiated Domains; should be similar in spirit to a RefTab, except needs to be a Graph. Should be an immutable data structure, like ROPE, so that Domains can be instantiated within a local environment (e.g. a particular invocation of type resolution) and temporarily inserted in the global lattice, then easily deleted later.
Categories: Object; -- SystemObject; .class of any Category
CategoriesData: TYPE ~ REF CategoriesDataRep;
CategoriesDataRep: TYPE; -- includes the system (global) lattice of currently instantiated Categories; needs to be a Graph a la DomainsDataRep. May or may not need to be immutable; unlike Domains, Categories will probably not be "temporarily" instantiated during type resolution, or any other time, and so it can be argued that the system should never forget a Category, once instantiated.
Views: Object; -- SystemObject; .class of any View
ViewsData: TYPE ~ REF ViewsDataRep;
ViewsDataRep: TYPE; -- probably a RefTab of current Views; any lattice activity done either in the Domain or Category lattices.
Each of these SystemObjects provides methods for access to the constituents of its Elements (i.e. Domains, Views, and Categories resp.), a $flavor method (returns $Domain, $View, or $Category resp.), and an $eltDisplay method.
(Multiple) inheritance is supported via the global Domain and Category lattices, that record all "isASubsetOf" relations among Domains and Categories, respectively. There is a certain consistency assumed between these lattices and the capabilities of the Domains and Categories involved in them. If we are trying to recast (an element of) Domain or Category S as (an element of) S', and if there is path from S to S' in the global lattice, then we assume that by (e.g. depth-first or breadth-first) search of the Widen or Narrow (depending on the direction of the path) edges rooted at S', we will find a "path" of procs which can be composed to actually do the recasting. Thus in general, the "transitive closure" of the Widen or Narrow "edges" rooted at a Structure S comprise a subgraph of one of the global lattices. The possible partiality of this subgraph is the major reason for the use of the global lattices: they give us a single place to express the full multiplicity of relationships among the Structures that are their nodes.
When a Domain or View is instantiated, we typically put in one or more links (the possibility of more than one link is, in a sense, the whole point of Views) from the new node into the Category lattice. Thus in fact, the Domain and Category lattices (and the list of current Views) are linked, and can be thought of as a single lattice.
A Domain should always be able to make a View of itself as a member of its category. This should normally be straightforward: the Category methods should be a subset of the Domain methods, with identical names. We may even go so far as to say that the elements of Categories ARE Views; setting the Class field of a Domain to point to a Category is just a "lazy" binding; it is becomes meaningful when we create the View of the Domain as a member of that Category.
Given a category C, a View V that is a member of C, and a (direct) supercategory C' of C, C should always know how to create a new View V' which is a View of V as a member of C'. This will typically involve retaining a subset of V's methods, and possibly giving some of them new names. We call this capability the "ViewWiden" method of C'. If C is not a direct subcategory of C', then we simply compose the ViewWiden methods along a chain of intermediate subcategories.
Perhaps in general, Widen and Narrow procs should not reside in Structures; they are more properly thought of as labels on edges in the global lattices. Hence when a Domain is instantiated, it should
1) create a node for itself in the Domain lattice
2) identify (Narrow and Widen) edges in the Domain lattice of which its a vertex, and provide a proc for each such edge. There should be a precedence ordering among the Narrow edges, and among the Widen edges, to guide searches.
3) provide at least one link (edge) from itself as a node in the Domain lattice, to a node of the Category lattice, together with a ViewAs proc for each such edge. Its .class field is one such link (except does not provide the ViewAs proc per se). Again, there should be a precedence ordering among these edges.
When a Category is instantiated, it should
1) create a node for itself in the Category lattice
2) identify (Widen) edges in the Category lattice of which its a vertex, and provide a proc for each such edge. (Narrow procs seem impossible for Categories; e.g. for Ring -> ID, how do you give a proc that determines whether a given Ring has zero divisors?). There should be an ordering among these Widen edges.
Some global proces may, from time to time, crawl over all links from the Domain lattice into the Category lattice, and update the aggregate of all "back" links from nodes of the Category lattice to nodes of the Domain lattice. This can be regarded as system data, namely the ability to report all currently instantiated Domains that can be viewed as elements of a particular Category (transitive closure in the Category graph should of course be used to generate the full such list).
There should be allowance for "equipotent" nodes in (at least) the Domain lattice, typically arising from Domains which are multiple representations for the same mathematical domain. Each such pair can be both "widened" and "narrowed" to each other.
END.