DIRECTORY AmpersandContext USING[MakeNodeFromNode], CedarCode USING[Code, ConcatCode, CodeToMakeAMNode, CodeToDoBinaryOp, CodeToDoUnaryOp, CodeToDoUnpopedCond, CodeToLoadContentsOfAMNode, CodeToLoadThroughIndirect, CodeToPop, CodeToStoreUnpopped, CreateCedarNode, GetDataFromNode, GetNodeRepresentation, GetTypeOfNode, NullCode, OperationsBody, Operator], CCTypes USING[BinaryTargetTypes, CCError, CCErrorCase, CCTypeProcs, ConformanceCheck, CreateCedarType, GetAnyTargetType, GetBooleanType, GetCharType, GetGroundTypeClass, GetIndirectType, GetNodeType, GetProcDataFromGroundType, GetProcDataFromType, GetRopeType, GetRTargetType, GetTypeRepresentation, GetWrongType, LoadIdVal, LR, SetBooleanType, SetCharType, sia], CedarNumericTypes USING[CreateNumericNode, CreateNumericType, GetDescriptorFromCedarNumericType, NumericDescriptor], CedarOtherPureTypes USING[EnumeratedTypeProcs, RopeInfo, TransparentNodeInfo, TransparentTypeInfo], CirioSyntacticOperations USING[ParseTree], CirioTypes USING[BasicTypeInfo, Code, CompilerContext, Mem, Node, Type, TypeClass, TypedCode, TypeIsntNil], Convert USING[RopeFromChar], IO, Rope, StructuredStreams; CedarOtherPureTypesImpl: CEDAR PROGRAM IMPORTS AmpersandContext, CCTypes, CedarCode, CedarNumericTypes, CirioTypes, Convert, IO, Rope, StructuredStreams EXPORTS CedarOtherPureTypes = BEGIN OPEN CCTypes, CedarCode, CirioTypes, SS:StructuredStreams; ROPE: TYPE ~ Rope.ROPE; CC: TYPE = CompilerContext; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE ¬ NIL] ¬ CCTypes.CCError; CreateBooleanType: PUBLIC PROC[cc: CC, bti: BasicTypeInfo] RETURNS[Type] = { nominal: Type ¬ CCTypes.GetBooleanType[cc]; IF nominal = NIL THEN CCTypes.SetBooleanType[cc, nominal ¬ CreateCedarType[$Boolean, BooleanCCTypeProcs, BooleanIndirectTypeProcs, cc, bti]]; RETURN[nominal]}; BooleanIndirectTypeProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬[ createIndirectNode: BooleanCreateIndirect, getBitSize: BooleanBitSize ]]; BooleanCCTypeProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬[ checkConformance: BooleanCheckConformance, binaryOperandTypes: BooleanBinaryOperandTypes, operand: BooleanOperand, coerceToType: BooleanCoerceToType, binaryOp: BooleanTypeBinaryOp, unaryOp: BooleanTypeUnaryOp, printType: BooleanPrintType ]]; BooleanCreateIndirect: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { bti: BasicTypeInfo ~ NARROW[procData]; RETURN bti.createIndirectNode[bti, cc, indirectType, targetType, mem]}; BooleanBitSize: PROC [indirectType, targetType: Type, cc: CC, procData: REF ANY] RETURNS [CARD] ~ { bti: BasicTypeInfo ~ NARROW[procData]; RETURN bti.getBitSize[bti, cc, indirectType, targetType]}; BooleanCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = {IF GetGroundTypeClass[varType, cc] = $Boolean THEN RETURN[yes] ELSE RETURN[no]}; BooleanBinaryOperandTypes: PROC[op: Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[BinaryTargetTypes] = BEGIN rightClass: TypeClass ¬ GetGroundTypeClass[right, cc]; SELECT rightClass FROM $Boolean => SELECT op FROM $assign => CCE[cirioError]; -- shouldn't happen ENDCASE => RETURN[[right, right]]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; BooleanOperand: PROC[op: Operator, lr: LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $plus, $minus, $div, $mult, $mod, $le, $lt, $eq, $gt, $ge, $max, $min => RETURN[[tc.code, GetWrongType[cc]]]; $and, $or, $not => RETURN[tc]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; BooleanCoerceToType: PROC[targetType: Type, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN targetClass: TypeClass ¬ GetGroundTypeClass[targetType, cc]; SELECT targetClass FROM $wrong => RETURN[[tc.code, GetWrongType[cc]]]; $amnode => RETURN[[ConcatCode[tc.code, CodeToMakeAMNode[tc.type]], GetNodeType[cc]]]; $Boolean => RETURN[tc]; ENDCASE => CCE[cirioError]; -- shouldn't happen (or can it occur due to a client type error?) END; BooleanTypeBinaryOp: PROC[op: Operator, left, right: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN -- assumes that both arguments have Boolean type code: Code ¬ SELECT op FROM $and => CodeToDoUnpopedCond[ left.code, ConcatCode[CodeToPop[1], right.code], NullCode[]], $or => CodeToDoUnpopedCond[ left.code, NullCode[], ConcatCode[CodeToPop[1], right.code]], ENDCASE => CCE[cirioError]; -- shouldn't happen RETURN[[code, left.type]]; END; BooleanTypeUnaryOp: PROC[op: Operator, arg: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN RETURN[[ConcatCode[ arg.code, CodeToDoUnaryOp[op, arg.type]], arg.type]]; END; BooleanPrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] = {to.PutRope["BOOLEAN"]}; CreateCharType: PUBLIC PROC[cc: CC, bti: BasicTypeInfo] RETURNS[Type] = { nominal: Type ¬ CCTypes.GetCharType[cc]; IF nominal = NIL THEN CCTypes.SetCharType[cc, nominal ¬ CreateCedarType[$char, CharCCTypeProcs, CharIndirectProcs, cc, bti]]; RETURN[nominal]}; CharIndirectProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬[ createIndirectNode: CharCreateIndirect, getBitSize: CharBitSize ]]; CharCCTypeProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬[ checkConformance: CharCheckConformance, binaryOperandTypes: CharBinaryOperandTypes, operand: CharOperand, binaryOp: CharTypeBinaryOp, printType: CharPrintType ]]; CharCreateIndirect: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { bti: BasicTypeInfo ~ NARROW[procData]; RETURN bti.createIndirectNode[bti, cc, indirectType, targetType, mem]}; CharBitSize: PROC [indirectType, targetType: Type, cc: CC, procData: REF ANY] RETURNS [CARD] ~ { bti: BasicTypeInfo ~ NARROW[procData]; RETURN bti.getBitSize[bti, cc, indirectType, targetType]}; CharCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = {IF GetGroundTypeClass[varType, cc] = $char THEN RETURN[yes] ELSE RETURN[no]}; CharBinaryOperandTypes: PROC[op: Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[BinaryTargetTypes] = BEGIN rightClass: TypeClass ¬ GetGroundTypeClass[right, cc]; SELECT rightClass FROM $numeric => SELECT op FROM $plus, $minus => BEGIN descriptor: REF CedarNumericTypes.NumericDescriptor ¬ CedarNumericTypes.GetDescriptorFromCedarNumericType[right, cc]; WITH descriptor SELECT FROM signed: REF signed CedarNumericTypes.NumericDescriptor => BEGIN IF signed.nBits > 16 THEN CCE[operation]; RETURN[[left, right]]; END; unsigned: REF unsigned CedarNumericTypes.NumericDescriptor => BEGIN IF unsigned.nBits > 16 THEN CCE[operation]; RETURN[[left, right]]; END; ENDCASE => CCE[operation]; END; ENDCASE => CCE[operation]; $char => SELECT op FROM $minus => RETURN[[left, right]]; ENDCASE => CCE[operation]; ENDCASE => CCE[operation]; END; CharOperand: PROC[op: Operator, lr: LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $plus => IF lr = left THEN RETURN[tc] ELSE CCE[operation]; $minus => IF lr = left OR lr = right THEN RETURN[tc] ELSE CCE[operation]; ENDCASE => CCE[operation]; END; CharTypeBinaryOp: PROC[op: Operator, left, right: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: Code ¬ ConcatCode[ left.code, ConcatCode[ right.code, CodeToDoBinaryOp[op, left.type, right.type]]]; type: Type; SELECT op FROM $plus => type ¬ left.type; $minus => BEGIN rightClass: TypeClass ¬ GetGroundTypeClass[right.type, cc]; SELECT rightClass FROM $numeric => type ¬ left.type; $char => type ¬ CedarNumericTypes.CreateNumericType[[16, signed[full[]]], cc, NIL]; ENDCASE => CCE[cirioError]; END; ENDCASE => CCE[cirioError]; RETURN[[code, type]]; END; CharPrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] = {to.PutRope["CHAR"]}; CreateUnknownType: PUBLIC PROC[cc: CC, explanation: ROPE ¬ NIL] RETURNS[Type] = {RETURN[CreateCedarType[$unknown, UnknownCCTypeProcs, IndirectUnknownCCTypeProcs, cc, explanation]]}; IndirectUnknownCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ createIndirectNode: IndirectCreate]]; UnknownCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ printType: PrintUnknownType]]; PrintUnknownType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] ~ { explanation: ROPE ~ NARROW[CCTypes.GetProcDataFromType[type]]; to.PutRope["]; RETURN}; IndirectCreate: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { explanation: ROPE ~ NARROW[procData]; RETURN CreateIndirectToAnUnknownType[targetType, explanation, cc]}; TransparentTypeInfo: TYPE ~ CedarOtherPureTypes.TransparentTypeInfo; CreateTransparentType: PUBLIC PROC[cc: CC, tti: TransparentTypeInfo] RETURNS[Type] ~ {RETURN[CreateCedarType[$transparent, TransparentCCTypeProcs, IndirectTransparentCCTypeProcs, cc, tti]]}; TransparentCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ printType: PrintTransparentType]]; IndirectTransparentCCTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ createIndirectNode: TransparentCreateIndirect, getBitSize: TransparentBitSize, load: TransparentTypeLoad, store: TransparentTypeStore, printType: PrintTransparentType]]; TransparentCreateIndirect: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { tti: TransparentTypeInfo ~ NARROW[procData]; RETURN tti.createIndirectNode[tti, cc, indirectType, targetType, mem]}; TransparentBitSize: PROC[indirectType, targetType: Type, cc: CC, procData: REF ANY] RETURNS[CARD] ~ { tti: TransparentTypeInfo ~ NARROW[procData]; RETURN[tti.bits]}; TransparentTypeLoad: PROC[indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] ~ { code: Code ¬ ConcatCode[ indirect.code, CodeToLoadThroughIndirect[indirect.type]]; type: Type ¬ GetRTargetType[indirect.type, cc]; RETURN[[code, type]]}; TransparentTypeStore: PROC[value, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] ~ { code: Code ¬ ConcatCode[ indirect.code, ConcatCode[ value.code, CodeToStoreUnpopped[indirect.type, value.type]]]; RETURN[[code, value.type]]}; PrintTransparentType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] ~ { tti: TransparentTypeInfo ~ NARROW[CCTypes.GetProcDataFromType[type]]; SELECT printDepth FROM >2 => to.PutF["", [rope[tti.intro]], [integer[tti.bits]] ]; ENDCASE => to.PutF1["<%g-bit transparent>", [integer[tti.bits]] ]}; EnumeratedTypeDescriptor: TYPE = RECORD[ nValues: INT, bottomIndex: INT, topIndex: INT, procs: REF EnumeratedTypeProcs, procsData: REF ANY]; EnumeratedTypeProcs: TYPE = CedarOtherPureTypes.EnumeratedTypeProcs; CreateEnumeratedType: PUBLIC PROC[nValues: INT, procs: REF EnumeratedTypeProcs, procsData: REF ANY, cc: CC] RETURNS[Type] = BEGIN desc: REF EnumeratedTypeDescriptor ¬ NEW[EnumeratedTypeDescriptor ¬ [nValues, 0, nValues-1, procs, procsData]]; RETURN[CCTypes.CreateCedarType[$enumerated, EnumeratedCCTypeProcs, IndirectEnumeratedCCTypeProcs, cc, desc]]; END; CreateEnumeratedSubtype: PUBLIC PROC[baseType: Type, bottomIndex, topIndex: INT, cc: CC] RETURNS[Type] = BEGIN baseDesc: REF EnumeratedTypeDescriptor ¬ NARROW[GetProcDataFromGroundType[baseType, cc]]; desc: REF EnumeratedTypeDescriptor ¬ NEW[EnumeratedTypeDescriptor ¬ [baseDesc.nValues, bottomIndex, topIndex, baseDesc.procs, baseDesc.procsData]]; IF bottomIndex < baseDesc.bottomIndex THEN CCE[cirioError]; IF topIndex > baseDesc.topIndex THEN CCE[cirioError]; RETURN[CCTypes.CreateCedarType[$enumerated, EnumeratedCCTypeProcs, NIL, cc, desc]]; END; EnumeratedCCTypeProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬ [ checkConformance: EnumeratedCheckConformance, binaryOperandTypes: EnumeratedBinaryOperandTypes, asIndexSet: EnumeratedAsIndexSet, operand: EnumeratedOperand, coerceToType: EnumeratedCoerceToType, binaryOp: EnumeratedBinaryOp, unaryOp: EnumeratedUnaryOp, loadIdVal: EnumeratedLoadIdVal, getNElements: EnumeratedGetNElements, getTypeRepresentation: EnumeratedGetTypeRepresentation, printType: EnumeratedPrintType ]]; IndirectEnumeratedCCTypeProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬ [ createIndirectNode: EnumeratedCreateIndirect, getBitSize: EnumeratedBitSize, printType: EnumeratedPrintType ]]; EnumeratedCreateIndirect: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { desc: REF EnumeratedTypeDescriptor ~ NARROW[procData]; RETURN desc.procs.createIndirectNode[desc.procsData, cc, indirectType, targetType, mem]}; EnumeratedBitSize: PROC[indirectType, targetType: Type, cc: CC, procData: REF ANY] RETURNS[CARD] ~ { desc: REF EnumeratedTypeDescriptor ~ NARROW[procData]; RETURN desc.procs.getBitSize[desc.procsData, cc, indirectType, targetType]}; EnumeratedCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN valDesc: REF EnumeratedTypeDescriptor ¬ NARROW[procData]; WITH GetProcDataFromGroundType[varType, cc] SELECT FROM varDesc: REF EnumeratedTypeDescriptor => RETURN[IF valDesc.procs.comparePaint[valDesc.procsData, varDesc.procs.getPaint[varDesc.procsData]] THEN yes ELSE no]; ENDCASE => RETURN[no]; END; EnumeratedBinaryOperandTypes: PROC[op: Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[BinaryTargetTypes] = BEGIN rightClass: TypeClass ¬ GetGroundTypeClass[right, cc]; SELECT rightClass FROM $enumerated => SELECT op FROM $assign => CCE[cirioError]; -- shouldn't happen ENDCASE => RETURN[[right, right]]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; EnumeratedAsIndexSet: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[Type] = {RETURN[type]}; EnumeratedOperand: PROC[op: Operator, lr: LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $plus, $minus, $div, $mult, $mod, $and, $or, $not => RETURN[[tc.code, GetWrongType[cc]]]; $le, $lt, $eq, $gt, $ge, $max, $min => RETURN[tc]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; EnumeratedCoerceToType: PROC[targetType: Type, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN targetClass: TypeClass ¬ GetGroundTypeClass[targetType, cc]; SELECT targetClass FROM $wrong => RETURN[[tc.code, GetWrongType[cc]]]; $amnode => RETURN[[ConcatCode[tc.code, CodeToMakeAMNode[tc.type]], GetNodeType[cc]]]; $enumerated => RETURN[tc]; ENDCASE => CCE[cirioError]; -- shouldn't happen (or can it occur due to a client type error?) END; EnumeratedBinaryOp: PROC[op: Operator, left, right: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN -- assumes that both arguments have enumerated type and that the operator is a relation code: Code ¬ CedarCode.ConcatCode[ left.code, CedarCode.ConcatCode[ right.code, CedarCode.CodeToDoBinaryOp[op, left.type, right.type]]]; RETURN[[code, CCTypes.GetBooleanType[cc]]]; END; EnumeratedUnaryOp: PROC[op: Operator, arg: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN -- such operations as succ and pred. RETURN[[ConcatCode[ arg.code, CodeToDoUnaryOp[op, arg.type]], arg.type]]; END; EnumeratedLoadIdVal: PROC[id: Rope.ROPE, targetType: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN desc: REF EnumeratedTypeDescriptor ¬ NARROW[procData]; FOR I: INT IN [desc.bottomIndex..desc.topIndex] DO IF Rope.Equal[id, desc.procs.indexToId[I, desc.procsData]] THEN BEGIN node: Node ¬ CreateEnumeratedTypeNode[targetType, id, cc]; code: CirioTypes.Code ¬ CedarCode.CodeToLoadContentsOfAMNode[node]; RETURN[[code, targetType]]; END; ENDLOOP; RETURN[CCTypes.LoadIdVal[id, targetType, cc, CCTypes.GetAnyTargetType[cc]]]; END; EnumeratedGetNElements: PROC [type: Type, cc: CC, procData: REF ANY] RETURNS [CARD] = BEGIN desc: REF EnumeratedTypeDescriptor ¬ NARROW[procData]; RETURN [desc.nValues]; END; EnumeratedGetTypeRepresentation: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[REF ANY] = BEGIN desc: REF EnumeratedTypeDescriptor ¬ NARROW[procData]; RETURN[desc.procsData]; END; EnumeratedPrintType: PROC [to: IO.STREAM, type: Type, printDepth, printWidth: INT, cc: CC, procData: REF ANY] = { desc: REF EnumeratedTypeDescriptor ¬ NARROW[procData]; to.PutChar['{]; FOR i: INT IN [0 .. desc.topIndex-desc.bottomIndex] DO IF i>0 THEN {to.PutChar[',]; SS.Bp[to, lookLeft, CCTypes.sia, " "]}; IF i>printWidth THEN {to.PutRope["..."]; EXIT}; to.PutRope[desc.procs.indexToId[desc.bottomIndex+i, desc.procsData]]; ENDLOOP; to.PutChar['}]; RETURN}; CreateRopeType: PUBLIC PROC[cc: CC, bti: BasicTypeInfo] RETURNS[Type] = BEGIN nominal: Type ¬ CCTypes.GetRopeType[cc]; IF nominal # NIL THEN RETURN[nominal]; RETURN[CreateCedarType[$rope, RopeCCTypeProcs, IndirectRopeCCTypeProcs, cc, bti]]; END; RopeCCTypeProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬[ printType: RopePrintType ]]; IndirectRopeCCTypeProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬[ createIndirectNode: RopeCreateIndirect, getBitSize: RopeBitSize, printType: RopePrintType ]]; RopeCreateIndirect: PROC [cc: CC, procData: REF ANY, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { bti: BasicTypeInfo ~ NARROW[procData]; RETURN bti.createIndirectNode[bti, cc, indirectType, targetType, mem]}; RopeBitSize: PROC[indirectType, targetType: Type, cc: CC, procData: REF ANY] RETURNS[CARD] ~ { bti: BasicTypeInfo ~ NARROW[procData]; RETURN bti.getBitSize[bti, cc, indirectType, targetType]}; RopePrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] = {to.PutRope["ROPE"]}; CreateBooleanNode: PUBLIC PROC[val: BOOLEAN, cc: CC] RETURNS[Node] = {RETURN[CreateCedarNode[BooleanOps, CCTypes.GetBooleanType[cc], NEW[BOOLEAN ¬ val]]]}; BooleanOps: REF OperationsBody ¬ NEW[OperationsBody ¬[ makeAMNode: BooleanMakeAMNode, examineBoolean: BooleanExamineBoolean, coerce: BooleanCoerce, binaryOp: BooleanBinaryOp, unaryOp: BooleanUnaryOp, show: BooleanShow, getNodeRepresentation: BooleanGetNodeRepresentation ]]; BooleanMakeAMNode: PROC[sourceType: Type, node: Node, cc: CC] RETURNS[Node] = {RETURN[AmpersandContext.MakeNodeFromNode[node, cc]]}; BooleanExamineBoolean: PROC[node: Node, cc: CC] RETURNS[BOOLEAN] = {RETURN[NARROW[CedarCode.GetDataFromNode[node], REF BOOLEAN]­]}; BooleanCoerce: PROC[sourceType, targetType: Type, node: Node, cc: CC] RETURNS[Node] = {CCE[cirioError]}; -- shouldn't happen BooleanBinaryOp: PROC[op: Operator, leftType, rightType: Type, leftNode, rightNode: Node, cc: CC] RETURNS[Node] = BEGIN -- can assume that both operands are Boolean left: REF BOOLEAN ¬ NARROW[CedarCode.GetDataFromNode[leftNode]]; right: REF BOOLEAN ¬ NARROW[CedarCode.GetDataFromNode[rightNode]]; result: BOOLEAN ¬ SELECT op FROM $and => left­ AND right­, $or => left­ OR right­, ENDCASE => CCE[cirioError]; -- shouldn't happen CCE[cirioError]; -- this code should not be called END; BooleanUnaryOp: PROC[op: Operator, type: Type, node: Node, cc: CC] RETURNS[Node] = BEGIN arg: REF BOOLEAN ¬ NARROW[CedarCode.GetDataFromNode[node]]; SELECT op FROM $not => RETURN[CreateBooleanNode[NOT arg­, cc]]; ENDCASE => CCE[cirioError]; -- shouldn't happen END; BooleanShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = {to.PutRope[IF NARROW[CedarCode.GetDataFromNode[node], REF BOOLEAN]­ THEN "TRUE" ELSE "FALSE"]}; BooleanGetNodeRepresentation: PROC[node: Node, cc: CC] RETURNS[REF ANY] = {RETURN[CedarCode.GetDataFromNode[node]]}; CreateCharNode: PUBLIC PROC[val: CHAR, cc: CC] RETURNS[Node] = {RETURN[CreateCedarNode[CharOps, CCTypes.GetCharType[cc], NEW[CHAR ¬ val]]]}; CharOps: REF OperationsBody ¬ NEW[OperationsBody ¬[ makeAMNode: CharMakeAMNode, binaryOp: CharBinaryOp, show: CharShow, getNodeRepresentation: CharGetRepresentation ]]; CharMakeAMNode: PROC[sourceType: Type, node: Node, cc: CC] RETURNS[Node] = {RETURN[AmpersandContext.MakeNodeFromNode[node, cc]]}; CharBinaryOp: PROC[op: Operator, leftType, rightType: Type, leftNode, rightNode: Node, cc: CC] RETURNS[Node] = BEGIN -- we will do the computation in INT and then convert back to char at end leftChar: REF CHAR ¬ NARROW[CedarCode.GetNodeRepresentation[leftNode, cc]]; leftVal: INT ¬ ORD[leftChar­]; rightNodeType: Type ¬ CedarCode.GetTypeOfNode[rightNode]; RightValAsNumeric: PROC RETURNS[INT] = BEGIN rightDescriptor: REF CedarNumericTypes.NumericDescriptor ¬ CedarNumericTypes.GetDescriptorFromCedarNumericType[rightNodeType, cc]; WITH rightDescriptor SELECT FROM signed: REF signed CedarNumericTypes.NumericDescriptor => BEGIN rightVal: REF INT ¬ NARROW[CedarCode.GetNodeRepresentation[rightNode, cc]]; RETURN[rightVal­]; END; unsigned: REF unsigned CedarNumericTypes.NumericDescriptor => BEGIN rightVal: REF CARD ¬ NARROW[CedarCode.GetNodeRepresentation[rightNode, cc]]; lastInt: CARD ¬ LAST[INT]; IF rightVal­ > lastInt THEN CCE[cirioError]; -- it was supposed to be a small numeric, and we are supposed to have checked that. RETURN[rightVal­]; END; ENDCASE => CCE[cirioError]; END; ModifiedChar: PROC[mod: INT] RETURNS[Node] = BEGIN newVal: INT ¬ leftVal+mod; IF newVal < 0 OR newVal > 377B THEN CCE[operation, "bounds fault"]; RETURN[CreateCharNode[VAL[INTEGER[newVal]], cc]]; END; SELECT op FROM $plus => BEGIN -- GetGroundTypeClass[rightNodeType] must be $numeric and small. rightVal: INT ¬ RightValAsNumeric[]; RETURN[ModifiedChar[rightVal]]; END; $minus => BEGIN rightClass: TypeClass ¬ GetGroundTypeClass[rightNodeType, cc]; SELECT rightClass FROM $numeric => BEGIN rightVal: INT ¬ RightValAsNumeric[]; RETURN[ModifiedChar[-rightVal]]; END; $char => BEGIN rightChar: REF CHAR ¬ NARROW[CedarCode.GetNodeRepresentation[rightNode, cc]]; rightVal: INT ¬ ORD[rightChar­]; resultVal: INT ¬ leftVal-rightVal; -- always will be inbounds resultType: Type ¬ CedarNumericTypes.CreateNumericType[[16, signed[full[]]], cc, NIL]; RETURN[CedarNumericTypes.CreateNumericNode[resultType, NEW[INT¬resultVal]]]; END; ENDCASE => CCE[cirioError]; END; ENDCASE => CCE[cirioError]; END; CharShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { val: CHAR ¬ NARROW[CedarCode.GetDataFromNode[node], REF CHAR]­; to.PutRope[Convert.RopeFromChar[val]]; }; CharGetRepresentation: PROC[node: Node, cc: CC] RETURNS[REF ANY] = {RETURN[CedarCode.GetDataFromNode[node]]}; CreateUnknownTypeNode: PUBLIC PROC[type: Type, explanation: ROPE, cc: CC] RETURNS[CirioTypes.Node] = {RETURN[CedarCode.CreateCedarNode[UnknownTypeNodeOps, type, explanation]]}; CreateIndirectToAnUnknownType: PUBLIC PROC[type: Type, explanation: ROPE, cc: CC] RETURNS[CirioTypes.Node] = {RETURN[CedarCode.CreateCedarNode[IndirectToUnknownTypeNodeOps, CCTypes.GetIndirectType[type], explanation]]}; IndirectToUnknownTypeNodeOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ load: UnknownIndirectLoad, show: UnknownShow]]; UnknownIndirectLoad: PROC[indirectType: Type, indirectNode: CirioTypes.Node, cc: CC] RETURNS[CirioTypes.Node] = BEGIN explanation: ROPE ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; RETURN[CedarCode.CreateCedarNode [UnknownTypeNodeOps, CCTypes.GetRTargetType [CedarCode.GetTypeOfNode [indirectNode], cc], Rope.Cat[""]]]; END; UnknownTypeNodeOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ show: UnknownShow]]; UnknownShow: PROC[to: IO.STREAM, node: CirioTypes.Node, depth, width: INT, cc: CC] = { explanation: ROPE ~ NARROW[CedarCode.GetDataFromNode[node]]; IF depth < 3 THEN {to.PutRope["??"]; RETURN}; to.PutRope["", [rope[explanation]] ]; RETURN}; TransparentNodeInfo: TYPE ~ CedarOtherPureTypes.TransparentNodeInfo; CreateTransparentTypeNode: PUBLIC PROC[type: Type, tni: TransparentNodeInfo, cc: CC] RETURNS[CirioTypes.Node] = { RETURN[CedarCode.CreateCedarNode[TransparentTypeNodeOps, type, tni]]}; TransparentTypeNodeOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ show: TransparentShow, getNodeRepresentation: TransparentGetNodeRepresentation]]; TransparentShow: PROC[to: IO.STREAM, node: CirioTypes.Node, depth: INT, width: INT, cc: CC] = { tni: TransparentNodeInfo ~ NARROW[CedarCode.GetDataFromNode[node]]; len: INT ~ MIN[tni.val.Length, width]; to.PutChar['<]; IF depth>2 THEN { type: Type ~ GetTypeOfNode[node]; tti: TransparentTypeInfo ~ NARROW[GetTypeRepresentation[type, cc]]; to.PutRope[tti.intro]; to.PutChar[' ]}; IF tni.lpad#0 OR tni.rpad#0 THEN to.PutF["(lpad=%g, rpad=%g) ", [integer[tni.lpad]], [integer[tni.rpad]] ]; FOR i: INT IN [0..len) DO to.PutF1["%02x", [cardinal[tni.val.Fetch[i].ORD]] ] ENDLOOP; to.PutChar['>]; RETURN}; TransparentGetNodeRepresentation: PROC[node: Node, cc: CC] RETURNS[REF ANY] ~ {RETURN CedarCode.GetDataFromNode[node]}; EnumeratedNodeInfo: TYPE = REF EnumeratedNodeInfoBody; EnumeratedNodeInfoBody: TYPE = RECORD[ type: Type, id: Rope.ROPE, index: CARD]; CreateEnumeratedTypeNode: PUBLIC PROC[type: Type, id: Rope.ROPE, cc: CC] RETURNS[CirioTypes.Node] = BEGIN desc: REF EnumeratedTypeDescriptor ¬ NARROW[GetProcDataFromGroundType[type, cc]]; index: CARD ¬ desc.procs.idToIndex[id, desc.procsData]; RETURN[CedarCode.CreateCedarNode[EnumeratedOps, type, NEW[EnumeratedNodeInfoBody ¬ [type, id, index]]]]; END; CreateEnumeratedTypeNodeFromIndex: PUBLIC PROC[type: Type, index: CARD, cc: CC] RETURNS[CirioTypes.Node] = BEGIN desc: REF EnumeratedTypeDescriptor ¬ NARROW[GetProcDataFromGroundType[type, cc]]; id: Rope.ROPE ¬ desc.procs.indexToId[index, desc.procsData]; RETURN[CedarCode.CreateCedarNode[EnumeratedOps, type, NEW[EnumeratedNodeInfoBody ¬ [type, id, index]]]]; END; EnumeratedOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody ¬[ binaryOp: EnumeratedBinaryNodeOp, asIndex: EnumeratedAsIndex, show: EnumeratedShow, getNodeRepresentation: EnumeratedGetNodeRepresentation ]]; EnumeratedBinaryNodeOp: PROC[op: Operator, leftType, rightType: Type, leftNode, rightNode: Node, cc: CC] RETURNS[Node] = BEGIN -- should only be relations linfo: EnumeratedNodeInfo ¬ NARROW[CedarCode.GetDataFromNode[leftNode]]; rinfo: EnumeratedNodeInfo ¬ NARROW[CedarCode.GetDataFromNode[rightNode]]; li: CARD ¬ linfo.index; ri: CARD ¬ rinfo.index; newBoolean: BOOLEAN ¬ SELECT op FROM $lt => li < ri, $le => li <= ri, $eq => li = ri, $ne => li # ri, $ge => li >= ri, $gt => li > ri, ENDCASE => CCE[cirioError]; RETURN[CreateBooleanNode[newBoolean, cc]]; END; EnumeratedAsIndex: PROC[type: Type, node: Node, cc: CC] RETURNS[CARD] = BEGIN info: EnumeratedNodeInfo ¬ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[info.index]; END; EnumeratedShow: PROC[to: IO.STREAM, node: CirioTypes.Node, depth: INT, width: INT, cc: CC] = { info: EnumeratedNodeInfo ¬ NARROW[CedarCode.GetDataFromNode[node]]; to.PutRope[info.id]; RETURN}; EnumeratedGetNodeRepresentation: PROC[node: Node, cc: CC] RETURNS[REF ANY] = BEGIN info: EnumeratedNodeInfo ¬ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[NEW[CARD ¬ info.index]]; END; CreateParseTreeType: PUBLIC PROC[cc: CC] RETURNS[Type] = BEGIN RETURN[CCTypes.CreateCedarType[$parseTree, ParseTreeCCTypeProcs, NIL, cc]]; END; ParseTreeCCTypeProcs: REF CCTypeProcs ¬ NEW[CCTypeProcs ¬ [ ]]; PTNData: TYPE = RECORD[tree: CirioSyntacticOperations.ParseTree]; CreateParseTreeNode: PUBLIC PROC[parseTree: CirioSyntacticOperations.ParseTree, cc: CC] RETURNS[Node] = {RETURN[CedarCode.CreateCedarNode[ParseTreeOps, CCTypes.GetNodeType[cc], NEW[PTNData ¬ [parseTree]]]]}; ParseTreeOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody ¬[ examineParseTree: ParseTreeExamineParseTree, show: ParseTreeShow ]]; ParseTreeExamineParseTree: PROC[node: Node, cc: CC] RETURNS[CirioSyntacticOperations.ParseTree] = {RETURN[NARROW[CedarCode.GetDataFromNode[node], REF PTNData].tree]}; ParseTreeShow: PROC[to: IO.STREAM, node: CirioTypes.Node, depth: INT, width: INT, cc: CC] = {to.PutRope["parseTree"]}; RopeInfo: TYPE ~ CedarOtherPureTypes.RopeInfo; CreateRopeNode: PUBLIC PROC[val: Rope.ROPE, cc: CC, addr: REF ANY ¬ NIL] RETURNS[Node] = {RETURN[CreateCedarNode[RopeOps, CCTypes.GetRopeType[cc].TypeIsntNil[cc], NEW [RopeInfo ¬ [val, addr]] ]]}; RopeOps: REF OperationsBody ¬ NEW[OperationsBody ¬[ show: RopeShow, getNodeRepresentation: RopeGetRepresentation ]]; RopeShow: PROC[to: IO.STREAM, node: Node, depth, width: INT, cc: CC] = { info: REF RopeInfo ¬ NARROW[CedarCode.GetDataFromNode[node]]; width ¬ width * 10; -- For ropes we interprete the printing width to be longer since characters have a very small width compared to other types. to.PutF["\"%q%g\"", [rope[info.val.Substr[0, width]]], [rope[IF info.val.Length[] > width THEN "..." ELSE NIL]] ]; RETURN}; RopeGetRepresentation: PROC[node: Node, cc: CC] RETURNS[REF ANY] = BEGIN info: REF RopeInfo ¬ NARROW[CedarCode.GetDataFromNode[node]]; RETURN[info]; END; END.. Ψ CedarOtherPureTypesImpl.mesa Copyright Σ 1991, 1992 by Xerox Corporation. All rights reserved. Sturgis, February 7, 1990 12:05:46 pm PST Last changed by Theimer on July 16, 1989 4:21:30 pm PDT Hopcroft July 26, 1989 10:41:50 am PDT Last tweaked by Mike Spreitzer on January 9, 1992 6:50 pm PST Laurie Horton, September 13, 1991 11:31 am PDT Willie-s, May 14, 1992 12:28 pm PDT valType was the control parameter By the time we get here, the left operand type is Boolean and both operands are suitable for the given op. Therefore, the right operand should also be Boolean or amnode $wrong, $amnode => RETURN[[right, right]]; tc.type is Boolean tc.type is Boolean Char type valType was the control parameter By the time we get here, the left operand type is Char and both operands are suitable for the given op. Therefore, the right operand should also be Char or amnode $wrong, $amnode => RETURN[[right, right]]; tc.type is Char Unknown Type We offer the following for unknown types. The idea is to permit the printing out of data structures that contain values with unknown types. That is, we should be able to manipulate the remainder of the data structure. We invent the type: UnknownType. So long as we never try to do anything significant with such a value, we should be alright. These public procedures are exported to CCTypes. Enumerated Types index belongs to [0..nValues) valType was the control parameter By the time we get here, the left operand type is enumerated and both operands are suitable for the given op. Therefore, the right operand should also be enumerated or amnode $wrong, $amnode => RETURN[[right, right]]; tc.type is Enumerated tc.type is Enumerated we look to see if the id is one of the values of the enumerated type, otherwise we fall back on the default code. I forsee trouble. The targetType might not be appropriate. I have to rethink my default mechanism. For this case, I could hide the Type in the desc, but that would create cycles. (Probably I already have cycles). the id was not an element of the enumerated type, so fall back on default mechanism. Rope Types At the moment we permit no operations. Perhaps later we want apply, so that we can do rope[10] to read the 10'th character in the rope? Does the current Cedar debuger supply that operation? Boolean Nodes THIS IS ALL WRONG. THE GENERATED CODE should do a test and avoid evaluating the second argument if the first argument determines the answer.!!!! RETURN[CreateBooleanNode[result, cc]]; Char nodes There are three possibilities: char+numeric, char-numeric, and char-char. Unknown Type Nodes, and Indirects thereto Transparent Type Nodes Enumerated Type Nodes (I suspect that we still have to implemented subrange enumerated types. If so, we will have to make some modifications here.) Parse Tree types Nodes of this type will be created when we have a node applied to a parse tree (as opposed to a procedure applied to a parse tree or an array applied to a parse tree). Parse Tree Nodes Rope Nodes Κ!0•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ Οeœ7™BKšœ)™)K™7K™&K™=K™.K™#—K˜šΟk ˜ Kšœžœ˜)Kšœ žœ ˜―Kšœžœή˜λKšœžœ]˜tKšœžœJ˜cKšœžœ ˜*Kšœ žœ[˜kKšœžœ˜Kšžœ˜Kšœ˜Kšœ˜—K˜šΟnœžœž˜&KšžœOžœ˜qKšžœ˜—Kšœžœžœ!žœ˜BK˜Kšžœžœžœ˜Kšžœžœ˜Kšžœžœ&žœžœ˜NK˜š Ÿœžœžœžœžœ ˜LK˜+šžœ žœžœ˜0K˜\—Kšžœ ˜—K˜šŸœžœžœ˜>Kšœ*˜*Kšœ˜K˜—K˜šŸœžœžœ˜8K˜*K˜.K˜K˜"K˜K˜K˜K˜—K˜š Ÿœžœžœ žœžœ,žœ ˜tKšœžœ ˜&KšžœA˜G—K˜šŸœžœ&žœ žœžœžœžœ˜cKšœžœ ˜&Kšžœ4˜:—˜Kšœ!™!—š Ÿœžœžœ žœžœžœ˜tKš œžœ,žœžœžœžœ˜Q—˜Kšœ©™©—š Ÿœžœ&žœ žœžœžœ˜xKšž˜K˜6K˜šžœ ž˜Kšœ*™*˜ šžœž˜Kšœ žœΟc˜/Kšžœžœ˜"——Kšžœžœ ˜/—Kšžœ˜K˜Kšœ™—šŸœžœžœžœ žœžœžœ ˜iKšž˜šžœž˜˜HKšžœ˜$—Kšœžœ˜Kšžœžœ ˜/—Kšžœ˜K˜Kšœ™—š Ÿœžœ&žœ žœžœžœ ˜jKšž˜K˜<šžœ ž˜Kšœ žœ˜.˜ KšžœD˜J—Kšœ žœ˜Kšžœžœ A˜]—Kšžœ˜K˜—š Ÿœžœ+žœ žœžœžœ ˜oKšžœ 0˜6K˜šœ žœž˜˜˜˜ K˜%K˜ ———˜˜˜ K˜ K˜&———Kšžœžœ ˜/—Kšžœ˜Kšžœ˜K˜—š Ÿœžœ#žœ žœžœžœ ˜fKšž˜šžœ ˜K˜ K˜+—Kšžœ˜—K˜šŸœžœžœžœžœžœžœ žœžœ˜oKšœ˜K˜—K˜K™šœ ™ K˜š Ÿœžœžœžœžœ ˜IK˜(šžœ žœžœ˜-K˜O—Kšžœ ˜—K˜šŸœžœžœ˜7K˜'K˜K˜—K˜šŸœžœžœ˜5K˜'K˜+K˜K˜K˜K˜—K˜š Ÿœžœžœ žœžœ,žœ ˜qKšœžœ ˜&KšžœA˜G—K˜šŸ œžœ&žœ žœžœžœžœ˜`Kšœžœ ˜&Kšžœ4˜:—˜Kšœ!™!—š Ÿœžœžœ žœžœžœ˜qKš œžœ)žœžœžœžœ˜N—˜Kšœ£™£—š Ÿœžœ&žœ žœžœžœ˜uKšž˜K˜6K˜šžœ ž˜Kšœ*™*˜ šžœž˜˜Kšž˜Kšœ žœf˜ušžœ žœž˜šœžœ.˜9Kšž˜Kšžœžœžœ ˜)Kšžœ˜Kšžœ˜—šœ žœ0˜=Kšž˜Kšžœžœžœ ˜+Kšžœ˜Kšžœ˜—Kšžœžœ ˜—Kšžœ˜—Kšžœžœ ˜——˜ šžœž˜Kšœ žœ˜ Kšžœžœ ˜——Kšžœžœ ˜—Kšžœ˜K˜Kšœ™—šŸ œžœžœžœ žœžœžœ ˜fKšž˜šžœž˜˜Kš žœ žœžœžœžœ ˜1—˜ Kš žœ žœ žœžœžœžœ ˜?—Kšžœžœ ˜—Kšžœ˜K˜K˜—š Ÿœžœ+žœ žœžœžœ ˜lKšž˜K˜˜K˜ ˜ K˜ K˜.——K˜K˜ K˜šžœž˜K˜˜ Kšž˜K˜;šžœ ž˜K˜KšœNžœ˜SKšžœžœ ˜—Kšžœ˜—šžœžœ ˜˜K˜———Kšžœ˜Kšžœ˜—K˜šŸ œžœžœžœžœžœžœ žœžœ˜lKšœ˜—K˜K˜K˜—šœ ™ K˜šœŒ™ŒK˜—šŸœžœžœžœžœžœžœ˜MKšœžœ^˜g—K˜šŸœžœžœ˜PKšœ%˜%—K˜šŸœžœžœ˜HK˜—K˜šŸœžœžœžœžœžœžœ žœžœ˜sKšœ žœžœ$˜>Kšœ˜šžœ žœžœ˜Kšžœ$˜&K˜(—K˜Kšžœ˜—K˜š Ÿœžœžœ žœžœ,žœ ˜mKšœ žœžœ ˜%Kšžœ=˜C—K˜Kšœžœ+˜DK˜š Ÿœžœžœžœžœ˜RKšœžœb˜k—K˜šŸœžœžœ˜LK˜"—K˜šŸœžœžœ˜TK˜.K˜K˜K˜K˜"—K˜š Ÿœžœžœ žœžœ,žœ ˜xKšœžœ ˜,KšžœA˜G—K˜šŸœžœ%žœ žœžœžœžœ˜eKšœžœ ˜,Kšžœ ˜—K˜š Ÿœžœžœ žœžœžœ˜`˜K˜K˜*—K˜/Kšžœ˜—K˜š Ÿœžœ!žœ žœžœžœ˜h˜K˜˜ K˜ K˜1——Kšžœ˜—K˜šŸœžœžœžœžœžœžœ žœžœ˜wKšœžœ$˜Ešžœ ž˜KšœT˜TKšžœ<˜C——K˜—šœ™K™K™šœžœžœ˜)Kšœ žœ˜ Kšœ žœ˜Kšœ žœ˜Kšœžœ˜Kšœ žœžœ˜K˜Kšœ™—Kšœžœ+˜D—˜šŸœžœžœ žœ žœ!žœžœžœžœ˜{Kšž˜KšœžœžœG˜oKšžœg˜mKšžœ˜—K˜š Ÿœžœžœ(žœžœžœ˜hKšž˜Kšœ žœžœ*˜YKšœžœžœk˜“Kšžœ$žœžœ ˜;Kšžœžœžœ ˜5Kšžœ=žœ ˜SKšžœ˜—K˜K˜šŸœžœžœ˜Kšœžœ3žœžœ ˜M—K˜šŸœžœžœ˜3K˜K˜K˜K˜,K˜—K˜šŸœžœ#žœžœ˜JKšœžœ/˜6—˜KšœI™I—šŸ œžœIžœžœ˜nKšžœ I˜OK˜Kšœ žœžœžœ0˜KKšœ žœžœ ˜K˜9K˜K˜šŸœžœžœžœ˜&Kšž˜Kšœžœn˜‚šžœžœž˜ šœžœ.˜9Kšž˜Kšœ žœžœžœ1˜KKšžœ ˜Kšžœ˜—šœ žœ0˜=Kšž˜Kšœ žœžœžœ1˜LKšœ žœžœžœ˜Kšžœžœžœ S˜€Kšžœ ˜Kšžœ˜—Kšžœžœ ˜—Kšžœ˜—K˜šŸ œžœžœžœ˜,Kšž˜Kšœžœ˜Kšžœ žœžœžœ˜CKšžœžœžœ˜1Kšžœ˜K˜—šžœž˜˜ Kšžœ A˜GKšœ žœ˜$Kšžœ˜Kšžœ˜—˜ Kšž˜K˜>šžœ ž˜˜ Kšž˜Kšœ žœ˜$Kšžœ˜ Kšžœ˜—˜ Kšž˜Kšœ žœžœžœ1˜MKšœ žœžœ ˜ Kšœ žœ ˜=KšœQžœ˜VKšžœ1žœžœ˜LKšžœ˜—Kšžœžœ ˜—Kšžœ˜—Kšžœžœ ˜—Kšžœ˜—K˜šŸœžœžœžœžœ žœžœ˜MKš œžœžœ"žœžœ˜?Kšœ&˜&Kšœ˜—K˜š Ÿœžœžœžœžœžœ˜BKšœžœ#˜*——K™šœ)™)K˜š Ÿœžœžœžœžœžœ˜dKšœžœD˜K—K˜š Ÿœžœžœžœžœžœ˜lKšœžœg˜n—K˜šŸœžœžœ˜[K˜Kšœ˜—K˜šŸœžœ8žœžœ˜oKšž˜Kšœ žœžœ*˜DKšžœž˜€šžœ˜K˜——šŸœžœžœ˜Q˜K˜——š Ÿ œžœžœžœ'žœžœ˜VKšœ žœžœ"˜