DIRECTORY Arrays USING[ArrayIndirectNodeInfo, ArrayTypeProcs], CCTypes USING[AsIndexSet, BinaryTargetTypes, BreakPrintType, CCError, CCErrorCase, CCTypeProcs, CheckConformance, CheckFamilyInclusion, CoerceToType, ConformanceCheck, ContainsVariance, CreateCedarType, GetIndirectType, GetNElements, GetProcDataFromGroundType, GetRTargetType, LR, GetGroundTypeClass, sia], CirioSyntacticOperations USING[CompileForRHS, ParseTree], CirioTypes USING[CompilerContext, Mem, Node, Type, TypedCode], CedarCode USING[AMNodeConstructArrayNode, Code, CodeToDoApply, CodeToDoIndex, CodeToExtractField, ConcatCode, CreateCedarNode, ForceNodeIn, GetDataFromNode, GetTypeOfNode, LoadThroughIndirectNode, NodeAsIndex, OperationsBody, Operator, ShowNode, ShowNodeBracketed, StoreThroughIndirectNode], IO, Records USING[CreateRecordType, RecordTypeProcs], Rope, StructuredStreams; ArraysImpl: CEDAR PROGRAM IMPORTS CCTypes, CedarCode, CirioSyntacticOperations, IO, Records, Rope, StructuredStreams EXPORTS Arrays = BEGIN OPEN CSO: CirioSyntacticOperations, SS: StructuredStreams; CC: TYPE = CirioTypes.CompilerContext; Code: TYPE = CedarCode.Code; Type: TYPE = CirioTypes.Type; TypedCode: TYPE = CirioTypes.TypedCode; Mem: TYPE = CirioTypes.Mem; Node: TYPE = CirioTypes.Node; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE ฌ NIL] ฌ CCTypes.CCError; Operator: TYPE = CedarCode.Operator; ArrayTypeInfo: TYPE = REF ArrayTypeInfoBody; ArrayTypeInfoBody: TYPE = RECORD[ containsVariance: VarianceInfo, procs: REF Arrays.ArrayTypeProcs, suppliedndexSet: Type, actualIndexSet: Type, indexRecord: Type, self: Type, indirectType: Type, data: REF ANY]; VarianceInfo: TYPE = {dontKnow, deciding, yes, no}; CreateArrayType: PUBLIC PROC[indexSet: Type, procs: REF Arrays.ArrayTypeProcs, cc: CC, data: REF ANY] RETURNS[Type] = BEGIN ati: ArrayTypeInfo ฌ NEW[ArrayTypeInfoBody ฌ [dontKnow, procs, indexSet, CCTypes.AsIndexSet[indexSet, cc], NIL, NIL, NIL, data]]; type: Type ฌ ati.self ฌ CCTypes.CreateCedarType[$array, ArrayTypeCCTypeProcs, IndirectArrayCCTypeProcs, cc, ati]; ati.indexRecord ฌ Records.CreateRecordType[IndexRecordTypeProcs, cc, ati]; RETURN[type]; END; ArrayTypeCCTypeProcs: REF CCTypes.CCTypeProcs ฌ NEW[CCTypes.CCTypeProcs ฌ[ checkConformance: ArrayCCTypesCheckConformance, checkFamilyInclusion: ArrayCCTypesCheckFamilyInclusion, isASingleton: ArrayCCTypesIsASingleton, binaryOperandTypes: ArrayCCTypesBinaryOperandTypes, containsVariance: ArrayCCTypesContainsVariance, operand: ArrayCCTypesOperand, applyOperand: ArrayCCTypesApplyOperand, apply: ArrayCCTypesApply, printType: ArrayCCTypesPrintType]]; ArrayCCTypesCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN valInfo: ArrayTypeInfo ฌ NARROW[procData]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varInfo: ArrayTypeInfo => BEGIN indexCheck1: CCTypes.ConformanceCheck ฌ CCTypes.CheckConformance[varInfo.actualIndexSet, valInfo.actualIndexSet, cc]; indexCheck2: CCTypes.ConformanceCheck ฌ CCTypes.CheckConformance[valInfo.actualIndexSet, varInfo.actualIndexSet, cc]; entryCheck: CCTypes.ConformanceCheck ฌ CCTypes.CheckConformance[valInfo.procs.getEntryType[cc, valInfo.data], varInfo.procs.getEntryType[cc, varInfo.data], cc]; IF indexCheck1 = no OR indexCheck2 = no OR entryCheck = no THEN RETURN[no]; IF indexCheck1 = dontKnow OR indexCheck2 = dontKnow OR entryCheck = dontKnow THEN RETURN[dontKnow]; RETURN[yes]; END; ENDCASE => RETURN[no]; END; ArrayCCTypesCheckFamilyInclusion: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = BEGIN valInfo: ArrayTypeInfo ฌ NARROW[procData]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varInfo: ArrayTypeInfo => BEGIN IF NOT CCTypes.CheckFamilyInclusion[valInfo.actualIndexSet, varInfo.actualIndexSet, cc] THEN RETURN[FALSE]; -- NOTE we know that the actualIndexSet will be a singleton Cedar Type family, hence we need not check in the opposite direction. IF NOT CCTypes.CheckFamilyInclusion[valInfo.procs.getEntryType[cc, valInfo.data], varInfo.procs.getEntryType[cc, varInfo.data], cc] THEN RETURN[FALSE]; RETURN[TRUE]; END; ENDCASE => RETURN[FALSE]; END; ArrayCCTypesIsASingleton: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = {RETURN [ArrayCCTypesContainsVariance[type, cc, procData]=oldCrocky]}; oldCrocky: BOOL ฌ FALSE; ArrayCCTypesContainsVariance: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = BEGIN info: ArrayTypeInfo ฌ NARROW[procData]; BEGIN ENABLE UNWIND => BEGIN IF info.containsVariance = deciding THEN info.containsVariance ฌ dontKnow; END; IF info.containsVariance = deciding THEN CCE[cirioError]; -- shouldnt happen IF info.containsVariance = dontKnow THEN BEGIN info.containsVariance ฌ deciding; IF CCTypes.ContainsVariance[info.procs.getEntryType[cc, info.data], cc] THEN info.containsVariance ฌ yes ELSE info.containsVariance ฌ no; END; RETURN[info.containsVariance = yes]; END; END; ArrayCCTypesBinaryOperandTypes: PROC[op: Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.BinaryTargetTypes] = BEGIN info: ArrayTypeInfo ฌ NARROW[procData]; RETURN[[left, info.actualIndexSet]]; END; ArrayCCTypesOperand: PROC[op: Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: ArrayTypeInfo ฌ NARROW[procData]; SELECT op FROM $apply => SELECT lr FROM left => RETURN[tc]; ENDCASE => CCE[operation]; ENDCASE => CCE[operation]; END; ArrayCCTypesApplyOperand: PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: ArrayTypeInfo ฌ NARROW[procData]; tc1: TypedCode ฌ CSO.CompileForRHS[operand, info.indexRecord, cc]; tc2: TypedCode ฌ CCTypes.CoerceToType[info.indexRecord, tc1, cc]; code: Code ฌ CedarCode.ConcatCode[ tc2.code, CedarCode.CodeToExtractField["", tc2.type]]; RETURN[[code, info.actualIndexSet]]; END; ArrayCCTypesApply: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: ArrayTypeInfo ฌ NARROW[procData]; code: Code ฌ CedarCode.ConcatCode[ operator.code, CedarCode.ConcatCode[ operand.code, CedarCode.CodeToDoApply[operator.type, operand.type]]]; type: Type ฌ info.procs.getEntryType[cc, info.data]; RETURN[[code, type]]; END; ArrayCCTypesPrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] = { info: ArrayTypeInfo ฌ NARROW[procData]; to.PutRope["ARRAY"]; CCTypes.BreakPrintType[to, info.actualIndexSet, 1, printWidth, cc, " "]; to.PutRope[" OF"]; CCTypes.BreakPrintType[to, info.procs.getEntryType[cc, info.data], printDepth-1, printWidth, cc, " "]; RETURN}; IndexRecordTypeProcs: REF Records.RecordTypeProcs ฌ NEW[Records.RecordTypeProcs ฌ [ getPaint: IndexRecordGetPaint, comparePaint: IndexRecordComparePaint, nFields: IndexRecordnFields, fieldIndexToName: IndexRecordFieldIndexToName, nameToFieldIndex: IndexRecordNameToFieldIndex, fieldIndexToType: IndexRecordFieldIndexToType]]; IndexRecordGetPaint: PROC[data: REF ANY] RETURNS[REF ANY] = {RETURN[NIL]}; IndexRecordComparePaint: PROC[data: REF ANY, otherPaint: REF ANY] RETURNS[BOOLEAN] = {RETURN[otherPaint = NIL]}; IndexRecordnFields: PROC[data: REF ANY] RETURNS[INT] = {RETURN[1]}; IndexRecordFieldIndexToName: PROC[index: INT, data: REF ANY] RETURNS[Rope.ROPE] = {RETURN[IF index = 0 THEN "" ELSE CCE[operation]]}; IndexRecordNameToFieldIndex: PROC[name: Rope.ROPE, data: REF ANY] RETURNS[INT] = {RETURN[IF Rope.Equal[name, ""] THEN 0 ELSE CCE[operation]]}; IndexRecordFieldIndexToType: PROC[index: INT, cc: CC, data: REF ANY] RETURNS[CirioTypes.Type] = BEGIN info: ArrayTypeInfo ฌ NARROW[data]; RETURN[info.actualIndexSet]; END; IndirectArrayCCTypeProcs: REF CCTypes.CCTypeProcs ฌ NEW[CCTypes.CCTypeProcs ฌ[ createIndirectNode: CreateIndirectArray, getBitSize: ArrayBitSize, operand: IndirectArrayCCTypesOperand, indexOperand: ArrayCCTypesApplyOperand, -- code was identical, so used the same procedure index: IndirectArrayCCTypesIndex, printType: ArrayCCTypesPrintType]]; CreateIndirectArray: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { info: ArrayTypeInfo ฌ NARROW[procData]; RETURN info.procs.createIndirectNode[cc, info.data, indirectType, targetType, mem]}; ArrayBitSize: PROC[indirectType, targetType: Type, cc: CC, procData: REF ANY] RETURNS[CARD] ~ { info: ArrayTypeInfo ฌ NARROW[procData]; RETURN info.procs.getBitSize[indirectType, cc, info.data]}; IndirectArrayCCTypesOperand: PROC[op: Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $index => SELECT lr FROM left => RETURN[tc]; ENDCASE => CCE[operation]; $address => RETURN [tc]; ENDCASE => CCE[operation, "illegal operation"]; -- client error, illegal operation END; IndirectArrayCCTypesIndex: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: ArrayTypeInfo ฌ NARROW[procData]; code: Code ฌ CedarCode.ConcatCode[ operator.code, CedarCode.ConcatCode[ operand.code, CedarCode.CodeToDoIndex[operator.type, operand.type]]]; type: Type ฌ info.procs.getEntryType[cc, info.data]; RETURN[[code, CCTypes.GetIndirectType[type]]]; END; CreateArrayIndirectNode: PUBLIC PROC[type: Type, info: Arrays.ArrayIndirectNodeInfo] RETURNS[Node] = BEGIN RETURN[CedarCode.CreateCedarNode[ArrayIndirectOps, type, info]]; END; ArrayIndirectOps: REF CedarCode.OperationsBody ฌ NEW[CedarCode.OperationsBody ฌ[ unaryOp: ArrayIndirectUnaryOp, store: ArrayIndirectStore, load: ArrayIndirectLoad, index: ArrayIndirectIndex, show: ArrayIndirectShow ]]; ArrayIndirectUnaryOp: PROC [op: CedarCode.Operator, type: CirioTypes.Type, node: CirioTypes.Node, cc: CC] RETURNS [CirioTypes.Node] = BEGIN indirectNodeData: Arrays.ArrayIndirectNodeInfo ฌ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[indirectNodeData.getPointer[indirectNodeData.data, cc]]; END; ArrayIndirectStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = BEGIN valTypeInfo: ArrayTypeInfo ฌ NARROW[CCTypes.GetProcDataFromGroundType[valType, cc]]; valNodeData: REF ArrayData ฌ NARROW[CedarCode.GetDataFromNode[valNode]]; indirectNodeData: Arrays.ArrayIndirectNodeInfo ฌ NARROW[CedarCode.GetDataFromNode[indirectNode]]; nEntries: CARD ฌ CCTypes.GetNElements[valTypeInfo.actualIndexSet, cc]; FOR I: CARD IN [0..nEntries) DO indirectField: Node ฌ indirectNodeData.selectEntry[I, cc, indirectNodeData.data]; indirectFieldType: Type ฌ CedarCode.GetTypeOfNode[indirectField]; valField: Node ฌ valNodeData.procs.extractEntry[I, cc, valNodeData.data]; valFieldType: Type ฌ CedarCode.GetTypeOfNode[valField]; CedarCode.StoreThroughIndirectNode[valFieldType, valField, indirectFieldType, indirectField, cc]; ENDLOOP; END; ArrayIndirectLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN targetType: Type ฌ CCTypes.GetRTargetType[indirectType, cc]; data: Arrays.ArrayIndirectNodeInfo ฌ NARROW[CedarCode.GetDataFromNode[indirectNode]]; RETURN[CreateArrayNode[targetType, DeferedLoadArrayProcs, data, cc, FALSE]] END; ArrayIndirectIndex: PROC[indirectOperatorType: Type, operandType: Type, indirectOperator: Node, operand: Node, cc: CC] RETURNS[Node] = BEGIN aiData: Arrays.ArrayIndirectNodeInfo ฌ NARROW[CedarCode.GetDataFromNode[indirectOperator]]; index: CARD ฌ CedarCode.NodeAsIndex[operandType, operand, cc]; RETURN[aiData.selectEntry[index, cc, aiData.data]]; END; ArrayIndirectShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { aiData: Arrays.ArrayIndirectNodeInfo ฌ NARROW[CedarCode.GetDataFromNode[node]]; iaType: Type ฌ CedarCode.GetTypeOfNode[node]; array: Node ฌ CedarCode.LoadThroughIndirectNode[iaType, node, cc]; to.PutChar['^]; CedarCode.ShowNode[to, array, depth, width, cc]; RETURN}; DeferedLoadArrayProcs: REF ArrayNodeProcs ฌ NEW[ArrayNodeProcs ฌ[ extractEntry: DeferedLoadArrayExtractEntry]]; DeferedLoadArrayExtractEntry: PROC[index: CARD, cc: CC, data: REF ANY] RETURNS[Node] = BEGIN info: Arrays.ArrayIndirectNodeInfo ฌ NARROW[data]; indirectEntry: Node ฌ info.selectEntry[index, cc, info.data]; indirectEntryType: Type ฌ CedarCode.GetTypeOfNode[indirectEntry]; RETURN[CedarCode.LoadThroughIndirectNode[indirectEntryType, indirectEntry, cc]]; END; ArrayData: TYPE = RECORD[ type: Type, alreadyLoaded: BOOLEAN, procs: REF ArrayNodeProcs, data: REF ANY]; ArrayNodeProcs: TYPE = RECORD[ extractEntry: PROC[index: CARD, cc: CC, data: REF ANY] RETURNS[Node]]; ArrayOps: REF CedarCode.OperationsBody ฌ NEW[CedarCode.OperationsBodyฌ[ forceIn: ArrayForceIn, apply: ArrayApply, show: ArrayShow]]; CreateArrayNode: PROC[arrayType: CirioTypes.Type, procs: REF ArrayNodeProcs, data: REF ANY, cc: CC, alreadyLoaded: BOOLEAN] RETURNS[CirioTypes.Node] = BEGIN node: Node ฌ CedarCode.CreateCedarNode[ArrayOps, arrayType, NEW[ArrayData ฌ [arrayType, alreadyLoaded, procs, data]]]; RETURN[node]; END; ArrayForceIn: PROC[type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN data: REF ArrayData ฌ NARROW[CedarCode.GetDataFromNode[node]]; IF data.alreadyLoaded THEN RETURN[node] ELSE BEGIN typeInfo: ArrayTypeInfo ฌ NARROW[CCTypes.GetProcDataFromGroundType[type, cc]]; nEntries: CARD ฌ CCTypes.GetNElements[typeInfo.actualIndexSet, cc]; entries: LIST OF CirioTypes.Node ฌ NIL; FOR I: CARD DECREASING IN [0..nEntries) DO nominalEntry: CirioTypes.Node ฌ data.procs.extractEntry[I, cc, data.data]; entryType: CirioTypes.Type ฌ CedarCode.GetTypeOfNode[nominalEntry]; entry: CirioTypes.Node ฌ CedarCode.ForceNodeIn[entryType, nominalEntry, cc]; entries ฌ CONS[entry, entries]; ENDLOOP; RETURN[ConstructArrayNode[type, entries, cc]]; END; END; ArrayApply: PROC[operatorType: Type, operandType: Type, operator: Node, operand: Node, cc: CC] RETURNS[Node] = BEGIN data: REF ArrayData ฌ NARROW[CedarCode.GetDataFromNode[operator]]; typeInfo: ArrayTypeInfo ฌ NARROW[CCTypes.GetProcDataFromGroundType[operatorType, cc]]; index: CARD ฌ CedarCode.NodeAsIndex[operandType, operand, cc]; RETURN[data.procs.extractEntry[index, cc, data.data]]; END; ArrayShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { data: REF ArrayData ฌ NARROW[CedarCode.GetDataFromNode[node]]; typeInfo: ArrayTypeInfo ฌ NARROW[CCTypes.GetProcDataFromGroundType[data.type, cc]]; nEntries: CARD ฌ CCTypes.GetNElements[typeInfo.actualIndexSet, cc]; cWidth: INT ฌ width; iwidth: INT ฌ IF nEntries>1 THEN (width*2)/3 ELSE width; to.PutF1["(%g)[", [cardinal[nEntries]] ]; IF depth < 1 THEN to.PutRope["..."] ELSE FOR I: CARD IN [0..nEntries) DO entry: Node ฌ data.procs.extractEntry[I, cc, data.data]; IF I>0 THEN {to.PutChar[',]; SS.Bp[to, lookLeft, CCTypes.sia, " "]} ELSE SS.Bp[to, lookLeft, CCTypes.sia]; IF cWidth < 0 THEN {to.PutRope["..."]; EXIT} ELSE CedarCode.ShowNodeBracketed[to, entry, depth-1, iwidth, cc]; cWidth ฌ cWidth-1; ENDLOOP; to.PutChar[']]; RETURN}; ConstructArrayNode: PUBLIC PROC[arrayType: CirioTypes.Type, entries: LIST OF CirioTypes.Node, cc: CC] RETURNS[CirioTypes.Node] = BEGIN IF entries = NIL OR CCTypes.GetGroundTypeClass[CedarCode.GetTypeOfNode[entries.first], cc] # $amnode THEN BEGIN typeInfo: ArrayTypeInfo ฌ NARROW[CCTypes.GetProcDataFromGroundType[arrayType, cc]]; nEntries: CARD ฌ CCTypes.GetNElements[typeInfo.actualIndexSet, cc]; ca: ConstructedArray ฌ NEW[ConstructedArrayBody[nEntries]]; entryIndex: CARD ฌ 0; FOR ln: LIST OF CirioTypes.Node ฌ entries, ln.rest WHILE ln # NIL DO ca[entryIndex] ฌ ln.first; entryIndex ฌ entryIndex + 1; ENDLOOP; IF entryIndex # nEntries THEN CCE[operation, "not enough entries supplied"]; RETURN[CreateArrayNode[arrayType, ConstructedArrayProcs, ca, cc, TRUE]]; END ELSE BEGIN -- first entry is an amnode. We assume that they all are. We uncrate them and recompile. BUT, somehow this code should be in the Node implmentation. (See similar remarks in RecordsImpl.) RETURN[CedarCode.AMNodeConstructArrayNode[arrayType, entries, cc]]; END; END; ConstructedArray: TYPE = REF ConstructedArrayBody; ConstructedArrayBody: TYPE = RECORD[ SEQUENCE nEntries: CARDINAL OF Node]; ConstructedArrayProcs: REF ArrayNodeProcs ฌ NEW[ArrayNodeProcsฌ[ extractEntry: CAExtractEntry]]; CAExtractEntry: PROC[index: CARD, cc: CC, data: REF ANY] RETURNS[CirioTypes.Node] = BEGIN ca: ConstructedArray ฌ NARROW[data]; RETURN[ca[index]]; END; END. า ArraysImpl.mesa Copyright ำ 1990, 1992 by Xerox Corporation. All rights reserved. Sturgis, March 4, 1989 1:22:52 pm PST Last changed by Theimer on May 25, 1989 3:11:53 pm PDT Hopcroft July 26, 1989 10:41:38 am PDT Spreitze, January 9, 1992 9:52 am PST Willie-s, May 14, 1992 12:27 pm PDT Array types by the time we get here left should an array type record type for index indirect array types indirect array nodes Array Nodes Constructed Arrays there is a possibility that we did not have full information about the entires at compile time. if so, the first entry will be of class $amnode. [we never permit amnodes to appear in arrays?] this is a lousy design. There should be a more explicity decision at compile time that this is what we are going to do, and compile time should have generated a different operation. But this will do for now. this design is copied from RecordsImpl, in which one will find similar remarks. Both should be fixed at the same time ส%•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ ฯeœ7™BKšœ%™%K™6K™&K™%K™#—šฯk ˜ Kšœžœ(˜4Kšœžœˆžœ˜ฒKšœžœ˜9Kšœ žœ.˜>Kšœ žœ”˜ฃKšžœ˜Kšœžœ$˜1Kšœ˜K˜—K˜šฯn œžœž˜Kšžœ/žœ"˜ZKšžœ˜—Kš œžœžœžœžœ˜BK˜Kšžœžœ˜&Kšœžœ˜Kšœžœ˜Kšœ žœ˜'Kšœžœ˜Kšœžœ˜Kšžœžœ&žœžœ˜NKšœ žœ˜$K˜Kšœ ™ ˜Kšœžœžœ˜,šœžœžœ˜!K˜Kšœžœ˜!K˜K˜K˜K˜ K˜Kšœžœžœ˜—K˜šœžœ!˜3K˜—šŸœžœžœžœžœžœžœžœ˜uKšž˜Kš œžœSžœžœžœ ˜K˜qK˜JKšžœ˜ Kšžœ˜—K˜šŸœžœžœ˜JK˜/K˜7K˜'K˜3K˜/K˜K˜'K˜K˜#—K˜š Ÿœžœžœ žœžœžœ˜w˜Kšž˜Kšœžœ ˜*šžœ0žœž˜?˜Kšž˜K˜uK˜uK˜ Kš žœžœžœžœžœ˜KKš žœžœžœžœžœ ˜cKšžœ˜ Kšžœ˜—Kšžœžœ˜—Kšžœ˜——K˜šŸ œžœžœ žœžœžœžœ˜j˜Kšž˜Kšœžœ ˜*šžœ0žœž˜?˜Kšž˜Kš žœžœRžœžœžœฯc˜ํKš žœžœ~žœžœžœ˜—Kšžœžœ˜ Kšžœ˜—Kšžœžœžœ˜—Kšžœ˜——K˜K˜šŸœžœžœ žœžœžœžœ˜VKšœžœ?˜HKšœ žœžœ˜—K˜šŸœžœžœ žœžœžœžœ˜\Kšž˜šœžœ ˜'Kšž˜šžœžœ˜Kšž˜Kšžœ"žœ"˜JKšžœ˜—Kšžœ"žœžœ ˜Lšžœ"ž˜(Kšž˜K˜!šžœFž˜LKšœžœ˜<—Kšžœ˜—Kšžœ˜$Kšžœ˜—Kšžœ˜—˜Kšœ1™1—š Ÿœžœ&žœ žœžœžœ˜…Kšž˜Kšœžœ ˜'Kšžœ˜$Kšžœ˜—K˜šŸœžœžœžœ žœžœžœ ˜vKšž˜Kšœžœ ˜'šžœž˜˜ šžœž˜Kšœžœ˜Kšžœžœ ˜——Kšžœžœ ˜—Kšžœ˜—K˜š ŸœžœFžœ žœžœžœ ˜Kšž˜Kšœžœ ˜'Kšœžœ.˜BK˜A˜"K˜ K˜,—Kšžœ˜$Kšžœ˜—K˜š Ÿœžœ.žœ žœžœžœ ˜pKšž˜Kšœžœ ˜'˜"K˜˜K˜ K˜7——K˜4Kšžœ˜Kšžœ˜—K˜šŸœžœžœžœžœžœžœ žœžœ˜xKšœžœ ˜'K˜KšœH˜HK˜Kšœf˜fKšžœ˜——K™šœ™K™šŸœžœžœ˜SK˜K˜&K˜K˜.K˜.K˜0—K˜šŸœžœžœžœžœžœžœ˜;Kšœžœžœ˜—K˜šŸœžœžœžœžœžœžœžœ˜TKšœžœžœ˜—K˜š Ÿœžœžœžœžœžœ˜6Kšœžœ˜ —K˜šŸœžœžœžœžœžœžœ˜QKš œžœžœ žœžœžœ˜3—K˜šŸœžœ žœžœžœžœžœ˜PKš œžœžœžœžœžœ˜=—K˜šŸœžœžœžœžœžœžœ˜_Kšž˜Kšœžœ˜#Kšžœ˜Kšžœ˜—K˜—šœ™K˜šŸœžœžœ˜NKšœ(˜(K˜K˜%Kšœ( 1˜YK˜!K˜#—K˜š Ÿœžœžœ žœžœ,žœ ˜rKšœžœ ˜'KšžœN˜T—K˜šŸ œžœ%žœ žœžœžœžœ˜_Kšœžœ ˜'Kšžœ5˜;—K˜šŸœžœžœžœ žœžœžœ ˜~Kšž˜šžœž˜˜ šžœž˜Kšœžœ˜Kšžœžœ ˜——Kšœ žœ˜Kšžœžœ" "˜R—Kšžœ˜—K˜š Ÿœžœ.žœ žœžœžœ ˜xKšž˜Kšœžœ ˜'˜"K˜˜K˜ K˜7——K˜4Kšžœ(˜.Kšžœ˜——K˜Kšœ™˜šŸœžœžœ1žœ˜dKšž˜Kšžœ:˜@Kšžœ˜—K˜šŸœžœžœ˜PK˜K˜K˜K˜K˜K˜—K™šฯbœžœLžœžœ˜…Kšž˜Kšœ1žœ"˜YKšžœ9˜?Kšžœ˜—K˜šŸœžœKžœ˜hKšž˜Kšœžœ1˜TKšœ žœ žœ%˜HKšœ1žœ*˜aKšœ žœ8˜FK˜š žœŸœžœžœž˜K˜QK˜AK˜IK˜7K˜aKšžœ˜—Kšžœ˜—K˜šŸœžœ-žœžœ˜WKšž˜K˜žœ˜KKšžœ˜—K˜šŸœžœ[žœžœ˜†Kšž˜Kšœ'žœ.˜[Kšœžœ3˜>Kšžœ-˜3Kšžœ˜—K˜šŸœžœžœžœžœ žœžœ˜VKšœ'žœ"˜OK˜-K˜BK˜K˜0Kšžœ˜—K˜šŸœžœžœ˜AK˜-—K˜šŸœžœžœžœžœžœžœ˜VKšž˜Kšœ%žœ˜2K˜=K˜AKšžœJ˜PKšžœ˜——K˜šœ ™ K˜šœ žœžœ˜K˜ Kšœžœ˜Kšœžœ˜Kšœžœžœ˜—K˜šœžœžœ˜Kš œžœžœžœžœžœžœ˜F—K˜K˜šŸœžœžœ˜GK˜K˜K˜—K˜šŸœžœ$žœžœžœžœžœžœ˜–Kšž˜Kšœ<žœ7˜vKšžœ˜ Kšžœ˜—K˜šŸ œžœžœžœ˜BKšž˜Kšœžœ žœ"˜>šžœžœžœ˜'šž˜Kšž˜Kšœžœ.˜NKšœ žœ5˜CKšœ žœžœžœ˜'K˜š žœŸœžœž œžœž˜*K˜JK˜CK˜LKšœ žœ˜Kšžœ˜—K˜Kšžœ(˜.Kšžœ˜——Kšžœ˜—K˜šŸ œžœKžœžœ˜nKšž˜Kšœžœ žœ&˜BKšœžœ6˜VKšœžœ3˜>Kšžœ0˜6Kšžœ˜—K˜šŸ œžœžœžœžœ žœžœ˜NKšœžœ žœ"˜>Kšœžœ3˜SKšœ žœ5˜CKšœžœ ˜Kš œžœžœ žœ žœ˜8K˜K˜)Kšžœ žœ˜#š žœžœŸœžœžœž˜$K˜8šžœ˜Kšžœžœ$˜