EvalQuote.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Russ Atkinson, April 11, 1985 3:20:13 pm PST
Paul Rovner, July 26, 1983 8:49 am
This provides a registry for &-procedures that examine and evaluate their own argument tree and return a TV (perhaps AMTypes.GetEmptyTV[]). Examples of its use:
1. (convenience) allow &fm[FooImpl] to mean &fm["FooImpl"]
2. allow a call on &tlf to appear to yield a local frame rather than a TV for a local frame.
See the comments about Register, below.
DIRECTORY
AMTypes USING [TV, nullType, Type],
InterpreterOps USING [EvalHead, Tree],
Rope USING [ROPE],
SymTab USING [Ref];
EvalQuote: CEDAR DEFINITIONS = BEGIN OPEN AMTypes, InterpreterOps, Rope;
Register: PROC [name: ROPE, proc: EvalQuoteProc, symTab: SymTab.Ref, data: REFNIL];
registers the specified &-proc as an EvalQuote proc to be associated with the specified SymTab. For an apparent &-proc name in the syntactic context of an application, the interpreter will first look for a registered EvalQuote proc to use as the definition of the name. If it finds one, it calls it (passing the Tree for the arg) and returns the TV that the call returns.
Register looks in symTab for a TV associated with "&EvalQuoteSymTab". If it finds one, it assumes it to ba a TV for a SymTab, and enters the specified EvalQuoteProc therein. (if symTab = NIL, Register will use the global SymTab; this feature is intended for use only by wizards). If Register does not find "&EvalQuoteSymTab" in symTab, it will create a new SymTab and make that association, then proceed to register proc. NOTE that each EvalQuote proc should have a corresponding entry in symTab; though the (proc) value associated with the corresponding entry will never be called, it is found by InterpreterOps.EnumeratePredefinedSymbols. This is useful for the ? facility (e.g.) &fm?
EvalQuoteProc: TYPE = PROC [head: EvalHead, tree: Tree, target: Type ← nullType, data: REFNIL] RETURNS [return: TV];
this is the type of proc that the client registers
Lookup: PROC [symTab: SymTab.Ref, name: ROPE--starting with &--] RETURNS [proc: EvalQuoteProc, data: REF];
Lookup finds the named EvalQuoteProc (if any). It returns [NIL, NIL] if not found.
The name-lookup proceeds as follows: it looks in symTab for a TV associated with "&EvalQuoteSymTab" (if symTab = NIL it will look in the global SymTab; this feature is intended for use only by wizards). If it finds one, it treats the TV as a TV for a SymTab, in which it then looks for the specified name to find the associated EvalQuote proc. If either &EvalQuoteSymTab is not found in symTab or the specified name is not found in the indicated SymTab, Lookup goes to the global SymTab to find "&EvalQuoteSymTab" and so on.
Enumerate: PROC [symTab: SymTab.Ref, visit: VisitProc];
enumerates the registered EvalQuote procs. See the above comment for details.
VisitProc: TYPE = PROC [name: ROPE, proc: EvalQuoteProc, data: REFNIL] RETURNS [--stop:-- BOOL];
this is the type of callback proc the user supplies to Pairs to enumerate the registered EvalQuote procs for the specified SymTab.
RegisterNameProc: PROC [name: Rope.ROPE, symTab: SymTab.Ref, proc: NameProc, data: REFNIL];
Registers a closure associated with the name, such that every time the name is evaluated the procedure is called with the given data.
LookupNameProc: PROC [symTab: SymTab.Ref, name: Rope.ROPE] RETURNS [proc: NameProc, data: REF];
Looks up the named value in the table and returns the associated proc and data (if any).
EnumerateNameProcs: PROC [ symTab: SymTab.Ref, perRegistration: PROC [name: ROPE, proc: NameProc, data: REF] RETURNS [stop: BOOL] ];
Enumerates the proc and data pairs in the table.
NameProc: TYPE = PROC [head: EvalHead, nameAsRope: ROPE, nameAsTree: Tree, target: Type ← nullType, data: REFNIL] RETURNS [value: TV];
... is the type of procedure supplied by the client.
This all works by associating a NameClosure (rather than the usual TV) with the name in the symbolTable.
NameClosure: TYPE = REF NameClosureRep;
NameClosureRep: TYPE = RECORD [proc: NameProc, data: REF ANY];
END.