CDBottomUpImpl.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, February 13, 1987 1:06:22 pm PST
DIRECTORY
CD,
CDBottomUp,
CDDirectory,
CDImports,
CDProperties;
CDBottomUpImpl:
CEDAR
MONITOR
IMPORTS CDDirectory, CDProperties
EXPORTS CDBottomUp =
BEGIN OPEN CDBottomUp;
PrivateRec:
TYPE =
RECORD [
lastInvocation: REF←NIL,
lastVal: REF←NIL,
originalInvocation: REF←NIL
];
--passed through invocations are never NIL: a NIL invocation means value not yet computed
MakeHandle:
PUBLIC
PROC [class: Class, design:
CD.Design, data:
REF←
NIL, invocation:
REF←
NIL]
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, enumerateChildren: EnumChildsProc←
NIL, key:
REF, reRegistrationKey:
REF, classData:
REF, xDesign:
BOOL]
RETURNS [class: Class] = {
IF key=NIL THEN key ← NEW[INT];
class ← NEW[ClassRec ← [do, reUse, enumerateChildren, key, classData, xDesign]];
[] ← CDProperties.RegisterProperty[key, reRegistrationKey];
CDProperties.InstallProcs[key, [autoRem: TRUE]];
};
Peek:
PUBLIC
PROC [key:
REF, ob:
CD.Object]
RETURNS [val:
REF←
NIL] = {
WITH CDProperties.GetObjectProp[ob, key]
SELECT
FROM
p: REF PrivateRec => val ← p.lastVal;
ENDCASE => NULL;
};
StartRecurse:
PUBLIC PROC [class: Class, ob:
CD.Object, design:
CD.Design, data:
REF←
NIL]
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:
REF←
NIL, new:
BOOL←
FALSE] = {
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.EachObjectProc = {
IF me.class.composed
THEN
IF DoRecurse[handle, me].new THEN new ← TRUE;
};
p: REF PrivateRec;
IF ob=
NIL
THEN {
IF handle.design=NIL THEN ERROR;
[] ← CDDirectory.EnumerateDesign[handle.design, EachChild];
RETURN;
};
p ← GetPrivate[handle.class.key, ob];
IF handle.invocation=p.lastInvocation
THEN
RETURN [p.lastVal, handle.invocation=p.originalInvocation];
IF handle.class.enumerateChildren#
NIL
THEN [] ← handle.class.enumerateChildren[me: ob, proc: EachChild, data: handle]
ELSE [] ← CDDirectory.EnumerateChildObjects[me: ob, proc: EachChild, data: handle];
IF ob.class.xDesign
AND handle.class.xDesign
THEN {
WITH ob.specific
SELECT
FROM
ip: CDImports.ImportSpecific =>
IF ip.boundOb#
NIL
AND ip.boundOb.class.composed
THEN {
h: Handle ← MakeHandle[handle.class, ip.boundDesign, handle.data, handle.invocation];
IF DoRecurse[h, ip.boundOb].new THEN new ← TRUE
}
ENDCASE => ERROR;
};
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.