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.PutF["(%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 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 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 ™codešœ™K™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šœœ$˜