MathEnvironments.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;
MathEnvironments: CEDAR DEFINITIONS
= BEGIN
Types From Referenced Interfaces
ROPE: TYPE = Rope.ROPE;
STREAM: TYPE = IO.STREAM;
Object: TYPE = MathObjects.Object;
MethodDictionary: TYPE = MathObjects.MethodDictionary;
Environment Types
A (Math)Environment is a collection of [name, value] bindings.
Environment: TYPE = Object;
EnvironmentData: TYPE ~ REF EnvironmentDataRep; -- probably should be a variant record which by default is a RefTab, but optionally a prop list. There should be some way to "concatenate" Environments, e.g. for appending a local scope to an inherited environment.
Should check how CedarScheme represents environments
EnvironmentDataRep: TYPE;
Global (System) Environment library
The .class of an Environment is the SystemObject Environments, which provides methods for access to the constituents of its Elements (i.e. Environments), e.g. search, a $flavor method (returns $Environment), and an $eltDisplay method
We may conceivably try to maintain knowledge of all currently active Environments via Environments' .data, consistent with the goal that externalization of all SystemObject's amounts to complete externalization of system state.
Environments: Object;
EnvironmentsData: TYPE ~ REF EnvironmentsDataRep; -- probably a forest of trees of (all currently active) Environments
EnvironmentsDataRep: TYPE;
Operation Type Definitions
EvalOp: MathObjects.BinaryToPairOp;
PROC [x: Object, env: Environment] RETURNS [y: Object, newEnv: Environment ← NIL];
EvalOp's have a special, nonstandard application semantics: whereas "standard" methods begin by applying some "system" EvalOp to their arguments, in the application of an EvalOp, we begin by applying it itself recursively to its arguments
EvalOp's are applied "with respect to", i.e. "in the context of", the "environment" env; they do not modify the env passed in, but return requested "perturbations" of it as newEnv. It is then the task (and privilege) of the "caller", i.e. "applier", of the EvalOp to determine how to combine env and newEnv.
UnpackOp: MathObjects.BinaryOp;
PROC [x: Object, e: Environment ← NIL] RETURNS [Object];
Return Object is either a CompositeExpr or a CompositeDisplayObject.
-- e specifies e.g. how many levels of unpacking to do, and also whether the current Domain/View S of each unpacked subObject should be "cached" in its unpacked form, via the $foo$[S, ...] convention.
Every Domain or View should have an $eltEval method for its Elements: if there isn't anything interesting to do, return the Object unchanged.
Ground Structures evaluate to themselves. For Structure constructors, the full semantics of Eval applies.
An example of an "interesting" thing to do is to consider the variables of a polynomial as symbols (i.e. names), look for values associated (which we assume to be Objects) with those names in e, (recursively) eval the values in environment e, substitute the results for the variables (by some regime of substitution, presumably simultaneous), and now "eval" the "substituted polynomial". We do so by assuming that the polynomial Domain has some "invertible" UnPackOp that we can apply to unpack any Element into a CompositeExpr U in which each of the variables the Element contains is an AtomicObject, and we apply Exprs.$eltEval (with Environment e) to U.
Of course, just because the UnPackOp was "invertible" within the polynmomial Domain (certainly we expect it to be if it caches Domains on the way down, and maybe it is even if it isn't), we really don't know what will happen after we have substituted for the variables and Exprs.$eltEval is applying MathEnvironments.AttemptMethod to build back up.
Our basic viewpoint is that a call to an EvalOp enters a new local "scope": thus newEnv records new [name, value] associations that are created by (e.g. evaluation of assignment statements within) this Eval, and also the removals of such associations (e.g. by evaluations of "Kill[Name]" or "kill[All]" ops) that happen within it, and makes no changes to env. It is the task (privilege) of the caller to determine whether to use the newEnv to make changes to env.
Method Application
LookupMethod: PROC [key: ATOM, env: Environment] RETURNS[method: Method, class: Object];
A global (system) proc for a (global) search of (some portion of) the entire system "knowledge base" ("library") of possible locations of Methods (e.g. Domains, Views, Categories, Packages, Environments) for a Method that can be accessed with the supplied key. If found, then class is Structure or Package or Environment where found. SIGNALs failure if can't find.
Thus the behavior of this particular Method lookup proc is completely controlled by its hardwired algorithm, the current system state, and the passed-in env.
Typically env may be used to pass in "control" information for e.g. the particular search that LookupMethod will conduct on the global Domain and Category lattices. For example, it may tell it not to look in certain Domains or Views, e.g. where they method has been found but arg recast failed.
LookupMethodInStructure: PROC [key: ATOM, s: Structure, tryOther: BOOLFALSE, env: Environment ← NIL] RETURNS[method: Method, class: Object];
Try to find the specified method among the Methods of s. If found there, then returns [Method, s]. If not found there and tryOther FALSE, returns [NIL, NIL].
If method not found in s and tryOther TRUE, then continue searching more widely for the method. If env = NIL, then simply call LookupMethod[key, NIL]. If env #NIL, then look for control info in it, extract an appropriate env', and call LookupMethod[key, env'].
AttemptMethod: PROC [method: REF, hint: Structure ← NIL, argList: LIST OF REF, env: Environment] RETURNS[value: REF, newEnv: Environment];
If method is an ATOM methodKey, and hint # NIL, then we first look for method in hint. If method is an ATOM methodKey, and hint = NIL or we fail to find it in hint, we do
Loop {
Method lookup for method (e.g. begin by looking for it in argList Domains);
attempt to resolve argList to its runtimeType;
record in environment that this Method failed, so must find another with this key;
}
until type resolve succeeds or method not found;
(if failure, pass back the appropriate SIGNAL)
If type resolve success exit, then MathObjects.ApplyMethod;
Note that args and return value, if not Objects, must be at least REF's. I.e. the ability of this method apply procedure to handle Cedar types is limited to REF's. Thus all methods to be invoked by the general method apply machinery must meet this constraint.
END.