DIRECTORY AMBridge, AMModel, AMTypes, Atom, Core, CoreClasses, CoreCompose, CoreOps, CoreProperties, CoreSequence, InterpreterOps, PPLeaves, PPTree, RefTab, Rope, SymTab; CoreComposeImpl: CEDAR PROGRAM IMPORTS AMBridge, AMModel, Atom, CoreClasses, CoreOps, CoreProperties, CoreSequence, InterpreterOps, RefTab, Rope, SymTab EXPORTS CoreCompose = BEGIN OPEN CoreCompose; ref: ATOM =$CtxREF; atom: ATOM =$CtxATOM; rope: ATOM =$CtxROPE; int: ATOM =$CtxINT; real: ATOM =$CtxREAL; bool: ATOM =$CtxBOOL; stMark: ATOM =$CtxStackMark; procMark: ATOM =$CtxprocMark; Tree: TYPE = InterpreterOps.Tree; Node: TYPE = REF PPTree.Node; Wire: TYPE = Core.Wire; CheckTypeVal: PROC [lit: PropertyLiteral] = { type: ATOM _ WITH lit.val SELECT FROM a: ATOM => atom, r: ROPE => rope, i: REF INT => int, r: REF REAL => real, r: REF => ref, ENDCASE => ERROR; CheckTypeProp[lit.key, type]; }; CheckTypeProp: PROC [prop, type: ATOM] = { IF ~RefTab.Fetch[propTable, prop].val=type THEN ERROR}; -- prop reg. with another type FetchRef: PROC [context: CContext, prop: ATOM] RETURNS [found: BOOL _ FALSE, ref: REF _ NIL] = { FOR l: Stack _ context.stack, l.rest WHILE l#NIL DO IF l.first.key=prop THEN RETURN[TRUE, l.first.val]; ENDLOOP; }; GetRef: PUBLIC PROC [context: CContext, prop: ATOM] RETURNS [REF] = { FOR l: Stack _ context.stack, l.rest WHILE l#NIL DO IF l.first.key=prop THEN RETURN[l.first.val]; ENDLOOP; ERROR; -- prop not found }; GetAtom: PUBLIC PROC [context: CContext, prop: ATOM] RETURNS [ATOM] = { CheckTypeProp[prop, atom]; RETURN[NARROW[GetRef[context, prop]]];}; GetRope: PUBLIC PROC [context: CContext, prop: ATOM] RETURNS [ROPE] = { CheckTypeProp[prop, rope]; RETURN[NARROW[GetRef[context, prop]]];}; GetInt: PUBLIC PROC [context: CContext, prop: ATOM] RETURNS [INT] = { CheckTypeProp[prop, int]; RETURN[NARROW[GetRef[context, prop], REF INT]^];}; GetReal: PUBLIC PROC [context: CContext, prop: ATOM] RETURNS [REAL] = { CheckTypeProp[prop, real]; RETURN[NARROW[GetRef[context, prop], REF REAL]^];}; GetBool: PUBLIC PROC [context: CContext, prop: ATOM] RETURNS [BOOL] = { CheckTypeProp[prop, bool]; RETURN[NARROW[GetRef[context, prop], REF BOOL]^];}; PushRef: PUBLIC PROC [context: CContext, prop: ATOM, val: REF] = TRUSTED{ context.stack _ CONS[[prop, val], context.stack]; [] _ SymTab.Store[context.tab, Atom.GetPName[prop], AMBridge.TVForReferent[val]]}; PushAtom: PUBLIC PROC [context: CContext, prop: ATOM, val: ATOM] = TRUSTED{ context.stack _ CONS[[prop, val], context.stack]; [] _ SymTab.Store[context.tab, Atom.GetPName[prop], AMBridge.TVForATOM[val]]}; PushRope: PUBLIC PROC [context: CContext, prop: ATOM, val: ROPE] = TRUSTED{ context.stack _ CONS[[prop, val], context.stack]; [] _ SymTab.Store[context.tab, Atom.GetPName[prop], AMBridge.TVForROPE[val]]}; PushInt: PUBLIC PROC [context: CContext, prop: ATOM, val: INT] = TRUSTED{ PushRef[context, prop, NEW[INT _ val]]}; PushReal: PUBLIC PROC [context: CContext, prop: ATOM, val: REAL] = TRUSTED{ PushRef[context, prop, NEW[REAL _ val]]}; PushBool: PUBLIC PROC [context: CContext, prop: ATOM, val: BOOL] = TRUSTED{ PushRef[context, prop, NEW[BOOL _ val]]}; RegisterProperty: PROC [prop, type: ATOM] = { [] _ RefTab.Store[propTable, prop, type]}; FetchPropertyType: PROC [prop: ATOM] RETURNS [type: ATOM] = { type _ NARROW[RefTab.Fetch[propTable, prop].val]}; RegisterRefProperty: PUBLIC PROC [prop: ATOM] = {RegisterProperty[prop, ref]}; RegisterAtomProperty: PUBLIC PROC [prop: ATOM] = {RegisterProperty[prop, atom]}; RegisterRopeProperty: PUBLIC PROC [prop: ATOM] = {RegisterProperty[prop, rope]}; RegisterIntProperty: PUBLIC PROC [prop: ATOM] = {RegisterProperty[prop, int]}; RegisterRealProperty: PUBLIC PROC [prop: ATOM] = {RegisterProperty[prop, real]}; RegisterBoolProperty: PUBLIC PROC [prop: ATOM] = {RegisterProperty[prop, bool]}; CreateContext: PUBLIC PROC [init: CContext _ NIL, props: PropertyLiterals _ NIL] RETURNS [CContext] = { new: CContext _ init; IF new=NIL THEN new _ NEW[ContextRec _ [tab: SymTab.Create[ ]]]; FOR l: PropertyLiterals _ props, l.rest WHILE l#NIL DO lit: PropertyLiteral _ l.first; CheckTypeVal[lit]; PushRef[new, lit.key, lit.val]; ENDLOOP; RETURN[new]; }; MarkContext: PUBLIC PROC [context: CContext, mark: ATOM] = { context.stack _ CONS[[stMark, mark], context.stack]}; Equal: PROC [lit1, lit2: PropertyLiteral] RETURNS [BOOL] = { RETURN[lit1.key=lit2.key AND lit1.val=lit2.val]; }; PopLit: PROC [context: CContext] RETURNS [lit: PropertyLiteral] = TRUSTED{ older: REF; found: BOOL; IF context.stack=NIL THEN ERROR; -- empty stack lit _ context.stack.first; context.stack _ context.stack.rest; [found, older] _ FetchRef[context, lit.key]; -- found in stack IF lit.key=stMark THEN RETURN; IF found THEN [] _ SymTab.Store[context.tab, Atom.GetPName[lit.key], AMBridge.TVForReferent[older]] ELSE [] _ SymTab.Delete[context.tab, Atom.GetPName[lit.key]]; }; PopContext: PUBLIC PROC [context: CContext, mark: ATOM] = { lit: PropertyLiteral _ PopLit[context]; goal: PropertyLiteral _ [stMark, mark]; UNTIL Equal[lit, goal] DO -- mark is the last one popped lit _ PopLit[context]; ENDLOOP; }; RegisterStructureProc: PUBLIC PROC [name: ROPE, proc: StructureProc] RETURNS [ROPE] = { val: REF StructureProc _ NEW[StructureProc _ proc]; ok: BOOL _ SymTab.Store[structProcTable, name, val]; -- larger table! RETURN[name]}; CreateStructure: PUBLIC PROC [name: ROPE, context: CContext] RETURNS [ct: CellType] = { val: REF; found: BOOL; proc: StructureProc; [found, val] _ SymTab.Fetch[structProcTable, name]; IF ~found THEN ERROR; -- proc not registered: should we return NIL? proc _ NARROW[val, REF StructureProc]^; MarkContext[context, procMark]; ct _ proc[context]; PopContext[context, procMark]; }; IsRegistered: PUBLIC PROC [name: ROPE] RETURNS [BOOL] = { RETURN [SymTab.Fetch[structProcTable, name].found]; }; CreateTransistor: PUBLIC PROC [name: ROPE _ NIL, type: TransistorType _ nE, length: NAT _ 2, width: NAT _ 4] RETURNS [cellType: CellType] = { trRec: CoreClasses.TransistorRec _ [ type: type, length: length, width: width]; cellType _ CoreClasses.TransistorCreate[trRec]; }; CreateSequenceCell: PUBLIC PROC [name: ROPE, baseCell: CellType, count: NAT, sequencePorts: ROPE _ NIL] RETURNS [cellType: CellType] = { node: Node _ NIL; n: INT _ 0; tree: Tree; seqCell: CoreSequence.SequenceCellType; IF sequencePorts#NIL THEN { tree _ Parse[sequencePorts]; WITH tree SELECT FROM ident: PPLeaves.HTIndex => { -- one wire in list seqCell _ NEW[CoreSequence.SequenceCellTypeRec[1]]; seqCell.sequence[0] _ FindIndexWire[ InterpreterOps.TreeToName[tree], baseCell.public]; }; node: Node => { n _ node.sonLimit-1; seqCell _ NEW[CoreSequence.SequenceCellTypeRec[n]]; FOR i: INT IN [0..n) DO -- hope we will not go in there if n=0 seqCell.sequence[i] _ FindIndexWire[ InterpreterOps.TreeToName[Nth[node, i+1]], baseCell.public]; ENDLOOP; }; ENDCASE => ERROR; } ELSE seqCell _ NEW [CoreSequence.SequenceCellTypeRec[0]]; seqCell.base _ baseCell; seqCell.count _ count; cellType _ CoreSequence.Create[name: name, args: seqCell]; }; CreateRecordCell: PUBLIC PROC [name: ROPE, public: WireSequence, onlyInternal: WireSequence _ NIL, instances: InstanceList _ NIL, context: Context] RETURNS [cellType: CellType] = { internal: WireSequence _ WireUnion[public, onlyInternal]; recCell: CoreClasses.RecordCellType _ NEW [CoreClasses.RecordCellTypeRec _ [ internal: internal, instances: ToCoreClassesInsts[instances, internal, context]]]; cellType _ CoreOps.CreateCellType[ class: CoreClasses.recordCellClass, public: public, data: recCell, name: name ]; }; ToCoreClassesInsts: PROC [insts: InstanceList, internal: WireSequence, context: Context] RETURNS [instances: CoreClasses.CellInstanceList _ NIL] = { newList: InstanceList _ NIL; FOR l: InstanceList _ insts, l.rest WHILE l#NIL DO newList _ CONS[l.first, newList] ENDLOOP; FOR l: InstanceList _ newList, l.rest WHILE l#NIL DO instances _ CONS[MakeInst[l.first.actual, l.first.type, internal, context], instances]; ENDLOOP; }; MakeInst: PROC [rope: ROPE, ct: CellType, internal: WireSequence, context: Context] RETURNS [inst: CoreClasses.CellInstance] = { inst _ NEW[CoreClasses.CellInstanceRec _ [ actual: EvalListOfBinding[Parse[rope], ct.public, internal, context].wire, type: ct]]; IF NOT CoreOps.Conform[inst.actual, ct.public] THEN ERROR; }; WireUnion: PROC [w1, w2: WireSequence] RETURNS [union: WireSequence] = { IF w1=NIL THEN RETURN [w2]; IF w2=NIL THEN RETURN [w1]; union _ NEW [Core.WireSequenceRec[w1.size+w2.size]]; FOR i: INT IN [0..w1.size) DO union[i] _ w1[i] ENDLOOP; FOR i: INT IN [0..w2.size) DO union[i+w1.size] _ w2[i] ENDLOOP; }; CreateSequenceWire: PROC [wire: Wire, n: INT] RETURNS [seq: Wire] = { comp: LIST OF Wire _ NIL; IF wire=NIL THEN wire _ CoreOps.CreateAtomWire[]; FOR i: INT IN [0..n) DO comp _ CONS [CoreOps.CopyWire[wire], comp]; ENDLOOP; seq _ CoreOps.CreateSequenceWire[components: comp]; }; CreateWires: PUBLIC PROC [context: CContext, rope: ROPE] RETURNS [wire: WireSequence] = { justAWire: Wire _ Eval[Parse[rope], NIL, context].compWire; wire _ IF CoreOps.GetWireName[justAWire]#NIL THEN CoreOps.WiresToWireSequence[LIST [justAWire]] ELSE justAWire.elements; }; FindNamedWire: PROC [name: ROPE, public: WireSequence] RETURNS [wire: Wire] = { RETURN [public[FindIndexWire[name, public]]]; }; FindIndexWire: PROC [name: ROPE, public: WireSequence] RETURNS [INT _ -1] = { FOR i: INT IN [0 .. public.size) DO IF Rope.Equal[name, NARROW [CoreProperties.GetWireProp[public[i], CoreOps.nameProp]]] THEN RETURN[i]; ENDLOOP; }; EvalListOfBinding: PROC [tree: Tree, public, internal: WireSequence, context: Context] RETURNS [wire: WireSequence] = { comp: LIST OF Wire _ NIL; refTab: RefTab.Ref _ RefTab.Create[]; IF tree#NIL THEN { WITH tree SELECT FROM node: Node => { formal, actual: Wire; IF node.name=list THEN -- list of bindings {FOR i: INT IN [1..node.sonLimit) DO [formal, actual] _ EvalActBinding[Nth[node, i], public, internal, context]; [] _ RefTab.Store[refTab, formal, actual]; ENDLOOP; } ELSE { -- single binding [formal, actual] _ EvalActBinding[tree, public, internal, context]; [] _ RefTab.Store[refTab, formal, actual];}; }; ENDCASE => ERROR}; FOR i: INT IN [0..public.size) DO subW: Wire _ public[i]; IF ~RefTab.Fetch[refTab, subW].found THEN [] _ RefTab.Store[ refTab, subW, FindNamedWire[CoreOps.GetWireName[subW], internal]]; ENDLOOP; comp _ VisitTopWire[public, refTab]; wire _ CoreOps.WiresToWireSequence[CoreOps.Reverse[comp]]; }; VisitTopWire: PROC [wire: WireSequence, refTab: RefTab.Ref] RETURNS [lw: LIST OF Wire _ NIL] = { FOR i: INT IN [0..wire.size) DO lw _ CONS[NARROW[RefTab.Fetch[refTab, wire[i]].val], lw]; ENDLOOP; }; EvalActBinding: PROC [tree: Tree, public, internal: WireSequence, context: Context] RETURNS [formal, actual: Wire] = { WITH tree SELECT FROM node: Node => { IF node.name#item THEN ERROR; -- must be an item formal:actual formal _ FindFormal[Left[node], public]; -- a public wire of small cell actual _ EvalActual[Right[node], NIL, internal, context].compWire; -- an internal of record cell }; ENDCASE => ERROR; }; EvalActual: PROC [tree: Tree, wire: Wire _ NIL, internal: WireSequence, context: Context] RETURNS [leftTree: Tree _ NIL, compWire: Wire] = { IF tree=NIL THEN RETURN[NIL, wire]; WITH tree SELECT FROM ident: PPLeaves.HTIndex => { -- find the wire with this name wire _ FindNamedWire[ident.name, internal]; RETURN[NIL, wire]}; const: PPLeaves.LTIndex => {ERROR}; -- constant? node: Node => { -- node l: Tree _ Left[node]; r: Tree _ Right[node]; SELECT node.name FROM dot => { -- field selection field: ROPE _ InterpreterOps.TreeToName[r]; compWire _ FindNamedWire[field, EvalActual[l, wire, internal, context].compWire.elements]; }; apply => { -- array indexing, subrange or record constructor IF l=NIL THEN { -- record constructor comp: LIST OF Wire _ NIL; list: Node _ NARROW[r]; -- a list IF list.name#list THEN ERROR; -- check that it is a list FOR i: INT IN [1..list.sonLimit) DO comp _ CONS[EvalActual[Nth[NARROW[list], i], NIL, internal, context].compWire, comp]; ENDLOOP; compWire _ CoreOps.CreateRecordWire[components: CoreOps.Reverse[comp]] } ELSE { WITH r SELECT FROM right: Node => { SELECT right.name FROM list => { -- subrange start, length: INT; comp: LIST OF Wire _ NIL; [start, length] _ EvalSubrange[r, context]; FOR i: INT IN [start..start+length) DO comp _ CONS[EvalActual[l, wire, internal, context].compWire.elements[i], comp]; ENDLOOP; compWire _ CoreOps.CreateRecordWire[components: CoreOps.Reverse[comp]] }; ENDCASE => { -- array indexing n: INT _ EvalToInt[r, context]; compWire _ EvalActual[l, wire, internal, context].compWire.elements[n]; }; }; right: PPLeaves.HTIndex => { SELECT right.name FROM ENDCASE => { -- array indexing n: INT _ EvalToInt[r, context]; compWire _ EvalActual[l, wire, internal, context].compWire.elements[n]; }; }; ENDCASE => ERROR }; }; ENDCASE => ERROR; }; ENDCASE => ERROR; }; FindFormal: PROC [tree: Tree, public: WireSequence] RETURNS [formal: Wire] = { WITH tree SELECT FROM ident: PPLeaves.HTIndex => {formal _ FindNamedWire[ident.name, public]}; ENDCASE => ERROR; }; Eval: PROC [tree: Tree, wire: Wire _ NIL, context: Context] RETURNS [leftTree: Tree _ NIL, compWire: Wire] = { IF tree=NIL THEN RETURN[NIL, wire]; WITH tree SELECT FROM ident: PPLeaves.HTIndex => { -- name IF wire=NIL THEN wire _ CoreOps.CreateAtomWire[ident.name] ELSE CoreProperties.PutWireProp[wire, CoreOps.nameProp, ident.name]; RETURN [NIL, wire]}; const: PPLeaves.LTIndex => {ERROR}; -- what is a constant doing here? node: Node => { -- node l: Tree _ Left[node]; r: Tree _ Right[node]; SELECT node.name FROM apply => { [leftTree, compWire] _ Eval[l, Eval[r, wire, context].compWire, context]; RETURN[leftTree, compWire]}; list => { -- record wire comp: LIST OF Wire _ NIL; IF wire#NIL THEN ERROR; -- record has nothing on the right FOR i: INT IN [1..node.sonLimit) DO comp _ CONS[Eval[Nth[node, i], NIL, context].compWire, comp]; ENDLOOP; compWire _ CoreOps.CreateRecordWire[components: CoreOps.Reverse[comp]]; }; item => { -- sequence spec SELECT TRUE FROM Rope.Equal[InterpreterOps.TreeToName[l], "seq", FALSE] => { compWire _ CreateSequenceWire[wire, EvalToInt[r, context]]; }; Rope.Equal[InterpreterOps.TreeToName[l], "enum", FALSE] => { IF wire#NIL THEN ERROR; -- enum has nothing on the right }; ENDCASE => ERROR; }; ENDCASE => ERROR; }; ENDCASE => ERROR; }; Parse: PROC [rope: ROPE] RETURNS [parseTree: Tree] = { node: Node; IF rope=NIL THEN RETURN[NIL]; parseTree _ InterpreterOps.ParseExpr[Rope.Cat["&fake _ [", rope, "]"]]; node _ NARROW[parseTree]; node _ NARROW[Right[node]]; -- remove "&fake _ " RETURN[Right[node]]; -- remove "[ ]" }; Left: PROC [node: Node] RETURNS [Tree] = {RETURN[node[1]]}; Right: PROC [node: Node] RETURNS [Tree] = {RETURN[node[2]]}; Nth: PROC [node: Node, i: INT] RETURNS [Tree] = { IF i IN [1..node.sonLimit) THEN RETURN[node.son[i]] ELSE RETURN[NIL]}; EvalToInt: PROC [parseTree: Tree, context: Context] RETURNS [n: INT] = TRUSTED { tv: AMTypes.TV _ InterpreterOps.Eval[ head: InterpreterOps.NewEvalHead[ context: AMModel.RootContext[], specials: context.tab], -- put the symbol table from the context here tree: parseTree]; n _ AMBridge.TVToLI[tv]; }; EvalSubrange: PROC [tree: Tree, context: Context] RETURNS [start, length: INT] = { start _ EvalAndCheck[Left[NARROW[tree]], "start", context]; length _ EvalAndCheck[Right[NARROW[tree]], "len", context]; }; EvalAndCheck: PROC [tree: Tree, rope: ROPE, context: Context] RETURNS [n: INT] = { IF ~Rope.Equal[InterpreterOps.TreeToName[Left[NARROW[tree]]], rope, FALSE] THEN ERROR; n _ EvalToInt[Right[NARROW[tree]], context]; }; propTable: RefTab.Ref _ RefTab.Create[]; structProcTable: SymTab.Ref _ SymTab.Create[]; END. δCoreComposeImpl.mesa Copyright c 1985 by Xerox Corporation. All rights reserved. Louis Monier October 29, 1985 7:26:55 pm PST Barth, November 5, 1985 2:16:33 pm PST Bertrand Serlet November 12, 1985 1:58:49 pm PST Context -- The properties are older as we move towards the end of the list -- and this is how the scoping mechanism works IF ~ok THEN ERROR; -- double registration? Cells Instances -- Light-weight instances (with binding specified through a rope) to CoreClasses instances -- preserve the ordering of instances -- rope is a list of bindings "a:x, b:M[3].b, c: T[16,8]" Wires w1.elements#NIL and w2.elements#NIL -- Return a public or internal wire -- top level only Parser and Evaluators -- Evaluator for Actual Wires -- The tree is of type list, unless there is only one binding, . . . -- Parse a list of "formal:actual", check that formal is in ct.public, return actual -- Completes by implicit binding (same names) -- now implicit binding Added by BS November 9, 1985 11:17:16 pm PST, SANS RIEN Y BITER list => { -- subrange start, length: INT; comp: LIST OF Wire _ NIL; [start, length] _ EvalSubrange[r, context]; FOR i: INT IN [start..start+length) DO comp _ CONS[EvalActual[l, wire, internal, context].compWire.elements[i], comp]; ENDLOOP; compWire _ CoreOps.CreateRecordWire[components: CoreOps.Reverse[comp]] }; -- Evaluator for Public and Internal Wires }; -- Parser and tree browsing primitives -- Given a rope, return the parse tree rooted as a list, or NIL if rope=NIL ΚΆ– "cedar" style˜codešœ™Kšœ Οmœ1™Kšžœžœžœ˜KšžœžœV˜cKšžœ9˜=Kšœ˜—šŸ œž œžœ˜;Kšœ'˜'Kšœ'˜'šžœžœ ˜9Kšœ˜Kšžœ˜—Kšœ˜—K˜š Ÿœž œžœžœžœ˜WKšœžœžœ˜3Kšœžœ. ˜FKšžœžœžœ ™*Kšžœ˜K™—šŸœž œžœžœ˜WKšœžœ žœ˜+Kšœ3˜3Kšžœžœžœ -˜DKšœžœžœ˜'Kšœ˜Kšœ˜Kšœ˜K˜—K˜š Ÿ œž œžœžœžœ˜9Kšžœ-˜3K˜——™šŸœž œžœžœ%žœ žœžœ˜šœ$˜$Kšœ ˜ Kšœ˜Kšœ˜—Kšœ/˜/K˜—šŸœžœžœžœžœžœžœžœ˜ˆKšœ žœžœ˜Kšœ ˜ Kšœ'˜'šžœžœžœ˜Kšœ˜šžœžœž˜šœ ˜1Kšœ žœ&˜3šœ$˜$Kšœ2˜2—Kšœ˜—šœ˜Kšœ˜Kšœ žœ&˜3š žœžœžœžœ &˜>šœ$˜$Kšœ+˜+Kšœ˜—Kšžœ˜—Kšœ˜—Kšžœž˜—Kšœ˜—Kšžœ žœ&˜9Kšœ˜Kšœ˜Kšœ:˜:K˜—šŸœžœžœžœ5žœžœžœ˜΄Kšœ9˜9šœ&žœ"˜LKšœ˜Kšœ>˜>—šœ"˜"Kšœ#˜#Kšœ˜Kšœ˜Kšœ ˜ Kšœ˜—K˜——™ KšœZ™ZšŸœžœAžœ,žœ˜”Kšœžœ˜K™%Kš žœ!žœžœžœ žœžœ˜\šžœ#žœžœž˜4Kšœ žœ;žœ ˜WKšžœ˜—K˜—Kšœ9™9šŸœžœžœ:žœ%˜€šœžœ ˜*KšœV˜V—Kšžœžœ)žœžœ˜:Kšœ˜——™Kšœ žœž™#šŸ œžœžœ˜HKšžœžœžœžœ˜Kšžœžœžœžœ˜Kšœžœ(˜4Kš žœžœžœžœžœ˜8Kš žœžœžœžœžœ˜@K˜—K˜šŸœžœžœžœ˜EKšœžœžœžœ˜Kšžœžœžœ!˜1Kš žœžœžœžœžœ žœ˜LKšœ3˜3K˜—K™K™#š Ÿ œžœžœžœžœ˜YKšœ$žœ˜;Kš œžœ žœžœžœžœ˜xK˜—K™šŸ œžœžœžœ˜OKšžœ&˜-Kšœ˜—š Ÿ œžœžœžœžœ ˜Mšžœžœžœž˜#Kšžœžœ<žœžœ˜eKšžœ˜—K˜—K˜—™KšœΟl™K™DKšœT™TKšœ-™-šŸœžœ@žœ˜wKšœžœžœžœ˜Kšœ%˜%šžœžœžœ˜šžœžœž˜šœ˜Kšœ˜šžœžœ ˜+šœžœžœžœž˜$KšœK˜KKšœ*˜*Kšžœ˜—K˜—šžœ ˜KšœC˜CKšœ,˜,—Kšœ˜—Kšžœžœ˜——K™šžœžœžœž˜!Kšœ˜šžœ#žœ˜