MathBoxTrees.mesa
Arnon, September 7, 1989 10:20:18 am PDT
Definitions for Two-Dimensional Displays of Mathematical Expressions
DIRECTORY
MathExpr USING [EXPR, AtomEXPR, CompoundEXPR, AtomClass, CompoundClass, MatrixClass],
MathBox USING [BOX],
MathTypes USING [Style],
MathRules USING [Size],
Rope USING [ROPE],
Imager USING [Context, Color];
MathBoxTrees: CEDAR DEFINITIONS ~
BEGIN
Type Abbreviations from Imported Interfaces
ROPE: TYPE ~ Rope.ROPE;
EXPR: TYPE ~ MathExpr.EXPR;
AtomEXPR: TYPE ~ MathExpr.AtomEXPR;
CompoundEXPR: TYPE ~ MathExpr.CompoundEXPR;
BOX: TYPE ~ MathBox.BOX;
Style: TYPE ~ MathTypes.Style;
Size: TYPE ~ MathRules.Size;
Element Type Definitions
BoxTree: TYPE ~ Object;
BoxTreeData: TYPE ~ REF BoxTreeDataRep; -- external abstract type
BoxTreeDataRep: TYPE; -- internal concrete rep
Element Operations
Object: PROC[o: BoxTree] RETURNS[Object];
Extracts the Object "imbedded" in a BoxTree. Trivial for an AtomicDisplayObject. For a CompositeDisplayObject, descends to its "leaves" (AtomicDisplayObject's), then reascends and builds the Object by successive calls to Pack at each internal node.
Accomplished by
Pack: PROC[o: BoxTree, e: Environment] RETURNS[BoxTree];
Pack up "leaf subtrees" of a CompositeDisplayObject (noop for AtomicDisplayObject), as specified by an Environment.
For a CompositeDisplayObject, can be done from the information present in the BoxTree.
Pack essentially mimics the "going up" part of Exprs.EltEval, i.e. it applies MathEnvironments.AttemptMethod[op, hint, eArgs, e] knowing that it will succeed.
PackAncestor: PROC[o: BoxTree, e: Environment] RETURNS[BoxTree];
nontrivial only for child of CompositeDisplayObject: in that case, means go to some ancestor x, as specified by e, and execute Pack[x, e'], for some e'.
Unpack: MathEnvironments.UnpackOp;
Unpack the leaves of a CompositeDisplayObject, if possible, as specified by an Environment
EltToExpr: PROC[o: BoxTree] RETURNS[Expr];
Convert a BoxTree to general expression representation
Domain Operations
The editor for the BoxTrees Domain, if there is one, either implicitly or explicitly, views a BoxTree as a privateBoxTree in which all subBoxes are selectable. I.e. "Object" information may be retained, but is ignored. Direct manipulation of a displayed BoxTree may be supported, or in the worst case you can EltToExpr a BoxTree, edit it as a string, and parse it back in.
Operation Type Definitions
DisplayOp: TYPE = MathEnvironments.EvalOp;
Create a BoxTree display for a given Object (of whatever flavor).
Typically, a Domain or View will have multiple such ops for its elements, which will e.g. do different amounts of unpacking, thereby supporting a range of amounts of iconification (holophrasting) in Element displays.
Note that we "model" a DisplayOp as an EvalOp, with the attendant special application semantics
DisplayOp's are free to construct their own local display "environment" (which might involve e.g. looking at this Structure's own display-related properties, or those of its superDomains, Categories, and superCategories), and to in some fashion "merge" this local data with the passed-in environment (env), to construct the environment that they will pass to the recursive appilcation of themselves to their (unpacked) Object arguments children.
Examples of typically possible signficant items in a passed-in context:
1. Enclosing Object (e.g. Document, or other mathematical object) "style", e.g. type size and face, other "generic" formatting constraints
2. "Page", i.e. "column", width to respect, assuming no scaling down, i.e. adherence to current type size.
3. A Box to confine the display to, assuming no scaling down.
4. A range, or a minimum and maximum values, for possible scaling. Thus if the generated display is significantly smaller than a given Box, the display may be scaled up.
5. How much unpacking to do.
6. Special formatting "rules" to apply, e.g. if the Object (or some subObject of it) satisfies some predicate (e.g. "matches some pattern"), then format it in some special way.
Straightforward for atomic Exprs - no unpacking needed, just render the value into a box.
For compound Exprs, unpacks them by some UnpackOp, then recursively applies "itself" (i.e. the appropriate DisplayOp of subObject domains) to child Objects, then uses method and # of args to consult a domain-specific (i.e. for this domain) dbase of special formatting procs to look for match, else uses default functional form display, to display its original, toplevel arg.
Note that one cannot expect the domain of a subObject of a displayed Object to necessarily be evident from its displayed appearance. E.g. when we see what looks like an integer, we don't know strictly from the rendered BoxTree for it whether it is the display of an element of Exprs, or an element of Integers. Same e.g. for "matrix of integers".
To facilitate system support for "letting a user model his data any way he wants to", we expect elements of all domains to have (one or more) "EltToExpr" procs, which produce a "completely Exprish" element of Exprs, i.e. a "pure functional" Expr, and which we would like to be "consistent" or "invertible" in at least one, preferably both of the following senses: 1) weaker: if you are given the destination domain, then by recursion, subObject instantiation, and composition, knowing domains in which to lookup the given method at each step, you can rebuild the object. 2) stronger: without being given the destination domain, then by recursion, subObject instantiation, and composition, using system type inference & resolution capabilities, and method lookup capabilities (including of course knowledge of the subObject domains at each step), you can rebuild the object.
Of course, the remarks below about absence of unique "natural" or "obvious" EltToExprRope procs apply equally to EltToExpr procs.
Assuming willingness to call instantiation of atomic subObjects "EltEval" (connoting e.g. evaluation (substitution and recursive evaluation until no change) of variables), then we are saying that we want "EltToExpr" and "EltEval" to be inverses of each other, at least in the weaker, and possibly also in the stronger, sense. Note that we are saying that EltEval means - recursively evaluate subObjects; given a variable, replace it by its value in the current environment (and recursively EltEval that value until no further change occurs); the result of each subObject EltEval is an object in some domain, then lookup a proc implementing the given method, in the "current environment", i.e. using the system's method lookup capabilities, and apply that proc to get a final object in some domain.
Thus we are implicitly suggesting that any use of pattern matching or rules in EltEval is expected to be bundled up inside some proc.
Domains may or may not support EltEval procs. If their Objects can contain "symbols" or "variables" (e.g. polynomials), rather than just "constants", then they probably should (because e.g. we may want to "eval in the presence of some environment". One typical way a domain can get an EltEval proc is by applying eltEval$Exprs to the result of a EltToExpr of the Object, since eltEval$Exprs is a locus of type inference & resolution, and method lookup, expertise.
In general, the implementor of a domain D should think carefully about what the ways in which clients might wish to "eltEval" Objects in it. If the verdict is that all elements of the domain are constants, then probably the domain should have a noOp $eltEval method, so that eltEval$Exprs[parse$D["<objectRep>"] ] can quickly do the right thing.
In general, of course, the $eltEval method for a structured domain simply recursively invokes the domains' $eltEval methods of subObjects, and then computes some function of the results. E.g. for matrix domains, it just evaluates the elements, then constructs up a new matrix to hold them. Again, this could be done by eltEval$Exprs[eltToExpr$Matrices(whatever)[<fooMatrix>] ].
Selection Operations
TreeForPoint: PROC[b: BoxTree, x, y: REAL] RETURNS[BoxTree];
effects: Returns the (smallest, tightest) subBoxTree associated with coordinates [x, y] in BoxTree b. For e.g. mouse hit detection
SIGNALS noSelection if no association exists.
END.