DIRECTORY CD, CDBottomUp, CDDirectory, CDOps, CDProperties; CDBottomUpImpl: CEDAR MONITOR IMPORTS CDDirectory, CDOps, CDProperties EXPORTS CDBottomUp = BEGIN OPEN CDBottomUp; PrivateRec: TYPE = RECORD [ lastInvocation: REF_NIL, lastVal: REF_NIL, originalInvocation: REF_NIL ]; 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, 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: REF_NIL] = { 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: 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.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]; 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. |CDBottomUpImpl.mesa Copyright c 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 --passed through invocations are never NIL: a NIL invocation means value not yet computed --check also real instances in case silly user violates directory invarinces ΚI˜J˜code™Kšœ Οmœ7™BK™3K™CK˜—šΟk ˜ Kšžœ˜K˜ K˜ Kšœ˜Kšœ ˜ —K˜šΟnœžœž˜Kšžœ!˜(Kšžœ ˜—Kšž œ ˜K˜šœ žœžœ˜Kšœžœžœ˜Kšœ žœžœ˜Kšœžœž˜Kšœ˜KšœY™Y—K˜šŸ œžœžœžœžœžœžœžœžœ˜zšœ žœ ˜Jšœ ˜ Jšœ˜Jšœ ˜ Jš œ žœ žœžœ žœžœžœ˜;J˜—Jšœ˜K˜—šŸœžœžœ$žœžœ žœžœ˜€Kš žœžœžœžœžœ˜Kšœžœ)˜4Kšœ;˜;Kšœ)žœ˜0Kšœ˜—K˜šŸœžœžœžœžœ žœžœžœ˜Fšžœ%žœž˜4Kšœžœ˜%Kšžœžœ˜—Kšœ˜—K˜šŸ œž œžœ žœžœžœžœžœžœ˜‹Kšœ)˜)Kšœ#˜#Kšœ˜—K˜šŸ œžœžœžœ žœžœžœžœžœ˜bK˜šŸ œžœžœžœ žœžœžœ˜Qšžœ%žœž˜4Kšœžœ˜Kšžœ+žœ˜D—Kšœ˜—K˜šΠbn œ&˜/šžœž˜Kšžœžœžœ˜-—Kšœ˜—K˜šŸœ!˜3Kšžœžœžœ˜-K˜—K˜Kšœžœ ˜šžœžœžœ˜Kšžœžœžœžœ˜ Kšœ>˜>KšœL™Lš žœžœ7žœžœž˜Pšžœž˜%Kšžœ$žœž˜5—Kšžœ˜—KšžœΟc+˜4K˜—Kšœ%˜%šžœ$žœ˜+Kšžœ4˜;—KšœC˜CKšœ žœžœ˜"šžœžœžœžœ˜*Kšœ<˜