DIRECTORY Alloc: TYPE USING [Notifier, AddNotify, DropNotify, Top, Words], ComData: TYPE USING [defBodyLimit, interface, nBodies, nInnerBodies, table, textIndex], CompilerUtil: TYPE USING [], Log: TYPE USING [Error, ErrorSei], SourceMap: TYPE USING [Loc, nullLoc, Down, Up], Symbols: TYPE USING [Base, BodyInfo, BodyRecord, ContextLevel, SERecord, ISEIndex, CSEIndex, RecordSEIndex, CTXIndex, BTIndex, CBTIndex, nullName, ISENull, RecordSENull, CTXNull, BTNull, lL, lZ, RootBti, typeTYPE, seType, ctxType, mdType, bodyType], SymbolOps: TYPE USING [ArgCtx, CopyArgSe, CopyXferType, CtxEntries, CtxLevel, DelinkBti, FindExtension, FirstCtxSe, LinkBti, MakeNonCtxSe, MakeSeChain, NewCtx, NextLevel, NextSe, ParentBti, SetCtxLevel, SetSeLink, SearchContext, TransferTypes, StaticNestError], Tree: TYPE USING [Base, Index, Link, Map, Scan, Null, NullIndex, treeType], TreeOps: TYPE USING [CopyTree, FreeNode, FreeTree, GetNode, ListTail, MakeList, MarkShared, NthSon, OpName, PopTree, PushList, PushNode, PushTree, ScanList, ScanSons, SetAttr, SetInfo, Shared, UpdateList, UpdateLeaves]; Pass3P: PROGRAM IMPORTS Alloc, Log, SourceMap, SymbolOps, TreeOps, dataPtr: ComData EXPORTS CompilerUtil = { OPEN TreeOps, SymbolOps, Symbols; tb: Tree.Base; -- tree base address (local copy) seb: Symbols.Base; -- se table base address (local copy) ctxb: Symbols.Base; -- context table base address (local copy) mdb: Symbols.Base; -- module table base address (local copy) bb: Symbols.Base; -- body table base address (local copy) PostNotify: Alloc.Notifier = { tb _ base[Tree.treeType]; seb _ base[seType]; ctxb _ base[ctxType]; mdb _ base[mdType]; bb _ base[bodyType]}; P3Postlude: PUBLIC PROC[expand: BOOL] = { (dataPtr.table).AddNotify[PostNotify]; IF expand THEN {LinkImportedBodies[]; ExpandInlines[RootBti]}; (dataPtr.table).DropNotify[PostNotify]}; LinkImportedBodies: PROC = { next: BTIndex; btLimit: BTIndex = (dataPtr.table).Top[bodyType]; FOR bti: BTIndex _ LOOPHOLE[dataPtr.defBodyLimit], next UNTIL bti = btLimit DO WITH body: bb[bti] SELECT FROM Callable => { IF body.inline THEN {body.link _ bb[RootBti].link; bb[RootBti].link _ [sibling, bti]}; next _ bti + (SELECT body.nesting FROM Inner => BodyRecord.Callable.Inner.SIZE, ENDCASE => BodyRecord.Callable.Outer.SIZE)}; ENDCASE => next _ bti + BodyRecord.Other.SIZE; ENDLOOP}; currentMaster: CBTIndex; masterBody: Tree.Index; copyCtx: CTXIndex; copying: BOOL; substSafe: BOOL; currentEnclosing: BTIndex; bodyNesting: CARDINAL; aStack: AList; -- current association list AItem: TYPE = RECORD [id: ISEIndex, name: BOOL, val: Tree.Link]; ANode: TYPE = RECORD [ next: AList, ctx: CTXIndex, nItems: CARDINAL, map: SEQUENCE maxItems: CARDINAL OF AItem]; AList: TYPE = REF ANode; ExpandInlines: PROC[rootBti: BTIndex] = { bti: BTIndex _ rootBti; aStack _ NIL; sharingMap _ NIL; UNTIL bti = BTNull DO ExpandInlines[bb[bti].firstSon]; WITH body: bb[bti] SELECT FROM Callable => IF body.inline THEN ExpandCalls[LOOPHOLE[bti, CBTIndex]]; ENDCASE; bti _ IF bb[bti].link.which=parent THEN BTNull ELSE bb[bti].link.index; ENDLOOP}; ExpandCalls: PROC[bti: CBTIndex] = { saveIndex: SourceMap.Loc = dataPtr.textIndex; sei: ISEIndex = bb[bti].id; current, subNode: Tree.Index; dataPtr.textIndex _ SourceMap.Up[bb[bti].sourceIndex]; WITH body: bb[bti].info SELECT FROM Internal => { currentMaster _ bti; IF seb[sei].mark4 THEN { t: Tree.Link = FindExtension[sei].tree; ComputeArgCounts[bb[bti].ioType, t]; masterBody _ GetNode[t]} ELSE masterBody _ body.bodyTree; copying _ TRUE; UNTIL (current _ body.thread) = Tree.NullIndex DO discard: BOOL; subNode _ GetNode[tb[current].son[1]]; discard _ tb[subNode].attr1; tb[current].son[1] _ tb[subNode].son[1]; currentEnclosing _ tb[subNode].info; body.thread _ GetNode[tb[subNode].son[2]]; tb[subNode].son[1] _ tb[subNode].son[2] _ Tree.Null; FreeNode[subNode]; tb[current].shared _ FALSE; IF body.thread = Tree.NullIndex AND (~dataPtr.interface OR bb[bti].level > lL) THEN copying _ FALSE; SELECT TRUE FROM discard => DiscardCall[current]; ~RecursiveSubst[bti, currentEnclosing] => ExpandCall[current] ENDCASE => Log.ErrorSei[recursiveInline, bb[bti].id]; ENDLOOP}; ENDCASE => ERROR; dataPtr.textIndex _ saveIndex}; DiscardCall: PROC[node: Tree.Index] = INLINE { -- orphan subtree [] _ DiscardTree[[subtree[node]]]}; ExpandCall: PROC[node: Tree.Index] = { typeIn, typeOut: RecordSEIndex; masterCtx: CTXIndex = bb[currentMaster].localCtx; formalCtx: CTXIndex; seChain, saveChain: ISEIndex; nAssigns, nVars: CARDINAL; extendedScope: BOOL; newBti: BTIndex; t: Tree.Link; IF tb[node].name = call THEN dataPtr.textIndex _ tb[node].info; bodyNesting _ 0; IF copying OR masterCtx = CTXNull THEN copyCtx _ CTXNull ELSE { saveChain _ ctxb[masterCtx].seList; ctxb[masterCtx].seList _ ISENull; SetCtxLevel[masterCtx, bb[currentEnclosing].level]; copyCtx _ masterCtx}; [typeIn, typeOut] _ TransferTypes[bb[currentMaster].ioType]; substSafe _ tb[node].attr3 AND bb[currentMaster].hints.nameSafe; nAssigns _ SELECT TRUE FROM (typeIn = RecordSENull) => 0, tb[node].attr1 => ExtractArgs[typeIn, seb[typeIn].fieldCtx, node], ENDCASE => MapArgs[seb[typeIn].fieldCtx, node]; tb[node].son[2] _ FreeTree[tb[node].son[2]]; IF RequiredFields[typeOut] THEN { formalCtx _ seb[typeOut].fieldCtx; IF copyCtx = CTXNull THEN copyCtx _ NewCtx[bb[currentEnclosing].level]; seChain _ MakeSeChain[copyCtx, CtxVars[formalCtx], TRUE]; AppendSeChain[copyCtx, seChain]; MapIds[formalCtx, seChain, 0]}; IF tb[masterBody].son[1] # Tree.Null THEN PushTree[ExpandOpens[tb[masterBody].son[1]]]; IF masterCtx # CTXNull THEN IF ~copying THEN AppendSeChain[copyCtx, saveChain] ELSE IF (nVars _ CtxVars[masterCtx]) # 0 THEN { IF copyCtx = CTXNull THEN copyCtx _ NewCtx[bb[currentEnclosing].level]; seChain _ MakeSeChain[copyCtx, nVars, FALSE]; MapIds[masterCtx, seChain, 0]; AppendSeChain[copyCtx, seChain]}; IF copyCtx # CTXNull THEN newBti _ MakeEnclosingBody[copyCtx]; t _ ExpandDecls[tb[masterBody].son[2]]; PushTree[ExpandTree[tb[masterBody].son[3]]]; IF copyCtx = CTXNull THEN extendedScope _ FALSE ELSE { extendedScope _ nAssigns # 0 OR tb[masterBody].son[1] # Tree.Null OR tb[masterBody].son[4] # Tree.Null; PushTree[t]; PushNode[block, -2]; SetInfo[newBti]; SetAttr[3, extendedScope]; SetAttr[1, tb[masterBody].attr1]; SetAttr[2, tb[masterBody].attr2]; WITH body: bb[newBti].info SELECT FROM Internal => {body.bodyTree _ GetNode[t_PopTree[]]; PushTree[t]}; ENDCASE => ERROR}; IF tb[masterBody].son[1] # Tree.Null THEN { PushNode[open, 2]; SetInfo[dataPtr.textIndex]}; IF tb[masterBody].son[4] # Tree.Null THEN { PushTree[ExpandTree[tb[masterBody].son[4]]]; PushNode[lock, 2]; SetInfo[dataPtr.textIndex]}; IF masterCtx # CTXNull AND copying AND nVars # 0 THEN UnmapIds[explicit]; IF copyCtx # CTXNull THEN currentEnclosing _ ParentBti[currentEnclosing]; IF ~copying THEN PruneBody[masterBody]; IF tb[node].nSons > 2 THEN { PushTree[tb[node].son[3]]; tb[node].son[3] _ Tree.Null; PushNode[enable, -2]; SetInfo[dataPtr.textIndex]; SetAttr[3, TRUE]}; IF RequiredFields[typeOut] THEN UnmapIds[implicit]; IF typeIn # RecordSENull THEN UnmapIds[implicit]; tb[node].son[2] _ MakeList[nAssigns+1]; IF copyCtx # CTXNull AND nAssigns # 0 THEN UpdateBodyNesting[tb[node].son[2], newBti]; tb[node].name _ IF tb[node].name = callx THEN substx ELSE subst; tb[node].attr1 _ tb[masterBody].attr1; tb[node].attr2 _ tb[masterBody].attr2; tb[node].attr3 _ extendedScope; sharingMap _ NIL }; RecursiveSubst: PROC[bti, parent: BTIndex] RETURNS[BOOL] = { UNTIL parent = BTNull DO IF bti = parent THEN RETURN[TRUE]; parent _ ParentBti[parent]; ENDLOOP; RETURN[FALSE]}; PruneBody: PROC[node: Tree.Index] = { OPEN tb[node]; son[1] _ son[2] _ son[3] _ son[4] _ Tree.Null; name _ procinit}; NameSafe: PROC[t: Tree.Link] RETURNS[safe: BOOL] = { RETURN[~bb[currentMaster].hints.argUpdated AND (substSafe OR (WITH t SELECT FROM symbol => seb[index].immutable, literal => TRUE, ENDCASE => SELECT OpName[t] FROM IN [relE..relLE], IN [plus..mod] => NameSafe[NthSon[t, 1]] AND NameSafe[NthSon[t, 2]], not, uminus, abs, pred, succ => NameSafe[NthSon[t, 1]], loophole, cast, check, lengthen, shorten, float => NameSafe[NthSon[t, 1]], clit, llit, mwconst, nil, atom => TRUE, cdot => NameSafe[NthSon[t, 2]], ENDCASE => FALSE))] }; VarRefs: PROC[sei: ISEIndex] RETURNS[CARDINAL] = INLINE { RETURN[seb[sei].idInfo]}; CheapEval: PROC[t: Tree.Link, top: BOOL_TRUE] RETURNS[BOOL] = { RETURN[WITH t SELECT FROM subtree => SELECT OpName[t] FROM clit, llit, mwconst, nil, atom => TRUE, loophole, cast, openx => CheapEval[NthSon[t, 1], top], addr, uparrow, dot, dollar => CheapEval[NthSon[t, 1], top], IN [index .. reloc] => CheapEval[NthSon[t, 1], FALSE] AND CheapEval[NthSon[t, 2], FALSE], IN [or .. mod] => top AND CheapEval[NthSon[t, 1], FALSE] AND CheapEval[NthSon[t, 2], FALSE], not, uminus, abs, pred, succ, lengthen, shorten => top AND CheapEval[NthSon[t, 1], FALSE], cdot => CheapEval[NthSon[t, 2], top], ENDCASE => FALSE, ENDCASE => TRUE]}; MapByName: PROC[sei: ISEIndex, t: Tree.Link] RETURNS[BOOL] = { n: CARDINAL = VarRefs[sei]; RETURN[NameSafe[t] AND (n <= 2 OR CheapEval[t])]}; CountVars: PROC[ctx: CTXIndex, t: Tree.Link] RETURNS[n: CARDINAL _ 0] = { sei: ISEIndex _ FirstCtxSe[ctx]; CountVar: Tree.Scan = { IF sei # ISENull THEN {IF ~MapByName[sei, t] THEN n _ n+1; sei _ NextSe[sei]}}; ScanList[t, CountVar]; RETURN}; RequiredFields: PROC[rSei: RecordSEIndex] RETURNS[BOOL] = { FOR sei: ISEIndex _ FirstCtxSe[FieldCtx[rSei]], NextSe[sei] UNTIL sei = ISENull DO IF seb[sei].hash = nullName THEN RETURN[FALSE]; IF seb[sei].idInfo # 0 THEN RETURN[TRUE]; ENDLOOP; RETURN[FALSE]}; DiscardTree: Tree.Map = { IF t # Tree.Null THEN WITH t SELECT FROM subtree => { node: Tree.Index _ index; SELECT tb[node].name FROM call, callx => IF OpName[tb[node].son[1]] = thread THEN { subNode: Tree.Index = GetNode[tb[node].son[1]]; tb[subNode].attr1 _ TRUE} ELSE { [] _ UpdateLeaves[t, DiscardTree]; FreeNode[node]}; ENDCASE => IF ~tb[node].shared THEN { [] _ UpdateLeaves[t, DiscardTree]; FreeNode[node]}}; ENDCASE; RETURN[Tree.Null]}; ExpandTree: Tree.Map = { WITH t SELECT FROM symbol => v _ ExpandSei[index]; subtree => { sNode: Tree.Index = index; IF tb[sNode].shared THEN v _ SELECT tb[sNode].name FROM call, callx => ExpandThreadedCall[sNode], ENDCASE => ExpandShared[sNode] ELSE SELECT tb[sNode].name FROM body => v _ ExpandBody[sNode]; block => v _ ExpandBlock[sNode, tb[sNode].attr3]; ditem => v _ ExpandBlock[sNode, FALSE]; do => v _ ExpandDo[sNode]; open, bind, bindx => v _ ExpandBinding[sNode]; subst, substx => v _ ExpandSubst[sNode]; lock => v _ ExpandLock[sNode]; thread => v _ ExpandThread[sNode]; ENDCASE => { v _ IF copying THEN CopyTree[[baseP:@tb, link:t], ExpandTree] ELSE UpdateLeaves[t, ExpandTree]; WITH v SELECT FROM subtree => { dNode: Tree.Index = index; SELECT tb[dNode].name FROM return => IF bodyNesting = 0 THEN UpdateReturn[dNode]; xerror => IF bodyNesting = 0 THEN tb[dNode].attr3 _ TRUE; ENDCASE => NULL}; ENDCASE => NULL}}; ENDCASE => v _ t; RETURN}; RewriteNode: PROC[node: Tree.Index, nSons: CARDINAL] RETURNS[Tree.Link] = { FOR i: CARDINAL DECREASING IN [1 .. nSons] DO tb[node].son[i] _ PopTree[] ENDLOOP; RETURN[[subtree[index: node]]]}; CopyNode: PROC[node: Tree.Index, nSons: CARDINAL] RETURNS[Tree.Link] = { PushNode[tb[node].name, nSons]; SetInfo[tb[node].info]; SetAttr[1, tb[node].attr1]; SetAttr[2, tb[node].attr2]; SetAttr[3, tb[node].attr3]; RETURN[PopTree[]]}; ExpandBlock: PROC[node: Tree.Index, extendedScope: BOOL] RETURNS[v: Tree.Link] = { EnterBlock[node, extendedScope]; PushTree[ExpandDecls[tb[node].son[1]]]; PushTree[ExpandTree[tb[node].son[2]]]; v _ IF copying THEN CopyNode[node, 2] ELSE RewriteNode[node, 2]; ExitBlock[GetNode[v]]; RETURN}; ExpandBody: PROC[node: Tree.Index] RETURNS[v: Tree.Link] = { EnterBody[node]; PushTree[ExpandOpens[tb[node].son[1]]]; PushTree[ExpandDecls[tb[node].son[2]]]; PushTree[ExpandTree[tb[node].son[3]]]; PushTree[ExpandTree[tb[node].son[4]]]; v _ IF copying THEN CopyNode[node, 4] ELSE RewriteNode[node, 4]; ExitBody[GetNode[v]]; RETURN}; ExpandDo: PROC[node: Tree.Index] RETURNS[v: Tree.Link] = { decl: BOOL; subNode: Tree.Index; IF tb[node].son[1] = Tree.Null THEN decl _ FALSE ELSE {subNode _ GetNode[tb[node].son[1]]; decl _ OpName[tb[subNode].son[1]] = decl}; IF decl THEN { nSons: CARDINAL = tb[subNode].nSons; EnterBlock[subNode, FALSE]; PushTree[ExpandDecls[tb[subNode].son[1]]]; FOR i: CARDINAL IN [2..nSons] DO PushTree[ExpandTree[tb[subNode].son[i]]] ENDLOOP; IF copying THEN {PushNode[tb[subNode].name, nSons]; SetInfo[tb[subNode].info]} ELSE PushTree[RewriteNode[subNode, nSons]]} ELSE PushTree[ExpandTree[tb[node].son[1]]]; PushTree[ExpandTree[tb[node].son[2]]]; PushTree[ExpandOpens[tb[node].son[3]]]; FOR i: CARDINAL IN [4..6] DO PushTree[ExpandTree[tb[node].son[i]]] ENDLOOP; v _ IF copying THEN CopyNode[node, 6] ELSE RewriteNode[node, 6]; IF decl THEN { newNode: Tree.Index = GetNode[v]; ExitBlock[GetNode[tb[newNode].son[1]], newNode]}; RETURN}; ExpandBinding: PROC[node: Tree.Index] RETURNS[Tree.Link] = { nSons: CARDINAL = tb[node].nSons; PushTree[ExpandOpens[tb[node].son[1]]]; FOR i: CARDINAL IN [2..nSons] DO PushTree[ExpandTree[tb[node].son[i]]] ENDLOOP; RETURN[IF copying THEN CopyNode[node, nSons] ELSE RewriteNode[node, nSons]]}; ExpandSubst: PROC[node: Tree.Index] RETURNS[Tree.Link] = { extendedScope: BOOL = tb[node].attr3; PushTree[ExpandTree[tb[node].son[1]]]; IF extendedScope THEN MapBlock[FindBlock[tb[node].son[2]]]; PushTree[ExpandTree[tb[node].son[2]]]; RETURN[IF copying THEN CopyNode[node, 2] ELSE RewriteNode[node, 2]]}; ExpandThreadedCall: PROC[node: Tree.Index] RETURNS[v: Tree.Link] = { nSons: CARDINAL = tb[node].nSons; FOR i: CARDINAL IN [1 .. nSons] DO PushTree[ExpandTree[tb[node].son[i]]] ENDLOOP; v _ IF copying THEN CopyNode[node, nSons] ELSE RewriteNode[node, nSons]; ThreadSubst[node, v]; RETURN}; ExpandThread: PROC[node: Tree.Index] RETURNS[v: Tree.Link] = { IF ~copying THEN {tb[node].son[1] _ ExpandTree[tb[node].son[1]]; v _ [subtree[node]]} ELSE { PushTree[ExpandTree[tb[node].son[1]]]; PushTree[Tree.Null]; PushNode[thread, 2]; SetInfo[tb[node].info]; v _ PopTree[]}; RETURN}; ExpandLock: PROC[node: Tree.Index] RETURNS[v: Tree.Link] = { PushTree[ExpandTree[tb[node].son[2]]]; PushTree[ExpandTree[tb[node].son[1]]]; IF copying THEN {PushNode[lock, -2]; SetInfo[tb[node].info]; v _ PopTree[]} ELSE { tb[node].son[1] _ PopTree[]; tb[node].son[2] _ PopTree[]; v _ [subtree[index: node]]}; RETURN}; UpdateReturn: PROC[node: Tree.Index] = { typeOut: RecordSEIndex; IF tb[node].son[1] = Tree.Null AND (typeOut_TransferTypes[bb[currentMaster].ioType].typeOut) # RecordSENull THEN { n: CARDINAL _ 0; FOR sei: ISEIndex _ FirstCtxSe[FieldCtx[typeOut]], NextSe[sei] UNTIL sei = ISENull DO PushTree[ExpandSei[sei]]; n _ n+1 ENDLOOP; tb[node].son[1] _ MakeList[n]}; tb[node].name _ result}; ExpandDecls: Tree.Map = { n: CARDINAL; ExpandDecl: Tree.Scan = { node: Tree.Index; LinkDecl: Tree.Scan = { WITH t SELECT FROM symbol => { sei: ISEIndex = index; seb[sei].idValue _ node; IF ~seb[sei].mark4 AND tb[node].son[3] = Tree.Null AND ~seb[sei].immutable THEN seb[sei].idInfo _ seb[sei].idInfo - 1}; ENDCASE}; copy: Tree.Link; IF OpName[t] # typedecl THEN { PushTree[copy _ ExpandTree[t]]; n _ n+1; node _ GetNode[copy]; ScanList[tb[node].son[1], LinkDecl]}}; IF OpName[t] = initlist THEN { node: Tree.Index = GetNode[t]; PushTree[ExpandTree[tb[node].son[1]]]; PushTree[ExpandDecls[tb[node].son[2]]]; IF copying THEN {PushNode[initlist, 2]; SetInfo[tb[node].info]; v _ PopTree[]} ELSE v _ RewriteNode[node, 2]} ELSE IF copying THEN {n _ 0; ScanList[t, ExpandDecl]; v _ MakeList[n]} ELSE v _ ExpandTree[t]; RETURN}; SharingItem: TYPE = RECORD [old, new: Tree.Link, next: SharingList]; SharingList: TYPE = REF SharingItem; sharingMap: SharingList; MapShared: PROC[t, v: Tree.Link] = { p: SharingList _ NEW[SharingItem]; p^ _ [old:t, new:v, next:sharingMap]; sharingMap _ p; MarkShared[v, TRUE]}; ExpandShared: PROC[node: Tree.Index] RETURNS[v: Tree.Link] = { target: Tree.Link = [subtree[index: node]]; UpdateCount: Tree.Scan = { WITH t SELECT FROM symbol => IncrCount[index]; subtree => ScanSons[t, UpdateCount]; ENDCASE => NULL}; FOR p: SharingList _ sharingMap, p.next UNTIL p = NIL DO IF p.old = target THEN GO TO Found; REPEAT Found => v _ p.new; FINISHED => v _ target; ENDLOOP; IF copying THEN UpdateCount[v]; RETURN}; ExpandOpens: Tree.Map = { n: CARDINAL; UpdateOpen: Tree.Scan = { node: Tree.Index = GetNode[t]; base: Tree.Link; tb[node].son[1] _ ExpandTree[tb[node].son[1]]; IF ~Shared[base _ tb[node].son[2]] THEN tb[node].son[2] _ ExpandTree[base] ELSE { MarkShared[base, FALSE]; base _ ExpandTree[base]; MarkShared[base, TRUE]; tb[node].son[2] _ base}}; ExpandOpen: Tree.Scan = { node: Tree.Index = GetNode[t]; base: Tree.Link = tb[node].son[2]; copy: Tree.Link; PushTree[ExpandTree[tb[node].son[1]]]; IF ~Shared[base] THEN PushTree[ExpandTree[base]] ELSE { MarkShared[base, FALSE]; PushTree[copy _ ExpandTree[base]]; MarkShared[base, TRUE]; MapShared[base, copy]}; PushNode[item, 2]; SetInfo[tb[node].info]; n _ n+1}; IF ~copying THEN {ScanList[t, UpdateOpen]; v _ t} ELSE {n _ 0; ScanList[t, ExpandOpen]; v _ MakeList[n]}; RETURN}; FindBlock: PROC[t: Tree.Link] RETURNS[node: Tree.Index] = { DO node _ GetNode[t]; SELECT tb[node].name FROM list => t _ ListTail[t]; block => EXIT; open, enable => t _ tb[node].son[2]; lock => t _ tb[node].son[1]; ENDCASE => ERROR; ENDLOOP; RETURN}; EnterBlock: PROC[node: Tree.Index, extendedScope: BOOL] = INLINE { IF ~extendedScope THEN MapBlock[node]}; MapBlock: PROC[node: Tree.Index] = { oldBti: BTIndex = tb[node].info; oldCtx: CTXIndex = bb[oldBti].localCtx; seChain: ISEIndex; newCtx: CTXIndex; SELECT TRUE FROM oldCtx = CTXNull => newCtx _ CTXNull; ~copying => {newCtx _ oldCtx; SetCtxLevel[newCtx, bb[currentEnclosing].level]}; ENDCASE => { newCtx _ NewCtx[bb[currentEnclosing].level]; seChain _ MakeSeChain[newCtx, CtxVars[oldCtx], FALSE]; AppendSeChain[newCtx, seChain]; MapIds[oldCtx, seChain, 0]}; [] _ MakeEnclosingBody[ newCtx, bb[oldBti].sourceIndex, IF copying THEN BTNull ELSE oldBti]; RETURN}; ExitBlock: PROC[node: Tree.Index, bodyNode: Tree.Index _ Tree.NullIndex] = { oldBti: BTIndex = tb[node].info; newBti: BTIndex = currentEnclosing; tb[node].info _ newBti; WITH body: bb[newBti].info SELECT FROM Internal => body.bodyTree _ IF bodyNode = Tree.NullIndex THEN node ELSE bodyNode; ENDCASE; IF copying AND bb[oldBti].localCtx # CTXNull THEN UnmapIds[explicit]; currentEnclosing _ ParentBti[currentEnclosing]}; MakeEnclosingBody: PROC[ ctx: CTXIndex, sourceIndex: CARDINAL_TRASH, oldBti: BTIndex_BTNull] RETURNS[newBti: BTIndex] = { newSon: BTIndex; IF oldBti = BTNull THEN { newBti _ (dataPtr.table).Words[bodyType, BodyRecord.Other.SIZE]; newSon _ BTNull} ELSE {newSon _ bb[oldBti].firstSon; DelinkBti[oldBti]; newBti _ oldBti}; bb[newBti] _ BodyRecord[ link: , firstSon: newSon, type: BodyType[ctx], localCtx: ctx, level: bb[currentEnclosing].level, sourceIndex: (IF bodyNesting = 0 THEN (SourceMap.nullLoc).Down ELSE sourceIndex), info: BodyInfo[Internal[ bodyTree: Tree.NullIndex, thread: Tree.NullIndex, frameSize: ]], extension: Other[relOffset: ]]; LinkBti[bti: newBti, parent: currentEnclosing]; currentEnclosing _ newBti; RETURN}; EnterBody: PROC[node: Tree.Index] = { oldBti: CBTIndex = tb[node].info; newBti: CBTIndex; ioType: CSEIndex; type: RecordSEIndex; level: ContextLevel = NextLevel[bb[currentEnclosing].level ! StaticNestError => {Log.Error[staticNesting]; RESUME}]; SetArgLevel: PROC[sei: CSEIndex] = { ctx: CTXIndex = ArgCtx[sei]; IF ctx # CTXNull THEN SetCtxLevel[ctx, level]}; ctx: CTXIndex; bodyNesting _ bodyNesting + 1; IF ~copying THEN DelinkBti[oldBti]; IF ~copying AND (bb[oldBti].level > lL) = (level > lL) THEN { ctx _ bb[oldBti].localCtx; IF ctx # CTXNull THEN SetCtxLevel[ctx, level]; ioType _ bb[oldBti].ioType; type _ bb[oldBti].type; newBti _ oldBti} ELSE { id: ISEIndex; IF level > lL THEN { newBti _ (dataPtr.table).Words[bodyType, BodyRecord.Callable.Inner.SIZE]; bb[newBti] _ [,,,,,,, Callable[,,,,,,,,,, Inner[frameOffset: ]]]} ELSE { newBti _ (dataPtr.table).Words[bodyType, BodyRecord.Callable.Outer.SIZE]; bb[newBti] _ [,,,,,,, Callable[,,,,,,,,,, Outer[]]]}; IF ~copying THEN { ctx _ bb[oldBti].localCtx; IF ctx # CTXNull THEN SetCtxLevel[ctx, level]; id _ bb[oldBti].id; ioType _ bb[oldBti].ioType; type _ bb[oldBti].type; bb[newBti].firstSon _ bb[oldBti].firstSon} ELSE { oldCtx: CTXIndex; IF (id _ bb[oldBti].id) # ISENull THEN id _ SearchContext[seb[id].hash, bb[currentEnclosing].localCtx]; ioType _ CopyXferType[bb[oldBti].ioType, NIL]; MapFormals[oldType: bb[oldBti].ioType, newType: ioType]; IF (oldCtx _ bb[oldBti].localCtx) = CTXNull THEN ctx _ CTXNull ELSE { ctx _ NewCtx[level]; ctxb[ctx].seList _ MakeSeChain[ctx, CtxVars[oldCtx], FALSE]; MapIds[oldCtx, ctxb[ctx].seList, 0]}; type _ BodyType[ctx]; bb[newBti].firstSon _ BTNull; dataPtr.nBodies _ dataPtr.nBodies+1; IF level > lL THEN dataPtr.nInnerBodies _ dataPtr.nInnerBodies+1}; bb[newBti].type _ type; bb[newBti].localCtx _ ctx; bb[newBti].sourceIndex _ bb[oldBti].sourceIndex; bb[newBti].info _ bb[oldBti].info; bb[newBti].inline _ bb[oldBti].inline; bb[newBti].resident _ bb[oldBti].resident; bb[newBti].id _ id; bb[newBti].ioType _ ioType; bb[newBti].monitored _ bb[oldBti].monitored; bb[newBti].entry _ bb[oldBti].entry; bb[newBti].internal _ bb[oldBti].internal; bb[newBti].noXfers _ bb[oldBti].noXfers; bb[newBti].hints _ bb[oldBti].hints}; bb[newBti].level _ level; WITH t: seb[ioType] SELECT FROM transfer => {SetArgLevel[t.typeIn]; SetArgLevel[t.typeOut]}; ENDCASE; LinkBti[bti: newBti, parent: currentEnclosing]; currentEnclosing _ newBti}; ExitBody: PROC[node: Tree.Index] = { newBti: CBTIndex = LOOPHOLE[currentEnclosing]; ExitBlock[node]; IF copying THEN UnmapFormals[bb[newBti].ioType]; bodyNesting _ bodyNesting - 1}; UpdateBodyNesting: PROC[list: Tree.Link, newBti: BTIndex] = { oldBti: BTIndex = ParentBti[newBti]; UpdateLinks: Tree.Map = { WITH t SELECT FROM subtree => { node: Tree.Index = index; SELECT tb[node].name FROM block => { bti: BTIndex = tb[node].info; IF ParentBti[bti] = oldBti THEN {DelinkBti[bti]; LinkBti[bti, newBti]}; v _ t}; thread => { IF tb[node].info = oldBti THEN tb[node].info _ newBti; tb[node].son[1] _ UpdateLeaves[tb[node].son[1], UpdateLinks]; v _ t}; ENDCASE => v _ UpdateLeaves[t, UpdateLinks]}; ENDCASE => v _ t}; UpdateItem: Tree.Scan = { WITH t SELECT FROM subtree => { node: Tree.Index = index; SELECT tb[node].name FROM assign, extract => tb[node].son[2] _ UpdateLeaves[tb[node].son[2], UpdateLinks]; ENDCASE}; ENDCASE}; ScanList[list, UpdateItem]}; BodyType: PROC[ctx: CTXIndex] RETURNS[rSei: RecordSEIndex] = { rSei _ LOOPHOLE[MakeNonCtxSe[SERecord.cons.record.notLinked.SIZE]]; seb[rSei].typeInfo _ record[ machineDep: FALSE, painted: TRUE, argument: FALSE, hints: [ unifield: FALSE, variant: FALSE, assignable: FALSE, comparable: FALSE, privateFields: TRUE, refField: FALSE, default: FALSE, voidable: FALSE], length: 0, fieldCtx: CTXNull, monitored: FALSE, linkPart: notLinked[]]; seb[rSei].fieldCtx _ ctx; seb[rSei].mark3 _ TRUE; RETURN}; AppendSeChain: PROC[ctx: CTXIndex, chain: ISEIndex] = { last, next: ISEIndex; SELECT TRUE FROM chain = ISENull => NULL; (last _ ctxb[ctx].seList) = ISENull => ctxb[ctx].seList _ chain; ENDCASE => { UNTIL (next _ NextSe[last]) = ISENull DO last _ next ENDLOOP; SetSeLink[last, chain]}}; CtxVars: PROC[ctx: CTXIndex] RETURNS[n: CARDINAL _ 0] = { FOR sei: ISEIndex _ FirstCtxSe[ctx], NextSe[sei] UNTIL sei = ISENull DO IF seb[sei].idType # typeTYPE THEN n _ n+1 ENDLOOP; RETURN}; AllocateAList: PROC[ctx: CTXIndex] RETURNS[aLink: AList] = { maxItems: CARDINAL = CtxEntries[ctx]; aLink _ NEW[ANode[maxItems] _ [next:NIL, ctx:ctx, nItems:0, map:]]}; AllocateCopyEntries: PROC[nVars: CARDINAL] RETURNS[seChain: ISEIndex] = { IF nVars = 0 THEN seChain _ ISENull ELSE { IF copyCtx = CTXNull THEN copyCtx _ NewCtx[bb[currentEnclosing].level]; seChain _ MakeSeChain[copyCtx, nVars, TRUE]; AppendSeChain[copyCtx, seChain]}; RETURN}; FillArgSe: PROC[copy, master: ISEIndex] = { CopyArgSe[copy, master]; IF seb[copy].mark4 THEN seb[copy].idValue _ Tree.NullIndex; seb[copy].mark4 _ FALSE; seb[copy].idInfo _ 0}; ExtractArgs: PROC[argType: RecordSEIndex, formalCtx: CTXIndex, node: Tree.Index] RETURNS[nAssigns: CARDINAL] = { aLink: AList = AllocateAList[formalCtx]; nVars: CARDINAL = CtxEntries[formalCtx]; seChain: ISEIndex = AllocateCopyEntries[nVars]; sei1: ISEIndex; sei2: ISEIndex _ seChain; FOR sei1 _ FirstCtxSe[formalCtx], NextSe[sei1] UNTIL sei1 = ISENull DO val: Tree.Link = [symbol[index: sei2]]; FillArgSe[copy: sei2, master: sei1]; PushTree[val]; PushTree[Tree.Null]; PushNode[assign, 2]; SetInfo[dataPtr.textIndex]; IncrCount[sei2]; aLink.map[aLink.nItems] _ [id: sei1, name: FALSE, val: val]; aLink.nItems _ aLink.nItems + 1; sei2 _ NextSe[sei2]; ENDLOOP; IF nVars = 0 THEN nAssigns _ 0 ELSE { PushList[nVars]; PushNode[exlist, 1]; SetInfo[argType]; PushTree[tb[node].son[2]]; tb[node].son[2] _ Tree.Null; PushNode[extract, 2]; SetInfo[dataPtr.textIndex]; nAssigns _ 1}; PushAList[aLink]; RETURN}; MapArgs: PROC[formalCtx: CTXIndex, node: Tree.Index] RETURNS[nAssigns: CARDINAL _ 0] = { aLink: AList = AllocateAList[formalCtx]; nVars: CARDINAL = CountVars[formalCtx, tb[node].son[2]]; seChain: ISEIndex = AllocateCopyEntries[nVars]; sei1, sei2: ISEIndex; MapArg: Tree.Map = { name: BOOL; val: Tree.Link; IF sei1 = ISENull THEN v _ t ELSE { IF MapByName[sei1, t] THEN { name _ TRUE; AdjustForName[t]; val _ t} ELSE { FillArgSe[copy: sei2, master: sei1]; name _ FALSE; val _ [symbol[index: sei2]]; IF t # Tree.Null THEN { PushTree[val]; PushTree[t]; PushNode[assign, 2]; SetInfo[dataPtr.textIndex]; IncrCount[sei2]; nAssigns _ nAssigns + 1}; sei2 _ NextSe[sei2]}; aLink.map[aLink.nItems] _ [id: sei1, name: name, val: val]; aLink.nItems _ aLink.nItems + 1; sei1 _ NextSe[sei1]; v _ Tree.Null}; RETURN}; sei1 _ FirstCtxSe[formalCtx]; sei2 _ seChain; tb[node].son[2] _ UpdateList[tb[node].son[2], MapArg]; PushAList[aLink]; RETURN}; MapIds: PROC[ctx: CTXIndex, chain: ISEIndex, nRefs: [0..1]] = { aLink: AList = AllocateAList[ctx]; sei1: ISEIndex _ FirstCtxSe[ctx]; sei2: ISEIndex _ chain; UNTIL sei1 = ISENull DO IF seb[sei1].idType # typeTYPE THEN { CopyArgSe[sei2, sei1]; IF seb[sei2].mark4 THEN seb[sei2].idValue _ Tree.NullIndex; seb[sei2].idInfo _ nRefs; aLink.map[aLink.nItems] _ [id: sei1, name: FALSE, val: [symbol[index:sei2]]]; aLink.nItems _ aLink.nItems + 1; sei2 _ NextSe[sei2]}; sei1 _ NextSe[sei1]; ENDLOOP; PushAList[aLink]}; UnmapIds: PROC[decl: {implicit, explicit}] = { aLink: AList _ PopAList[]; FOR i: CARDINAL IN [0..aLink.nItems) DO WITH aLink.map[i].val SELECT FROM symbol => IF decl = implicit AND ~aLink.map[i].name THEN seb[index].mark4 _ TRUE; ENDCASE; aLink.map[i].val _ DiscardTree[aLink.map[i].val]; ENDLOOP; aLink _ NIL}; MapFields: PROC[oldRecord, newRecord: CSEIndex, nRefs: [0..1]] = { oldCtx: CTXIndex = ArgCtx[oldRecord]; IF oldCtx # CTXNull THEN { aLink: AList = AllocateAList[oldCtx]; sei1: ISEIndex _ FirstCtxSe[oldCtx]; sei2: ISEIndex _ FirstCtxSe[ArgCtx[newRecord]]; UNTIL sei1 = ISENull DO seb[sei2].idInfo _ nRefs; aLink.map[aLink.nItems] _ [id: sei1, name: FALSE, val: [symbol[index:sei2]]]; aLink.nItems _ aLink.nItems + 1; sei1 _ NextSe[sei1]; sei2 _ NextSe[sei2]; ENDLOOP; PushAList[aLink]}}; MapFormals: PROC[oldType, newType: CSEIndex] = { WITH new: seb[newType] SELECT FROM transfer => WITH old: seb[oldType] SELECT FROM transfer => { MapFields[old.typeIn, new.typeIn, 1]; MapFields[old.typeOut, new.typeOut, 0]}; ENDCASE => ERROR; ENDCASE}; UnmapFormals: PROC[type: CSEIndex] = { WITH t: seb[type] SELECT FROM transfer => { IF ArgCtx[t.typeOut] # CTXNull THEN UnmapIds[implicit]; IF ArgCtx[t.typeIn] # CTXNull THEN UnmapIds[implicit]}; ENDCASE}; CountedSei: PROC[sei: ISEIndex] RETURNS[BOOL] = { ctx: CTXIndex = seb[sei].idCtx; RETURN[~seb[sei].constant AND CtxLevel[ctx] # lZ AND ctxb[ctx].ctxType # included]}; IncrCount: PROC[sei: ISEIndex] = { -- modified BumpCount (Pass3I) IF seb[sei].idType # typeTYPE AND (~seb[sei].mark4 OR CountedSei[sei]) THEN seb[sei].idInfo _ seb[sei].idInfo + 1}; DecrCount: PROC[sei: ISEIndex] = { IF seb[sei].idType # typeTYPE AND (~seb[sei].mark4 OR CountedSei[sei]) THEN IF seb[sei].idInfo # 0 THEN seb[sei].idInfo _ seb[sei].idInfo - 1}; AdjustForName: Tree.Scan = { WITH t SELECT FROM symbol => DecrCount[index]; subtree => { node: Tree.Index = index; SELECT tb[node].name FROM thread => AdjustForName[tb[node].son[1]]; ENDCASE => ScanSons[t, AdjustForName]}; ENDCASE}; SetCtxCounts: PROC[ctx: CTXIndex, nRefs: [0..1]] = { FOR sei: ISEIndex _ FirstCtxSe[ctx], NextSe[sei] UNTIL sei = ISENull DO IF ~seb[sei].constant THEN seb[sei].idInfo _ nRefs; ENDLOOP}; BumpCtxCounts: PROC[ctx: CTXIndex, incr: CARDINAL] = { FOR sei: ISEIndex _ FirstCtxSe[ctx], NextSe[sei] UNTIL sei = ISENull DO IF ~seb[sei].constant THEN seb[sei].idInfo _ seb[sei].idInfo + incr; ENDLOOP}; ComputeArgCounts: PROC[type: CSEIndex, body: Tree.Link] = { typeIn, typeOut: RecordSEIndex; argCtx, resultCtx: CTXIndex; [typeIn, typeOut] _ TransferTypes[type]; argCtx _ FieldCtx[typeIn]; resultCtx _ FieldCtx[typeOut]; IF argCtx # CTXNull OR resultCtx # CTXNull THEN { UpdateCount: Tree.Scan = { WITH t SELECT FROM symbol => { sei: ISEIndex = index; SELECT seb[sei].idCtx FROM CTXNull => NULL; argCtx, resultCtx => seb[sei].idInfo _ seb[sei].idInfo + 1; ENDCASE}; subtree => { node: Tree.Index = index; IF tb[node].name = return AND tb[node].son[1] = Tree.Null THEN BumpCtxCounts[resultCtx, 1]; ScanSons[t, UpdateCount]}; ENDCASE => NULL}; SetCtxCounts[argCtx, 1]; SetCtxCounts[resultCtx, 0]; ScanSons[body, UpdateCount]}}; FieldCtx: PROC[rSei: RecordSEIndex] RETURNS[CTXIndex] = { RETURN[IF rSei = RecordSENull THEN CTXNull ELSE seb[rSei].fieldCtx]}; PushAList: PROC[aLink: AList] = {aLink.next _ aStack; aStack _ aLink}; PopAList: PROC RETURNS[aLink: AList] = { IF aStack = NIL THEN ERROR; aLink _ aStack; aStack _ aLink.next}; ExpandSei: PROC[sei: ISEIndex] RETURNS[v: Tree.Link] = { i: CARDINAL; FOR aLink: AList _ aStack, aLink.next UNTIL aLink = NIL DO IF seb[sei].idCtx = aLink.ctx THEN FOR i IN [0 .. aLink.nItems) DO IF aLink.map[i].id = sei THEN GO TO Found ENDLOOP; REPEAT Found => { saveCopying: BOOL = copying; copying _ TRUE; v _ ExpandTree[aLink.map[i].val]; copying _ saveCopying}; FINISHED => {IF copying THEN IncrCount[sei]; v _ [symbol[index:sei]]}; ENDLOOP; RETURN}; ThreadSubst: PROC[node: Tree.Index, dest: Tree.Link] = { dThread: Tree.Index = GetNode[NthSon[dest, 1]]; IF copying THEN { sThread: Tree.Index; DO sThread _ GetNode[tb[node].son[1]]; IF tb[sThread].name # thread THEN ERROR; IF tb[sThread].son[2] = Tree.Null THEN EXIT; node _ GetNode[tb[sThread].son[2]]; ENDLOOP; tb[dThread].son[2] _ Tree.Null; tb[sThread].son[2] _ dest; MarkShared[dest, TRUE]}; tb[dThread].info _ currentEnclosing}; }. XPass3P.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Satterthwaite, April 16, 1986 10:24:41 am PST Paul Rovner, September 7, 1983 4:47 pm Russ Atkinson (RRA) March 6, 1985 10:48:35 pm PST called by allocator whenever table area is repacked driver included body copying inline expansion state information overall control process the thread (son[1]) expand the body complete the setup argument list testing/processing tree manipulation mark for later discard (see DiscardCall) blocks and bodies id translation mapping reference count adjustment association lists nested calls Κ˜codešœ ™ Kšœ Οmœ1™KšœŸ)˜K˜(K˜K˜——Kšœ™˜š œžœ˜K˜K˜1šžœžœžœž˜Nšžœžœž˜˜ Kšžœ žœC˜Všœžœž˜&Kšœ#žœ˜(Kšžœžœ˜,——Kšžœ"žœ˜.—Kšžœ˜ K˜K˜———Kšœ™˜Kšœ™˜K˜K˜K˜Kšœ žœ˜Kšœ žœ˜K˜Kšœ žœ˜K˜KšœŸ˜*K˜Kšœžœžœžœ˜@šœžœžœ˜K˜ K˜Kšœžœ˜Kšœžœ žœžœ˜+—Kšœžœžœ˜K˜K˜——Kšœ™˜š  œžœ˜)K˜Kšœ žœžœ˜ šžœž˜K˜ šžœžœž˜Kšœ žœ žœ žœ˜EKšžœ˜—Kšœžœžœžœ˜GKšžœ˜ K˜——š  œžœ˜$Kšœ-˜-K˜K˜K˜6šžœžœž˜#˜ K˜šžœžœ˜K˜'K˜$K˜—Kšžœ˜ Kšœ žœ˜šžœ*ž˜1Kšœ žœ˜šœ™K˜&K˜K˜(K˜$K˜*K˜4K˜Kšœžœ˜—šžœ˜Kšžœžœžœ žœ˜D—šžœžœž˜K˜ K˜=Kšžœ.˜5—Kšžœ˜ ——Kšžœžœ˜—K˜K˜—š  œžœžœŸ˜@K˜#K˜—š  œžœ˜&K˜K˜1K˜K˜Kšœžœ˜Kšœžœ˜K˜K˜ Kšžœžœ#˜?K˜Kšžœ žœžœ˜8šžœ˜K˜EK˜3K˜—K˜K˜'K˜,Kšžœžœž˜/šžœ˜šœžœ"˜AKšžœ#˜%—K˜"K˜,K˜Cšžœžœž˜&K˜@Kšžœžœ˜——šžœ#žœ˜+K˜0—šžœ#žœ˜+K˜,K˜0—Kšžœžœ žœ žœ˜IKšžœžœ0˜IKšžœ žœ˜'—šœ™šžœžœ˜K˜8Kšœ>žœ˜E—Kšžœžœ˜3Kšžœžœ˜1K˜'Kšžœžœžœ,˜VKšœžœžœžœ˜@K˜MK˜Kšœ ž˜—šœ˜K˜——š œžœžœžœ˜<šžœž˜Kšžœžœžœžœ˜"K˜Kšžœ˜—Kšžœžœ˜K˜—š  œžœ˜%Kšžœ ˜K˜AK˜K˜——Kšœ ™ ˜š œžœžœžœ˜4šžœ%ž˜.šœ ž˜ šœžœžœž˜K˜Kšœ žœ˜šžœ˜ šžœ ž˜šžœžœ˜#Kšœžœ˜2—K˜7K˜JKšœ"žœ˜'K˜Kšžœžœ˜—————šœ˜K˜——š  œžœžœžœžœ˜9Kšžœ˜K˜—š   œžœžœžœžœžœ˜?šžœžœžœž˜˜ šžœ ž˜Kšœ"žœ˜'K˜6K˜;šžœ˜Kšœžœžœžœ˜B—šžœ˜šœžœžœ˜&Kšžœžœ˜#——˜2Kšœžœžœ˜'—K˜%Kšžœžœ˜——Kšžœžœ˜K˜K˜——š  œžœžœžœ˜>Kšœžœ˜Kšžœ žœ žœ˜2K˜K˜—š  œžœžœžœ ˜IK˜ K˜˜Kšžœžœžœžœ˜OK˜—Kšœžœ˜ K˜K˜—š œžœžœžœ˜;šžœ9žœž˜RKšžœžœžœžœ˜/Kšžœžœžœžœ˜)Kšžœ˜—Kšžœžœ˜K˜K˜——Kšœ™˜˜šžœž˜šžœžœž˜˜ K˜šžœž˜˜šžœ"žœ˜*Kšœ(™(K˜/Kšœžœ˜—šžœ˜K˜3——šžœ˜ šžœžœ˜K˜4————Kšžœ˜——Kšžœ ˜K˜—˜šžœžœž˜K˜˜ K˜šžœž˜šœžœž˜K˜)Kšžœ˜——šž˜šžœž˜K˜K˜1Kšœ žœ˜'K˜K˜.K˜(K˜K˜"šžœ˜ šœžœ˜Kšžœ*˜.Kšžœ˜!—šžœžœž˜˜ K˜šžœž˜Kšœ žœžœ˜6Kšœ žœžœžœ˜9Kšžœžœ˜——Kšžœžœ˜—————Kšžœ ˜—Kšžœ˜K˜K˜—š  œžœžœžœ˜KKš žœžœž œžœžœžœ˜RKšžœ˜ K˜—š œžœžœžœ˜HK˜8K˜SKšžœ ˜K˜—š  œžœ"žœžœ˜RK˜ K˜'K˜&Kšœžœ žœžœ˜@K˜Kšžœ˜K˜—š  œžœžœ˜Kšžœ žœE˜Ušžœ˜K˜—Kšžœ˜K˜K˜—š  œžœžœ˜K˜+K˜˜šžœžœž˜K˜K˜$Kšžœžœ˜K˜——šžœ%žœžœž˜8Kšžœžœžœžœ˜#šž˜K˜Kšžœ˜—Kšžœ˜—Kšžœ žœžœ˜)K˜—˜Kšœžœ˜ K˜˜K˜K˜K˜.Kšžœ!žœ#˜Jšžœ˜Kšœžœ˜2Kšœžœ˜2K˜——˜K˜K˜"K˜K˜&Kšžœžœ˜0šžœ˜Kšœžœ&˜šžœ˜K˜Kšœ5žœ˜Kšœžœ-žœ˜C˜Kšœ žœ žœ žœ˜2˜Kšœ žœ žœ˜ Kšœ žœžœžœ˜:Kšœ žœ žœ žœ˜2—K˜ K˜Kšœ žœ˜K˜—Kšœ-žœ˜2Kšžœ˜K˜K˜——Kšœ™˜š  œžœ$˜7K˜šžœžœž˜Kšœžœ˜K˜@šžœ˜ Kšžœ!žœ žœ˜=K˜K˜———š œžœžœžœ ˜9šžœ.žœž˜GKšžœžœ žœ˜3—Kšžœ˜K˜—š  œžœžœ˜K˜—K˜—Kšžœžœ˜K˜——K˜5K˜K˜——š œžœžœ˜9Kšžœžœžœ žœ˜EK˜K˜——Kšœ™˜Kš  œžœ7˜FK˜š œžœžœ˜(Kšžœ žœžœžœ(˜BK˜—š  œžœžœ˜8Kšœžœ˜ šžœ#žœ žœž˜:šžœž˜"Kšžœžœžœžœžœžœžœžœ˜R—šž˜˜ Kšœ žœ ˜Kšœ žœ$˜2K˜—Kšžœžœ žœ*˜F—Kšžœ˜—Kšžœ˜K˜K˜——Kšœ ™ ˜š  œžœ'˜8K˜/šžœ žœ˜K˜šž˜K˜#Kšžœžœžœ˜(Kšžœ žœžœ˜,K˜#Kšžœ˜—K˜Kšœ-žœ˜4—K˜%K˜—K˜K˜——…—ytšΟ