DIRECTORY Atom, Convert, Core, CoreFlatten, CoreOps, CoreProperties, CoreRecord, Process, Rope; CoreFlattenImpl: CEDAR MONITOR IMPORTS CoreOps, CoreProperties, CoreRecord, Process EXPORTS CoreFlatten = BEGIN OPEN Core, CoreRecord, CoreFlatten; instantiationPath: PUBLIC ATOM _ $CoreFlatInstantiationPath; wireSource: PUBLIC ATOM _ $CoreFlatWireSource; InstantiationPath: TYPE = REF InstantiationPathRep; InstantiationPathRep: PUBLIC TYPE = RECORD [ head: CellInstanceList, tail: CellInstanceList ]; easyExhibitDirection: InstantiationPathDirection _ shallower; IsEmpty: PUBLIC PROC [ip: InstantiationPath] RETURNS [BOOL] = {RETURN [ip.head = NIL]}; Split: PUBLIC PROC [ip: InstantiationPath, end: InstantiationPathDirection] RETURNS [step: CellInstance, rest: InstantiationPath] = { SELECT end FROM deeper => RETURN [ ip.head.first, NEW [InstantiationPathRep _ [ head: ip.head.rest, tail: IF ip.head.rest = NIL THEN NIL ELSE ip.tail ]] ]; shallower => { rest: InstantiationPath _ NEW [InstantiationPathRep _ [NIL, NIL]]; FOR il: CellInstanceList _ ip.head, il.rest WHILE il # ip.tail DO rest _ IPAdd[rest, il.first, shallower, TRUE]; ENDLOOP; RETURN [ip.tail.first, rest]; }; ENDCASE => ERROR; }; Exhibit: PUBLIC PROC [ip: InstantiationPath, later: InstantiationPathDirection, to: PROC [step: CellInstance]] = { WorkD: PROC [il: CellInstanceList] = { IF il # NIL THEN {WorkD[il.rest]; to[il.first]}; }; SELECT later FROM shallower => { IF ip.tail # NIL THEN FOR il: CellInstanceList _ ip.head, il.rest WHILE il # ip.tail.rest DO to[il.first]; ENDLOOP; ip _ ip; }; deeper => WorkD[ip.head]; ENDCASE => ERROR; }; IPAdd: PROC [ip: InstantiationPath, step: CellInstance, end: InstantiationPathDirection, destructively: BOOL] RETURNS [longer: InstantiationPath] = { longer _ ip; SELECT destructively FROM FALSE => SELECT end FROM shallower => { longer _ IPCopy[ip]; longer _ IPAdd[longer, step, shallower, TRUE]; }; deeper => { longer _ NEW [InstantiationPathRep _ ip^]; longer.head _ CONS[step, longer.head]; IF longer.tail = NIL THEN longer.tail _ longer.head; }; ENDCASE => ERROR; TRUE => SELECT end FROM shallower => { this: CellInstanceList _ LIST[step]; IF longer.tail # NIL THEN longer.tail.rest _ this ELSE longer.head _ this; longer.tail _ this; }; deeper => { longer.head _ CONS[step, longer.head]; IF longer.tail = NIL THEN longer.tail _ longer.head; }; ENDCASE => ERROR; ENDCASE => ERROR; }; IPCopy: PROC [ip: InstantiationPath] RETURNS [copy: InstantiationPath] = { copy _ EmptyPath[]; IF ip.tail # NIL THEN FOR il: CellInstanceList _ ip.head, il.rest WHILE il # ip.tail.rest DO copy _ IPAdd[copy, il.first, shallower, TRUE]; ENDLOOP; copy _ copy; }; IPCat: PROC [shallow, deep: InstantiationPath, destroyShallow, destroyDeep: BOOL] RETURNS [both: InstantiationPath] = { IF shallow.tail = NIL THEN RETURN [deep]; IF deep.head = NIL THEN RETURN [shallow]; IF shallow = deep THEN ERROR; SELECT destroyShallow FROM TRUE => { shallow.tail.rest _ deep.head; shallow.tail _ deep.tail; RETURN [shallow]; }; FALSE => { shallow _ IPCopy[shallow]; RETURN [IPCat[shallow, deep, TRUE, destroyDeep]]; }; ENDCASE => ERROR; }; EmptyPath: PROC RETURNS [empty: InstantiationPath] = {empty _ NEW [InstantiationPathRep _ [NIL, NIL]]}; UnitPath: PROC [step: CellInstance] RETURNS [ip: InstantiationPath] = { this: CellInstanceList _ LIST[step]; ip _ NEW [InstantiationPathRep _ [this, this]]}; Sym: TYPE = REF SymRec; SymRec: TYPE = RECORD [atom: ATOM, curKey: Key _ Key.FIRST, inUse: BOOL _ FALSE]; Key: TYPE = LONG CARDINAL; Holder: TYPE = REF HolderRec; HolderRec: TYPE = RECORD [key: Key, value: REF ANY]; symChange: CONDITION; AllocSym: ENTRY PROC [s: Sym] = { ENABLE UNWIND => NULL; WHILE s.inUse DO WAIT symChange ENDLOOP; IF s.curKey = Key.LAST THEN ERROR; s.curKey _ s.curKey + 1; s.inUse _ TRUE; }; ReleaseSym: ENTRY PROC [s: Sym] = { s.inUse _ FALSE; BROADCAST symChange; }; CreateSym: PROC [atom: ATOM] RETURNS [s: Sym] = { s _ NEW [SymRec _ [atom]]; CoreProperties.RegisterProperty[s.atom]; }; GetSym: PROC [from: Core.Properties, sym: Sym] RETURNS [value: REF ANY] = { h: Holder _ NARROW[CoreProperties.GetProp[from, sym.atom]]; value _ IF (h = NIL) OR (h.key # sym.curKey) THEN NIL ELSE h.value; }; PutSym: PROC [on: Core.Properties, sym: Sym, value: REF ANY] RETURNS [updated: Core.Properties] = { h: Holder _ NARROW[CoreProperties.GetProp[on, sym.atom]]; IF h # NIL THEN { h.key _ sym.curKey; h.value _ value; RETURN [on]}; updated _ CoreProperties.PutProp[on, sym.atom, NEW [HolderRec _ [sym.curKey, value]] ]; }; AssocWire: PROC [key: Sym, from, to: Wire] = { from.properties _ PutSym[from.properties, key, to]; IF from.elements # NIL THEN { FOR i: INT IN [0 .. from.elements.size) DO AssocWire[key, from.elements[i], to.elements[i]]; ENDLOOP; key _ key}; }; GetWireAssoc: PROC [key: Sym, from: Wire] RETURNS [to: Wire] = {to _ NARROW[GetSym[from.properties, key]]}; Promotions: TYPE = REF PromotionsRec; PromotionsRec: TYPE = RECORD [ count: NAT _ 0, wires: WireList _ NIL]; WireList: TYPE = LIST OF Wire; formalToActual: Sym _ CreateSym[$CoreFlattenFormalToActual]; templateToCopy: Sym _ CreateSym[$CoreFlattenTemplateToCopy]; partPublic: Sym _ CreateSym[$CoreFlattenPartPublic]; FlattenOnce: PROC [design: Design, cellType: CellType, control: FlattenControl] RETURNS [flat: CellType] = { oldRec, newRec: RecordCellType; promotions: Promotions _ NEW [PromotionsRec _ []]; AllocSym[formalToActual]; AllocSym[templateToCopy]; AllocSym[partPublic]; {ENABLE UNWIND => { ReleaseSym[formalToActual]; ReleaseSym[templateToCopy]; ReleaseSym[partPublic]; }; cellType _ Recordify[design, cellType]; [oldRec, newRec, flat] _ CopyCellType[design, templateToCopy, cellType]; newRec.instances _ NIL; FOR cl: CellInstanceList _ oldRec.instances, cl.rest WHILE cl # NIL DO child: CellInstance _ cl.first; childType: CellType _ Recordify[design, child.type]; childRec: RecordCellType _ NARROW[childType.data]; childPath: InstantiationPath _ UnitPath[child]; SELECT control.Decide[control.data, childPath] FROM expand => { AssocWire[formalToActual, child.type.publicWire, child.actualWire]; PromotePrivates[design, flat, newRec, childType, childRec, formalToActual, templateToCopy, partPublic, promotions, UnitPath[child]]; FOR gl: CellInstanceList _ childRec.instances, gl.rest WHILE gl # NIL DO oldGrandchild: CellInstance _ gl.first; gcPath: InstantiationPath _ IPAdd[childPath, oldGrandchild, deeper, FALSE]; newGrandchild: CellInstance; newGrandchild _ CopyInstance[design, oldGrandchild, formalToActual, templateToCopy, gcPath, childPath]; newRec.instances _ CONS[newGrandchild, newRec.instances]; ENDLOOP; child _ child; }; leaf => { newChild: CellInstance _ CopyInstance[design, child, formalToActual, templateToCopy, childPath, EmptyPath[]]; newRec.instances _ CONS[newChild, newRec.instances]; }; ENDCASE => ERROR; child _ child; ENDLOOP; flat _ flat; IF promotions.count # 0 THEN { oldPW: Wire _ flat.publicWire; newPW: Wire _ NEW [WireRec _ [ name: NIL, structure: record, elements: NEW [WireSequenceRec[oldPW.elements.size + promotions.count]], properties: oldPW.properties ]]; i: NAT _ 0; IF oldPW.structure # record THEN ERROR; THROUGH [0 .. oldPW.elements.size) DO newPW.elements[i] _ oldPW.elements[i]; i _ i + 1; ENDLOOP; FOR wl: WireList _ promotions.wires, wl.rest WHILE wl # NIL DO newPW.elements[i] _ wl.first; i _ i + 1; ENDLOOP; IF i # (oldPW.elements.size + promotions.count) THEN ERROR; flat.publicWire _ newPW; }; }; ReleaseSym[formalToActual]; ReleaseSym[templateToCopy]; ReleaseSym[partPublic]; }; Recordify: PROC [design: Design, ct: CellType] RETURNS [rct: CellType] = { FOR rct _ ct, CoreOps.Recast[rct] UNTIL rct.class = recordCellClass DO NULL ENDLOOP; rct _ rct}; CopyCellType: PROC [design: Design, templateToCopy: Sym, old: CellType] RETURNS [oldRec, newRec: RecordCellType, new: CellType] = { oldRec _ NARROW[old.data]; newRec _ NEW [RecordCellTypeRec _ [ internalWire: CoreOps.CopyWire[oldRec.internalWire], instances: oldRec.instances]]; NoteWireSource[newRec.internalWire, [EmptyPath[], oldRec.internalWire], TRUE]; AssocWire[templateToCopy, oldRec.internalWire, newRec.internalWire]; new _ NEW [CellTypeRec _ old^]; new.data _ newRec; new.properties _ CoreProperties.CopyProps[old.properties]; new.publicWire _ DuplicatePublicWire[design, templateToCopy, old.publicWire]; new _ new}; DuplicatePublicWire: PROC [design: Design, templateToCopy: Sym, oldPublicWire: Wire] RETURNS [newPublicWire: Wire] = { newPublicWire _ GetWireAssoc[templateToCopy, oldPublicWire]; IF newPublicWire # NIL --means this is part of internalWire-- THEN RETURN; newPublicWire _ NEW [WireRec _ [ name: NIL, structure: oldPublicWire.structure, elements: NIL, properties: CoreProperties.CopyProps[oldPublicWire.properties] ]]; NoteWireSource[newPublicWire, [EmptyPath[], oldPublicWire], FALSE]; IF oldPublicWire.elements # NIL THEN { newPublicWire.elements _ NEW [WireSequenceRec[oldPublicWire.elements.size]]; FOR i: INT IN [0 .. oldPublicWire.elements.size) DO newPublicWire.elements[i] _ DuplicatePublicWire[design, templateToCopy, oldPublicWire.elements[i]]; ENDLOOP; design _ design}; design _ design}; PromotePrivates: PROC [design: Design, parent: CellType, parentRec: RecordCellType, child: CellType, childRec: RecordCellType, formalToActual, templateToCopy, partPublic: Sym, promotions: Promotions, path: InstantiationPath] = { FindPublic: PROC [childsInternal: Wire] RETURNS [somePublic: BOOL] = { somePublic _ GetWireAssoc[formalToActual, childsInternal] # NIL; IF (NOT somePublic) AND childsInternal.structure # atom THEN { FOR i: NAT IN [0 .. childsInternal.elements.size) DO subWire: Wire _ childsInternal.elements[i]; subSomePublic: BOOL _ FindPublic[subWire]; somePublic _ somePublic OR subSomePublic; ENDLOOP; child _ child; }; IF somePublic THEN childsInternal.properties _ PutSym[childsInternal.properties, partPublic, $T]; }; DoForPrivateCover: PROC [childsInternal: Wire] = { allPublic: BOOL _ GetWireAssoc[formalToActual, childsInternal] # NIL; somePublic: BOOL _ allPublic OR (GetSym[childsInternal.properties, partPublic] = $T); IF NOT somePublic THEN { new: Wire _ CoreOps.CopyWire[childsInternal]; NoteWireSource[new, [path, childsInternal], TRUE]; AssocWire[templateToCopy, childsInternal, new]; promotions.count _ promotions.count + 1; promotions.wires _ CONS[new, promotions.wires]; } ELSE IF allPublic THEN { AssocToCopy[childsInternal]; } ELSE { FOR i: NAT IN [0 .. childsInternal.elements.size) DO DoForPrivateCover[childsInternal.elements[i]]; ENDLOOP; design _ design; }; }; AssocToCopy: PROC [childsInternal: Wire] = { actual: Wire _ GetWireAssoc[formalToActual, childsInternal]; copy: Wire _ GetWireAssoc[templateToCopy, actual]; IF copy # NIL THEN AssocWire[templateToCopy, childsInternal, copy] ELSE { FOR i: NAT IN [0 .. childsInternal.elements.size) DO AssocToCopy[childsInternal.elements[i]]; ENDLOOP; design _ design; }; }; [] _ FindPublic[childRec.internalWire]; DoForPrivateCover[childRec.internalWire]; }; CopyInstance: PROC [design: Design, old: CellInstance, formalToActual, templateToCopy: Sym, longPath, shortPath: InstantiationPath] RETURNS [new: CellInstance] = { CopyActual: PROC [old: Wire] RETURNS [new: Wire] = { new _ GetWireAssoc[templateToCopy, old]; IF new # NIL THEN RETURN; new _ NEW [WireRec _ [ name: NIL, structure: old.structure, elements: NIL, properties: CoreProperties.CopyProps[old.properties] ]]; NoteWireSource[new, [shortPath, old], FALSE]; IF old.elements = NIL THEN ERROR --this recursion must ground out in a piece of already copied template--; new.elements _ NEW [WireSequenceRec[old.elements.size]]; FOR i: INT IN [0 .. old.elements.size) DO new.elements[i] _ CopyActual[old.elements[i]]; ENDLOOP; new _ new; }; new _ NEW [CellInstanceRec _ [ name: NIL, actualWire: CopyActual[old.actualWire], type: old.type, properties: CoreProperties.CopyProps[old.properties] ]]; NoteInstanceSource[new, longPath]; }; Flatten: PUBLIC PROC [design: Design, cellType: CellType, control: FlattenControl] RETURNS [flat: CellType] = { oldRec, newRec: RecordCellType; promotions: Promotions _ NEW [PromotionsRec _ []]; AllocSym[formalToActual]; AllocSym[templateToCopy]; AllocSym[partPublic]; {ENABLE UNWIND => { ReleaseSym[formalToActual]; ReleaseSym[templateToCopy]; ReleaseSym[partPublic]; }; Work: PROC [cl: CellInstanceList, pathPrefix: InstantiationPath] = { flat _ flat; FOR cl _ cl, cl.rest WHILE cl # NIL DO child: CellInstance _ cl.first; path: InstantiationPath _ IPAdd[pathPrefix, child, deeper, FALSE]; childType: CellType _ Recordify[design, child.type]; childRec: RecordCellType _ NARROW[childType.data]; SELECT control.Decide[control.data, path] FROM expand => { AssocWire[formalToActual, child.type.publicWire, child.actualWire]; PromotePrivates[design, flat, newRec, childType, childRec, formalToActual, templateToCopy, partPublic, promotions, path]; Work[childRec.instances, path]; child _ child; }; leaf => { newChild: CellInstance _ CopyInstance[design, child, formalToActual, templateToCopy, path, pathPrefix]; newRec.instances _ CONS[newChild, newRec.instances]; }; ENDCASE => ERROR; child _ child; ENDLOOP; flat _ flat; }; cellType _ Recordify[design, cellType]; [oldRec, newRec, flat] _ CopyCellType[design, templateToCopy, cellType]; newRec.instances _ NIL; Work[oldRec.instances, EmptyPath[]]; IF promotions.count # 0 THEN { oldPW: Wire _ flat.publicWire; newPW: Wire _ NEW [WireRec _ [ name: NIL, structure: record, elements: NEW [WireSequenceRec[oldPW.elements.size + promotions.count]], properties: oldPW.properties ]]; i: NAT _ 0; IF oldPW.structure # record THEN ERROR; THROUGH [0 .. oldPW.elements.size) DO newPW.elements[i] _ oldPW.elements[i]; i _ i + 1; ENDLOOP; FOR wl: WireList _ promotions.wires, wl.rest WHILE wl # NIL DO newPW.elements[i] _ wl.first; i _ i + 1; ENDLOOP; IF i # (oldPW.elements.size + promotions.count) THEN ERROR; flat.publicWire _ newPW; }; }; ReleaseSym[formalToActual]; ReleaseSym[templateToCopy]; ReleaseSym[partPublic]; }; FlattenInstantiationPath: PROC [org: InstantiationPath] RETURNS [flat: InstantiationPath] = { alreadyFlat: BOOL _ TRUE; Test: PROC [step: CellInstance] = { IF CoreProperties.GetProp[step.properties, instantiationPath] # NIL THEN alreadyFlat _ FALSE; }; Cons: PROC [step: CellInstance] = { ip: InstantiationPath _ NARROW[CoreProperties.GetProp[step.properties, instantiationPath]]; IF ip = NIL THEN flat _ IPAdd[flat, step, easyExhibitDirection, TRUE] ELSE SELECT easyExhibitDirection FROM deeper => flat _ IPCat[ip, flat, FALSE, TRUE]; shallower => flat _ IPCat[flat, ip, TRUE, FALSE]; ENDCASE => ERROR; }; Exhibit[org, easyExhibitDirection, Test]; IF alreadyFlat THEN RETURN [org]; flat _ EmptyPath[]; Exhibit[org, easyExhibitDirection, Cons]; flat _ flat; }; NoteInstanceSource: PROC [newInstance: CellInstance, path: InstantiationPath] = { flatPath: InstantiationPath _ FlattenInstantiationPath[path]; newInstance.properties _ CoreProperties.PutProp[newInstance.properties, instantiationPath, flatPath]; }; NoteWireSource: PROC [newWire: Wire, source: WireSourceRec, recursively: BOOL] = { source.instantiationPath _ FlattenInstantiationPath[source.instantiationPath]; DO oldSource: WireSource _ GetWireSource[source.wire]; IF oldSource = NIL THEN EXIT; source _ [ instantiationPath: IPCat[source.instantiationPath, FlattenInstantiationPath[oldSource.instantiationPath], FALSE, FALSE], wire: oldSource.wire]; ENDLOOP; newWire.properties _ CoreProperties.PutProp[newWire.properties, wireSource, NEW [WireSourceRec _ source] ]; IF recursively AND newWire.elements # NIL THEN { FOR i: NAT IN [0 .. newWire.elements.size) DO NoteWireSource[newWire.elements[i], [source.instantiationPath, source.wire.elements[i]], recursively]; ENDLOOP; newWire _ newWire; }; }; GetWireSource: PROC [w: Wire] RETURNS [ws: WireSource] = { ws _ NARROW[CoreProperties.GetProp[w.properties, wireSource]]; }; ControlByFile: PUBLIC PROC [fileName: ROPE] RETURNS [control: FlattenControl] = {ERROR --not yet implemented--}; Start: PROC = TRUSTED { Process.InitializeCondition[@symChange, Process.SecondsToTicks[60]]; Process.EnableAborts[@symChange]; }; Start[]; END. ΘCoreFlattenImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Spreitzer, August 15, 1985 8:09:21 pm PDT Barth, August 16, 1985 6:04:09 pm PDT INVARIANT Sym.inUse describes whether some process is using that Sym. Introduction This interface implements a utility for flattening the data structure defined in Core. Flat Core deeper earlier points to the last CONS cell in the list Symbols A Symbol is like a property, except that it logically is retained for only a bounded period of time. The following implementation assumes there will be only one instance of itself in any VM. Wire Binding Flattening Each child is expanded or not, depending on what control says. Don't need to NoteWireSource[newPW, oldPW, NIL] because already done in CopyCellType Each descendent is expanded or not, depending on what control says. Don't need to NoteWireSource[newPW, oldPW, NIL] because already done in CopyCellType Backpointers Control by File Start Code Κy˜code– "Cedar" stylešœ™Kšœ Οmœ1™Kšœžœ ˜,——™ Kšœ žœžœ˜%šœžœžœ˜Kšœžœ˜Kšœžœ˜—K˜Kšœ žœžœžœ˜K˜Kšœ<˜Kšœ˜Kšœžœ˜2Kšœ˜Kšœ˜Kšœ˜šœžœžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ'˜'KšœH˜HKšœžœ˜šžœ2žœžœž˜FKšœ˜K˜4Kšœžœ˜2Kšœ/˜/šžœ)ž˜3šœ ˜ K˜CKšœ„˜„šžœ4žœžœž˜HKšœ'˜'KšœDžœ˜KKšœ˜Kšœg˜gKšœžœ"˜9Kšžœ˜—K˜K˜—šœ ˜ Kšœm˜mKšœžœ˜4K˜—Kšžœžœ˜—K˜Kšžœ˜—K˜ šžœžœ˜Kšœ˜šœžœ ˜Kšœžœ˜ K˜Kšœ žœ;˜HKšœ˜K˜—Kšœžœ˜ KšœT™TKšžœžœžœ˜'šžœž˜%K˜&K˜ Kšžœ˜—šžœ*žœžœž˜>K˜K˜ Kšžœ˜—Kšžœ.žœžœ˜;K˜Kšœ˜—K˜Kšœ˜Kšœ˜Kšœ˜K˜—K˜š  œžœ žœ˜JKš žœžœžœžœžœ˜TK˜ —K˜š  œžœ6žœ4˜ƒKšœ žœ ˜šœ žœ˜#Kšœ4˜4Kšœ˜—KšœHžœ˜NKšœD˜DKšœžœ˜Kšœ˜Kšœ:˜:KšœM˜MK˜ —K˜š œžœ<žœ˜vKšœ<˜˜>K˜—Kšœ<žœ˜Cšžœžœžœ˜&Kšœžœ0˜Lšžœžœžœ$ž˜3Kšœc˜cKšžœ˜—Kšœ˜—Kšœ˜—K˜š œžœΟ˜δš  œžœžœžœ˜FKšœ<žœ˜@šžœžœ žœ!žœ˜>šžœžœžœ%ž˜4Kšœ+˜+Kšœžœ˜*Kšœžœ˜)Kšžœ˜—Kšœ˜K˜—Kšžœ žœO˜aK˜—š œžœ˜2Kšœ žœ2žœ˜EKšœ žœ žœ6˜Ušžœžœ žœ˜Kšœ-˜-Kšœ,žœ˜2Kšœ/˜/Kšœ(˜(Kšœžœ˜/K˜—šžœžœ žœ˜Kšœ˜K˜—šžœ˜šžœžœžœ%ž˜4Kšœ.˜.Kšžœ˜—K˜K˜—K˜—š  œžœ˜,Kšœ<˜K˜K˜ Kšžœ˜—Kšžœ.žœžœ˜;K˜Kšœ˜—K˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜——™ š œžœžœ˜]Kšœ žœžœ˜š œžœ˜#Kšžœ>žœžœžœ˜]K˜—š œžœ˜#Kšœžœ=˜[šžœž˜ Kšžœ0žœ˜9šžœžœž˜%Kšœ!žœžœ˜.Kšœ$žœžœ˜1Kšžœžœ˜——K˜—Kšœ)˜)Kšžœ žœžœ˜!Kšœ˜Kšœ)˜)K˜ K˜—K˜š œžœ9˜QKšœ=˜=Kšœe˜eK˜—K˜š œžœ5žœ˜RKšœN˜Nšž˜Kšœ3˜3Kšžœ žœžœžœ˜˜ Kšœjžœžœ˜xKšœ˜—Kšžœ˜—KšœLžœ˜kšžœ žœžœžœ˜0šžœžœžœž˜-Kšœf˜fKšžœ˜—Kšœ˜K˜—K˜—K˜š  œžœ žœ˜:Kšœžœ3˜>K˜——™Kš  œžœžœ žœžœžœ’œ˜p—™ š œžœžœ˜K˜DKšœ!˜!K˜—K˜K˜K˜—Jšžœ˜—…—?UE