DIRECTORY Basics USING [bitsPerWord], Symbols USING [Base, Limit, SERecord, Type, CSEIndex, ArraySEIndex, RecordSEIndex, ISEIndex, CSENull, ISENull, CTXRecord, CTXIndex, CTXNull, nullName, BitAddress, MDIndex], SymbolTable USING [Base], PrincOps USING [wordsPerPage], PrincOpsUtils USING [LongCopy], RCMap, RCMapOps USING [MapMapItem, MapMapObj, MapMap], VM USING [Allocate, Free, PageNumberForAddress, AddressForPageNumber]; RCMapBuilderImpl: MONITOR -- protects the current RCMap Base IMPORTS PrincOpsUtils, VM EXPORTS RCMapOps = { OPEN Symbols, RCMap; bitsPerWord: CARDINAL = Basics.bitsPerWord; -- Types -- UnionSEIndex: TYPE = Symbols.Base RELATIVE POINTER [0..Symbols.Limit) TO SERecord.cons.union; SequenceSEIndex: TYPE = Symbols.Base RELATIVE POINTER [0..Symbols.Limit) TO SERecord.cons.sequence; Handle: TYPE = RECORD[base: Base, index: Index]; MapMapItem: TYPE = RCMapOps.MapMapItem; MapMapObj: TYPE = RCMapOps.MapMapObj; MapMap: TYPE = RCMapOps.MapMap; -- Variables that define the current RCMap Base-- rcmb: Base _ NIL; rcmbPages: INT _ 0; rcmbLimit: INT _ 0; rcmbx: INT _ 0; -- number of words in the base expansionAllowed: BOOL _ FALSE; outer: PROC[stb: SymbolTable.Base, mdi: MDIndex, inner: PROC[base: SymbolTable.Base]] _ NIL; --Errors -- TooManyRCMaps: ERROR = CODE; NIY: ERROR[msg: STRING] = CODE; Initialize: PUBLIC ENTRY PROC[ ptr: Base, nPages: CARDINAL, expansionOK: BOOL _ FALSE] = { ENABLE UNWIND => NULL; expansionAllowed _ expansionOK; rcmb _ ptr--ASSUME allocated by VM.Allocate--; rcmbx _ 0; rcmbPages _ nPages; rcmbLimit _ nPages*PrincOps.wordsPerPage; IF rcmbLimit < 3 THEN ExpandRCMSpace[]; rcmb[nullIndex] _ [null[]]; rcmb[refIndex] _ [ref[]]; rcmb[controlLinkIndex] _ [controlLink[]]; rcmbx _ 3}; EstablishOuter: PUBLIC ENTRY PROC[ outerProc: PROC [ stb: SymbolTable.Base, mdi: Symbols.MDIndex, inner: PROC[base: SymbolTable.Base]]] = { ENABLE UNWIND => NULL; outer _ outerProc}; Finalize: PUBLIC ENTRY PROC = { ENABLE UNWIND => NULL; IF rcmb # NIL THEN { VM.Free[[page: VM.PageNumberForAddress[rcmb], count: rcmbPages]]; rcmb _ NIL; rcmbPages _ 0; rcmbLimit _ 0; rcmbx _ 0; }; }; GetBase: PUBLIC ENTRY PROC RETURNS[base: Base, nWords: CARDINAL] = { ENABLE UNWIND => NULL; RETURN[rcmb, rcmbx]}; Acquire: PUBLIC ENTRY PROC[stb: SymbolTable.Base, sei: Type] RETURNS[rcmx: Index] = { ENABLE UNWIND => NULL; RETURN[DoAcquire[stb, stb.UnderType[sei]]]}; DoAcquire: INTERNAL PROC [stb: SymbolTable.Base, csei: CSEIndex] RETURNS[rcmx: Index] = { RETURN[WITH cse: stb.seb[csei] SELECT FROM record => MakeRCMapForRecord[stb, LOOPHOLE[csei, RecordSEIndex]], array => MakeRCMapForArray[stb, LOOPHOLE[csei, ArraySEIndex]], sequence => MakeRCMapForSequence[stb, LOOPHOLE[csei, SequenceSEIndex]], union => MakeRCMapForUnion[stb, LOOPHOLE[csei, UnionSEIndex]], zone => (IF cse.counted THEN refIndex ELSE nullIndex), long => (IF (WITH rse: stb.seb[stb.UnderType[cse.rangeType] ] SELECT FROM ref => rse.counted, ENDCASE => FALSE) THEN refIndex ELSE nullIndex), ENDCASE => nullIndex]}; Include: PUBLIC ENTRY PROC [rcmb: Base, nWords: CARDINAL, zone: UNCOUNTED ZONE_NIL] RETURNS[mm: MapMap _ NIL] = { ENABLE UNWIND => NULL; count: INTERNAL PROC[Index] RETURNS[stop: BOOL_FALSE] = { mmEntries _ mmEntries + 1}; include: INTERNAL PROC[index: Index] RETURNS[stop: BOOL_FALSE] = { mmi: MapMapItem = [old: index, new: MapRCMIndex[[rcmb, index]]]; IF mm # NIL THEN mm[nextMMX] _ mmi; nextMMX _ nextMMX + 1}; mmEntries: CARDINAL _ 0; nextMMX: CARDINAL _ 0; IF zone # NIL THEN { [] _ DoEnumerate[rcmb, nWords, count]; mm _ zone.NEW[MapMapObj[mmEntries]]}; [] _ DoEnumerate[rcmb, nWords, include]}; FindMapMapEntry: PUBLIC PROC[mapMap: MapMap, oldIndex: Index] RETURNS[Index] = { FOR i: CARDINAL IN [0..mapMap.length) DO IF mapMap[i].old = oldIndex THEN RETURN[mapMap[i].new]; ENDLOOP; RETURN[invalidIndex]}; Enumerate: PUBLIC ENTRY PROC[ base: RCMap.Base, nWords: CARDINAL, proc: PROC[Index] RETURNS[stop: BOOL]] RETURNS[stopped: BOOL] = { ENABLE UNWIND => NULL; RETURN[DoEnumerate[base, nWords, proc]]}; DoEnumerate: INTERNAL PROC[ base: RCMap.Base, nWords: CARDINAL, proc: PROC[Index] RETURNS[stop: BOOL]] RETURNS[stopped: BOOL _ FALSE] = { FOR rcmx: Index _ Index.FIRST, rcmx + InlineSize[[base, rcmx]] UNTIL LOOPHOLE[rcmx, CARDINAL] >= nWords DO IF Complete[[base, rcmx]] AND proc[rcmx] THEN RETURN[TRUE]; ENDLOOP}; NextRCMap: SIGNAL = CODE; ListRCMaps: ENTRY PROC = { ENABLE UNWIND => NULL; p: PROC[index: Index] RETURNS[stop: BOOL] = {SIGNAL NextRCMap; RETURN[FALSE]}; [] _ DoEnumerate[rcmb, rcmbx, p]}; Complete: INTERNAL PROC[h: Handle] RETURNS[BOOL] = INLINE { RETURN[WITH rcmr: h.base[h.index] SELECT FROM null => TRUE, ref => TRUE, controlLink => TRUE, oneRef => TRUE, simple => TRUE, nonVariant => rcmr.complete, variant => rcmr.complete, array => TRUE, sequence => TRUE, ENDCASE => ERROR]}; NewARCM: INTERNAL PROC RETURNS[ans: AIndex] = { ans _ LOOPHOLE[AllocRCMap[Object.array.SIZE]]; rcmb[ans] _ [array[]]}; NewNVRCM: INTERNAL PROC[nComponents: [0..componentMaxIndex]] RETURNS[ans: NVIndex] = { ans _ LOOPHOLE[AllocRCMap[Object.nonVariant.SIZE + nComponents*RCField.SIZE]]; rcmb[ans] _ [nonVariant[nComponents: nComponents, components: TRASH]]; FOR i: CARDINAL IN [0..nComponents) DO rcmb[ans].components[i] _ []; ENDLOOP}; -- LOOPHOLE NewVRCM: INTERNAL PROC[nVariants: [0..componentMaxIndex], fdTag: FieldDescriptor] RETURNS[ans: VIndex] = { ans _ LOOPHOLE[AllocRCMap[Object.variant.SIZE + nVariants*Index.SIZE]]; rcmb[ans] _ [variant[fdTag: fdTag, nVariants: nVariants, variants: TRASH]]; FOR i: CARDINAL IN [0..nVariants) DO rcmb[ans].variants[i] _ nullIndex; ENDLOOP}; NewSeqRCM: INTERNAL PROC RETURNS[ans: SeqIndex] = { ans _ LOOPHOLE[AllocRCMap[Object.sequence.SIZE]]; rcmb[ans] _ [sequence[]]}; PopRCMX: INTERNAL PROC[x: CARDINAL] = {rcmbx _ x}; InstallSimplifiedRCM: INTERNAL PROC[srcm: UNSPECIFIED] RETURNS[ans: Index] = { proc: INTERNAL PROC[index: Index] RETURNS[stop: BOOL] = { stop _ (rcmb[index].type = simple AND srcm = rcmb[LOOPHOLE[index, SimpIndex]]) OR (rcmb[index].type = oneRef AND srcm = rcmb[LOOPHOLE[index, OneRefIndex]]); IF stop THEN ans _ index}; IF LOOPHOLE[srcm, Object.null].type = null THEN RETURN[nullIndex]; IF LOOPHOLE[srcm, Object.ref].type = ref THEN RETURN[refIndex]; IF DoEnumerate[rcmb, rcmbx, proc].stopped THEN RETURN[ans]; ans _ AllocRCMap[Object.simple.SIZE]; rcmb[LOOPHOLE[ans, RefIndex]] _ srcm}; MakeRCMapForRecord: INTERNAL PROC[stb: SymbolTable.Base, rsei: RecordSEIndex] RETURNS[Index] = { IF ~stb.seb[rsei].hints.refField THEN RETURN[nullIndex]; IF stb.seb[rsei].hints.variant THEN RETURN[MakeRCMapForVRecord[stb, rsei]] ELSE RETURN[MakeRCMapForNVRecord[stb, rsei]]}; MakeRCMapForArray: INTERNAL PROC[stb: SymbolTable.Base, asei: ArraySEIndex] RETURNS[Index] = { compSEI: CSEIndex = stb.UnderType[stb.seb[asei].componentType]; IF IsRC[stb, compSEI] THEN { oldrcmbx: CARDINAL = rcmbx; ercmx: Index _ DoAcquire[stb, compSEI]; arcmx: AIndex _ NewARCM[]; simpRCM: UNSPECIFIED; simplified: BOOL; rcmb[arcmx] _ [array[wordsPerElement: stb.WordsForType[compSEI], nElements: stb.Cardinality[stb.seb[asei].indexType], rcmi: ercmx]]; [simpRCM, simplified] _ SimplifyRCM[arcmx]; IF simplified THEN {PopRCMX[oldrcmbx]; RETURN[InstallSimplifiedRCM[simpRCM]]} ELSE { x: Index; found: BOOL; [found, x] _ FindRCMap[[rcmb, arcmx], oldrcmbx]; IF found THEN {PopRCMX[oldrcmbx]; RETURN[x]} ELSE RETURN[arcmx]}} ELSE RETURN[nullIndex]}; MakeRCMapForSequence: INTERNAL PROC[stb: SymbolTable.Base, seqsei: SequenceSEIndex] RETURNS[ans: Index] = { tagSEI: ISEIndex = stb.seb[seqsei].tagSei; componentSEI: Type = stb.seb[seqsei].componentType; ercmi: Index; seqrcmx: SeqIndex; found: BOOL; oldrcmbx: CARDINAL = rcmbx; IF TRUE THEN ERROR NIY["Stand-alone Sequences"L]; IF ~IsRC[stb, componentSEI] THEN RETURN[nullIndex]; IF ~stb.seb[seqsei].controlled THEN ERROR NIY["computed sequences"L]; ercmi _ DoAcquire[stb, stb.UnderType[componentSEI]]; seqrcmx _ NewSeqRCM[]; rcmb[seqrcmx].wordsPerElement _ stb.WordsForType[componentSEI]; rcmb[seqrcmx].fdLength _ [ wordOffset: 0, bitFirst: stb.seb[tagSEI].idValue MOD bitsPerWord, bitCount: stb.seb[tagSEI].idInfo]; rcmb[seqrcmx].commonPart _ nullIndex; rcmb[seqrcmx].dataOffset _ (stb.seb[tagSEI].idValue + stb.seb[tagSEI].idInfo) / bitsPerWord; rcmb[seqrcmx].rcmi _ ercmi; [found, ans] _ FindRCMap[[rcmb, seqrcmx], oldrcmbx]; IF found THEN {PopRCMX[oldrcmbx]; RETURN[ans]} ELSE RETURN[seqrcmx]}; MakeRCMapForUnion: INTERNAL PROC[stb: SymbolTable.Base, usei: UnionSEIndex] RETURNS[rcmx: Index _ invalidIndex] = { GetRCMX: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = { rcsei: CSEIndex _ stb.UnderType[stb.TypeLink[isei]]; IF rcsei = CSENull THEN ERROR; rcmx _ MakeRCMapForRecord[stb, LOOPHOLE[rcsei, RecordSEIndex]]; RETURN[TRUE]}; -- stop the enumeration nVariants: CARDINAL = stb.Cardinality[stb.seb[stb.seb[usei].tagSei].idType]; nFields: CARDINAL _ 0; IF ~stb.seb[usei].hints.refField THEN RETURN[nullIndex]; FOR isei: ISEIndex _ stb.FirstCtxSe[stb.seb[usei].caseCtx], stb.NextSe[isei] UNTIL isei = ISENull DO nFields _ nFields + 1 ENDLOOP; [] _ EnumerateCtxIseis[stb, stb.seb[usei].caseCtx, GetRCMX, (nVariants = nFields)]; IF rcmx = invalidIndex THEN ERROR}; MakeRCMapForNVRecord: INTERNAL PROC[stb: SymbolTable.Base, rsei: RecordSEIndex] RETURNS[Index] = { n: CARDINAL = CountRCCommonComponents[stb, rsei]; oldrcmbx: CARDINAL = rcmbx; nvrcmx: NVIndex; simpRCM: UNSPECIFIED; simplified: BOOL; IF n = 0 THEN RETURN[nullIndex]; nvrcmx _ NewNVRCM[n]; IF StuffRCCommonComponents[stb, rsei, nvrcmx] # n THEN ERROR; [simpRCM, simplified] _ SimplifyRCM[nvrcmx]; IF simplified THEN {PopRCMX[oldrcmbx]; RETURN[InstallSimplifiedRCM[simpRCM]]} ELSE { x: Index; found: BOOL; rcmb[nvrcmx].complete _ TRUE; [found, x] _ FindRCMap[[rcmb, nvrcmx], oldrcmbx]; IF found THEN {PopRCMX[oldrcmbx]; RETURN[x]} ELSE RETURN[nvrcmx]}}; MakeRCMapForVRecord: INTERNAL PROC[stb: SymbolTable.Base, rsei: RecordSEIndex] RETURNS[ans: Index] = { -- maybe a sequence-containing record ncc: CARDINAL = CountRCCommonComponents[stb, rsei]; oldrcmbx: CARDINAL = rcmbx; nvrcmx: Index _ MakeRCMapForNVRecord[stb, rsei]; up: INTERNAL PROC[ucstb: SymbolTable.Base, ucser: SERecord.cons.union] = { -- called once nvc: CARDINAL = CountRCVariants[ucstb, ucser]; x: Index; found: BOOL; IF nvc + ncc = 0 THEN ERROR; IF nvc = 0 THEN ans _ nvrcmx ELSE { tagSEI: ISEIndex = ucser.tagSei; nVariants: CARDINAL = ucstb.Cardinality[ucstb.seb[tagSEI].idType]; vrcmx: VIndex _ NewVRCM[ nVariants: nVariants, fdTag: [wordOffset: ucstb.seb[tagSEI].idValue / bitsPerWord, bitFirst: ucstb.seb[tagSEI].idValue MOD bitsPerWord, bitCount: ucstb.seb[tagSEI].idInfo]]; FOR i: CARDINAL IN [0..nVariants) DO rcmb[vrcmx].variants[i] _ nvrcmx; ENDLOOP; -- NOTE LOOPHOLE IF StuffRCVariantComponents[ucstb, ucser, vrcmx, nVariants] # nvc THEN ERROR; rcmb[vrcmx].complete _ TRUE; [found, x] _ FindRCMap[[rcmb, vrcmx], oldrcmbx]; IF found THEN {PopRCMX[oldrcmbx]; ans _ x} ELSE ans _ vrcmx}}; sp: INTERNAL PROC[scstb: SymbolTable.Base, scser: SERecord.cons.sequence] = { -- called once IF ~scser.controlled THEN ERROR NIY["computed sequences"L]; IF ncc = 0 AND ~IsRC[scstb, scser.componentType] THEN ERROR; IF ~IsRC[scstb, scser.componentType] THEN ans _ nvrcmx ELSE { ercmi: Index = DoAcquire[scstb, scstb.UnderType[scser.componentType]]; tagSEI: ISEIndex = scser.tagSei; seqrcmx: SeqIndex; found: BOOL; x: Index; seqrcmx _ NewSeqRCM[]; rcmb[seqrcmx].wordsPerElement _ scstb.WordsForType[scser.componentType]; rcmb[seqrcmx].fdLength _ [wordOffset: scstb.seb[tagSEI].idValue / bitsPerWord, bitFirst: scstb.seb[tagSEI].idValue MOD bitsPerWord, bitCount: scstb.seb[tagSEI].idInfo]; rcmb[seqrcmx].commonPart _ nvrcmx; rcmb[seqrcmx].dataOffset _ (scstb.seb[tagSEI].idValue + scstb.seb[tagSEI].idInfo) / bitsPerWord; rcmb[seqrcmx].rcmi _ ercmi; [found, x] _ FindRCMap[[rcmb, seqrcmx], oldrcmbx]; IF found THEN {PopRCMX[oldrcmbx]; ans _ x} ELSE ans _ seqrcmx}}; IF ~FindVariantField[stb, stb.seb[rsei].fieldCtx, up, sp] THEN ERROR}; StuffRCCommonComponents: INTERNAL PROC[ -- if looking, will find old eqv ones stb: SymbolTable.Base, rsei: RecordSEIndex, nvrcmx: NVIndex] RETURNS[nextIndex: CARDINAL _ 0] = { argrec: BOOL = stb.seb[rsei].argument; append: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = { sei: Type _ stb.seb[isei].idType; foffset: INTERNAL PROC[isei: ISEIndex] RETURNS[BitAddress] = INLINE {RETURN[IF argrec THEN stb.FnField[isei].offset ELSE stb.seb[isei].idValue]}; IF (~(IsUnion[stb, sei] OR IsSequence[stb, sei])) AND (~stb.seb[isei].constant) AND IsRC[stb, sei] THEN { rcmb[nvrcmx].components[nextIndex] _ [wordOffset: foffset[isei].wd, rcmi: DoAcquire[stb, stb.UnderType[sei]]]; nextIndex _ nextIndex + 1}; RETURN[FALSE]}; -- keep counting [] _ EnumerateRecordIseis[stb, rsei, append]}; StuffRCVariantComponents: INTERNAL PROC[ stb: SymbolTable.Base, uc: SERecord.cons.union, vrcmx: VIndex, nVariants: CARDINAL] RETURNS[n: CARDINAL] = { srcvc: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = { IF IsRC[stb, isei, FALSE] THEN { rcmb[vrcmx].variants[stb.seb[isei].idValue] _ DoAcquire[stb, stb.UnderType[isei]]; n _ n + 1}; RETURN[FALSE]}; -- keep counting nFields: CARDINAL _ 0; FOR isei: ISEIndex _ stb.FirstCtxSe[uc.caseCtx], stb.NextSe[isei] UNTIL isei = ISENull DO nFields _ nFields + 1; ENDLOOP; n _ 0; [] _ EnumerateCtxIseis[stb, uc.caseCtx, srcvc, (nVariants = nFields)]}; SimplifyRCM: INTERNAL PROC[rcmx: Index] RETURNS[rcmr: UNSPECIFIED, simplified: BOOL] = { srcmr: Object.simple _ [simple[]]; rrcmr: Object.oneRef _ [oneRef[]]; nRefOffsets: CARDINAL _ 0; nSimpleVecEntries: CARDINAL _ 0; p: INTERNAL PROC[refOffset: CARDINAL] RETURNS[stop: BOOL] = { nRefOffsets _ nRefOffsets+1; IF ((nRefOffsets # 1) OR (refOffset > componentMaxIndex)) AND (refOffset > simpleMaxIndex) THEN RETURN[TRUE]; -- can't simplify. Fail. IF nRefOffsets = 1 AND refOffset <= componentMaxIndex THEN rrcmr.offset _ refOffset; IF refOffset <= simpleMaxIndex THEN { nSimpleVecEntries _ nSimpleVecEntries + 1; IF nSimpleVecEntries # nRefOffsets THEN RETURN[TRUE]; -- can't simplify. Fail. srcmr.refs[refOffset] _ TRUE; srcmr.length _ MAX[srcmr.length, refOffset + 1]}; RETURN[FALSE]}; -- keep going simplified _ ~EnumerateForSimplify[rcmx, p].stopped; IF simplified THEN { IF nRefOffsets = 0 THEN rcmr _ Object[null[]] ELSE IF nRefOffsets = 1 THEN { IF rrcmr.offset = 0 THEN rcmr _ Object[ref[]] ELSE rcmr _ rrcmr} ELSE rcmr _ srcmr} ELSE rcmr _ NIL}; EnumerateForSimplify: INTERNAL PROC[ rcmx: Index, p: PROC[refOffset: CARDINAL] RETURNS[stop: BOOL], offset: CARDINAL _ 0] RETURNS[stopped: BOOL] = { MapArrayRCM: INTERNAL PROC[refOffset: CARDINAL, arcmx: AIndex] RETURNS[stop: BOOL] = { FOR i: CARDINAL IN [0..rcmb[arcmx].nElements) DO IF EnumerateForSimplify[ rcmb[arcmx].rcmi, p, refOffset+i*rcmb[arcmx].wordsPerElement].stopped THEN RETURN[stop: TRUE]; ENDLOOP; RETURN[stop: FALSE]}; MapRecordRCM: INTERNAL PROC[refOffset: CARDINAL, nvrcmx: NVIndex] RETURNS[stop: BOOL] = { FOR i: CARDINAL IN [0..rcmb[nvrcmx].nComponents) DO IF EnumerateForSimplify[ rcmb[nvrcmx].components[i].rcmi, p, refOffset+rcmb[nvrcmx].components[i].wordOffset].stopped THEN RETURN[stop: TRUE]; ENDLOOP; RETURN[stop: FALSE]}; WITH rcmr: rcmb[rcmx] SELECT FROM nonVariant => stopped _ MapRecordRCM[offset, LOOPHOLE[rcmx]]; array => stopped _ MapArrayRCM[offset, LOOPHOLE[rcmx]]; null => stopped _ FALSE; ref => stopped _ p[offset]; controlLink => stopped _ p[offset]; oneRef => stopped _ p[offset+rcmr.offset]; simple => { FOR i: CARDINAL IN [0..rcmr.length) DO IF rcmr.refs[i] THEN IF p[offset+i].stop THEN RETURN[TRUE]; ENDLOOP; stopped _ FALSE}; variant, sequence => stopped _ TRUE; ENDCASE => ERROR}; IsUnion: INTERNAL PROC [stb: SymbolTable.Base, seIndex: Type] RETURNS[BOOL] = {RETURN[stb.seb[stb.UnderType[seIndex]].typeTag = union]}; IsSequence: INTERNAL PROC [stb: SymbolTable.Base, seIndex: Type] RETURNS[BOOL] = {RETURN[stb.seb[stb.UnderType[seIndex]].typeTag = sequence]}; EnumerateRecordIseis: INTERNAL PROC [ stb: SymbolTable.Base, rsei: RecordSEIndex, p: PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL], level: CARDINAL _ 0] RETURNS [stopped: BOOL] = { proc: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = { sei: Type _ stb.seb[isei].idType; IF ~(IsUnion[stb, sei] OR IsSequence[stb, sei]) OR level = 0 THEN RETURN[p[stb, isei]]; RETURN[FALSE]}; IF rsei = CSENull THEN RETURN[FALSE]; WITH lrc: stb.seb[rsei] SELECT FROM linked => { stopped _ EnumerateRecordIseis[stb, LOOPHOLE[stb.UnderType[lrc.linkType]], p, level + 1]; IF stopped THEN RETURN[TRUE]}; ENDCASE; RETURN[EnumerateCtxIseis[stb, stb.seb[rsei].fieldCtx, proc]]}; EnumerateCtxIseis: INTERNAL PROC [ stb: SymbolTable.Base, ctx: CTXIndex, proc: PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL], reallyComplete: BOOL _ FALSE] RETURNS[stopped: BOOL] = { isei: ISEIndex; IF ctx = CTXNull THEN RETURN[FALSE]; IF ~reallyComplete THEN WITH c: stb.ctxb[ctx] SELECT FROM included => IF ~c.complete THEN { p: INTERNAL PROC[base: SymbolTable.Base] = -- called once { stopped _ EnumerateCtxIseis[base, c.map, proc]}; IF outer = NIL THEN ERROR ELSE outer[stb, c.module, p]; RETURN[stopped]; }; simple => NULL; ENDCASE => ERROR; FOR isei _ stb.FirstCtxSe[ctx], stb.NextSe[isei] UNTIL isei = ISENull DO IF stb.seb[isei].hash = nullName AND stb.seb[isei].idCtx = CTXNull THEN LOOP; -- padding IF proc[stb, isei] THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]}; FindVariantField: INTERNAL PROC [ stb: SymbolTable.Base, ctx: CTXIndex, unionProc: PROC[ucstb: SymbolTable.Base, ucser: SERecord.cons.union], sequenceProc: PROC[scstb: SymbolTable.Base, scser: SERecord.cons.sequence]] RETURNS[BOOL] = { p: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = { c: SERecord.cons; sei: Type _ stb.seb[isei].idType; c _ stb.seb[stb.UnderType[sei]]; WITH c: c SELECT FROM union => unionProc[stb, c]; sequence => sequenceProc[stb, c]; ENDCASE => RETURN[FALSE]; RETURN[TRUE]; }; RETURN[EnumerateCtxIseis[stb, ctx, p]]}; CountRCVariants: INTERNAL PROC [stb: SymbolTable.Base, uc: SERecord.cons.union] RETURNS [n: CARDINAL] = { count: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = { IF IsRC[stb, isei, FALSE] THEN n _ n+1; RETURN[FALSE]; -- keep counting }; tagCardinality: CARDINAL _ stb.Cardinality[stb.seb[uc.tagSei].idType]; n _ 0; [] _ EnumerateCtxIseis[stb, uc.caseCtx, count, (tagCardinality = stb.CtxEntries[uc.caseCtx])]}; CountRCCommonComponents: INTERNAL PROC [stb: SymbolTable.Base, rsei: RecordSEIndex] RETURNS [n: CARDINAL] = { count: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = { sei: Type _ stb.seb[isei].idType; IF (~(IsUnion[stb, sei] OR IsSequence[stb, sei])) AND (~stb.seb[isei].constant) AND IsRC[stb, sei] THEN n _ n+1; -- don't count the variant part RETURN[FALSE]; -- keep counting }; n _ 0; [] _ EnumerateRecordIseis[stb, rsei, count]}; IsRC: INTERNAL PROC [stb: SymbolTable.Base, seIndex: Type, checkCommon: BOOL _ TRUE] RETURNS[BOOL] = { cse: SERecord.cons _ stb.seb[stb.UnderType[seIndex]]; WITH cr: cse SELECT FROM record => BEGIN rcP: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = BEGIN cse1: SERecord.cons; sei: Type _ stb.seb[isei].idType; cse1 _ stb.seb[stb.UnderType[sei]]; WITH cse1: cse1 SELECT FROM union => BEGIN urcP: INTERNAL PROC[stb: SymbolTable.Base, isei: ISEIndex] RETURNS[stop: BOOL] = BEGIN IF IsRC[stb, isei, FALSE] THEN RETURN[TRUE]; -- stop looking. This is it RETURN[FALSE]; -- keep looking END; tagCardinality: CARDINAL _ stb.Cardinality[stb.seb[cse1.tagSei].idType]; RETURN[EnumerateCtxIseis[stb, cse1.caseCtx, urcP, (tagCardinality = stb.CtxEntries[cse1.caseCtx])]]; END; sequence => IF IsRC[stb, cse1.componentType] THEN RETURN[TRUE]; -- stop looking. here tis ENDCASE => IF IsRC[stb, sei] THEN RETURN[TRUE]; -- stop looking. This is it RETURN[FALSE]; -- keep looking END; IF checkCommon THEN RETURN[cr.hints.refField] -- easy if the common parts are to be included ELSE IF ~cr.hints.refField THEN RETURN[FALSE] -- neither the variants nor the common parts are RC ELSE RETURN[EnumerateCtxIseis[stb, cr.fieldCtx, rcP]]; -- look individually at the fields END; sequence, union => ERROR; transfer => RETURN[FALSE]; -- NOTE for now relative => RETURN[FALSE]; -- NOTE for now long => RETURN[WITH rse: stb.seb[stb.UnderType[cr.rangeType] ] SELECT FROM ref => rse.counted, ENDCASE => FALSE]; zone => RETURN[cr.counted]; array => RETURN[IsRC[stb, cr.componentType]]; ENDCASE => RETURN[FALSE]}; InlineSize: INTERNAL PROC[h: Handle] RETURNS[CARDINAL] = INLINE { RETURN[WITH rcmh: h.base[h.index] SELECT FROM null => Object.null.SIZE, --NOTE better be 1 ref => Object.ref.SIZE, --NOTE better be 1 controlLink => Object.controlLink.SIZE, --NOTE better be 1 oneRef => Object.oneRef.SIZE, --NOTE better be 1 simple => Object.simple.SIZE, --NOTE better be 1 nonVariant => Object.nonVariant.SIZE + rcmh.nComponents*RCField.SIZE, variant => Object.variant.SIZE + rcmh.nVariants*Index.SIZE, array => Object.array.SIZE, sequence => Object.sequence.SIZE, ENDCASE => ERROR]}; FastEqualMaps: INTERNAL PROC [h1, h2: Handle] RETURNS [BOOL] = INLINE { DO WITH m1: h1.base[h1.index] SELECT FROM null, ref, controlLink => RETURN [h1.index = h2.index]; -- StandardRCMap's oneRef => RETURN [m1 = h2.base[h2.index]]; simple => RETURN [m1 = h2.base[h2.index]]; nonVariant => WITH m2: h2.base[h2.index] SELECT FROM nonVariant => { matched: BOOL _ (m1.complete AND m2.complete) AND (m1.nComponents = m2.nComponents); FOR i: NAT IN [0 .. m1.nComponents) WHILE matched DO matched _ (m1.components[i].wordOffset = m2.components[i].wordOffset) AND EqualMaps[[h1.base, m1.components[i].rcmi], [h2.base, m2.components[i].rcmi]]; ENDLOOP; RETURN [matched]}; ENDCASE; variant => WITH m2: h2.base[h2.index] SELECT FROM variant => { matched: BOOL _ (m1.complete AND m2.complete) AND (m1.nVariants = m2.nVariants) AND (m1.fdTag = m2.fdTag); FOR i: NAT IN [0 .. m1.nVariants) WHILE matched DO matched _ EqualMaps[[h1.base, m1.variants[i]], [h2.base, m2.variants[i]]]; ENDLOOP; RETURN [matched]}; ENDCASE; array => { WITH m2: h2.base[h2.index] SELECT FROM array => { SELECT TRUE FROM m1.wordsPerElement # m2.wordsPerElement => {}; m1.nElements # m2.nElements => {}; ENDCASE => { h1 _ [h1.base, m1.rcmi]; h2 _ [h2.base, m2.rcmi]; LOOP; }; }; ENDCASE; }; sequence => { WITH m2: h2.base[h2.index] SELECT FROM sequence => SELECT TRUE FROM m1.wordsPerElement # m2.wordsPerElement => {}; m1.fdLength # m2.fdLength => {}; m1.dataOffset # m2.dataOffset => {}; EqualMaps[[h1.base, m1.commonPart], [h2.base, m2.commonPart]] => { h1 _ [h1.base, m1.rcmi]; h2 _ [h2.base, m2.rcmi]; LOOP; }; ENDCASE; ENDCASE; }; ENDCASE => ERROR; RETURN [FALSE]; ENDLOOP; }; EqualMaps: INTERNAL PROC [h1, h2: Handle] RETURNS [BOOL] = { RETURN [FastEqualMaps[h1, h2]]; }; FindRCMap: INTERNAL PROC [h: Handle, nWords: CARDINAL _ LOOPHOLE[invalidIndex]] RETURNS [found: BOOL, index: Index] = { IF nWords = LOOPHOLE[invalidIndex, CARDINAL] THEN nWords _ rcmbx; WITH rcm: h.base[h.index] SELECT FROM null, ref, controlLink => {found _ TRUE; index _ h.index}; -- standard entries ENDCASE => { FOR rcmx: Index _ Index.FIRST, rcmx + InlineSize[[rcmb, rcmx]] UNTIL LOOPHOLE[rcmx, CARDINAL] >= nWords DO IF Complete[[rcmb, rcmx]] AND FastEqualMaps[h, [rcmb, rcmx]] THEN RETURN[TRUE, rcmx]; ENDLOOP; found _ FALSE; }; RETURN; }; EnterRCMap: INTERNAL PROC [h: Handle] RETURNS [new: Index] = { nw: CARDINAL = InlineSize[h]; new _ AllocRCMap[nw]; WITH m: h.base[h.index] SELECT FROM null, ref, controlLink, oneRef, simple => { PrincOpsUtils.LongCopy[from: @h.base[h.index], to: @rcmb[new], nwords: nw]; }; array => { cRcmi: Index = MapRCMIndex[[h.base, m.rcmi]]; rcmb[new] _ [array[ wordsPerElement: m.wordsPerElement, nElements: m.nElements, rcmi: cRcmi]]; }; nonVariant => { nvRcmi: RCMap.NVIndex _ LOOPHOLE[new]; rcmb[nvRcmi] _ [nonVariant[ nComponents: m.nComponents, components: TRASH, complete: FALSE]]; FOR i: NAT IN [0..m.nComponents) DO rcmb[nvRcmi].components[i] _ [ m.components[i].wordOffset, MapRCMIndex[[h.base, m.components[i].rcmi]]]; ENDLOOP; rcmb[nvRcmi].complete _ TRUE; }; variant => { vRcmi: RCMap.VIndex = LOOPHOLE[new]; rcmb[vRcmi] _ [variant[ nVariants: m.nVariants, fdTag: m.fdTag, variants: TRASH, complete: FALSE]]; FOR i: NAT IN [0..m.nVariants) DO rcmb[vRcmi].variants[i] _ MapRCMIndex[[h.base, m.variants[i]]]; ENDLOOP; rcmb[vRcmi].complete _ TRUE; }; sequence => { commonRcmi: Index = MapRCMIndex[[h.base, m.commonPart]]; cRcmi: Index = MapRCMIndex[[h.base, m.rcmi]]; rcmb[new] _ [sequence[ wordsPerElement: m.wordsPerElement, fdLength: m.fdLength, commonPart: commonRcmi, dataOffset: m.dataOffset, rcmi: cRcmi]]; }; ENDCASE => ERROR; RETURN}; MapRCMIndex: INTERNAL PROC [old: Handle] RETURNS [new: Index] = { found: BOOL; [found, new] _ FindRCMap[old]; IF ~found THEN new _ EnterRCMap[old]; RETURN}; AllocRCMap: INTERNAL PROC [nw: CARDINAL] RETURNS [Index] = { short: CARDINAL _ rcmbx; new: Index _ LOOPHOLE[short]; IF new = invalidIndex THEN ERROR TooManyRCMaps; rcmbx _ rcmbx + nw; IF rcmbx > rcmbLimit THEN ExpandRCMSpace[]; rcmb[new] _ [null[]]; IF nw > 1 THEN PrincOpsUtils.LongCopy[from: @rcmb[new], to: @rcmb[new+1], nwords: nw-1]; RETURN[LOOPHOLE[new]]; }; ExpandRCMSpace: INTERNAL PROC = { newLimit: CARDINAL = rcmbLimit + 4*PrincOps.wordsPerPage; newRCMB: RCMap.Base; IF NOT expansionAllowed THEN ERROR TooManyRCMaps; newRCMB _ LOOPHOLE[VM.AddressForPageNumber[VM.Allocate[count: rcmbPages + 4].page], RCMap.Base]; IF rcmb # NIL THEN { PrincOpsUtils.LongCopy[from: rcmb, to: newRCMB, nwords: rcmbLimit]; VM.Free[[page: VM.PageNumberForAddress[rcmb], count: rcmbPages]]}; rcmb _ newRCMB; rcmbPages _ rcmbPages + 4; rcmbLimit _ newLimit}; IF Object.null.SIZE # 1 OR Object.ref.SIZE # 1 OR Object.oneRef.SIZE # 1 OR Object.simple.SIZE # 1 OR Object.controlLink.SIZE # 1 THEN ERROR; }.  RCMapBuilderImpl.mesa Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. Satterthwaite On March 23, 1983 10:18 am Levin, August 8, 1983 4:06 pm Paul Rovner On September 19, 1983 9:31 pm Russ Atkinson On February 19, 1985 6:05:17 pm PST PROCs make standard entries FOR DEBUGGING first level utility PROCs for constructing RCMap Objects IF stb.seb[asei].packed THEN ERROR NIY["packed RC arrays"L]; NOTE unlike for unions, there is no way to get back to the enclosing record type IF stb.seb[seqsei].packed THEN ERROR NIY["packed RC sequence elements"L]; get the rcmx for the enclosing record NOTE offset, inclusion of common parts IF scser.packed THEN ERROR NIY["packed RC sequence elements"L]; second level utility PROCs for constructing RCMap Objects EnumerateForSimplify begins here PROCS for poking around in the symbol table copied (GROAN) from RTWalkSymbolsImpl copied (GROAN) from RTWalkSymbolsImpl copied (GROAN) from RTWalkSymbolsImpl copied (GROAN) from RTWalkSymbolsImpl copied (GROAN) from RTWalkSymbolsImpl PROCs for managing RCMap Bases Tail-recursive check for element maps Tail-recursive check for element maps Frequent case of DoEnumerate is placed INLINE and specialized! Ensure valid initialization for this map entry to avoid finding crap! START HERE Κ f˜codešœ™Kšœ Οmœ7™BKšœ(™(Kšœ™Kšœ)™)Kšœ1™1—K˜šΟk ˜ Kšœžœ˜KšœžœŸ˜¬Kšœ žœ˜Kšœ žœ˜Kšœžœ ˜Kšœ˜Kšœ žœ!˜/Kšžœžœ>˜FK˜—šœžœΟc"˜=Kšžœž˜Kšžœ ˜K˜Kšžœ˜K˜Kšœ žœ˜+K˜šŸ ˜ šœžœžœžœ˜EKšžœ˜—šœžœžœžœ˜HKšžœ˜K˜—Kšœžœžœ˜0K˜Kšœ žœ˜'Kšœ žœ˜%Kšœžœ˜K˜—šŸ1˜1Kšœ žœ˜Kšœ žœ˜Kšœ žœ˜KšœžœŸ˜/K˜Kšœžœžœ˜K˜šœžœ-žœ˜UKšœžœ˜—K˜—šŸ ˜ Kšœžœžœ˜Kšžœžœžœžœ˜K˜—Kšœ™˜šΟn œžœžœžœ˜Kšœžœžœžœ˜;Kšžœžœžœ˜Kšœ˜Kšœ Ÿ#œ ˜:K˜K˜)Kšžœžœ˜'šœ™K˜K˜K˜)—K˜ K˜—š œžœžœžœ˜"šœ žœ˜K˜K˜Kšœžœ˜)—Kšžœžœžœ˜K˜K˜—š œžœžœžœ˜Kšžœžœžœ˜šžœžœžœ˜Kšžœ žœ0˜AKšœžœ˜ Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜—Kšœ˜—K˜š  œžœžœžœžœžœ˜DKšžœžœžœ˜Kšžœ˜K˜—š  œžœžœžœ#žœ˜UKšžœžœžœ˜Kšžœ&˜,K˜—š  œžœž˜Kšœ(žœ˜@šžœžœžœž˜*Kšœ"žœ˜AKšœ žœ˜>Kšœ&žœ˜GKšœ žœ˜>Kšœ žœ žœ žœ ˜6šœ žœžœ-žœž˜IK˜Kšžœžœ˜Kšžœ žœ ˜—Kšžœ˜K˜——š œžœžœž˜Kš œžœž œžœžœ˜8Kšžœžœ˜Kšžœžœžœ˜K˜š œžœžœžœžœžœ˜9K˜K˜—š œ žœžœžœžœžœ˜BK˜@Kšžœžœžœ˜#K˜K˜—Kšœ žœ˜Kšœ žœ˜šžœžœžœ˜Kšœ&˜&Kšœ žœ˜%—K˜)K˜—š œžœžœ"žœ ˜Pšžœžœžœž˜(Kšžœžœžœžœ˜@—Kšžœ˜K˜—š  œžœžœžœ˜Kš œžœžœžœžœ˜JKšžœ žœ˜Kšžœžœžœ˜Kšžœ#˜)K˜—š  œžœžœ˜Kš œžœžœžœžœ˜JKšžœ žœžœ˜"šžœžœ!˜>šžœžœžœ ž˜+Kš žœžœ žœžœžœžœ˜EK˜K˜————šœ ™ Kšœ žœžœ˜š  œžœžœ˜Kšžœžœžœ˜Kš œžœžœžœžœ žœžœ˜NK˜"K˜—š  œžœžœ žœžœžœ˜;šžœžœžœž˜-Kšœžœ˜ Kšœžœ˜ Kšœžœ˜Kšœ žœ˜Kšœ žœ˜K˜K˜Kšœ žœ˜Kšœ žœ˜Kšžœžœ˜K˜K˜————Kšœ8™8˜š œžœžœžœ˜/Kšœžœžœ˜.K˜K˜—š œžœžœ%˜žœ˜FKš žœžœžœžœžœŸ ˜[K˜—š œžœžœ;˜QKšžœ˜Kšœžœžœžœ˜GKšœCžœ˜KKš žœžœžœžœ$žœ˜QK˜—š  œžœžœžœ˜3Kšœžœžœ˜1K˜K˜—Kš œžœžœžœ˜2K˜š  œžœžœž œžœ˜Nš œžœžœžœžœ˜9šœ"žœ žœ˜NKšž˜Kšœžœ žœ˜J—Kšžœžœ˜K˜—Kšžœžœ žœžœ ˜BKšžœžœžœžœ ˜?Kšžœ(žœžœ˜;Kšœžœ˜%Kšœžœ˜&K˜—š œžœžœ,˜MKšžœ ˜Kšžœžœžœ ˜8Kšžœžœžœ ˜JKšžœžœ#˜.K˜—š œžœžœ+˜KKšžœ ˜K˜?šžœžœ˜Kšœ žœ ˜K˜'K˜Kšœ ž œ˜Kšœ žœ˜K˜———šœ<™<˜@K˜4K˜—K˜+Kšžœ žœžœ ˜Mšžœ˜K˜ Kšœžœ˜ K˜0Kš žœžœžœžœžœ ˜A—Kšžœžœ ˜K˜š œžœžœ0˜SKšžœ˜K˜*K˜3K˜ K˜Kšœžœ˜ Kšœ žœ ˜˜KšœP™P—Kš žœžœžœžœžœ˜1Kšžœžœžœ ˜3Kšžœžœžœžœ˜E——KšœI™I˜K˜4K˜K˜?˜K˜Kšœ"žœ ˜2K˜"—K˜%K˜\K˜K˜4Kš žœžœžœžœžœ ˜EK˜š œžœžœ+˜KKšžœ ˜'š  œžœžœ(žœžœ˜UKšœ%™%K˜4Kšžœžœžœ˜Kšœ&™&Kšœžœ˜?KšžœžœŸ˜'—Kšœ žœ9˜LKšœ žœ˜Kšžœžœžœ ˜8šžœI˜LKšžœžœžœ˜6—K˜SKšžœžœžœ˜#K˜—š œžœžœ,˜OKšžœ ˜Kšœžœ&˜1Kšœ žœ ˜K˜Kšœ ž œ˜Kšœ žœ˜K˜Kšžœžœžœ ˜ K˜Kšžœ0žœžœ˜=K˜,Kšžœ žœžœ ˜Mšžœ˜K˜ Kšœžœ˜ Kšœžœ˜K˜1Kš žœžœžœžœžœ ˜CK˜——š œžœžœ,˜NKšžœŸ%˜>Kšœžœ&˜3Kšœ žœ ˜K˜0K˜šœžœžœ;Ÿ˜ZKšœžœ!˜.K˜ Kšœžœ˜ Kšžœžœžœ˜Kšžœ žœ ˜šžœ˜K˜ Kšœ žœ/˜B˜K˜˜K˜——šœžœžœ=Ÿ˜\Kšžœžœžœžœ˜;Kšžœ žœ#žœžœ˜Kšžœžœ˜šžœžœžœž˜0šžœ˜KšœFž˜JKšžœžœ˜—Kšžœ˜—Kšžœžœ˜K˜—š  œžœžœ žœ˜AKšžœžœ˜šžœžœžœž˜3šžœ˜K˜ K˜Kšœ9ž˜=Kšžœžœ˜—Kšžœ˜—Kšžœžœ˜K˜Kšœ ™ —šžœžœž˜!Kšœ-žœ˜=Kšœ'žœ˜7Kšœžœ˜K˜K˜#K˜*˜ šžœžœžœž˜&Kš žœžœžœžœžœžœ˜;Kšžœ˜—Kšœ žœ˜—Kšœžœ˜$Kšžœžœ˜K˜K˜————Kšœ+™+˜Kšœ%™%—š  œžœžœ(žœžœ˜MKšœžœ3˜:K˜Kšœ%™%—š   œžœžœ(žœžœ˜PKšœžœ6˜=K˜Kšœ%™%—š œžœž˜#˜K˜Kšœžœ(žœžœ˜CKšœžœ˜—Kšžœ žœ˜—š œžœžœ(žœžœ˜R˜#Kš žœžœžœ žœžœ˜WKšžœžœ˜K˜—Kšžœžœžœžœ˜%šžœžœž˜#˜ šœ&žœ-˜[Kšžœ žœžœžœ˜——Kšžœ˜—Kšžœ8˜>K˜Kšœ%™%—š œžœž˜ ˜(Kšœžœ(žœžœ˜F—Kšœžœžœ˜Kšžœ žœ˜—˜Kšžœžœžœžœ˜$šžœ˜šžœžœžœž˜&˜ Kšžœ ž˜šœžœžœŸ˜=K˜2Kš žœ žœžœžœžœ˜7Kšžœ ˜—K˜—Kšœ žœ˜Kšžœžœ˜——šžœ.žœž˜HKš žœžœžœžœŸ ˜YKš žœžœžœžœžœ˜.—Kšžœžœ˜K˜—š œžœžœ(˜GKšœ žœ6˜EKšœžœ9˜KKšžœžœ˜š œžœžœ(žœžœ˜O˜K˜!K˜ šžœžœž˜K˜K˜!Kšžœžœžœ˜—Kšžœžœ˜ —K˜Kšžœ"˜(K˜——š œžœžœ2˜PKšžœžœ˜š œ žœžœ(žœžœ˜Sšœžœžœžœ ˜)KšžœžœŸ˜ —K˜Kšœžœ.˜FK˜K˜_K˜——š œžœžœ.˜TKšžœžœ˜š œ žœžœ(žœžœ˜S˜#šžœžœ˜1Kšžœ˜Kšžœžœ Ÿ˜A—KšžœžœŸ˜ —K˜K˜K˜-K˜—Kšœ%™%—š  œžœžœ5žœžœ˜TKšžœžœ˜—˜7šžœ žœž˜˜ šž˜Kš œžœžœ(žœžœ˜Ošž˜K˜K˜!K˜#šžœ žœž˜˜šž˜Kš œžœžœ(žœžœ˜Pšž˜Kš žœžœžœžœžœŸ˜HKšžœžœŸ˜—Kšžœ˜Kšœžœ0˜Hšžœ+˜1K˜2——Kšžœ˜—Kš œ žœžœžœžœŸ˜YKš žœžœžœžœžœŸ˜K—KšžœžœŸ˜—Kšžœ˜K˜šžœ žœžœŸ.˜]šžœžœ˜KšžœžœžœŸ3˜GKšžœžœ-Ÿ"˜Z———Kšžœ˜—Kšœžœ˜Kšœ žœžœŸ˜+Kšœ žœžœŸ˜+šœžœžœ,žœž˜JK˜Kšžœžœ˜—Kšœžœ ˜Kšœ žœ˜-Kšžœžœžœ˜K˜K˜——Kšœ™˜š   œžœžœ žœžœžœ˜Ašžœžœžœž˜-KšœžœŸ˜,KšœžœŸ˜*Kšœ"žœŸ˜:KšœžœŸ˜0KšœžœŸ˜0Kšœ žœžœ˜EKšœžœžœ˜;Kšœžœ˜Kšœžœ˜!Kšžœžœ˜K˜——š   œžœžœžœžœžœ˜Gšž˜šžœžœž˜&KšœžœŸ˜JKšœ žœ˜*Kšœ žœ˜*˜ šžœžœž˜&˜šœ žœ˜Kšœ žœžœ#˜D—š žœžœžœžœ ž˜4˜Ešžœ,˜/K˜"——Kšžœ˜—Kšžœ ˜—Kšžœ˜——˜ šžœžœž˜&˜ šœ žœžœ ˜-Kšžœžœ˜<—š žœžœžœžœ ž˜2K˜JKšžœ˜—Kšžœ ˜—Kšžœ˜——˜ šžœžœž˜&˜ šžœžœž˜Kšœ.˜.Kšœ"˜"šžœ˜ Kšœ%™%Kšœ˜Kšœ˜Kšžœ˜K˜——K˜—Kšžœ˜—K˜—˜ šžœžœž˜&˜ šžœžœž˜Kšœ.˜.Kšœ ˜ Kšœ$˜$šœB˜BKšœ%™%Kšœ˜Kšœ˜Kšžœ˜Kšœ˜—Kšžœ˜——Kšžœ˜—K˜—Kšžœžœ˜—Kšžœžœ˜Kšžœ˜—šœ˜˜K˜———š   œžœžœžœžœ˜šžœžœ!˜>šžœžœžœ ž˜+šžœžœ ž˜AKšžœžœ˜—Kšžœ˜——Kšœžœ˜K˜——Kšž˜Kšœ˜K˜—š  œžœžœ žœ˜>Kšœžœ˜Kšœ˜K˜šžœžœž˜#˜+KšœK˜KK˜—˜ K˜-˜K˜J—K˜—˜Kšœžœ˜&šœ˜Kšœ(žœ žœ˜A—šžœžœžœž˜#˜K˜I—Kšžœ˜—Kšœžœ˜Kšœ˜—˜ Kšœžœ˜$šœ˜Kšœ2žœ žœ˜K—šžœžœžœž˜!K˜?Kšžœ˜—Kšœž˜Kšœ˜—˜ K˜8K˜-˜K˜9K˜@—K˜—Kšžœžœ˜—Kšžœ˜K˜—š  œžœžœžœ˜AKšœžœ˜ K˜Kšžœžœ˜%Kšžœ˜K˜—š   œžœžœžœžœ ˜