CDBottomUpImpl.mesa
Copyright © 1985, 1986 by Xerox Corporation. All rights reserved.
Created by Jacobi, December 13, 1985 5:49:59 pm PST
Last edited by: Christian Jacobi, September 30, 1986 5:44:51 pm PDT
DIRECTORY
CD,
CDBottomUp,
CDDirectory,
CDOps,
CDProperties;
CDBottomUpImpl: CEDAR MONITOR
IMPORTS CDDirectory, CDOps, CDProperties
EXPORTS CDBottomUp =
BEGIN OPEN CDBottomUp;
PrivateRec: TYPE = RECORD [
lastInvocation: REFNIL,
lastVal: REFNIL,
originalInvocation: REFNIL
];
--passed through invocations are never NIL: a NIL invocation means value not yet computed
MakeHandle: PUBLIC PROC [class: Class, design: CD.Design, data: REFNIL, invocation: REFNIL] RETURNS [handle: Handle] = {
handle ← NEW[HandleRec←[
class: class,
design: design,
data: data,
invocation: IF invocation#NIL THEN invocation ELSE NEW[INT]
]];
};
Register: PUBLIC PROC[do: DoProc, reUse: ReUseProc, key: REF, reRegistrationKey: REF, classData: REF] RETURNS [class: Class] = {
IF key=NIL THEN key ← NEW[INT];
class ← NEW[ClassRec ← [do, reUse, key, classData]];
[] ← CDProperties.RegisterProperty[key, reRegistrationKey];
CDProperties.InstallProcs[key, [autoRem: TRUE]];
};
Peek: PUBLIC PROC [key: REF, ob: CD.Object] RETURNS [val: REFNIL] = {
WITH CDProperties.GetObjectProp[ob, key] SELECT FROM
p: REF PrivateRec => val ← p.lastVal;
ENDCASE => NULL;
};
StartRecurse: PUBLIC PROC [class: Class, design: CD.Design, ob: CD.Object, data: REFNIL] RETURNS [val: REF, new: BOOL, handle: Handle] = {
handle ← MakeHandle[class, design, data];
[val, new] ← DoRecurse[handle, ob];
};
DoRecurse: PUBLIC PROC [handle: Handle, ob: CD.Object] RETURNS [val: REFNIL, new: BOOLFALSE] = {
GetPrivate: PROC [key: REF, ob: CD.Object] RETURNS [h: REF PrivateRec] = INLINE {
WITH CDProperties.GetObjectProp[ob, key] SELECT FROM
p: REF PrivateRec => h ← p;
ENDCASE => CDProperties.PutObjectProp[ob, key, (h←NEW[PrivateRec])];
};
EachChild: CDDirectory.EnumerateObjectsProc = {
IF me.class.inDirectory THEN
IF DoRecurse[handle, me].new THEN new ← TRUE;
};
EachDirectoryEntry: CDDirectory.EachEntryAction = {
IF DoRecurse[handle, ob].new THEN new ← TRUE;
};
p: REF PrivateRec;
IF ob=NIL THEN {
IF handle.design=NIL THEN ERROR;
[] ← CDDirectory.Enumerate[handle.design, EachDirectoryEntry];
--check also real instances in case silly user violates directory invarinces
FOR il: CD.InstanceList ← CDOps.InstList[handle.design], il.rest WHILE il#NIL DO
IF il.first.ob.class.inDirectory THEN
IF DoRecurse[handle, il.first.ob].new THEN new ← TRUE
ENDLOOP;
RETURN; --the pushed in levels are not delt with...
};
p ← GetPrivate[handle.class.key, ob];
IF handle.invocation=p.lastInvocation THEN
RETURN [p.lastVal, handle.invocation=p.originalInvocation];
CDDirectory.EnumerateChildObjects[me: ob, p: EachChild, x: handle];
new ← new OR p.lastInvocation=NIL;
IF ~new AND handle.class.reUse#NIL THEN {
new ← handle.class.reUse[handle, ob, p.lastVal].shouldDoAain
};
IF new THEN {
p.lastVal ← handle.class.do[handle, ob];
p.originalInvocation ← handle.invocation;
};
p.lastInvocation ← handle.invocation;
RETURN [p.lastVal, new];
};
END.