CDBottomUp.mesa
Copyright © 1985, 1987 by Xerox Corporation. All rights reserved.
Created by Christian Jacobi, December 13, 1985 5:49:59 pm PST
Last edited by: Christian Jacobi, April 15, 1987 5:40:47 pm PDT
DIRECTORY
CD, CDDirectory, Rope;
CDBottomUp: CEDAR DEFINITIONS =
BEGIN
A module which allows easy implementation of bottom up calls which cache the results.
Each independent call creates a new invocation key. Results which are created with the same invocation key are allways trusted and taken from the cache. Results with a different invocation key are re-used if all the subcells in the specified hierarchy haven't changed.
Calls for each application (class) - design pair should be monitored by the client, to prevent conflicts on the cached results and which invocation is the latest.
Class: TYPE = REF --READONLY-- ClassRec;
ClassRec: TYPE = RECORD [do: DoProc, reUse: ReUseProc, enumerateChildren: EnumChildsProc←NIL, key: REF, classData: REF, xDesign: BOOL];
--A class represents the application program; what analysis procedure should be called
--Clients of the actual analysis do not need any field except key and classData; consider
--other fields private to the actual analysis package.
Handle: TYPE = REF HandleRec;
HandleRec: TYPE = RECORD [class: Class, data: REF, invocation: REF, design: CD.Design←NIL, r: Rope.ROPENIL, cnt: INT𡤀];
--A handle represents one bottom up call sequence
--data, r, cnt and design are reserved for clients only and not used by CDBottomUpImpl
-- (there are never many HandleRec's arround)
--Non sequential classes should not use r or cnt; different r might be catenated
DoProc: TYPE = PROC [handle: Handle, ob: CD.Object] RETURNS [val: REFNIL];
--A DoProc should not recurse directly but may call DoRecurse to get recursion going
--If ~ob.class.mutable then results must NOT depend on design
--val: value which will be cached
ReUseProc: TYPE = PROC [handle: Handle, ob: CD.Object, previousVal: REF] RETURNS [shouldDoAain: BOOL�LSE];
--A ReUseProc should be fast and should not recurse directly nor call DoRecurse
EnumChildsProc: TYPE = CDDirectory.EnumerateChildObjectsProc;
--Children enumerator to define hierarchy.
--A NIL EnumChildsProc proc causes CDBottomUp to use
--CDDirectory.EnumerateChildObjects to find children; the recursion is going
--through the physical nesting hierarchy. A client EnumChildsProc proc is
--the means to implement going down an icon - implementor hierarchy.
Peek: PROC [key: REF, ob: CD.Object] RETURNS [val: REF];
--Returns cached result; independent whether valid or not...
--key: as in Class registration
DoRecurse: PROC [handle: Handle, ob: CD.Object] RETURNS [val: REF, new: BOOL];
--Gets value from cache or start recursion if value is not valid
--May be called recursively at clients own will; caches results (not slower then Peek)
--val: the result which was computed or cached
--new: whether a new result was computed this invocation (important for the engine room!)
--The automatic recursion calls only objects in the directory; however, if the client himself
-- calls DoRecurse for objects not in the directory, the procedures are invoked and the
-- results cached.
MakeHandle: PROC [class: Class, design: CD.Design←NIL, data: REFNIL, invocation: REFNIL] RETURNS [handle: Handle];
--Creates the handle data structure which will be passed through the recursion.
--class: determines application (procedures to be called)
--data: reserved for the client (implementor of class)
--design: is optional except if required by class
--invocation: invocation-key; (NIL for a new invocation-key)
StartRecurse: PROC [class: Class, ob: CD.Object, design: CD.Design←NIL, data: REFNIL] RETURNS [val: REF, new: BOOL, handle: Handle];
--Short cut for DoRecurse[MakeHandle[...], ...]
Register: PROC [do: DoProc, reUse: ReUseProc←NIL, enumerateChildren: EnumChildsProc←NIL, key: REFNIL, reRegistrationKey: REFNIL, classData: REFNIL, xDesign: BOOL←TRUE] RETURNS [class: Class];
--Registers an application of CDBottomUp
--do: to be called bottom up for all objects in the directory. Do will typically
-- call DoRecurse to get recursion going; but for objects in the
-- directory, recursive calls of DoRecurse might have been precalled and
-- the result cached.
--reUse: is called to figure out whether objects which are already handled should
-- be handled again. It is called only for objects in the directory and
-- if do is not called anyway.
--enumerateChildren: enumerating children defines the hierarchy; NIL for using
-- ChipNDale's physical nesting hierarchy.
--key: property used to cache previous results; a NIL value creates a new property key.
-- The key property will be registered.
-- Clients must not access properties directly, but may use Peek.
-- Clients may remove cache by putting NIL on the key property.
--reRegistrationKey: property re-registration key; a NIL value ensures a new registration.
--xDesign: Continues automatic analysis over design boundaries.
-- But client could do that himself anyway, except reUse check.
--class: identity of application; reserved for clients.
END.