<> <> <> <> DIRECTORY CD, Rope; CDBottomUp: CEDAR DEFINITIONS = BEGIN <> <<>> <> <<>> <> Class: TYPE = REF --READONLY-- ClassRec; ClassRec: TYPE = RECORD [do: PRIVATE DoProc, reUse: PRIVATE ReUseProc, key: PRIVATE REF, classData: REF]; <<--A class represents the application program; what analysis procedure should be called>> Handle: TYPE = REF HandleRec; HandleRec: TYPE = RECORD [class: Class, design: CD.Design, data: REF, invocation: REF, r: Rope.ROPE_NIL, cnt: INT_0]; <<--A handle represents one bottom up call sequence>> <<--data, r, cnt are reserved for clients (there are never many HandleRec's arround)>> DoProc: TYPE = PROC [handle: Handle, ob: CD.Object] RETURNS [val: REF_NIL]; <<--A DoProc should not recurse directly but may call DoRecurse to get recursion going>> <<--If ~ob.class.inDirectory 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_FALSE]; <<--A ReUseProc should be fast and should not recurse directly nor call DoRecurse>> 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: REF_NIL, invocation: REF_NIL] RETURNS [handle: Handle]; <<--Creates the handle data structure which will be passed through the recursion.>> <<--class: determines application (procedures to be called)>> <<--design: for client's use>> <<--data: reserved for the client (implementor of class)>> <<--invocation: invocation-key; (NIL for a new invocation-key)>> StartRecurse: PROC [class: Class, design: CD.Design, ob: CD.Object, data: REF_NIL] RETURNS [val: REF, new: BOOL, handle: Handle]; <<--Short cut for DoRecurse[MakeHandle[...], ...]>> Register: PROC [do: DoProc, reUse: ReUseProc_NIL, key: REF_NIL, reRegistrationKey: REF_NIL, classData: REF_NIL] 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.>> <<--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.>> <<--class: identity of application.>> END.