CDBottomUpImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Jacobi, December 13, 1985 5:49:59 pm PST
Jacobi, December 13, 1985 5:50:01 pm PST
DIRECTORY
CD,
CDBottomUp,
CDDirectory,
CDEvents,
CDProperties;
CDBottomUpImpl:
CEDAR
MONITOR
IMPORTS CDDirectory, CDEvents, CDProperties
EXPORTS CDBottomUp =
BEGIN OPEN CDBottomUp;
registration:
LIST
OF
REF
ANY ←
NIL;
--these properties must be removed when objects change
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] =
BEGIN
handle ←
NEW[HandleRec←[
class: class,
design: design,
data: data,
invocation: IF invocation#NIL THEN invocation ELSE NEW[INT]
]];
END;
Register:
PUBLIC
PROC[do: DoProc, reUse: ReUseProc←
NIL, key:
REF←
NIL, reRegistrationKey:
REF←
NIL]
RETURNS [class: Class] =
BEGIN
RegisterProtected:
ENTRY
PROC [] = {
ENABLE UNWIND => NULL;
registration ← CONS[key, registration];
};
IF key=NIL THEN key ← NEW[INT];
class ← NEW[ClassRec←[do, reUse, key]];
[] ← CDProperties.RegisterProperty[key, reRegistrationKey];
RegisterProtected[];
END;
GetPrivate:
ENTRY
PROC [key:
REF, ob:
CD.Object]
RETURNS [h:
REF PrivateRec] =
BEGIN ENABLE UNWIND => NULL;
WITH CDProperties.GetPropFromObject[ob, key]
SELECT
FROM
p: REF PrivateRec => h ← p;
ENDCASE => CDProperties.PutPropOnObject[ob, key, (h←NEW[PrivateRec])];
END;
ObChanged: CDEvents.EventProc =
BEGIN ENABLE UNWIND => NULL;
WITH x
SELECT
FROM
ob:
CD.Object =>
FOR list:
LIST
OF
REF
ANY ← registration, list.rest
WHILE list#
NIL
DO
CDProperties.PutPropOnObject[ob, list.first, NIL];
ENDLOOP;
ENDCASE => NULL;
END;
DoRecurse:
PUBLIC
PROC [handle: Handle, ob:
CD.Object]
RETURNS [val:
REF←
NIL, new:
BOOL←
FALSE] =
BEGIN
EachChild: CDDirectory.EnumerateObjectsProc = {
IF me.class.inDirectory
THEN
IF DoRecurse[handle, me].new THEN new ← TRUE;
};
p: REF PrivateRec;
IF ob=
NIL
THEN
ob ← NEW[CD.ObjectRep←handle.design.actual.first.dummyCell.ob^]; --copy, so will not find property again ?
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;
CDEvents.RegisterEventProc[$AfterCellReplacement, ObChanged];
END.