DIRECTORY CCTypes USING[ApplyOperand, BinaryTargetTypes, BreakPrintType, CCError, CCErrorCase, CCTypeProcs, CheckConformance, CheckFamilyInclusion, CoerceToType, ConformanceCheck, ContainsVariance, CreateCedarType, GetGroundTypeClass, GetIndirectType, GetNilRefType, GetNodeType, GetNVariants, GetProcDataFromGroundType, GetProcDataFromType, GetRefAnyType, GetRTargetType, GetTargetTypeOfIndirect, Index, IsAnIndirect, IsASingleton, Load, LR, Operand, Operator, SelectIdField, UnaryOp], CedarCode USING[CodeToExtractField, CodeToLoadContentsOfAMNode, CodeToDoUnaryOp, CodeToLoadThroughIndirect, CodeToStoreUnpopped, ConcatCode, CreateCedarNode, ExtractFieldFromNode, ForceNodeIn, GetDataFromNode, GetTypeOfNode, LoadThroughIndirectNode, OperationsBody, SelectFieldFromNode, ShowNode, StoreThroughIndirectNode], CedarOtherPureTypes USING[CreateParseTreeNode], CirioSyntacticOperations USING[ParseTree], CirioTypes USING[BasicTypeInfo, Code, CompilerContext, Mem, Node, Type, TypedCode, TypeClass], IO, PointerTypes USING [CreatePointerType], RefTypes USING[RefNodeInfo], Rope; RefTypesImpl: CEDAR PROGRAM IMPORTS CCTypes, CedarCode, CedarOtherPureTypes, IO, PointerTypes, Rope EXPORTS RefTypes = BEGIN CC: TYPE = CirioTypes.CompilerContext; BasicTypeInfo: TYPE = CirioTypes.BasicTypeInfo; Type: TYPE = CirioTypes.Type; TypedCode: TYPE = CirioTypes.TypedCode; Code: TYPE = CirioTypes.Code; Mem: TYPE = CirioTypes.Mem; Node: TYPE = CirioTypes.Node; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE ¬ NIL] ¬ CCTypes.CCError; RefTargetTypeInfo: TYPE = REF RefTargetTypeInfoBody; RefTargetTypeInfoBody: TYPE = RECORD[ containsVarianceIsKnown: RTTCVKnown, containsVariance: BOOLEAN, self: Type, indirect: Type, bodyType: Type, -- NIL for a REF ANY target type, T for a REF T target. codeForBodyType: INT]; RTTCVKnown: TYPE = {no, deciding, yes}; CreateRefTargetType: PROC[bodyType: Type, codeForBodyType: INT, cc: CC] RETURNS[Type] = BEGIN rttInfo: RefTargetTypeInfo ¬ NEW[RefTargetTypeInfoBody¬[ no, FALSE, -- any value will do, it will be ignored NIL, NIL, bodyType, codeForBodyType]]; type: Type ¬ rttInfo.self ¬ CCTypes.CreateCedarType[$refTargetType, RefTargetTypeCCTypeProcs, IndirectRefTargetTypeCCTypeProcs, cc, rttInfo]; RETURN[type]; END; SetRefTargetTypeContainsVariance: PROC[rttInfo: RefTargetTypeInfo, cc: CC] = BEGIN SELECT rttInfo.containsVarianceIsKnown FROM no => BEGIN rttInfo.containsVarianceIsKnown ¬ deciding; rttInfo.containsVariance ¬ (rttInfo.bodyType = NIL) OR CCTypes.ContainsVariance[rttInfo.bodyType, cc]; rttInfo.containsVarianceIsKnown ¬ yes; END; deciding => CCE[cirioError]; yes => RETURN; ENDCASE => CCE[cirioError]; END; RefTargetTypeCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ checkConformance: RTTCCTypesCheckConformance, checkFamilyInclusion: RTTCCTypesCheckFamilyInclusion, isASingleton: RTTCCTypesIsASingleton, getNVariants: RTTCCTypesGetNVariants]]; RTTCCTypesCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN valInfo: RefTargetTypeInfo ¬ NARROW[procData]; IF valInfo.containsVarianceIsKnown # yes THEN SetRefTargetTypeContainsVariance[valInfo, cc]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varInfo: RefTargetTypeInfo => BEGIN IF varInfo.containsVarianceIsKnown # yes THEN SetRefTargetTypeContainsVariance[varInfo, cc]; IF varInfo.bodyType = NIL THEN RETURN[yes]; RETURN[CCTypes.CheckConformance[valInfo.bodyType, varInfo.bodyType, cc]]; END; ENDCASE => RETURN[no]; END; RTTCCTypesCheckFamilyInclusion: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = BEGIN valInfo: RefTargetTypeInfo ¬ NARROW[procData]; IF valInfo.containsVarianceIsKnown # yes THEN SetRefTargetTypeContainsVariance[valInfo, cc]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varInfo: RefTargetTypeInfo => BEGIN IF varInfo.containsVarianceIsKnown # yes THEN SetRefTargetTypeContainsVariance[varInfo, cc]; IF varInfo.bodyType = NIL THEN RETURN[TRUE]; IF valInfo.codeForBodyType # varInfo.codeForBodyType THEN RETURN[FALSE]; IF NOT CCTypes.CheckFamilyInclusion[valInfo.bodyType, varInfo.bodyType, cc] THEN CCE[cirioError, "ref target types found with equal typecodes and unequal body types"]; -- if the body type codes agree then the families should bloody well be equal. RETURN[TRUE]; END; ENDCASE => RETURN[FALSE]; END; RTTCCTypesIsASingleton: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = BEGIN valInfo: RefTargetTypeInfo ¬ NARROW[procData]; IF valInfo.bodyType = NIL THEN RETURN[FALSE]; -- RTT(ANY) RETURN[CCTypes.IsASingleton[valInfo.bodyType, cc]]; END; RTTCCTypesGetNVariants: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[INT] = BEGIN info: RefTargetTypeInfo ¬ NARROW[procData]; IF info.containsVarianceIsKnown # yes THEN SetRefTargetTypeContainsVariance[info, cc]; RETURN[CCTypes.GetNVariants[info.bodyType, cc]]; END; IndirectRefTargetTypeCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ store: IRTTCCTypesStore, load: IRTTCCTypesLoad]]; IRTTCCTypesStore: PROC[value: TypedCode, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: RefTargetTypeInfo ¬ NARROW[procData]; IF info.containsVariance THEN CCE[operation, "attempt to store into a variant record field"]; -- client error, attempt to store into a (possibly nested) variant record field or target of a REF ANY. (We shall eventually have to allow this for initialization.) BEGIN code: Code ¬ CedarCode.ConcatCode[ indirect.code, CedarCode.ConcatCode[ value.code, CedarCode.CodeToStoreUnpopped[indirect.type, value.type]]]; RETURN[[code, value.type]]; END; END; IRTTCCTypesLoad: PROC[indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code ¬ CedarCode.ConcatCode[ indirect.code, CedarCode.CodeToLoadThroughIndirect[indirect.type]]; type: Type ¬ CCTypes.GetRTargetType[indirect.type, cc]; RETURN[[code, type]]; END; RefInfo: TYPE = REF RefInfoBody; RefInfoBody: TYPE = RECORD[ made: BOOL ¬ FALSE, target: Type, -- target = NIL is used for NIL REF. bti: BasicTypeInfo]; CreateRefAnyType: PUBLIC PROC[cc: CC, bti: BasicTypeInfo] RETURNS[Type] = { nominal: Type ¬ CCTypes.GetRefAnyType[cc]; IF nominal # NIL THEN RETURN[nominal]; {refInfo: RefInfo ¬ NEW[RefInfoBody¬[TRUE, CreateRefTargetType[NIL, 0, cc], bti]]; -- the zero code here is meaningless type: Type ¬ CCTypes.CreateCedarType[$refAny, RefTypeCCTypeProcs, IndirectRefTypeCCTypeProcs, cc, refInfo]; RETURN[type]}}; CreateRefType: PUBLIC PROC[cc: CC, bti: BasicTypeInfo] RETURNS[Type] = { refInfo: RefInfo ¬ NEW[RefInfoBody¬[FALSE, NIL, bti]]; type: Type ¬ CCTypes.CreateCedarType[$ref, RefTypeCCTypeProcs, IndirectRefTypeCCTypeProcs, cc, refInfo]; RETURN[type]}; SetReferent: PUBLIC PROC [refType, clientTargetType: Type, codeForClientTargetType: INT, cc: CC] ~ { refInfo: RefInfo ~ NARROW[CCTypes.GetProcDataFromType[refType]]; IF refInfo.made THEN CCE[cirioError, "Re-SetReferent"]; refInfo.target ¬ CreateRefTargetType[clientTargetType, codeForClientTargetType, cc]; refInfo.made ¬ TRUE; RETURN}; CreateNilRefType: PUBLIC PROC[cc: CC] RETURNS[Type] = BEGIN nominal: Type ¬ CCTypes.GetNilRefType[cc]; IF nominal # NIL THEN RETURN[nominal]; BEGIN refInfo: RefInfo ¬ NEW[RefInfoBody¬[TRUE, NIL]]; type: Type ¬ CCTypes.CreateCedarType[$nilRef, NilRefTypeCCTypeProcs, IndirectNilRefTypeCCTypeProcs, cc, refInfo]; RETURN[type]; END; END; RefTypeCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ checkConformance: RefCCTypesCheckConformance, binaryOperandTypes: RefCCTypesBinaryOperandTypes, getRTargetType: RefCCTypesGetRTargetType, operand: RefCCTypesOperand, indexOperand: RefCCTypesIndexOperand, coerceToType: RefCCTypesCoerceToType, unaryOp: RefCCTypesUnaryOp, selectIdField: RefCCTypesSelectIdField, index: RefCCTypesIndex, printType: RefCCTypesPrintType]]; RefCCTypesCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN valInfo: RefInfo ¬ NARROW[procData]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varInfo: RefInfo => BEGIN IF varInfo.target = NIL THEN RETURN[no]; -- var is NIL REF, we are not. RETURN[CCTypes.CheckConformance[CCTypes.GetIndirectType[valInfo.target], CCTypes.GetIndirectType[varInfo.target], cc]]; END; ENDCASE => RETURN[no]; END; RefCCTypesBinaryOperandTypes: PROC[op: CCTypes.Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.BinaryTargetTypes] = BEGIN leftInfo: RefInfo ¬ NARROW[procData]; leftTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[leftInfo.target, cc]]; SELECT op FROM $assign => RETURN[[CCTypes.GetIndirectType[leftTargetTypeInfo.bodyType], leftTargetTypeInfo.bodyType]]; $eq, $ne, $lt, $gt, $le, $ge => RETURN [[left, left]]; ENDCASE => CCE[cirioError]; END; RefCCTypesGetRTargetType: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[Type] = BEGIN refTypeInfo: RefInfo ¬ NARROW[procData]; refTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refTypeInfo.target, cc]]; RETURN[refTargetTypeInfo.bodyType]; END; RefCCTypesOperand: PROC[op: CCTypes.Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN refTypeInfo: RefInfo ¬ NARROW[procData]; refTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refTypeInfo.target, cc]]; IF refTargetTypeInfo.bodyType = NIL THEN -- we are dealing with a REF ANY RETURN[CCTypes.CoerceToType[CCTypes.GetNodeType[cc], tc, cc]] ELSE -- we are not dealing with a REF ANY SELECT op FROM $selectId, $uparrow, $index, $leftSideuparrow => RETURN[tc]; $dot, $extractId, $apply => -- try dereferencing first BEGIN tc1: TypedCode ¬ CCTypes.UnaryOp[$uparrow, tc, cc]; RETURN[CCTypes.Operand[op, lr, tc1, cc]]; END; $eq, $ne, $lt, $gt, $le, $ge => RETURN [tc]; ENDCASE => CCE[operation]; -- client error, invalid operation END; RefCCTypesIndexOperand: PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN refTypeInfo: RefInfo ¬ NARROW[procData]; refTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refTypeInfo.target, cc]]; IF refTargetTypeInfo.bodyType = NIL THEN -- we are dealing with a REF ANY BEGIN node: Node ¬ CedarOtherPureTypes.CreateParseTreeNode[operand, cc]; code: CirioTypes.Code ¬ CedarCode.CodeToLoadContentsOfAMNode[node]; type: Type ¬ CCTypes.GetNodeType[cc]; RETURN[[code, type]]; END ELSE -- we are not dealing with a REF ANY RETURN[CCTypes.ApplyOperand[refTargetTypeInfo.bodyType, operand, cc]]; END; RefCCTypesCoerceToType: PROC[targetType: Type, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN refTypeInfo: RefInfo ¬ NARROW[procData]; refTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refTypeInfo.target, cc]]; bodyType: Type ¬ refTargetTypeInfo.bodyType; IF bodyType = NIL THEN CCE[typeConformity] ELSE BEGIN code1: Code ¬ CedarCode.ConcatCode[ tc.code, CedarCode.CodeToExtractField["&indirectToBody", tc.type]]; type1: Type ¬ CCTypes.GetIndirectType[bodyType]; RETURN[CCTypes.CoerceToType[targetType, [code1, type1], cc]]; END; END; RefCCTypesUnaryOp: PROC[op: CCTypes.Operator, arg: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN refTypeInfo: RefInfo ¬ NARROW[procData]; refTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refTypeInfo.target, cc]]; bodyType: Type ¬ refTargetTypeInfo.bodyType; code1: Code ¬ CedarCode.CodeToExtractField["&indirectToBody", arg.type]; SELECT op FROM $leftSideuparrow => BEGIN code: Code ¬ CedarCode.ConcatCode[ arg.code, code1]; type: Type ¬ CCTypes.GetIndirectType[bodyType]; RETURN[[code, type]]; END; $uparrow => BEGIN code2: Code ¬ CedarCode.CodeToLoadThroughIndirect[CCTypes.GetIndirectType[bodyType]]; code: Code ¬ CedarCode.ConcatCode[ arg.code, CedarCode.ConcatCode[ code1, code2]]; RETURN[[code, bodyType]]; END; ENDCASE => CCE[typeConformity]; -- client type error END; RefCCTypesSelectIdField: PROC[id: Rope.ROPE, fieldIndirectContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN refTypeInfo: RefInfo ¬ NARROW[procData]; refTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refTypeInfo.target, cc]]; bodyType: Type ¬ refTargetTypeInfo.bodyType; code1: Code ¬ CedarCode.CodeToExtractField["&indirectToBody", fieldIndirectContext]; type1: Type ¬ CCTypes.GetIndirectType[bodyType]; tc2: TypedCode ¬ CCTypes.SelectIdField[id, type1, cc]; code: Code ¬ CedarCode.ConcatCode[code1, tc2.code]; RETURN[[code, tc2.type]]; END; RefCCTypesIndex: PROC[operator: TypedCode, operand: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN refTypeInfo: RefInfo ¬ NARROW[procData]; refTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refTypeInfo.target, cc]]; bodyType: Type ¬ refTargetTypeInfo.bodyType; code1: Code ¬ CedarCode.ConcatCode[ operator.code, CedarCode.CodeToExtractField["&indirectToBody", operator.type]]; type1: Type ¬ CCTypes.GetIndirectType[bodyType]; tc1: TypedCode ¬ [code1, type1]; RETURN[CCTypes.Index[tc1, operand, cc]]; END; RefCCTypesPrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] = { refTypeInfo: RefInfo ¬ NARROW[procData]; refTargetTypeInfo: RefTargetTypeInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refTypeInfo.target, cc]]; bodyType: Type ¬ refTargetTypeInfo.bodyType; refTypeClass: CirioTypes.TypeClass ¬ CCTypes.GetGroundTypeClass[type, cc]; IF refTypeClass = $refAny THEN to.PutRope["REF ANY"] ELSE { to.PutRope["REF"]; CCTypes.BreakPrintType[to, bodyType, printDepth-1, printWidth, cc, " "]; }; }; NilRefTypeCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ checkConformance: NilRefCCTypesCheckConformance]]; NilRefCCTypesCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN valInfo: RefInfo ¬ NARROW[procData]; WITH CCTypes.GetProcDataFromGroundType[varType, cc] SELECT FROM varInfo: RefInfo => RETURN[yes]; -- NIL REF conforms to all REF types. ENDCASE => RETURN[no]; END; IndirectRefTypeCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ createIndirectNode: RefCreateIndirect, getBitSize: RefBitSize, operand: IRefCCTypesOperand, unaryOp: IRefCCTypesUnaryOp, store: IRefCCTypesStore, load: IRefCCTypesLoad, printType: RefCCTypesPrintType]]; IndirectNilRefTypeCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ store: INilRefCCTypesStore, load: INilRefCCTypesLoad]]; RefCreateIndirect: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { refInfo: RefInfo ¬ NARROW[procData]; IF refInfo.bti=NIL THEN CCE[cirioError, "CreateIndirect[bti-less Type]"]; RETURN refInfo.bti.createIndirectNode[refInfo.bti, cc, indirectType, targetType, mem]}; RefBitSize: PROC[indirectType, targetType: Type, cc: CC, procData: REF ANY] RETURNS[CARD] ~ { refInfo: RefInfo ¬ NARROW[procData]; IF refInfo.bti=NIL THEN CCE[cirioError, "GetBitSize[bti-less Type]"]; RETURN refInfo.bti.getBitSize[refInfo.bti, cc, indirectType, targetType]}; IRefCCTypesOperand: PROC[op: CCTypes.Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $selectId, $index, $leftSideuparrow => -- try dereferencing first BEGIN tc1: TypedCode ¬ CCTypes.Load[tc, cc]; RETURN[CCTypes.Operand[op, lr, tc1, cc]]; END; $address => RETURN[tc]; ENDCASE => CCE[operation]; -- client error, invalid operation END; IRefCCTypesUnaryOp: PROC[op: CCTypes.Operator, arg: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $address => BEGIN code: CirioTypes.Code ¬ CedarCode.ConcatCode[ arg.code, CedarCode.CodeToDoUnaryOp[op, arg.type]]; ptrType: Type ¬ PointerTypes.CreatePointerType[CCTypes.GetTargetTypeOfIndirect[arg.type], cc, NIL--same reasons as always (see default)--]; RETURN [[code, ptrType]]; END; ENDCASE => CCE[cirioError]; END; IRefCCTypesStore: PROC[value: TypedCode, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code ¬ CedarCode.ConcatCode[ indirect.code, CedarCode.ConcatCode[ value.code, CedarCode.CodeToStoreUnpopped[indirect.type, value.type]]]; RETURN[[code, value.type]]; END; IRefCCTypesLoad: PROC[indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code ¬ CedarCode.ConcatCode[ indirect.code, CedarCode.CodeToLoadThroughIndirect[indirect.type]]; type: Type ¬ CCTypes.GetRTargetType[indirect.type, cc]; RETURN[[code, type]]; END; INilRefCCTypesStore: PROC[value: TypedCode, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code ¬ CedarCode.ConcatCode[ indirect.code, CedarCode.ConcatCode[ value.code, CedarCode.CodeToStoreUnpopped[indirect.type, value.type]]]; RETURN[[code, value.type]]; END; INilRefCCTypesLoad: PROC[indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code ¬ CedarCode.ConcatCode[ indirect.code, CedarCode.CodeToLoadThroughIndirect[indirect.type]]; type: Type ¬ CCTypes.GetRTargetType[indirect.type, cc]; RETURN[[code, type]]; END; RefNodeData: TYPE = RECORD[ indirectToRefTarget: Node, info: RefTypes.RefNodeInfo]; CreateRefNode: PUBLIC PROC[type: Type, info: RefTypes.RefNodeInfo, cc: CC] RETURNS[Node] = { IF NOT CCTypes.IsAnIndirect[CedarCode.GetTypeOfNode[info.indirectToClientTarget], cc] THEN CCE[cirioError, "RefTypesImpl.CreateRefNode given a non-indirect target node"]; {indirectToRefTarget: Node ¬ CreateIndirectRefTargetNode[info.clientTargetType, info.codeForClientTargetType, info.indirectToClientTarget, cc]; actualRefType: Type ¬ CreateRefType[cc, NIL--MJS, May 22, 1991: Hypothesis: this is OK 'case it'll never be needed--]; data: REF RefNodeData ¬ NEW[RefNodeData¬[indirectToRefTarget, info]]; SetReferent[actualRefType, info.clientTargetType, info.codeForClientTargetType, cc]; RETURN[CedarCode.CreateCedarNode[RefNodeOps, actualRefType, data]]; }}; CreateNilRefNode: PUBLIC PROC[cc: CC] RETURNS[Node] = {RETURN[CedarCode.CreateCedarNode[NilRefNodeOps, CreateNilRefType[cc], NIL]]}; RefNodeOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ getCurrentType: RefNodeGetCurrentType, extractField: RefNodeExtractField, show: RefNodeShow, getNodeRepresentation: RefNodeGetRepresentation]]; RefNodeGetCurrentType: PROC[node: Node, cc: CC] RETURNS[Type] = {RETURN[CedarCode.GetTypeOfNode[node]]}; RefNodeExtractField: PROC[id: Rope.ROPE, type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN data: REF RefNodeData ¬ NARROW[CedarCode.GetDataFromNode[node]]; SELECT TRUE FROM Rope.Equal[id, "&indirectToBody"] => BEGIN RETURN[CedarCode.SelectFieldFromNode["&body", CedarCode.GetTypeOfNode[data.indirectToRefTarget], data.indirectToRefTarget, cc]]; END; ENDCASE => CCE[cirioError]; -- shouldn't happen END; RefNodeShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { data: REF RefNodeData ¬ NARROW[CedarCode.GetDataFromNode[node]]; refType: Type ¬ CedarCode.GetTypeOfNode[node]; refTypeInfo: RefInfo ¬ NARROW[CCTypes.GetProcDataFromGroundType[refType, cc]]; target: Node ¬ CedarCode.LoadThroughIndirectNode[CCTypes.GetIndirectType[refTypeInfo.target], data.indirectToRefTarget, cc]; to.PutChar['^]; CedarCode.ShowNode[to, target, depth, width, cc]; RETURN}; RefNodeGetRepresentation: PROC[node: Node, cc: CC] RETURNS[REF ANY] = BEGIN data: REF RefNodeData ¬ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[data.info]; END; NilRefNodeOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ getCurrentType: NilRefNodeGetCurrentType, extractField: NilRefNodeExtractField, show: NilRefNodeShow, getNodeRepresentation: NilRefNodeGetRepresentation]]; NilRefNodeGetCurrentType: PROC[node: Node, cc: CC] RETURNS[Type] = {CCE[cirioError]}; NilRefNodeExtractField: PROC[id: Rope.ROPE, type: Type, node: Node, cc: CC] RETURNS[Node] = {CCE[operation, "NIL fault"]}; NilRefNodeShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = {to.PutRope["NIL"]}; NilRefNodeGetRepresentation: PROC[node: Node, cc: CC] RETURNS[REF ANY] = {RETURN[NIL]}; IRefTargetData: TYPE = RECORD[ bodyType: Type, indirectToBody: Node]; CreateIndirectRefTargetNode: PROC[bodyType: Type, codeForBodyType: INT, indirectToBody: Node, cc: CC] RETURNS[Node] = BEGIN irtData: REF IRefTargetData ¬ NEW[IRefTargetData¬[bodyType, indirectToBody]]; refTargetType: Type ¬ CreateRefTargetType[bodyType, codeForBodyType, cc]; node: Node ¬ CedarCode.CreateCedarNode[IndirectRTOps, CCTypes.GetIndirectType[refTargetType], irtData]; RETURN[node]; END; IndirectRTOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ getCurrentType: IndirectRTGetCurrentType, store: IndirectRTStore, load: IndirectRTLoad, selectField: IndirectRTSelectField, show: IndirectRTShow]]; IndirectRTGetCurrentType: PROC[node: Node, cc: CC] RETURNS[Type] = BEGIN irtData: REF IRefTargetData ¬ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[CCTypes.GetIndirectType[irtData.bodyType]]; END; IndirectRTStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = BEGIN indirectData: REF IRefTargetData ¬ NARROW[CedarCode.GetDataFromNode[indirectNode]]; indirectBody: Node ¬ CedarCode.SelectFieldFromNode["&body", indirectType, indirectNode, cc]; indirectBodyType: Type ¬ CedarCode.GetTypeOfNode[indirectBody]; valBody: Node ¬ CedarCode.ExtractFieldFromNode["&body", valType, valNode, cc]; valBodyType: Type ¬ CedarCode.GetTypeOfNode[valBody]; CedarCode.StoreThroughIndirectNode[valBodyType, valBody, indirectBodyType, indirectBody, cc]; END; IndirectRTLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN -- note: indirectType is compile time, and does not know the actual type. valType: Type ¬ CCTypes.GetRTargetType[CedarCode.GetTypeOfNode[indirectNode], cc]; data: REF IRefTargetData ¬ NARROW[CedarCode.GetDataFromNode[indirectNode]]; RETURN[CreateRTNode[valType, DelayedLoadExtractBody, data, cc, FALSE]]; END; IndirectRTSelectField: PROC[id: Rope.ROPE, indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN data: REF IRefTargetData ¬ NARROW[CedarCode.GetDataFromNode[indirectNode]]; SELECT TRUE FROM Rope.Equal[id, "&body"] => RETURN[data.indirectToBody]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; IndirectRTShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { to.PutChar['^]; IF depth = 0 THEN {to.PutRope["..."]; RETURN}; { irtType: Type ¬ CedarCode.GetTypeOfNode[node]; rt: Node ¬ CedarCode.LoadThroughIndirectNode[irtType, node, cc]; CedarCode.ShowNode[to, rt, depth, width, cc]; RETURN}}; DelayedLoadExtractBody: PROC[procData: REF ANY, cc: CC] RETURNS[Node] = BEGIN data: REF IRefTargetData ¬ NARROW[procData]; indirectBody: Node ¬ data.indirectToBody; indirectBodyType: Type ¬ CedarCode.GetTypeOfNode[indirectBody]; RETURN[CedarCode.LoadThroughIndirectNode[indirectBodyType, indirectBody, cc]]; END; RTData: TYPE = RECORD[ type: Type, alreadyIn: BOOLEAN, extractBody: PROC[procData: REF ANY, cc: CC] RETURNS[Node], procData: REF ANY]; CreateRTNode: PROC[type: Type, extractBody: PROC[procData: REF ANY, cc: CC] RETURNS[Node], procData: REF ANY, cc: CC, alreadyIn: BOOLEAN] RETURNS[Node] = BEGIN rtData: REF RTData ¬ NEW[RTData¬[type, alreadyIn, extractBody, procData]]; node: Node ¬ CedarCode.CreateCedarNode[RTOps, type, rtData]; RETURN[node]; END; RTOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ forceIn: RTForceIn, extractField: RTExtractField, show: RTShow]]; RTForceIn: PROC[type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN rtData: REF RTData ¬ NARROW[CedarCode.GetDataFromNode[node]]; IF rtData.alreadyIn THEN RETURN[node] ELSE BEGIN nominalBody: Node ¬ rtData.extractBody[rtData.procData, cc]; bodyType: Type ¬ CedarCode.GetTypeOfNode[nominalBody]; body: Node ¬ CedarCode.ForceNodeIn[bodyType, nominalBody, cc]; RETURN[ConstructRTNode[type, body, cc]]; END; END; RTExtractField: PROC[id: Rope.ROPE, type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN rtData: REF RTData ¬ NARROW[CedarCode.GetDataFromNode[node]]; SELECT TRUE FROM Rope.Equal[id, "&body"] => RETURN[rtData.extractBody[rtData.procData, cc]]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; RTShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { rtData: REF RTData ¬ NARROW[CedarCode.GetDataFromNode[node]]; body: Node ¬ rtData.extractBody[rtData.procData, cc]; CedarCode.ShowNode[to, body, depth, width, cc]}; CRTNodeData: TYPE = RECORD[ body: Node]; ConstructRTNode: PROC[type: Type, body: Node, cc: CC] RETURNS[Node] = BEGIN data: REF CRTNodeData ¬ NEW[CRTNodeData¬[body]]; RETURN[CreateRTNode[type, CRTNodeExtractBody, data, cc, TRUE]]; END; CRTNodeExtractBody: PROC[procData: REF ANY, cc: CC] RETURNS[Node] = BEGIN data: REF CRTNodeData ¬ NARROW[procData]; RETURN[NARROW[data.body]]; END; END.. 'î RefTypesImpl.mesa Copyright Ó 1990, 1992 by Xerox Corporation. All rights reserved. Sturgis, September 5, 1989 9:42:59 am PDT Last changed by Theimer on June 1, 1989 3:19:17 pm PDT Hopcroft July 26, 1989 10:41:56 am PDT Last tweaked by Mike Spreitzer on January 9, 1992 11:09 am PST Sturgis: November 28, 1988 11:10:39 am PST REF types present several problems because such constructors as REF VariantRecord do not produce the types that one would initially expect. We offer a brief discourse on how the following types work: VariantRecord ANY Sequence REF VariantRecord REF ANY REF Sequence REF REF VariantRecord REF REF ANY REF REF Sequence In this list of constructors, we use VariantRecord as shorthand for any record type expression containing a variant record construction, and we use Sequence as shorthand for any record type expression containing a SEQUENCE. Let VR stand for any of the type expressions: ANY, Sequence, and VariantRecord. VR denotes the obvious union type. (Let this type be T, a collection of types t B T.) REF VR denotes a union type, {Indirect TO RECORD[typeIndex: TypeIndex, body: t] | t B T}, with the constraint that if @[i, b] B REF VR, then i is an index for the type of b. Note that REF VR does not denote an Indirect To Union type, but rather a union of Indirect types. (I use Indirect as an unloaded word for pointer.) REF REF VR denotes an indirect type, specifically, an indirect to a union type: Indirect To {Indirect TO RECORD[typeIndex: TypeIndex, body: t] | t B T}. We can load through a REF VR. The result is that some record belonging to VR is (virtually) placed on the stack. This is implemented by the load through indirect code in the VariantRecordsImpl module. We cannot store through a REF VR. (Because REF VR is a union type, and the store would have to be type safe for all possible elements of REF VR. The actual Cedar compiler treats this a unsafe.) (It is possible to initialize the target of a REF VR, this is in effect a store through the Indirect TO VR, i.e., an indirect to a union type.) If we perform a field selection on a REF VR, there are three possibilities: 1) all components of the union have target types which accept the field selection using the same implementation, 2) some, but not all, of the targets of components of the union accept the field selection (or perhaps all accept the field selection, but with differing implementations), and 3) none of the targets of components of the union accept the field selection In case 1 we emit the field selection operation. In cases 2 and 3 a Cedar compiler would report a type error. We report a type error in case 3, while in case 2 we bundle the value into a Node, and let the run time figure out what to do. Further, in case 1, sometimes the resulting type is a union and sometimes not. If the selected field includes the variable part of the record constructor VR, then the resulting type is an appropriate union of indirect types. If the selected field does not include the variable part of the record constructor, then we get an indirect type. Finally, a REF REF VR is an indirect to a union type, not a union of indirects. We define the following four type families: RefTargets This is a collection of types. A union type (the target of a REF ANY), together with various levels of discrimination. This first level of discrimination will be a type. Subsequent levels depend on the first level type. If the first level type is a variant record, then subsequent levels are those appropriate to the variant record. IndirectRefTargets These are indirects to the various RefTargets types. Refs This is a collection of types. Each is an indirect, or union of indirects, to fully discriminated types among RefTargets. i.e., each is an indirect, or union of indirects, from among the IndirectRefTargets. Further, while REF ANY and REF VR are union types, REF REF ANY and REF REF VR are indirects to union types, rather than unions of indirects. If T is a union type, then REF T is a union of indirects if GetNVariants[T] # 0, otherwise it is an indirect to a union. [This will be modified when we add Sequence types, which have not been added as of December 15, 1988 9:30:16 am PST.] There are three classes of Ref types: REF ANY, REF T, and NIL REF. See comments in RefTypes.mesa. The REF ANY class is implemented as a REF T class, where T is the REF ANY Target type. IndirectRefs These are vanilla indirects to Ref types. The target type is sometimes a union, depending on the Ref. We begin with RefTargets We could proceed as we do in the VariantRecords module: define a Struct record that describes the whole family of types, then define an Info record that describes a specific type in the family. However, there is only one family, hence there is no need for a Struct. Further, we need not keep around the list of modifiers (such as we do in VariantRecords.VRInfo) because they will be embedded in the specific target type. We choose not to keep an array of the possible variants, but build them on demand. WARNING: At some point we have to add the code to (1) treat REF ANY TARGET as a value to be bundled up into a node whenever any operation approaches, and (2) be prepared to try field references through an intermediate node. These should follow from the default coercion mechanisms invoked by Operand etc. We avoid setting containsVariance at creation. Otherwise the following nasty loop occurs: someone asks if rcd type R contains variance. That question results in asking that question for each field, and in particular, creating each field type. Suppose one of these field types is REF R. Then we end up creating REF R, hence creating a RefTargetType for R. If we ask about the variance for R during that operation, we have a cycle. But we must ask about the variance for R in order to set the containsVariance field. This will blow up for a REF ANY, what should we do? What should be the correct anwer? Better yet, how can we prevent anyone from calling this? We continue with Indirect Ref Targets Warning: At some point I have to come to grips with both the coerce mechansim (that inserts needed default dereferences and unbracketing), and the node mechanism (that packages everything up into nodes for run time examination (when we are presented with a ref any target type). That is, if an operation can be applied to the target type, then we must generate code to get us to a value of that targt type. Further, when it might be applied to a target type, then we bundle up into nodes. The code for load and store seems to be common to a lot of types. How can we make use of this fact? so it is ok to do it It is legal to load through an indirect to a union type. What we must prevent is loading through a union of indirects, i.e., a REF type. Now we can address REF types themselves. When made is FALSE, we don't yet know what this is a REF to. The target is the RefTargetType to which the Ref implicitly points Note: ClientTarget is frequently called Body in the code in this module someone is trying to store through the REF arrange to give him an indirect to the body Someone is trying to do an assignment through a REF and needs a (tentative) target type for the compilation of the right hand side. Lets give him the client target type. True Cedar would reject this situation We package everything up into nodes and try again at run time True Cedar would reject this situation generate code to package the operand into a node. This will cause the caller to package the operator into a node and try again at run time. treat the operand the same as would be done for an ApplyOperand of the ref target type By the time we get here, we know that we do not conform So we try handing out an indirect to the body of the target This is exactly what RefCCTypesBinaryOperandTypes is expecting us to do when we are the left hand side of an assignment. we are a ref any. We can not be coerced to any reasonable type Moreover, the nominal mechanism would produce a NIL for a type at a later stage and this would be very bad. (I could fix that by not using a NIL at refTargetTypeInfo.bodyType to represent REF ANY.) So we just generate a type error. hopefully, the id will be recognized by the body The code for load and store seems to be common to a lot of types. How can we make use of this fact? note: this is identical to the code for DefaultIndirect. How might we safely take advantage of this? Nodes begin here There are four types which are candidates for node constructions. Not all are necessary here. Currently (December 15, 1988) PrincOpsFrameContextImpl provides a general mechanism for indirects to fields from which atomic loads and stores will be made. This mechanism suffices for Indirects to Refs. (Eventually, that mechanism will be moved to a more general location that is not target world specific. However, it should still be a general machanism that will cover indirects to Refs.) That leaves nodes of three varieties: Refs, indirects to RefTargets, and RefTargets. Ref nodes Note: ClientTarget is frequently refered to as Body in the code in this module. We can compute the actualRefType safely since the target of a REF can not change its type. Or, another way to say this, is that if type is for a REF ANY, then type is a union type, and the rule is that when loading a union type, we construct a node whose type is the type of the actually loaded value. since ref targets never change type, when this node was created it acquired a type that will always be good. Not sure what I should implement. A NARROW should always succeed. Not sure if there are other clients. hmm, if the rope was "&indirectToBody" maybe I should have returned a nilIndirectToClientBody, which would have rejected whatever the subsequent operation was. The interface says this returns NIL. Indirects to RefTargets GetCurrentType returns an indirect to the type of the client data in the target, as opposed to the type of the RefTarget, i.e., a pair . I am not sure what is intended here. At this writing, I am now sure when these store will be generated RefTarget nodes Constructed RTNodes Êr–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ Ïeœ7™BKšœ)™)K™6K™&K™>—K˜Kšœ*™*K˜šÏk ˜ Kšœžœ žœ-˜ÜKšœ žœ´˜ÃKšœžœ˜/Kšœžœ ˜*Kšœ žœN˜^Kšžœ˜Kšœ žœ˜'Kšœ žœ˜Kšœ˜—K˜šÏn œžœž˜Kšžœ*žœ˜GKšžœ ˜—Kšœž˜Kšžœžœ˜&Kšœžœ˜/Kšœžœ˜Kšœ žœ˜'Kšœžœ˜Kšœžœ˜Kšœžœ˜Kšžœžœ&žœžœ˜NK˜šœÉ™ÉKšœ ™ Kšœ™Kšœ™Kšœ™Kšœ™Kšœ ™ Kšœ™Kšœ ™ Kšœ™—K™Kšœ°™°K™KšœV™VKšœÃ™ÃšœO™OKšœH™H—K™KšœÊ™ÊK™KšœÔ™ÔK™Kšœÿ™ÿK™KšœO™OK™K™šœ+™+K™šœ ™ KšœÐ™Ð—K™šœ™Kšœ4™4—K™šœ™KšœÏ™Ïšœº™ºK™——šœ ™ Kšœf™f——K™šœ™™Kšœ¦™¦K™KšœR™RK™Kšœ±™±K™Kšœˆ™ˆ—K™Kšœžœžœ˜4šœžœžœ˜%K˜$Kšœžœ˜K˜ K˜KšœÏc7˜GKšœžœ˜—K˜Kšœ žœ˜'K˜š Ÿœžœ"žœžœžœ˜WKšž˜šœžœ˜8K˜Kšžœ (˜/Kšžœ˜Kšžœ˜K˜ K˜—K˜Kšžœ˜ Kšžœ˜—K˜šŸ œžœ!žœ˜LKšž˜šžœ!ž˜+˜Kšž˜K˜+Kšœ/žœžœ0˜fK˜&Kšžœ˜—Kšœ žœ ˜Kšœžœ˜Kšžœžœ ˜—Kšžœ˜—K˜šŸœžœžœ˜NK˜-K˜5K˜%K˜'—K˜š Ÿœžœžœ žœžœžœ˜wKšž˜Kšœžœ ˜.Kšžœ'žœ/˜\šžœ0žœž˜?˜Kšž˜Kšžœ'žœ/˜\Kšžœžœžœžœ˜+KšžœC˜IKšžœ˜—Kšžœžœ˜—Kšžœ˜—K˜šŸœžœžœ žœžœžœžœ˜jKšž˜Kšœžœ ˜.Kšžœ'žœ/˜\šžœ0žœž˜?˜Kšž˜Kšžœ'žœ/˜\Kš žœžœžœžœžœ˜,K˜Kšžœ3žœžœžœ˜HKš žœžœFžœžœT N˜öKšžœžœ˜ K˜Kšžœ˜—Kšžœžœžœ˜—Kšžœ˜—K˜šŸœžœžœ žœžœžœžœ˜VKšž˜Kšœžœ ˜.Kš žœžœžœžœžœ  ˜9Kšžœ-˜3Kšžœ˜—˜Kšœ™—šŸœžœžœ žœžœžœžœ˜RKšž˜Kšœžœ ˜+Kšžœ$žœ,˜VKšžœ*˜0Kšžœ˜K˜—K˜K˜—K™šœ%™%K™Kšœê™êK™šŸ œžœžœ˜VK˜K˜—˜Kšœd™d—K˜š Ÿœžœ,žœ žœžœžœ ˜mKšž˜Kšœžœ ˜+K˜Kšžœžœžœ= ¤˜‚K˜šœ™Kšž˜˜"K˜˜K˜ K˜;——Kšžœ˜Kšžœ˜—Kšžœ˜—˜Kšœ‰™‰—š Ÿœžœžœ žœžœžœ ˜ZKšž˜˜"K˜K˜4—K˜7Kšžœ˜Kšžœ˜—K˜—K˜šœ(™(K™—Kšœ žœžœ ˜ šœ žœžœ˜šœžœžœ˜K™<—Kšœ $˜2Kšœ˜KšœB™BšœG™GK™——K˜š Ÿœžœžœžœžœ ˜KK˜*Kšžœ žœžœžœ ˜&Kšœžœžœžœ $˜xK˜kKšžœ ˜—K˜š Ÿ œžœžœžœžœ ˜HKšœžœžœžœ˜6K˜hKšžœ˜—K˜š Ÿ œžœžœ<žœžœ˜dKšœžœ'˜@Kšžœžœžœ˜7K˜TKšœžœ˜Kšžœ˜—K˜š Ÿœžœžœžœžœ˜5Kšž˜K˜*šžœ žœžœžœ ˜&Kšž˜Kšœžœžœžœ˜0K˜qKšžœ˜ Kšžœ˜—Kšžœ˜—K˜šŸœžœžœ˜HK˜-K˜1K˜)K˜K˜%K˜%K˜K˜'K˜K˜!—K˜š Ÿœžœžœ žœžœžœ˜wKšž˜Kšœžœ ˜$šžœ0žœž˜?˜Kšž˜Kš žœžœžœžœ ˜GKšžœq˜wKšžœ˜—Kšžœžœ˜—Kšžœ˜—K˜š Ÿœžœ.žœ žœžœžœ˜‹Kšž˜Kšœžœ ˜%Kšœ(žœ9˜gšžœž˜˜ Kšœ*™*Kšœ+™+KšžœV˜\—Kšœ žœ˜6Kšžœžœ ˜—Kšžœ˜—K˜™Kšœ©™©—š Ÿœžœžœ žœžœžœ˜UKšž˜Kšœžœ ˜(Kšœ'žœ<˜iKšžœ˜#Kšžœ˜—K˜šŸœžœ#žœžœ žœžœžœ ˜|Kšž˜Kšœžœ ˜(Kšœ'žœ<˜išžœžœžœ  ˜IKšœ&™&Kšœ=™=Kšžœ7˜=—šžœ $˜)šžœž˜Kšœ1žœ˜<šœ ˜6Kšž˜K˜3Kšžœ#˜)Kšžœ˜—Kšœ žœ˜,Kšžœžœ  "˜=——Kšžœ˜—K˜š ŸœžœFžœ žœžœžœ ˜Kšž˜Kšœžœ ˜(Kšœ'žœ<˜išžœžœžœ  ˜IKšœ&™&KšœŒ™ŒKšž˜K˜BK˜CK˜%Kšžœ˜Kšž˜šžœ $˜)KšœV™VKšžœ@˜F——Kšžœ˜—˜Kšœ7™7šœ;™;Kšœx™x——š Ÿœžœ&žœ žœžœžœ ˜mKšž˜Kšœžœ ˜(Kšœ'žœ<˜iK˜,šžœ žœžœ˜Kšœ?™?KšœÆ™ÆKšœ!™!Kšžœ˜šž˜Kšž˜˜#K˜K˜:—K˜0Kšžœ7˜=Kšžœ˜——Kšžœ˜—K˜š Ÿœžœ+žœ žœžœžœ ˜mKšž˜Kšœžœ ˜(Kšœ'žœ<˜iK˜,K˜Hšžœž˜˜Kšž˜˜"K˜ K˜—K˜/Kšžœ˜Kšžœ˜—˜ Kšž˜K˜U˜"K˜ ˜K˜K˜——Kšžœ˜Kšžœ˜—Kšžœžœ ˜4—Kšžœ˜—K˜˜Kšœ0™0—šŸœžœ žœ"žœ žœžœžœ ˜xKšž˜Kšœžœ ˜(Kšœ'žœ<˜iK˜,K˜TK˜0K˜6K˜3Kšžœ˜Kšžœ˜—K˜š Ÿœžœ.žœ žœžœžœ ˜nKšž˜Kšœžœ ˜(Kšœ'žœ<˜iK˜,˜#K˜K˜@—K˜0K˜ Kšžœ"˜(Kšžœ˜—K˜šŸœžœžœžœžœžœžœ žœžœ˜vKšœžœ ˜(Kšœ'žœ<˜iK˜,K˜Jšžœ˜Kšžœ˜šžœ˜K˜KšœH˜HKšœ˜——K˜—K˜šŸœžœžœ˜KK˜2—K˜š Ÿœžœžœ žœžœžœ˜zKšž˜Kšœžœ ˜$šžœ0žœž˜?˜Kšžœ %˜2—Kšžœžœ˜—Kšžœ˜—K˜K˜K˜šŸœžœžœ˜PK˜&K˜K˜K˜K˜K˜K˜!—K˜šŸœžœžœ˜SK˜K˜—˜Kšœd™d—K˜š Ÿœžœžœ žœžœ,žœ ˜pKšœžœ ˜$Kšžœ žœžœžœ.˜IKšžœQ˜W—K˜šŸ œžœ%žœ žœžœžœžœ˜]Kšœžœ ˜$Kšžœ žœžœžœ*˜EKšžœD˜J—K˜šŸœžœ#žœžœ žœžœžœ ˜}Kšž˜šžœž˜šœ' ˜AKšž˜K˜&Kšžœ#˜)Kšžœ˜—Kšœ žœ˜Kšžœžœ  "˜=—Kšžœ˜—K˜˜K™e—š Ÿœžœ+žœ žœžœžœ ˜nKšž˜šžœž˜šœ ˜ Kšž˜˜-K˜ Kšœ)˜)—Kšœ^ž (œ˜‹Kšžœ˜Kšžœ˜—Kšžœžœ ˜—Kšžœ˜K˜—š Ÿœžœ,žœ žœžœžœ ˜mKšž˜˜"K˜˜K˜ K˜;——Kšžœ˜Kšžœ˜—K˜š Ÿœžœžœ žœžœžœ ˜ZKšž˜˜"K˜K˜4—K˜7Kšžœ˜Kšžœ˜—K˜š Ÿœžœ,žœ žœžœžœ ˜pKšž˜˜"K˜˜K˜ K˜;——Kšžœ˜Kšžœ˜—K˜š Ÿœžœžœ žœžœžœ ˜]Kšž˜˜"K˜K˜4—K˜7Kšžœ˜Kšžœ˜—K˜šœ™K™—˜Kšœê™êKšœT™TK˜K˜Kšœ ™ ™šœ žœžœ˜K˜K˜˜KšœO™O—Kšœ¯™¯—š Ÿ œžœžœ-žœžœ ˜\KšžœžœPžœžœL˜ªK˜Kšœ(ž Iœ˜vKšœžœžœ*˜EKšœT˜TKšžœ=˜CKšœ˜—K˜š Ÿœžœžœžœžœ˜5Kšœžœ@žœ˜NK˜K˜K˜—K˜šŸ œžœžœ˜IK˜&K˜"K˜K˜2—K˜˜Kšœl™l—šŸœžœžœžœ˜?Kšœžœ!˜(—K™K˜š Ÿœžœ žœžœžœ˜XKšž˜Kšœžœžœ"˜@šžœžœž˜˜$Kšž˜K˜Kšžœz˜€Kšžœ˜—Kšžœžœ ˜/—Kšžœ˜—K˜šŸ œžœžœžœžœ žœžœ˜PKšœžœžœ"˜@K˜.Kšœžœ1˜NK˜|K˜Kšœ1˜1Kšžœ˜—K˜š Ÿœžœžœžœžœžœ˜EKšž˜Kšœžœžœ"˜@Kšžœ ˜Kšžœ˜—K˜šŸ œžœžœ˜LK˜)K˜%K˜K˜5—K˜šŸœžœžœžœ˜Bšœžœ˜Kšœh™h——K˜š Ÿœžœ žœžœžœ˜[šœžœ˜KšœŸ™Ÿ——K˜šŸœžœžœžœžœ žœžœ˜OKšœ˜—K˜š Ÿœžœžœžœžœžœ˜Hšœžœžœ˜Kšœ$™$———K˜šœ™K˜K˜šœžœžœ˜K˜K˜—K˜š Ÿœžœ"žœžœžœ˜uKšž˜Kšœ žœžœ,˜MK˜IK˜gKšžœ˜ Kšžœ˜—K˜šŸ œžœžœ˜LK˜)K˜K˜K˜#K˜—˜KšœÀ™À—šŸœžœžœžœ˜BKšž˜Kšœ žœžœ"˜FKšžœ,˜2Kšžœ˜—˜KšœA™A—šŸœžœKžœ˜eKšž˜Kšœžœžœ*˜SK˜\K˜?K˜NK˜5K˜]Kšžœ˜—K˜šŸœžœ-žœžœ˜TKšžœ I˜PK˜RKšœžœžœ*˜KKšžœ9žœ˜GKšžœ˜—K˜š Ÿœžœ žœ.žœžœ˜jKšž˜Kšœžœžœ*˜Kšžœžœž˜Kšœžœ˜7Kšžœžœ ˜/—Kšžœ˜K˜—šŸœžœžœžœžœ žœžœ˜SK˜Kšžœ žœžœ˜.Kšœ˜K˜.K˜@Kšœ-˜-Kšžœ˜ —K˜š Ÿœžœ žœžœžœžœ˜GKšž˜Kšœžœžœ ˜,K˜)K˜?KšžœH˜NKšžœ˜——K˜šœ™K˜šœžœžœ˜K˜ Kšœ žœ˜Kš œ žœ žœžœžœžœ˜;Kšœ žœžœ˜—K˜šŸ œžœžœ žœžœžœžœžœžœžœ žœžœ˜™Kšž˜Kšœžœ žœ2˜JK˜Kšžœ"˜(Kšžœ˜——K˜Kšžœ˜—K˜š Ÿœžœ žœžœžœ˜SKšž˜Kšœžœ žœ"˜=šžœžœž˜Kšœžœ*˜KKšžœžœ ˜/—Kšžœ˜—K˜šŸœžœžœžœžœ žœžœ˜KKšœžœ žœ"˜=K˜5Kšœ0˜0—K˜K˜K˜—šœ™K˜šœ žœžœ˜K˜ —K˜šŸœžœžœžœ˜EKšž˜Kšœžœžœ˜0Kšžœ2žœ˜?Kšžœ˜—K˜š Ÿœžœ žœžœžœžœ˜CKšž˜Kšœžœžœ ˜)Kšžœžœ ˜Kšžœ˜—K˜K˜——Kšžœ˜—…—a¬¥