<> <> <> DIRECTORY AMBridge USING [RefFromTV, TVForReferent], AMTypes USING [TV], EvalQuote USING [EvalQuoteProc, VisitProc], InterpreterPrivate USING [GetGlobalSymTab], Rope USING [ROPE, Fetch], SymTab USING [Create, EachPairAction, Fetch, Pairs, Store, Ref]; EvalQuoteImpl: CEDAR PROGRAM IMPORTS AMBridge, InterpreterPrivate, Rope, SymTab EXPORTS EvalQuote = BEGIN OPEN AMTypes, Rope, EvalQuote; MyClosure: TYPE = REF MyClosureRep; MyClosureRep: TYPE = RECORD [proc: EvalQuoteProc, data: REF _ NIL]; Register: PUBLIC PROC [ name: ROPE, --starting with & proc: EvalQuoteProc, symTab: SymTab.Ref, data: REF _ NIL ] = { closure: MyClosure _ NEW[MyClosureRep _ [proc: proc, data: data]]; found: BOOL; sttv: TV; IF symTab = NIL THEN symTab _ InterpreterPrivate.GetGlobalSymTab[]; [found, sttv] _ symTab.Fetch["&EvalQuoteSymTab"]; TRUSTED{ IF found THEN symTab _ LOOPHOLE[AMBridge.RefFromTV[sttv], SymTab.Ref] ELSE { newST: SymTab.Ref = SymTab.Create[]; [] _ symTab.Store["&EvalQuoteSymTab", AMBridge.TVForReferent[newST]]; symTab _ newST; }; }; [] _ symTab.Store[name, closure]; }; Lookup: PUBLIC PROC [symTab: SymTab.Ref, name: ROPE] RETURNS [proc: EvalQuoteProc _ NIL, data: REF _ NIL] = { <> closure: MyClosure; found: BOOL; wasNilSymTab: BOOL = symTab = NIL; sttv: TV; IF name.Fetch[0] # '& THEN RETURN; IF symTab = NIL THEN symTab _ InterpreterPrivate.GetGlobalSymTab[]; [found, sttv] _ symTab.Fetch["&EvalQuoteSymTab"]; IF NOT found THEN { IF NOT wasNilSymTab THEN [proc, data] _ Lookup[NIL, name]; -- try the global one RETURN; }; TRUSTED{symTab _ LOOPHOLE[AMBridge.RefFromTV[sttv], SymTab.Ref]}; closure _ NARROW[symTab.Fetch[name].val]; IF closure = NIL THEN {IF NOT wasNilSymTab THEN [proc, data] _ Lookup[NIL, name]} ELSE {proc _ closure.proc; data _ closure.data}; }; Enumerate: PUBLIC PROC [symTab: SymTab.Ref, visit: VisitProc] = { <> action: SymTab.EachPairAction = { <<[key: Key, val: Val] RETURNS [quit: BOOL];>> closure: MyClosure _ NARROW[val]; IF closure # NIL THEN quit _ visit[key, closure.proc, closure.data]; }; found: BOOL; sttv: TV; IF symTab = NIL THEN symTab _ InterpreterPrivate.GetGlobalSymTab[]; [found, sttv] _ symTab.Fetch["&EvalQuoteSymTab"]; IF NOT found THEN RETURN; TRUSTED{symTab _ LOOPHOLE[AMBridge.RefFromTV[sttv], SymTab.Ref]}; [] _ symTab.Pairs[action]; }; END.