DIRECTORY CD, CDCacheBase, CDGenerate, CDGenerateBackdoor, CDDirectory, CDMenuSpecials, CDProperties, Rope, SymTab; CDGenerateImpl: CEDAR MONITOR IMPORTS CDCacheBase, CDDirectory, CDMenuSpecials, CDProperties, SymTab EXPORTS CDGenerate, CDGenerateBackdoor SHARES CDDirectory = BEGIN publicContexts: PUBLIC SymTab.Ref _ SymTab.Create[case: TRUE]; Context: TYPE = CDGenerate.Context; ContextRep: TYPE = CDGenerate.ContextRep; GeneratorProc: TYPE = CDGenerate.GeneratorProc; IGeneratorProc: TYPE = CDGenerateBackdoor.IGeneratorProc; SelectorProc: TYPE = CDGenerateBackdoor.SelectorProc; Registration: TYPE = RECORD [generator: GeneratorProc, cache: BOOL, data: REF]; Entry: TYPE = RECORD [ob: CD.Object, registration: REF Registration, lastChange: REF_NIL]; Indirection: TYPE = RECORD [onTopOf: Context, iGenerator: IGeneratorProc, selector: SelectorProc, flush: BOOL, clear: BOOL, register: BOOL]; GetCache: ENTRY PROC [context: Context, design: CD.Design] RETURNS [cache: SymTab.Ref] = { ENABLE UNWIND => NULL; WITH CDProperties.GetDesignProp[design, context] SELECT FROM symtab: SymTab.Ref => cache _ symtab; ENDCASE => { cache _ SymTab.Create[case: context.case]; CDProperties.PutDesignProp[design, context, cache]; }; }; OkObject: PROC [design: CD.Design, entry: REF Entry] RETURNS [ok: BOOL_TRUE] = { IF entry.ob.class.composed AND ~entry.ob.immutable THEN { IF ~CDDirectory.CompatibleOwner[design, entry.ob] THEN RETURN [ok_FALSE]; ok _ CDCacheBase.Match[[entry.ob, entry.lastChange]]; }; }; Create: PUBLIC PROC [case: BOOL _ TRUE, cache: BOOL _ TRUE] RETURNS [context: Context] = { context _ NEW[ContextRep_[rep: SymTab.Create[case: case, mod: 51], case: case, cache: cache]]; }; CreateIndirect: PUBLIC PROC [onTopOf: Context, iGenerator: IGeneratorProc, selector: SelectorProc_NIL, cache: BOOL _ TRUE, flushThrough: BOOL _ TRUE, clearThrough: BOOL _ TRUE, registerThrough: BOOL _ TRUE] RETURNS [context: Context] = { ind: REF Indirection _ NEW[Indirection _ [iGenerator: iGenerator, onTopOf: onTopOf, selector: selector, flush: flushThrough, clear: clearThrough, register: registerThrough]]; context _ NEW[ContextRep _ [rep: ind, case: onTopOf.case, cache: cache AND onTopOf.cache]]; }; Indiretee: PUBLIC PROC [context: Context] RETURNS [Context] = { WITH context.rep SELECT FROM ind: REF Indirection => RETURN [ind.onTopOf] ENDCASE => RETURN [NIL] }; Clear: PUBLIC PROC [context: Context] = { WITH context.rep SELECT FROM symtab: SymTab.Ref => { EachPair: SymTab.EachPairAction = { [] _ symtab.Delete[key]; quit _ FALSE; }; [] _ symtab.Pairs[EachPair]; }; ind: REF Indirection => IF ind.clear THEN Clear[ind.onTopOf]; ENDCASE => ERROR }; Register: PUBLIC PROC [context: Context, key: Rope.ROPE, generator: GeneratorProc, cache: BOOL, data: REF] RETURNS [first: BOOL] = { WITH context.rep SELECT FROM symtab: SymTab.Ref => { IF generator=NIL THEN first _ ~ symtab.Delete[key] ELSE first _ symtab.Store[key, NEW[Registration _ [generator: generator, cache: cache AND context.cache, data: data]]] }; ind: REF Indirection => IF ind.register THEN RETURN [Register[ind.onTopOf, key, generator, cache, data]]; ENDCASE => ERROR }; FetchRegRef: PROC [context: Context, key: Rope.ROPE] RETURNS [reg: REF Registration_NIL] = { WITH context.rep SELECT FROM symtab: SymTab.Ref => WITH symtab.Fetch[key].val SELECT FROM reg: REF Registration => RETURN [reg]; ENDCASE => NULL; ind: REF Indirection => RETURN [FetchRegRef[ind.onTopOf, key]] ENDCASE => NULL; }; FetchRegistration: PUBLIC PROC [context: Context, key: Rope.ROPE] RETURNS [generator: GeneratorProc_NIL, cache: BOOL_FALSE, data: REF_NIL] = { reg: REF Registration = FetchRegRef[context, key]; IF reg#NIL THEN { generator _ reg.generator; cache _ reg.cache AND context.cache; data _ reg.data }; }; FetchCached: PUBLIC PROC[context: Context, design: CD.Design, key: Rope.ROPE] RETURNS [ob: CD.Object_NIL] = { IF context.cache THEN { reg: REF Registration _ FetchRegRef[context, key]; IF reg=NIL OR reg.cache THEN { obCache: SymTab.Ref _ GetCache[context, design]; entry: REF Entry _ NARROW[obCache.Fetch[key].val]; IF entry#NIL AND entry.registration=reg THEN { IF OkObject[design, entry] THEN RETURN [entry.ob] ELSE [] _ obCache.Delete[key] } } } }; FetchNCall: PUBLIC PROC[context: Context, design: CD.Design, key: Rope.ROPE, cache: BOOL] RETURNS [ob: CD.Object_NIL] = { ob _ FetchIndirect[passContext: context, realContext: context, design: design, key: key, cache: cache] }; Flush: PUBLIC PROC [context: Context, design: CD.Design, key: Rope.ROPE] = { IF context.cache THEN { cache: SymTab.Ref _ GetCache[context, design]; [] _ cache.Delete[key] }; WITH context.rep SELECT FROM ind: REF Indirection => IF ind.flush THEN Flush[ind.onTopOf, design, key]; ENDCASE => NULL; }; FlushAll: PUBLIC PROC [context: Context, design: CD.Design] = { IF context.cache THEN { cache: SymTab.Ref _ SymTab.Create[case: context.case]; CDProperties.PutDesignProp[design, context, cache] }; WITH context.rep SELECT FROM ind: REF Indirection => IF ind.flush THEN FlushAll[ind.onTopOf, design] ENDCASE => NULL; }; SelectOneOf: PUBLIC PROC[context: Context, label: Rope.ROPE] RETURNS [key: Rope.ROPE_NIL] = { WITH context.rep SELECT FROM symtab: SymTab.Ref => key _ CDMenuSpecials.SelectOneOf[symtab, label]; ind: REF Indirection => { IF ind.selector=SelectOneOf THEN key _ SelectOneOf[ind.onTopOf, label] ELSE IF ind.selector#NIL THEN key _ ind.selector[context, label] }; ENDCASE => ERROR }; AssertContext: PUBLIC PROC [project: Rope.ROPE] RETURNS [context: Context] = { WITH publicContexts.Fetch[project].val SELECT FROM tab: Context => context _ tab; ENDCASE => { [] _ publicContexts.Insert[project, Create[]]; context _ AssertContext[project]; } }; FetchIndirect: PUBLIC PROC [passContext, realContext: Context, design: CD.Design, key: Rope.ROPE, cache: BOOL_FALSE] RETURNS [ob: CD.Object_NIL] = { reg: REF Registration_NIL; obCache: SymTab.Ref; entry: REF Entry_NIL; IF cache AND realContext.cache THEN { --THEN also onTopOf.cache ! reg _ FetchRegRef[realContext, key]; IF reg=NIL OR reg.cache THEN { obCache _ GetCache[realContext, design]; entry _ NARROW[obCache.Fetch[key].val]; IF entry#NIL AND entry.registration=reg THEN { IF OkObject[design, entry] THEN RETURN [entry.ob] ELSE [] _ obCache.Delete[key] }; }; }; WITH realContext.rep SELECT FROM st: SymTab.Ref => { IF reg=NIL THEN reg _ FetchRegRef[realContext, key]; IF reg#NIL THEN ob _ reg.generator[design: design, key: key, context: passContext, data: reg.data]; }; ind: REF Indirection => { ob _ ind.iGenerator[design: design, key: key, passContext: passContext, realContext: realContext]; }; ENDCASE => ERROR; IF cache AND realContext.cache THEN { IF reg=NIL OR reg.cache THEN { IF ob=NIL THEN [] _ obCache.Delete[key] ELSE { entry _ NEW[Entry _ [ob: ob, registration: reg, lastChange: CDCacheBase.CurrentKey[ob]]]; [] _ obCache.Store[key, entry]; } } }; }; END. ΦCDGenerateImpl.mesa (part of ChipNDale) Copyright c 1985, 1987 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, June 5, 1985 8:02:35 pm PDT Last edited by: Christian Jacobi, April 2, 1987 7:31:32 pm PST --NIL if not indirect --fetches registration of real generator --cache means original registration and is not updated according to any indirection --returns NIL if not found, not cached or looks different --returns NIL if not found or generated --Removes this entry from the cache --Removes all entries from the cache --Interactive selection --NIL if discarded --Fetches a context; if not done then create one and store it for next call of AssertContext. --This context can be imported by lots of unknown applications... --Like FetchNCall except: --passContext will be passed trough only --realContext context to be really called. --To be called from indirection generators --check fetch from cache --make an actual call... --store in cache Κ ˜codešœ'™'Kšœ Οmœ7™BKšœ8™8K™>—K˜šΟk œ˜ Kšžœ˜Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜Kšœ˜K˜—šΟnœžœž˜Kšžœ?˜FKšžœ˜&Kšžœ˜—Kšž˜K˜Kšœžœ"žœ˜>K˜Kšœ žœ˜#Kšœ žœ žœ ž˜)Kšœžœ˜/Kšœžœ%˜9Kšœžœžœ ž˜5K˜Kš œžœžœ#žœžœ˜OKš œžœžœžœžœžœžœ˜ZKš œ žœžœOžœ žœ žœ˜ŒK˜šŸœž œžœ žœ˜ZKšžœžœžœ˜šžœ-žœž˜Kšžœžœ˜—Kšœ˜—K˜šŸœžœžœžœžœžœ žœžœžœžœ˜ŽKšœS™SKšœžœ*˜2šžœžœžœ˜Kšœ˜Kšœžœ˜%Kšœ˜Kšœ˜—Kšœ˜—K˜šŸ œž œžœžœžœžœžœ˜mKšœ9™9šžœžœ˜Kšœžœ*˜2š žœžœžœ žœž˜Kšœ0˜0Kšœžœ žœ˜2šžœžœžœžœ˜.Kšžœžœžœ ˜1Kšžœ˜K˜—K˜—K˜—Kšœ˜K™—šŸ œžœžœžœžœ žœžœžœžœ˜yKšœ'™'Kšœf˜fKšœ˜K™—š Ÿœžœžœžœžœ˜LKšœ#™#šžœžœ˜Kšœ.˜.Kšœ˜K˜—šžœ žœž˜Kšœžœžœ žœ!˜JKšžœžœ˜—Kšœ˜K™—šŸœžœžœžœ ˜?Kšœ$™$šžœžœ˜Kšœ6˜6Kšœ2˜2K˜—šžœ žœž˜Kšœžœžœ žœ˜GKšžœžœ˜—Kšœ˜K™—šŸ œžœžœžœžœ žœžœ˜]Kšœ™Kšœ™šžœ žœžœ˜KšœF˜Fšœžœ˜Kšžœžœ&˜FKšžœžœžœžœ#˜@K˜—Kšžœž˜—Kšœ˜—K˜š Ÿ œžœžœžœžœ˜NKšœ]™]KšœA™Ašžœ#žœž˜2Kšœ˜šžœ˜ Kšœ.˜.Kšœ!˜!K˜——Kšœ˜—K˜šŸ œžœžœ-žœžœ žœžœžœžœžœ˜”Kšœ™Kšœ)™)Kšœ+™+Kšœ*™*Kšœžœžœ˜Kšœ˜Kšœžœžœ˜Kšœ™šžœžœžœ‘˜AKšœ$˜$šžœžœžœ žœ˜Kšœ(˜(Kšœžœ˜'šžœžœžœžœ˜.Kšžœžœžœ ˜1Kšžœ˜K˜—K˜—K˜—Kšœ™šžœžœžœ˜!šœ˜Kšžœžœžœ%˜4šžœžœž˜KšœS˜S—K˜—šœžœ˜Kšœb˜bK˜—Kšžœž˜—Kšœ™šžœžœžœ˜&šžœžœžœ žœ˜Kšžœžœžœ˜'šžœ˜KšœžœN˜YKšœ˜Kšœ˜—K˜—K˜—Kšœ˜—K˜Kšžœ˜K˜—…—τ(ί