DIRECTORY AmpersandContext USING[CreateAmpersandContextType, CreateNodeType], Basics USING[BITXOR, HighHalf, LowHalf], CCTypes USING[BinaryTargetTypes, CCError, CCErrorCase, CCTypeProcs, CheckConformance, ConformanceCheck, Conforms, CreateFrameNodeForSelf, IdFieldCase, IsAnIndirect, LoadIdField, LR, Operator, SelectIdField, GetScopeIndex, GetTargetTypeOfIndirect, LocalCedarTargetWorld], CedarCode USING[CodeToGetNameContext, CodeToLoadNameScope, CodeToLoadThroughIndirect, CodeToMakeAMNode, CodeToSelectField, CodeToStoreUnpopped, CodeToDoUnaryOp, ConcatCode, CreateCedarNode, ExtractFieldFromNode, GetDataFromNode, GetTypeOfNode, LoadThroughIndirectNode, OperationsBody, Operator, SelectFieldFromNode, StoreThroughIndirectNode, AdvanceNameScope, ShowNode], CedarNumericTypes, CirioSyntacticOperations USING[NameArgPair, ParseTree], CirioTypes USING[bitsPerAu, bitsPerPtr, BitAddr, BitStretch, CirioAddress, CirioAddressBody, Code, CompilerContext, CompilerContextBody, Mem, Nat, Node, PtrReg, Type, TypeBody, TypeClass, TypedCode, unspecdBA, zeroBA], IO, RefTypes USING[CreateNilRefType], PointerTypes USING[CreatePointerType, CreateNilPointerType], RefTab USING[Create, Fetch, Key, Ref, Store], Rope USING[Fetch, ROPE, Cat], StructuredStreams; CCTypesImpl: CEDAR PROGRAM IMPORTS AmpersandContext, Basics, CCTypes, CedarCode, CedarNumericTypes, IO, RefTab, RefTypes, PointerTypes, Rope, StructuredStreams EXPORTS CCTypes, CirioTypes SHARES CirioTypes = BEGIN OPEN SS:StructuredStreams; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE ¬ NIL] ¬ CCTypes.CCError; Nat: TYPE = CirioTypes.Nat; ROPE: TYPE = Rope.ROPE; BitAddr: TYPE = CirioTypes.BitAddr; BitStretch: TYPE = CirioTypes.BitStretch; PtrReg: TYPE = CirioTypes.PtrReg; Mem: TYPE = CirioTypes.Mem; Node: TYPE = CirioTypes.Node; TypedCode: TYPE = CirioTypes.TypedCode; Operator: TYPE = CCTypes.Operator; CC: TYPE = CirioTypes.CompilerContext; unspecdBA: BitAddr ~ CirioTypes.unspecdBA; zeroBA: BitAddr ~ CirioTypes.zeroBA; bitsPerAu: Nat ~ CirioTypes.bitsPerAu; bitsPerPtr: Nat ~ CirioTypes.bitsPerPtr; CompilerTypeContext: TYPE = REF CompilerTypeContextBody; CompilerTypeContextBody: PUBLIC TYPE = RECORD[ finalDefaultType: Type, wrongType: Type, nodeType: Type, booleanType: Type, charType: Type, ropeType: Type, anyTargetType: Type, refAnyType: Type, nilRefType: Type, ampersandContextType: Type, ampersandVarType: Type, emptyType: Type, conformingTypePairs: RefTab.Ref, conformanceTestDepth: INT, nilPointerType: Type, localCedarTargetWorld: CCTypes.LocalCedarTargetWorld, cirioAddressType: Type, cedarNumericTypes: RefTab.Ref ]; CreateCedarCompilerContext: PUBLIC PROC RETURNS[CirioTypes.CompilerContext] = BEGIN ctc: CompilerTypeContext ¬ NEW[CompilerTypeContextBody]; tempCC: CirioTypes.CompilerContext ¬ NEW[CirioTypes.CompilerContextBody¬[ctc:ctc]]; ctc.finalDefaultType ¬ NIL; ctc.finalDefaultType ¬ CreateCedarType[$finalDefault, FinalDefaultTypeTypeProcs, DefaultIndirectTypeProcs, tempCC]; -- note that cc.finalDefaultType = NIL during this call, so that the defaults placed in cc.finalDefaultType will be NIL ctc.wrongType ¬ CreateCedarType[$wrong, NIL, NIL, tempCC]; ctc.nodeType ¬ AmpersandContext.CreateNodeType[tempCC]; ctc.booleanType ¬ NIL; --filled in by target world ctc.charType ¬ NIL; --filled in by target world ctc.ropeType ¬ NIL; --filled in by target world ctc.anyTargetType ¬ CreateAnyTargetType[tempCC]; ctc.refAnyType ¬ NIL; --filled in by target world ctc.nilRefType ¬ RefTypes.CreateNilRefType[tempCC]; ctc.nilPointerType ¬ PointerTypes.CreateNilPointerType[tempCC]; ctc.ampersandContextType ¬ AmpersandContext.CreateAmpersandContextType[tempCC]; ctc.ampersandVarType ¬ GetIndirectType[ctc.nodeType]; ctc.emptyType ¬ CreateEmptyType[tempCC]; ctc.conformingTypePairs ¬ RefTab.Create[equal: EqualTypePairs, hash: HashTypePairs]; ctc.conformanceTestDepth ¬ 0; ctc.localCedarTargetWorld ¬ NIL; ctc.cirioAddressType ¬ NIL; ctc.cedarNumericTypes ¬ RefTab.Create[equal: EqualND, hash: HashND]; RETURN[NEW[CirioTypes.CompilerContextBody¬[ ctc: ctc, moduleScope: NIL, nameScope: NIL]]]; END; Type: TYPE = REF TypeBody; TypeBody: TYPE = CirioTypes.TypeBody; CreateCedarType: PUBLIC PROC[class: CirioTypes.TypeClass, typeOps, indirectTypeOps: REF CCTypes.CCTypeProcs, cc: CC, procData: REF ANY ¬ NIL, defaultType: Type ¬ NIL] RETURNS[Type] = BEGIN adt: Type ¬ IF defaultType # NIL THEN defaultType ELSE cc.ctc.finalDefaultType; dt: Type ¬ NEW[TypeBody¬[class, typeOps, procData, adt, NIL, NIL]]; it: Type ¬ NEW[TypeBody¬[class, indirectTypeOps, procData, IF adt=NIL THEN NIL ELSE adt.indirectType, NIL, NIL]]; dt.indirectType ¬ it; it.targetType ¬ dt; RETURN[dt]; END; TypeIsntNil: PUBLIC PROC [t: Type, cc: CC] RETURNS [Type] ~ { IF t=NIL THEN CCError[cirioError, "some special type isn't defined yet"]; RETURN[t]}; IsIndirectType: PUBLIC PROC [type: Type] RETURNS [BOOLEAN] = BEGIN IF type.indirectType = NIL THEN RETURN [TRUE] ELSE RETURN [FALSE]; END; GetTargetTypeOfIndirect: PUBLIC PROC[indirectType: Type] RETURNS[Type] = BEGIN IF indirectType.targetType = NIL THEN CCError[cirioError]; RETURN[indirectType.targetType]; END; GetIndirectType: PUBLIC PROC[targetType: Type] RETURNS[Type] = BEGIN IF targetType.indirectType = NIL THEN CCError[cirioError]; RETURN[targetType.indirectType]; END; GetTypeClass: PUBLIC PROC[type: Type] RETURNS[CirioTypes.TypeClass] = { IF type.class # $defer THEN RETURN[type.class]; RETURN GetTypeClass[type.defaultType]}; GetProcDataFromType: PUBLIC PROC[type: Type] RETURNS[REF ANY] = { IF type.class # $defer THEN RETURN[type.procData]; RETURN GetProcDataFromType[type.defaultType]}; GetDefaultTypeFromType: PUBLIC PROC[type: Type] RETURNS[Type] = { IF type.class # $defer THEN RETURN[type.defaultType]; RETURN GetDefaultTypeFromType[type.defaultType]}; GetGroundTypeClass: PUBLIC PROC [type: Type, cc: CC] RETURNS [CirioTypes.TypeClass] = { groundType: Type ¬ GetGroundType[type, cc, NIL]; RETURN GetTypeClass[groundType]}; GetProcDataFromGroundType: PUBLIC PROC[type: Type, cc: CC] RETURNS[REF ANY] = { groundType: Type ¬ GetGroundType[type, cc, NIL]; RETURN GetProcDataFromType[groundType]}; FinalDefaultTypeTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ checkConformance: FinalDefaultCheckConformance, checkFamilyInclusion: FinalDefaultCheckFamilyInclusion, isASingleton: FinalDefaultIsASingleton, storable: FinalDefaultStorable, isAnIndirect: FinalDefaultIsAnIndirect, containsVariance: FinalDefaultContainsVariance, getNVariants: FinalDefaultGetNVariants, coerceToType: FinalDefaultCoerceToType, binaryOperandTypes: FinalDefaultBinaryOperandTypes, loadIdVal: FinalDefaultLoadIdVal, getTypeRepresentation: FinalDefaultGetTypeRepresentation, getGroundType: FinalDefaultGetGroundType, printType: FinalDefaultPrintType]]; FinalDefaultCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = {RETURN[IF valType = varType THEN yes ELSE no]}; FinalDefaultCheckFamilyInclusion: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = {RETURN[IsASingleton[varType, cc] AND Conforms[valType, varType, cc] AND Conforms[varType, valType, cc]]}; FinalDefaultIsASingleton: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = {RETURN[TRUE]}; FinalDefaultStorable: PROC[valType, indirectType: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = {RETURN[Conforms[valType, GetLTargetType[indirectType, cc], cc]]}; FinalDefaultIsAnIndirect: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = {RETURN[FALSE]}; FinalDefaultContainsVariance: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = {RETURN[FALSE]}; FinalDefaultGetNVariants: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[INT] = {RETURN[0]}; FinalDefaultCoerceToType: PROC[targetType: Type, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN IF CCTypes.Conforms[tc.type, targetType, cc] THEN RETURN[tc] ELSE CCError[operation, "can not coerce to an appropriate type for the given operation"]; END; FinalDefaultBinaryOperandTypes: PROC[op: CedarCode.Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.BinaryTargetTypes] = BEGIN rightClass: CirioTypes.TypeClass ¬ GetGroundTypeClass[right, cc]; SELECT rightClass FROM $wrong, $amnode => RETURN[[right, right]]; ENDCASE => RETURN[[left, right]]; END; FinalDefaultLoadIdVal: PROC[id: ROPE, targetType: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN actualNameScope: Node ¬ cc.nameScope; load: TypedCode ¬ CCTypes.LoadIdField[id, CedarCode.GetTypeOfNode[actualNameScope], cc]; value: TypedCode ¬ [ CedarCode.ConcatCode[ CedarCode.CodeToLoadNameScope[], load.code], load.type]; RETURN[value]; END; FinalDefaultGetTypeRepresentation: PROC [type: Type, cc: CC, procData: REF ANY] RETURNS[REF ANY] = {RETURN[type.procData]}; FinalDefaultGetGroundType: PROC [type: Type, cc: CC, procData: REF ANY] RETURNS [Type] = { RETURN [type]; }; FinalDefaultPrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY]= { to.PutRope[""]; RETURN}; DefaultIndirectPrintType: PROC [to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, procData: REF ANY] = { to.PutRope["VAR "]; PrintType[to, GetTargetTypeOfIndirect[type], printDepth-(IF brave THEN 0 ELSE 1), printWidth, cc]; RETURN}; brave: BOOL ¬ FALSE; CreateAnyTargetType: PROC[cc: CC] RETURNS[Type] = {RETURN[CreateCedarType[$anyTarget, AnyTargetTypeProcs, NIL, cc, NIL]]}; AnyTargetTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ ]]; DefaultIndirectTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ checkConformance: DefaultIndirectTypeCheckConformance, binaryOperandTypes: DefaultIndirectTypeBinaryOperandTypes, isAnIndirect: DefaultIndirectTypeIsAnIndirect, getRTargetType: DefaultIndirectGetRTargetType, getLTargetType: DefaultIndirectGetLTargetType, operand: DefaultIndirectOperand, coerceToType: DefaultIndirectTypeCoerceToType, unaryOp: DefaultIndirectUnaryOp, store: DefaultIndirectTypeStore, load: DefaultIndirectTypeLoad, getGroundType: FinalDefaultGetGroundType, printType: DefaultIndirectPrintType]]; DefaultIndirectTypeCheckConformance: PROC[valType, varType: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.ConformanceCheck] = BEGIN IF NOT CCTypes.IsAnIndirect[varType, cc] THEN RETURN[no] ELSE BEGIN nominalValTarget: Type ¬ GetRTargetType[valType, cc]; nominalVarTarget: Type ¬ GetRTargetType[varType, cc]; IF IsASingleton[nominalValTarget, cc] AND IsASingleton[nominalVarTarget, cc] THEN BEGIN conforms1: CCTypes.ConformanceCheck; conforms2: CCTypes.ConformanceCheck; conforms1 ¬ CCTypes.CheckConformance[nominalValTarget, nominalVarTarget, cc]; IF conforms1 = no THEN RETURN[no]; conforms2 ¬ CCTypes.CheckConformance[nominalVarTarget, nominalValTarget, cc]; IF conforms2 = no THEN RETURN[no]; IF conforms1 = yes AND conforms2 = yes THEN RETURN[yes]; RETURN[dontKnow]; END ELSE IF CheckFamilyInclusion[nominalValTarget, nominalVarTarget, cc] THEN RETURN[yes] ELSE RETURN[no]; END; END; DefaultIndirectTypeBinaryOperandTypes: PROC[op: CedarCode.Operator, left, right: Type, cc: CC, procData: REF ANY] RETURNS[CCTypes.BinaryTargetTypes] = BEGIN rightClass: CirioTypes.TypeClass ¬ GetGroundTypeClass[right, cc]; IF rightClass = $wrong OR rightClass = $amnode THEN RETURN[[right, right]]; SELECT op FROM $assign => BEGIN target: Type ¬ GetRTargetType[left, cc]; IF CCTypes.Conforms[right, target, cc] THEN RETURN[[left, right]] ELSE RETURN[[left, target]]; END; ENDCASE => CCError[typeConformity]; END; DefaultIndirectTypeIsAnIndirect: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[BOOLEAN] = {RETURN[TRUE]}; DefaultIndirectGetRTargetType: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[Type] = {RETURN[GetTargetTypeOfIndirect[type]]}; DefaultIndirectGetLTargetType: PROC[type: Type, cc: CC, procData: REF ANY] RETURNS[Type] = BEGIN nominalTarget: Type ¬ GetTargetTypeOfIndirect[type]; IF IsASingleton[nominalTarget, cc] THEN RETURN[nominalTarget] ELSE RETURN[cc.ctc.emptyType]; END; DefaultIndirectOperand: PROC[op: CedarCode.Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN SELECT op FROM $address => RETURN[tc]; ENDCASE => CCE[operation, "illegal operation"]; -- client error, illegal operation END; DefaultIndirectTypeCoerceToType: PROC[targetType: Type, tc: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN IF CCTypes.Conforms[tc.type, targetType, cc] THEN RETURN[tc]; IF GetGroundTypeClass[targetType, cc] = $amnode THEN RETURN[[CedarCode.ConcatCode[tc.code, CedarCode.CodeToMakeAMNode[tc.type]], GetNodeType[cc]]]; CCError[operation, "can not coerce to an appropriate type for given operation"]; END; DefaultIndirectUnaryOp: 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[GetTargetTypeOfIndirect[arg.type], cc, NIL--it's OK to give a NIL bti because the resultant pointer Type will never be asked to CreateIndirectNode or GetBitSize--]; RETURN [[code, ptrType]]; END; ENDCASE => CCE[cirioError]; END; DefaultIndirectTypeStore: PROC[value: TypedCode, indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: CirioTypes.Code ¬ CedarCode.ConcatCode[ indirect.code, CedarCode.ConcatCode[ value.code, CedarCode.CodeToStoreUnpopped[indirect.type, value.type]]]; type: Type ¬ value.type; RETURN[[code, type]]; END; DefaultIndirectTypeLoad: PROC[indirect: TypedCode, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN code: CirioTypes.Code ¬ CedarCode.ConcatCode[ indirect.code, CedarCode.CodeToLoadThroughIndirect[indirect.type]]; type: Type ¬ GetRTargetType[indirect.type, cc]; RETURN[[code, type]]; END; EmptyData: TYPE = RECORD[fillEmpty: INTEGER]; CreateEmptyType: PROC[cc: CC] RETURNS[Type] = {RETURN[CreateCedarType[$empty, EmptyTypeTypeProcs, EmptyTypeIndirectTypeProcs, cc, NEW[EmptyData¬[0]]]]}; EmptyTypeTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[]]; EmptyTypeIndirectTypeProcs: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[]]; CCError: PUBLIC ERROR[case: CCTypes.CCErrorCase, msg: ROPE ¬ NIL] = CODE; GetCedarNumericType: PUBLIC PROC[desc: CedarNumericTypes.NumericDescriptor, cc: CC, insist: BOOL] RETURNS[Type] ~ { ctc: CompilerTypeContext ~ cc.ctc; rnd: REF CedarNumericTypes.NumericDescriptor ~ NEW[CedarNumericTypes.NumericDescriptor ¬ desc]; t: Type ¬ NARROW[ctc.cedarNumericTypes.Fetch[rnd].val]; IF insist AND t=NIL THEN { ndr: ROPE ~ CedarNumericTypes.NDFormat[desc]; CCError[cirioError, "fetching undefined numeric type"]}; RETURN[t]}; SetCedarNumericType: PUBLIC PROC[cc: CC, desc: CedarNumericTypes.NumericDescriptor, t: Type] ~ { rnd: REF CedarNumericTypes.NumericDescriptor ~ NEW[CedarNumericTypes.NumericDescriptor ¬ desc]; news: BOOL ¬ cc.ctc.cedarNumericTypes.Store[rnd, t]; [] ¬ GetCedarNumericType[desc, cc, TRUE]; RETURN}; EqualND: PROC [key1, key2: REF ANY] RETURNS [BOOL] ~ { r1: REF CedarNumericTypes.NumericDescriptor ~ NARROW[key1]; r2: REF CedarNumericTypes.NumericDescriptor ~ NARROW[key2]; RETURN CedarNumericTypes.NDEqual[r1­, r2­]}; HashND: PROC [key: REF ANY] RETURNS [CARDINAL] ~ { rnd: REF CedarNumericTypes.NumericDescriptor ~ NARROW[key]; RETURN CedarNumericTypes.NDHash[rnd­]}; GetWrongType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.wrongType]}; GetNodeType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.nodeType]}; GetBooleanType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.booleanType]}; SetBooleanType: PUBLIC PROC[cc: CC, t: Type] = {cc.ctc.booleanType ¬ t}; GetCharType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.charType]}; SetCharType: PUBLIC PROC[cc: CC, t: Type] = {cc.ctc.charType ¬ t}; GetRopeType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.ropeType]}; SetRopeType: PUBLIC PROC[cc: CC, t: Type] = {cc.ctc.ropeType ¬ t}; GetAnyTargetType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.anyTargetType]}; GetRefAnyType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.refAnyType]}; SetRefAnyType: PUBLIC PROC[cc: CC, t: Type] = {cc.ctc.refAnyType ¬ t}; GetNilRefType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.nilRefType]}; GetNilPointerType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.nilPointerType]}; SetNilPointerType: PUBLIC PROC[cc: CC, t: Type] = {cc.ctc.nilPointerType ¬ t}; GetAmpersandContextType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.ampersandContextType]}; GetAmpersandVarType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[cc.ctc.ampersandVarType]}; GetNameScopeType: PUBLIC PROC[cc: CC] RETURNS[Type] = {RETURN[CedarCode.GetTypeOfNode[cc.nameScope]]}; CheckConformity: PROC[valType, varType: CirioTypes.Type, continueCheck: PROC RETURNS[CCTypes.ConformanceCheck], cc: CC] RETURNS[CCTypes.ConformanceCheck] = BEGIN pair: TypePair ¬ NEW[TypePairBody¬[valType, varType]]; markRef: REF PairMark ¬ NARROW[RefTab.Fetch[cc.ctc.conformingTypePairs, pair].val]; IF markRef = NIL THEN BEGIN markRef ¬ NEW[PairMark ¬ notKnown]; IF NOT RefTab.Store[cc.ctc.conformingTypePairs, pair, markRef] THEN CCError[cirioError]; END; IF markRef­ = currentlyUnderTest THEN BEGIN IF cc.ctc.conformanceTestDepth = 0 THEN CCError[cirioError]; -- shouldn't happen RETURN[dontKnow]; END; IF markRef­ = notKnown THEN BEGIN result: CCTypes.ConformanceCheck; markRef­ ¬ currentlyUnderTest; cc.ctc.conformanceTestDepth ¬ cc.ctc.conformanceTestDepth+1; result ¬ continueCheck[ !UNWIND => BEGIN -- uh oh, we had better clean up cc.ctc.conformanceTestDepth ¬ cc.ctc.conformanceTestDepth-1; IF markRef­ # currentlyUnderTest THEN ERROR; -- I don't even want to think about this possibility! markRef­ ¬ notKnown; END]; cc.ctc.conformanceTestDepth ¬ cc.ctc.conformanceTestDepth-1; IF markRef­ # currentlyUnderTest THEN CCError[cirioError]; markRef­ ¬ SELECT result FROM yes => knownToConform, no => knownNotToConform, dontKnow => IF cc.ctc.conformanceTestDepth = 0 THEN knownToConform ELSE notKnown, ENDCASE => CCError[cirioError]; IF result = dontKnow AND cc.ctc.conformanceTestDepth = 0 THEN result ¬ yes; RETURN[result]; END; RETURN[SELECT markRef­ FROM knownToConform => yes, knownNotToConform => no, ENDCASE => CCError[cirioError]]; END; PairMark: TYPE = {currentlyUnderTest, knownToConform, knownNotToConform, notKnown}; TypePair: TYPE = REF TypePairBody; TypePairBody: TYPE = RECORD[valType, varType: CirioTypes.Type]; EqualTypePairs: PROC[key1, key2: RefTab.Key] RETURNS[BOOL] = BEGIN pair1: TypePair ¬ NARROW[key1]; pair2: TypePair ¬ NARROW[key2]; RETURN[(pair1.valType = pair2.valType) AND (pair1.varType = pair2.varType)]; END; HashTypePairs: PROC[key: RefTab.Key] RETURNS[CARDINAL] = BEGIN pair: TypePair ¬ NARROW[key]; RETURN[Basics.BITXOR[ Basics.BITXOR[ Basics.HighHalf[LOOPHOLE[pair.valType, CARD32]], Basics.LowHalf[LOOPHOLE[pair.valType, CARD32]]], Basics.BITXOR[ Basics.HighHalf[LOOPHOLE[pair.varType, CARD32]], Basics.LowHalf[LOOPHOLE[pair.varType, CARD32]]]]]; END; TryStandardCoercion: PUBLIC PROC[targetType: CirioTypes.Type, tc: TypedCode, continueCoerce: PROC RETURNS[TypedCode], cc: CC] RETURNS[TypedCode] = BEGIN IF CCTypes.Conforms[tc.type, targetType, cc] THEN RETURN[tc] ELSE BEGIN targetClass: CirioTypes.TypeClass ¬ GetGroundTypeClass[targetType, cc]; SELECT targetClass FROM $wrong => RETURN[[tc.code, GetWrongType[cc]]]; $amnode => RETURN[[CedarCode.ConcatCode[tc.code, CedarCode.CodeToMakeAMNode[tc.type]], GetNodeType[cc]]]; ENDCASE => BEGIN newtc: TypedCode ¬ continueCoerce[]; IF NOT CCTypes.Conforms[newtc.type, targetType, cc] THEN CCE[cirioError]; RETURN[newtc]; END; END; END; RegisterLocalCedarTargetWorld: PUBLIC PROC[lctw: CCTypes.LocalCedarTargetWorld, cc: CC] = BEGIN IF cc.ctc.localCedarTargetWorld # NIL THEN CCE[cirioError]; cc.ctc.localCedarTargetWorld ¬ lctw; BEGIN address: CirioTypes.CirioAddress ¬ NEW[CirioTypes.CirioAddressBody¬[NIL, NIL, NIL, NIL, NIL]]; cirioAddressType: CirioTypes.Type ¬ InnerGetTypeForCirioAddress[address, cc]; cc.ctc.cirioAddressType ¬ cirioAddressType; END; END; InnerGetTypeForCirioAddress: PROC[dum: CirioTypes.CirioAddress, cc: CC] RETURNS[CirioTypes.Type] = BEGIN indirectFrameForSelf: CirioTypes.Node ¬ CCTypes.CreateFrameNodeForSelf[cc]; indirectTypeForSelf: CirioTypes.Type ¬ CedarCode.GetTypeOfNode[indirectFrameForSelf]; indirectArgs: CirioTypes.Node ¬ CedarCode.SelectFieldFromNode["&args", indirectTypeForSelf, indirectFrameForSelf, cc]; indirectTypeForArgs: CirioTypes.Type ¬ CedarCode.GetTypeOfNode[indirectArgs]; indirectDum: CirioTypes.Node ¬ CedarCode.SelectFieldFromNode["dum", indirectTypeForArgs, indirectArgs, cc]; indirectDumType: CirioTypes.Type ¬ CedarCode.GetTypeOfNode[indirectDum]; dumType: CirioTypes.Type ¬ CCTypes.GetTargetTypeOfIndirect[indirectDumType]; RETURN[dumType] END; OldRegisterLocalCedarTargetWorld: PUBLIC PROC[lctw: CCTypes.LocalCedarTargetWorld, cc: CC] = BEGIN IF cc.ctc.localCedarTargetWorld # NIL THEN CCE[cirioError]; cc.ctc.localCedarTargetWorld ¬ lctw; BEGIN dummyCirioAddessNode: Node ¬ CreateNodeFromRefAny[NEW[CirioTypes.CirioAddress¬NIL], cc]; cirioAddressType: Type ¬ CedarCode.GetTypeOfNode[dummyCirioAddessNode]; cc.ctc.cirioAddressType ¬ cirioAddressType; END; END; CreateNodeFromRefAny: PUBLIC PROC[refAny: REF ANY, cc: CC] RETURNS[Node] = BEGIN IF cc.ctc.localCedarTargetWorld = NIL THEN CCE[cirioError]; RETURN[cc.ctc.localCedarTargetWorld.createNodeFromRefAny[refAny, cc.ctc.localCedarTargetWorld, cc]]; END; CreateFrameNodeForSelf: PUBLIC PROC[cc: CC] RETURNS[Node] = BEGIN ourselves: Node ¬ cc.ctc.localCedarTargetWorld.createFrameNodeForSelf[cc.ctc.localCedarTargetWorld, cc]; ourType: Type ¬ CedarCode.GetTypeOfNode[ourselves]; RETURN[CedarCode.ExtractFieldFromNode["&caller", ourType, ourselves, cc]]; END; GetCirioAddressType: PUBLIC PROC[cc: CC] RETURNS[Type] = {IF cc.ctc.cirioAddressType = NIL THEN CCError[cirioError] ELSE RETURN[cc.ctc.cirioAddressType]}; Conforms: PUBLIC PROC[valType, varType: Type, cc: CC, oc: Type ¬ NIL] RETURNS[BOOLEAN] = BEGIN result: CCTypes.ConformanceCheck ¬ CheckConformance[valType, varType, cc, oc]; IF result = dontKnow THEN CCE[cirioError]; RETURN[result = yes]; END; CheckConformance: PUBLIC PROC[valType, varType: Type, cc: CC, oc: Type ¬ NIL] RETURNS[CCTypes.ConformanceCheck] = { ConformsInner: PROC RETURNS[CCTypes.ConformanceCheck] = {RETURN[CheckConformanceMain[valType, varType, cc, oc]]}; ans: CCTypes.ConformanceCheck ~ CheckConformity[valType, varType, ConformsInner, cc]; IF ans=no THEN someNotConform ¬ TRUE; RETURN [ans]}; someNotConform: BOOL ¬ FALSE; CheckConformanceMain: PROC[valType, varType: Type, cc: CC, oc: Type ¬ NIL] RETURNS[CCTypes.ConformanceCheck] = BEGIN groundValType: Type ¬ GetGroundType[valType, cc, oc]; groundVarType: Type ¬ GetGroundType[varType, cc, oc]; ct: Type ¬ IF oc # NIL THEN oc ELSE valType; IF ct.procs = NIL OR ct.procs.checkConformance = NIL THEN {IF ct.defaultType = NIL THEN CCE[cirioError, "some type can't check conformance"] ELSE RETURN[CheckConformanceMain[groundValType, groundVarType, cc, ct.defaultType]]} ELSE RETURN[ct.procs.checkConformance[groundValType, groundVarType, cc, ct.procData]] END; CheckFamilyInclusion: PUBLIC PROC[valType, varType: Type, cc: CC, oc: Type ¬ NIL] RETURNS[BOOLEAN] = BEGIN groundValType: Type ¬ GetGroundType[valType, cc, oc]; groundVarType: Type ¬ GetGroundType[varType, cc, oc]; ct: Type ¬ IF oc # NIL THEN oc ELSE valType; IF ct.procs = NIL OR ct.procs.checkFamilyInclusion = NIL THEN {IF ct.defaultType = NIL THEN CCE[cirioError] ELSE RETURN[CheckFamilyInclusion[groundValType, groundVarType, cc, ct.defaultType]]} ELSE { ans: BOOL ~ ct.procs.checkFamilyInclusion[groundValType, groundVarType, cc, ct.procData]; IF NOT ans THEN someFamilyNotIncluded ¬ TRUE; RETURN [ans]}; END; someFamilyNotIncluded: BOOL ¬ FALSE; IsASingleton: PUBLIC PROC[type: Type, cc: CC, oc: Type ¬ NIL] RETURNS[BOOLEAN] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.isASingleton = NIL THEN {IF ct.defaultType = NIL THEN CCE[cirioError] ELSE RETURN[IsASingleton[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.isASingleton[type, cc, ct.procData]] END; Storable: PUBLIC PROC[valType, indirectType: Type, cc: CC, oc: Type ¬ NIL] RETURNS[BOOLEAN] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE valType; IF ct.procs = NIL OR ct.procs.storable = NIL THEN {IF ct.defaultType = NIL THEN CCE[cirioError] ELSE RETURN[Storable[valType, indirectType, cc, ct.defaultType]]} ELSE RETURN[ct.procs.storable[valType, indirectType, cc, ct.procData]] END; BinaryOperandTypes: PUBLIC PROC[op: Operator, left, right: Type, cc: CC, oc: Type] RETURNS[CCTypes.BinaryTargetTypes] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE left; IF ct.procs = NIL OR ct.procs.binaryOperandTypes = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[BinaryOperandTypes[op, left, right, cc, ct.defaultType]]} ELSE RETURN[ct.procs.binaryOperandTypes[op, left, right, cc, ct.procData]] END; IsAnIndirect: PUBLIC PROC[type: Type, cc: CC, oc: Type] RETURNS[BOOLEAN] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.isAnIndirect = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[IsAnIndirect[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.isAnIndirect[type, cc, ct.procData]]; END; GetRTargetType: PUBLIC PROC[type: Type, cc: CC, oc: Type ¬ NIL] RETURNS[Type] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.getRTargetType = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[GetRTargetType[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getRTargetType[type, cc, ct.procData]]; END; GetLTargetType: PUBLIC PROC[type: Type, cc: CC, oc: Type ¬ NIL] RETURNS[Type] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.getLTargetType = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[GetLTargetType[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getLTargetType[type, cc, ct.procData]]; END; GetFieldsType: PUBLIC PROC[rcdType: Type, cc: CC, oc: Type] RETURNS[Type] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE rcdType; IF ct.procs = NIL OR ct.procs.getFieldsType = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[GetFieldsType[rcdType, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getFieldsType[rcdType, cc, ct.procData]]; END; GetRefType: PUBLIC PROC[rhs: Type, cc: CC, oc: Type] RETURNS[Type] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE rhs; IF ct.procs = NIL OR ct.procs.getRefType = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[GetRefType[rhs, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getRefType[rhs, cc, ct.procData]]; END; HasIdField: PUBLIC PROC[id: ROPE, fieldContext: Type, cc: CC, oc: Type ¬ NIL] RETURNS[CCTypes.IdFieldCase] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE fieldContext; IF ct.procs = NIL OR ct.procs.hasIdField = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[HasIdField[id, fieldContext, cc, ct.defaultType]]} ELSE RETURN[ct.procs.hasIdField[id, fieldContext, cc, ct.procData]]; END; ContainsVariance: PUBLIC PROC[type: Type, cc: CC, oc: Type ¬ NIL] RETURNS[BOOLEAN] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.containsVariance = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[ContainsVariance[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.containsVariance[type, cc, ct.procData]]; END; GetNVariants: PUBLIC PROC[type: Type, cc: CC, oc: Type ¬ NIL] RETURNS[INT] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.getNVariants = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[GetNVariants[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getNVariants[type, cc, ct.procData]]; END; AsIndexSet: PUBLIC PROC[type: Type, cc: CC, oc: Type] RETURNS[Type] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.asIndexSet = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[AsIndexSet[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.asIndexSet[type, cc, ct.procData]]; END; Operand: PUBLIC PROC[op: Operator, lr: CCTypes.LR, tc: TypedCode, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE tc.type; IF ct.procs = NIL OR ct.procs.operand = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation, IO.PutFR["Unable to determine operand type for op %g and TYPE %g", [atom[op]], [rope[FmtType[tc.type, 2, 16, cc]]] ]] ELSE RETURN[Operand[op, lr, tc, cc, ct.defaultType]]} ELSE RETURN[ct.procs.operand[op, lr, tc, cc, ct.procData]]; END; ApplyOperand: PUBLIC PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, oc: Type ¬ NIL] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE operatorType; IF ct.procs = NIL OR ct.procs.applyOperand = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[ApplyOperand[operatorType, operand, cc, ct.defaultType]]} ELSE RETURN[ct.procs.applyOperand[operatorType, operand, cc, ct.procData]]; END; IndexOperand: PUBLIC PROC[operatorType: Type, operand: CirioSyntacticOperations.ParseTree, cc: CC, oc: Type ¬ NIL] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE operatorType; IF ct.procs = NIL OR ct.procs.indexOperand = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[IndexOperand[operatorType, operand, cc, ct.defaultType]]} ELSE RETURN[ct.procs.indexOperand[operatorType, operand, cc, ct.procData]]; END; CoerceToType: PUBLIC PROC[targetType: Type, tc: TypedCode, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN CoerceToTypeInner: PROC RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE tc.type; IF ct.procs = NIL OR ct.procs.coerceToType = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation, IO.PutFR["Unable to coerce TYPE %g to %g", [rope[FmtType[tc.type, 3, 16, cc]]], [rope[FmtType[targetType, 3, 16, cc]]] ]] ELSE RETURN[CoerceToType[targetType, tc, cc, ct.defaultType]]} ELSE RETURN[ct.procs.coerceToType[targetType, tc, cc, ct.procData]]; END; RETURN[TryStandardCoercion[targetType, tc, CoerceToTypeInner, cc]]; END; BinaryOp: PUBLIC PROC[op: Operator, left, right: TypedCode, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE left.type; IF ct.procs = NIL OR ct.procs.binaryOp = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation, IO.PutFR["Binary operation %g not implemented for TYPE %g", [atom[op]], [rope[FmtType[left.type, 2, 10, cc]]] ]] ELSE RETURN[BinaryOp[op, left, right, cc, ct.defaultType]]} ELSE RETURN[ct.procs.binaryOp[op, left, right, cc, ct.procData]]; END; UnaryOp: PUBLIC PROC[op: Operator, arg: TypedCode, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE arg.type; IF ct.procs = NIL OR ct.procs.unaryOp = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation, IO.PutFR["Unary operation %g not implemented for TYPE %g", [atom[op]], [rope[FmtType[arg.type, 2, 10, cc]]] ]] ELSE RETURN[UnaryOp[op, arg, cc, ct.defaultType]]} ELSE RETURN[ct.procs.unaryOp[op, arg, cc, ct.procData]]; END; NAryOperandType: PUBLIC PROC[op: Operator, typeSoFar, nextType: Type, cc: CC, oc: Type] RETURNS[Type] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE typeSoFar; IF ct.procs = NIL OR ct.procs.nAryOperandType = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[NAryOperandType[op, typeSoFar, nextType, cc, ct.defaultType]]} ELSE RETURN[ct.procs.nAryOperandType[op, typeSoFar, nextType, cc, ct.procData]]; END; NAryOp: PUBLIC PROC[op: Operator, args: LIST OF TypedCode, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE args.first.type; IF ct.procs = NIL OR ct.procs.nAryOp = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[NAryOp[op, args, cc, ct.defaultType]]} ELSE RETURN[ct.procs.nAryOp[op, args, cc, ct.procData]]; END; TypeOp: PUBLIC PROC[op: Operator, type: Type, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.typeOp = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[TypeOp[op, type, cc, ct]]} ELSE RETURN[ct.procs.typeOp[op, type, cc, ct.procData]]; END; TypeOp2OperandType: PUBLIC PROC[op: Operator, type: Type, cc: CC, oc: Type] RETURNS[Type] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.typeOp2OperandType = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[TypeOp2OperandType[op, type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.typeOp2OperandType[op, type, cc, ct.procData]]; END; TypeOp2: PUBLIC PROC[op: Operator, type: Type, arg: TypedCode, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.typeOp2 = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[TypeOp2[op, type, arg, cc, ct.defaultType]]} ELSE RETURN[ct.procs.typeOp2[op, type, arg, cc, ct]]; END; Constructor: PUBLIC PROC[list: LIST OF CirioSyntacticOperations.ParseTree, targetType: Type, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE targetType; IF ct.procs = NIL OR ct.procs.constructor = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[Constructor[list, targetType, cc, ct.defaultType]]} ELSE RETURN[ct.procs.constructor[list, targetType, cc, ct.procData]]; END; PairConstructor: PUBLIC PROC[list: LIST OF CirioSyntacticOperations.NameArgPair, targetType: Type, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE targetType; IF ct.procs = NIL OR ct.procs.pairConstructor = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[PairConstructor[list, targetType, cc, ct.defaultType]]} ELSE RETURN[ct.procs.pairConstructor[list, targetType, cc, ct.procData]]; END; Store: PUBLIC PROC[value: TypedCode, indirect: TypedCode, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE indirect.type; IF ct.procs = NIL OR ct.procs.store = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[Store[value, indirect, cc, ct.defaultType]]} ELSE RETURN[ct.procs.store[value, indirect, cc, ct.procData]]; END; Load: PUBLIC PROC[indirect: TypedCode, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE indirect.type; IF ct.procs = NIL OR ct.procs.load = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[Load[indirect, cc, ct.defaultType]]} ELSE RETURN[ct.procs.load[indirect, cc, ct.procData]]; END; ExtractIdField: PUBLIC PROC[id: ROPE, fieldContext: Type, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE fieldContext; IF ct.procs = NIL OR ct.procs.extractIdField = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[ExtractIdField[id, fieldContext, cc, ct.defaultType]]} ELSE RETURN[ct.procs.extractIdField[id, fieldContext, cc, ct.procData]]; END; LoadIdVal: PUBLIC PROC[id: ROPE, targetType: Type, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE targetType; IF ct.procs = NIL OR ct.procs.loadIdVal = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[LoadIdVal[id, targetType, cc, ct.defaultType]]} ELSE RETURN[ct.procs.loadIdVal[id, targetType, cc, ct.procData]]; END; SelectIdField: PUBLIC PROC[id: ROPE, fieldIndirectContext: Type, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE fieldIndirectContext; IF ct.procs = NIL OR ct.procs.selectIdField = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[SelectIdField[id, fieldIndirectContext, cc, ct.defaultType]]} ELSE RETURN[ct.procs.selectIdField[id, fieldIndirectContext, cc, ct.procData]]; END; LoadIdField: PUBLIC PROC[id: ROPE, fieldIndirectContext: Type, cc: CC, oc: Type] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE fieldIndirectContext; IF ct.procs = NIL OR ct.procs.loadIdField = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[LoadIdField[id, fieldIndirectContext, cc, ct.defaultType]]} ELSE RETURN[ct.procs.loadIdField[id, fieldIndirectContext, cc, ct.procData]]; END; Apply: PUBLIC PROC[operator: TypedCode, operand: TypedCode, cc: CC, oc: Type ¬ NIL] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE operator.type; IF ct.procs = NIL OR ct.procs.apply = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[Apply[operator, operand, cc, ct.defaultType]]} ELSE RETURN[ct.procs.apply[operator, operand, cc, ct.procData]]; END; Index: PUBLIC PROC[operator: TypedCode, operand: TypedCode, cc: CC, oc: Type ¬ NIL] RETURNS[TypedCode] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE operator.type; IF ct.procs = NIL OR ct.procs.index = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[Index[operator, operand, cc, ct.defaultType]]} ELSE RETURN[ct.procs.index[operator, operand, cc, ct.procData]]; END; GetTypeRepresentation: PUBLIC PROC[type: Type, cc: CC, oc: Type ¬ NIL] RETURNS[REF ANY] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.getTypeRepresentation = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[GetTypeRepresentation[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getTypeRepresentation[type, cc, ct.procData]]; END; GetNElements: PUBLIC PROC[type: Type, cc: CC, oc: Type ¬ NIL] RETURNS[CARD] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.getNElements = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation, "some Type doesn't know how to getNElements"] ELSE RETURN[GetNElements[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getNElements[type, cc, ct.procData]]; END; GetScopeIndex: PUBLIC PROC [type: Type, cc: CC, oc: Type ¬ NIL] RETURNS [CARD] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.getScopeIndex = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[GetScopeIndex[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getScopeIndex[type, cc, ct.procData]]; END; GetGroundType: PUBLIC PROC[type: Type, cc: CC, oc: Type ¬ NIL] RETURNS[Type] = BEGIN ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF ct.procs = NIL OR ct.procs.getGroundType = NIL THEN {IF ct.defaultType = NIL THEN CCE[operation] ELSE RETURN[GetGroundType[type, cc, ct.defaultType]]} ELSE RETURN[ct.procs.getGroundType[type, cc, ct.procData]]; END; FmtType: PROC [type: Type, printDepth: INT, printWidth: INT, cc: CC, oc: Type ¬ NIL] RETURNS [ans: ROPE] = { ENABLE CCE => {ans ¬ "??"; CONTINUE}; buf1: IO.STREAM ~ IO.ROS[]; PrintType[buf1, type, printDepth, printWidth, cc, oc]; RETURN [buf1.RopeFromROS]}; PrintType: PUBLIC PROC[to: IO.STREAM, type: Type, printDepth, printWidth: INT, cc: CC, oc: Type ¬ NIL] = { ct: Type ¬ IF oc # NIL THEN oc ELSE type; IF printDepth<0 THEN {to.PutRope[".."]; RETURN}; IF ct.procs = NIL OR ct.procs.printType = NIL THEN {IF ct.defaultType = NIL THEN CCE[cirioError, IO.PutFR1["a type of class %g doesn't know how to print itself", [atom[type.class]] ]] ELSE PrintType[to, type, printDepth, printWidth, cc, ct.defaultType]} ELSE ct.procs.printType[to, type, printDepth, printWidth, cc, ct.procData]; }; sia: PUBLIC INT ¬ 3; DoObject: PUBLIC PROC [to: IO.STREAM, printit: PROC] ~ { SS.Begin[to]; printit[!UNWIND => SS.End[to]]; SS.End[to]; RETURN}; BreakObject: PUBLIC PROC [to: IO.STREAM, printit: PROC, sep: ROPE ¬ NIL] ~ { SS.Bp[to, lookLeft, sia, sep]; DoObject[to, printit]; RETURN}; PrintTypeBracketed: PUBLIC PROC[to: IO.STREAM, type: Type, printDepth: INT, printWidth: INT, cc: CC, oc: Type ¬ NIL] = { SS.Begin[to]; PrintType[to, type, printDepth, printWidth, cc, oc !UNWIND => SS.End[to]]; SS.End[to]; RETURN}; BreakPrintType: PUBLIC PROC[to: IO.STREAM, type: Type, printDepth, printWidth: INT, cc: CC, sep: ROPE ¬ NIL, oc: Type ¬ NIL] = { InnerPrint: PROC ~ {PrintType[to, type, printDepth, printWidth, cc, oc]}; BreakObject[to, InnerPrint, sep]}; GetIndirectCreateNode: PUBLIC PROC[targetType: Type, mem: Mem, cc: CC] RETURNS[Node] ~ { indirectType: Type ~ GetIndirectType[targetType]; RETURN CreateIndirectNode[indirectType, mem, cc]}; CreateIndirectNode: PUBLIC PROC[indirectType: Type, mem: Mem, cc: CC, oc: Type ¬ NIL] RETURNS[Node] ~ { ct: Type ¬ IF oc # NIL THEN oc ELSE indirectType; IF ct.procs#NIL AND ct.procs.createIndirectNode#NIL THEN { targetType: Type ~ GetTargetTypeOfIndirect[indirectType]; RETURN ct.procs.createIndirectNode[cc, ct.procData, indirectType, targetType, mem]}; IF ct.defaultType=NIL THEN CCE[cirioError, "some type doesn't know how to create an indirect node"]; RETURN CreateIndirectNode[indirectType, mem, cc, ct.defaultType]}; GetBitSize: PUBLIC PROC[indirectType: Type, cc: CC, oc: Type ¬ NIL] RETURNS[CARD] ~ { ct: Type ¬ IF oc # NIL THEN oc ELSE indirectType; IF ct.procs#NIL AND ct.procs.getBitSize#NIL THEN { targetType: Type ~ GetTargetTypeOfIndirect[indirectType]; RETURN ct.procs.getBitSize[indirectType, targetType, cc, ct.procData]}; IF ct.defaultType=NIL THEN { asRope: ROPE ¬ FmtType[indirectType, 3, 32, cc]; CCE[cirioError, Rope.Cat["some type doesn't know how to compute its bit size (", asRope, ")"]]}; RETURN GetBitSize[indirectType, cc, ct.defaultType]}; CompoundNameScopeInfo: TYPE = REF CompoundNameScopeInfoBody; MaxNumberOfTWContext: CARDINAL = 16; CompoundNameScopeInfoBody: TYPE = RECORD[ ampersandContext1: Node, ampersandContext2: Node, scopeIndex: CARDINAL, targetWorldContexts: ARRAY [1..MaxNumberOfTWContext] OF Node]; CreateCompoundNameScope: PUBLIC PROC[ampersandContext1, ampersandContext2, targetWorldContext: Node, cc: CC] RETURNS[Node] = BEGIN contextType: Type ¬ CedarCode.GetTypeOfNode[targetWorldContext]; scopeIndex: CARDINAL ¬ CCTypes.GetScopeIndex[contextType, cc]; info: CompoundNameScopeInfo ¬ NEW[CompoundNameScopeInfoBody]; type: Type ¬ CreateCedarType[$compoundNameScope, NIL, CompoundNameScopeTypeOps, cc, info]; node: Node ¬ CedarCode.CreateCedarNode[CompoundNameScopeNodeOps, GetIndirectType[type], info]; info.ampersandContext1 ¬ ampersandContext1; info.ampersandContext2 ¬ ampersandContext2; IF scopeIndex > MaxNumberOfTWContext THEN CCE[cirioError] ELSE info.scopeIndex ¬ scopeIndex; info.targetWorldContexts[scopeIndex] ¬ targetWorldContext; FOR i: CARDINAL DECREASING IN [1..scopeIndex) DO info.targetWorldContexts[i] ¬ CedarCode.AdvanceNameScope[info.targetWorldContexts[i+1], cc]; ENDLOOP; RETURN[node]; END; CompoundNameScopeTypeOps: REF CCTypes.CCTypeProcs ¬ NEW[CCTypes.CCTypeProcs ¬[ selectIdField: CompoundNameScopeSelectIdField, loadIdField: CompoundNameScopeLoadIdField]]; CompoundNameScopeSelectIdField: PROC[id: ROPE, fieldIndirectContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: CompoundNameScopeInfo ¬ NARROW[procData]; SELECT Rope.Fetch[id, 0] FROM '&, '_ => {-- we are expected to look into the ampersand contexts code: CirioTypes.Code ¬ CedarCode.CodeToSelectField[id, GetAmpersandContextType[cc]]; type: Type ¬ GetAmpersandVarType[cc]; RETURN[[ CedarCode.ConcatCode[ CedarCode.CodeToGetNameContext[0], code], type]]}; ENDCASE => {-- we are expected to look into the targetWorldContext type: Type ¬ CedarCode.GetTypeOfNode[info.targetWorldContexts[info.scopeIndex]]; select: TypedCode ¬ CCTypes.SelectIdField[id, type, cc]; RETURN [select]}; END; CompoundNameScopeLoadIdField: PROC[id: ROPE, fieldIndirectContext: Type, cc: CC, procData: REF ANY] RETURNS[TypedCode] = BEGIN info: CompoundNameScopeInfo ¬ NARROW[procData]; SELECT Rope.Fetch[id, 0] FROM '&, '_ => {-- we are expected to look into the ampersand contexts varType: Type ¬ GetAmpersandVarType[cc]; code: CirioTypes.Code ¬ CedarCode.ConcatCode[ CedarCode.CodeToSelectField[id, GetAmpersandContextType[cc]], CedarCode.CodeToLoadThroughIndirect[varType]]; RETURN[[code, GetTargetTypeOfIndirect[varType]]]}; ENDCASE => {-- we are expected to look into the targetWorldContext type: Type ¬ CedarCode.GetTypeOfNode[info.targetWorldContexts[info.scopeIndex]]; load: TypedCode ¬ CCTypes.LoadIdField[id, type, cc]; RETURN [load]}; END; CompoundNameScopeNodeOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ getNameContext: CompoundNameScopeGetNameContext, selectField: CompoundNameScopeSelectField, show: CompoundNameScopeShow]]; CompoundNameScopeGetNameContext: PROC [scopeIndex: CARDINAL, node: Node, cc: CC] RETURNS [Node] = BEGIN nsInfo: CompoundNameScopeInfo ¬ NARROW[CedarCode.GetDataFromNode[node]]; IF scopeIndex = 0 THEN RETURN [node] ELSE RETURN [nsInfo.targetWorldContexts[scopeIndex]]; END; CompoundNameScopeSelectField: PROC[id: ROPE, indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN nsInfo: CompoundNameScopeInfo ¬ NARROW[CedarCode.GetDataFromNode[indirectNode]]; indirectData: DoubleAmpersandIndirectInfo ¬ NEW[DoubleAmpersandIndirectInfoBody¬[ id, nsInfo]]; RETURN[CedarCode.CreateCedarNode[DoubleAmpersandVarOps, GetAmpersandVarType[cc], indirectData]]; END; CompoundNameScopeShow: PROC[to: IO.STREAM, node: Node, depth: INT, width: INT, cc: CC] = { nsInfo: CompoundNameScopeInfo ¬ NARROW[CedarCode.GetDataFromNode[node]]; DoPair: PROC [intro: ROPE, n: Node] ~ { to.PutRope[intro]; CedarCode.ShowNode[to, n, depth-1, width, cc]; SS.Bp[to, always, 0]; RETURN}; to.PutChar['{]; DoPair["AmpersandContext1: ", nsInfo.ampersandContext1]; DoPair["AmpersandContext2: ", nsInfo.ampersandContext2]; DoPair["Target World Context: ", nsInfo.targetWorldContexts[nsInfo.scopeIndex] ]; to.PutChar['}]; RETURN}; DoubleAmpersandIndirectInfo: TYPE = REF DoubleAmpersandIndirectInfoBody; DoubleAmpersandIndirectInfoBody: TYPE = RECORD[ id: ROPE, nsInfo: CompoundNameScopeInfo]; DoubleAmpersandVarOps: REF CedarCode.OperationsBody ¬ NEW[CedarCode.OperationsBody¬[ store: StoreToDoubleAmpersandVar, load: LoadFromDoubleAmpersandVar]]; StoreToDoubleAmpersandVar: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = BEGIN indirectData: DoubleAmpersandIndirectInfo ¬ NARROW[CedarCode.GetDataFromNode[indirectNode]]; ampersand2: Node ¬ indirectData.nsInfo.ampersandContext2; ampersand2Type: Type ¬ CedarCode.GetTypeOfNode[ampersand2]; var: Node ¬ CedarCode.SelectFieldFromNode[indirectData.id, ampersand2Type, ampersand2, cc]; varType: Type ¬ CedarCode.GetTypeOfNode[var]; CedarCode.StoreThroughIndirectNode[valType, valNode, varType, var, cc]; END; LoadFromDoubleAmpersandVar: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN indirectData: DoubleAmpersandIndirectInfo ¬ NARROW[CedarCode.GetDataFromNode[indirectNode]]; ampersand1: Node ¬ indirectData.nsInfo.ampersandContext1; ampersand1Type: Type ¬ CedarCode.GetTypeOfNode[ampersand1]; var1: Node ¬ CedarCode.SelectFieldFromNode[indirectData.id, ampersand1Type, ampersand1, cc]; var1Type: Type ¬ CedarCode.GetTypeOfNode[var1]; val1: Node ¬ NIL; val1 ¬ CedarCode.LoadThroughIndirectNode[var1Type, var1, cc ! CCE => IF case = operation THEN {val1 ¬ NIL; CONTINUE}]; IF val1 # NIL THEN RETURN[val1]; BEGIN ampersand2: Node ¬ indirectData.nsInfo.ampersandContext2; ampersand2Type: Type ¬ CedarCode.GetTypeOfNode[ampersand2]; var2: Node ¬ CedarCode.SelectFieldFromNode[indirectData.id, ampersand2Type, ampersand2, cc]; var2Type: Type ¬ CedarCode.GetTypeOfNode[var2]; val2: Node ¬ CedarCode.LoadThroughIndirectNode[var2Type, var2, cc]; RETURN[val2]; END; END; END.. ΰ CCTypesImpl.mesa Copyright Σ 1990, 1992 by Xerox Corporation. All rights reserved. Sturgis: April 2, 1990 4:51 pm PDT theimer May 17, 1989 3:56:07 pm PDT Last changed by Theimer on August 10, 1989 3:17:00 pm PDT Hopcroft July 26, 1989 11:02:36 am PDT Last tweaked by Mike Spreitzer on January 9, 1992 2:32 pm PST Laurie Horton, September 18, 1991 6:04 pm PDT Willie-s, May 14, 1992 12:25 pm PDT (An indirect type will have indirectType=NIL and targetType#NIL. A direct type will have indirectType#NIL and targetType=NIL.) (TypeBody is exported to CirioTypes) 13-Dec-90 MJS: I surveyed all calls on CreateCedarType, and found that only definition types (created in DefinitionsImpl) supply a non-nil defaultType. 16-Dec-91 MJS: DeferringTypes now also supply non-nil defaultTypes. exported to CC should eventually add appropriate error msg stuff a rather crude test. We only get here if the valType is a singleton. I don't know if what I have coded here is correct. What I should be doing is checking that the valType occurs in the varType family. (That would be family inclusion.) This test is stronger than that. (If the varType were a multi-type family including valType, then this test would fail.) However, perhaps any point at which this might be called the varType is aware that it is a special case of a collection of CedarTypes, some of which are multi-element families. This is certainly the case for RefTargetTypes. On the other hand, this test is weaker than family inclusion, because it only checks that the singleton types conform in both directions, not that they are equal. Its ok if we already conform Use the current nameScope [WARNING: at least when loading frame name scopes, a run time type check should be made. This corresponds to handling union types. Therefore, some of this code will migrate out to the Type object routines?] not yet sure what should be here I still don't understand indirect type conformity. However, if one takes the view that an indirect really supplies two procs and that we are checking conformity of those two proc types, then we get the following test. However, this doesn't check higher order features of the indirect. Merely checks that target types are ok. note: valType was the control parameter got to be able to handle non indirect varType types without an error perhaps the first level routine could check for target type = $amnode and treat that as a special case. we really should make a last ditch type check The empty type will show up as the LTarget type of an attempt to store through an indirect to a non singleton family. We want to be sure nothing ever conforms to it The following are exported to CCTypes Here we have the hash table code that forms the basis for conformity checking. This algorithm is not good, but it is correct. Unfortunately, with this algorithm we can never mark any cell as knownToConform. There are several ways to modify the algorithm so that we can apply such marks. (We should visualize a large graph with nodes. Some of the nodes have been initially marked with knownNotToConform. We can mark a node as knownNotToConform if any node so marked is reachable from it. We can mark a node as knownToConform if no node reachable from it is marked knownNotToConform.) (1) do a full scale strongly connected components algorithm. The components are connected together as an acyclic graph. We can now do a depth first walk over the graph. Any component that contains a node marked as knownNotToConform gets all of its nodes marked as knownNotToConform. Any component containing no such node, and from which there is no reachable component containing any such node, can have all of its components marked as knownToConform (2) Have checkConformity return three cases: yes, dontKnow, and no. Never return yes unless we have explored all reachable nodes. return dontKnow whenever we bump into an onStack node. If any subnode returns no, then we mark our current node as knownNotToConform and return no. If all subnodes return yes, then mark our current node as knownToConform and return yes. If some subnode returns dontKnow, then don't mark our current node, and return dontKnow. If we return from the top level with dontKnow, then we are safe in marking that top level node as knownToConform, and returning yes. (In effect here, we know that when we return from the top level node we have explored its entire strongly connected component. We dont know this when we return from any other node.) (3) like 2, except that when we find ourselves marking the top level node as knownToConform, then revisit all reachable nodes and mark them as knownToConform. (This is Demer's proposed scheme.) I shall implement scheme 2. This procedure is performed first on every attempt to perform a coercion access to the local Cedar target world we do this because it is easier to get to the args than to a nested block can't live in a world without a workable CreateNodeFromRefAny CCTypeProcs object style implementations It is neccessary that the default code recurse through CheckConformance Main, to avoid an inner call to CheckConformity applied to the same pair of types. If such an inner call occurred, then the result would be an instant return of yes, incorrectly. NOTE: We do "stripping" of valType and varType to their ground types (the recursive application of underType until a non-definition type is encountered in this routine. Conformance checking should be the only place where definition types aren't transparent to type operations. They matter for conformance-checking because our algorithm basically follows the type graphs for valType and varType and compares them. Stripping the definition types deals with the problem of following down an arbitrary number of definition types in each type graph. Howard thinks that definition types may be nontransparent in other places as well; so we eventually need to check if we've done things right for definition types. -MMT- May 17, 1989 10:39:36 pm PDT Even though this can not recurs back to the same type pair (it can't go through indirects or PROCS, etc) it might be useful to include a hash table mechanism. NOTE: We do "stripping" of valType and varType to their ground types (the recursive application of underType until a non-definition type is encountered in this routine. Conformance checking should be the only place where definition types aren't transparent to type operations. They matter for conformance-checking because our algorithm basically follows the type graphs for valType and varType and compares them. Stripping the definition types deals with the problem of following down an arbitrary number of definition types in each type graph. Howard thinks that definition types may be nontransparent in other places as well; so we eventually need to check if we've done things right for definition types. -MMT- May 17, 1989 10:39:36 pm PDT Compound Name Scopes The name scopes used in Cirio will contain one or more ampersand contexts followed by the target world context. We shall treat the two ampersandContexts as a single context. Writes always go to ampersandContext2, reads go to ampersandContext1 first, then if the name is not there, we try ampersandContext2. advanceNameScope goes to targetWorldContext. Note: these guys are only indirects, there are no stack values WARNING: the world will misbehave in unbelievably bad ways if the first two nodes are not ampersand contexts. Somehow I should check this. an ampersand name is always defined and always has type AmpersandVar (AmpersandVars always contain Nodes) WARNING: a lot of checking should be imposed, i.e., these names scopes are frames, which are essentialy union types. an ampersand name is always defined and always has type AmpersandVar (AmpersandVars always contain Nodes) WARNING: a lot of checking should be imposed, i.e., these names scopes are frames, which are essentialy union types. This select will always succeed, but we get a special indirect which will behave differently for loads and stores. we always store to ampersandContext2 We try to load from ampersandContext1 first. This implementation has the problem that it places empty vars in ampersandContext1. we CONTINUE if we get a CCE[operation], which should only be due to attempting to load from a non existent ampersandVar. it wasn't in ampersand1, so lets try ampersand2 Κ9Š•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ Οeœ7™BKšΟnœ™"Kšœ Οk™#Kšœ9™9K™&K™=K™-K™#K™—šŸ ˜ KšœŸœ-˜CKšœŸœŸœ˜(KšœŸœ₯ŸœZ˜ŽKšœ Ÿœγ˜ςK˜KšœŸœ˜7Kšœ ŸœΛ˜ΫKšŸœ˜Kšœ Ÿœ˜!Kšœ Ÿœ*˜KšŸ˜KšŸœŸœŸœ˜:KšŸœ˜ KšŸœ˜K˜—š ž œŸœŸœ ŸœŸœ˜GKšŸœŸœŸœ ˜/KšŸœ!˜'Kšœ™K˜—šžœŸœŸœ ŸœŸœŸœŸœ˜AKšŸœŸœŸœ˜2KšŸœ(˜.—K˜š žœŸœŸœ ŸœŸœ˜AKšŸœŸœŸœ˜5KšŸœ+˜1K™—K™š žœŸœŸœŸœŸœ˜WKšœ,Ÿœ˜1KšŸœ˜!K˜—šžœŸœŸœŸœŸœŸœŸœ˜OKšœ,Ÿœ˜1KšŸœ"˜(—˜K˜—˜Kšœ1™1—šžœŸœŸœ˜OK˜/K˜7K˜'K˜K˜'K˜/K˜'K˜'K˜3K˜!Kšœ9˜9K˜)K˜#—˜Kšœ™—š žœŸœŸœ ŸœŸœŸœ˜yKš œŸœŸœŸœŸœ˜0—˜Kšœ/™/Kšœ¨™¨KšœΫ™ΫKšœ’™’—šž œŸœŸœ ŸœŸœŸœŸœ˜lKšœŸœŸœ Ÿœ"˜j—K˜šžœŸœŸœ ŸœŸœŸœŸœ˜XKšœŸœŸœ˜K˜—šžœŸœ"Ÿœ ŸœŸœŸœŸœ˜eKšœŸœ;˜B—K˜K˜šžœŸœŸœ ŸœŸœŸœŸœ˜XKšœŸœŸœ˜—K˜šžœŸœŸœ ŸœŸœŸœŸœ˜\KšœŸœŸœ˜—K˜šžœŸœŸœ ŸœŸœŸœŸœ˜TKšœŸœ˜ —˜Kšœ™—š žœŸœ&Ÿœ ŸœŸœŸœ ˜oKšŸ˜šŸœ+Ÿ˜1KšŸœ˜ KšŸœU˜Y—KšŸœ˜—K˜š žœŸœ0Ÿœ ŸœŸœŸœ˜KšŸ˜K˜AšŸœ Ÿ˜KšœŸœ˜*KšŸœŸœ˜!—KšŸœ˜—˜šœ™KšœŸœΘ™Π——šžœŸœŸœŸœ ŸœŸœŸœ ˜gKšŸ˜K˜%K˜X˜˜K˜ K˜ —K˜ —KšŸœ˜KšŸœ˜—K˜šž!œŸœŸœ ŸœŸœŸœŸœŸœ˜`KšœŸœ˜—K˜š žœŸœŸœ ŸœŸœŸœ ˜ZKšŸœ˜K˜—K˜šžœŸœŸœŸœŸœŸœŸœ ŸœŸœ˜wKšœ4˜4KšŸœ˜—K˜šžœŸœŸœŸœŸœŸœŸœ ŸœŸœ˜{K˜Kšœ9ŸœŸœŸœ˜bKšŸœ˜KšœŸœŸœ˜—K˜šžœŸœŸœŸœ˜1KšœŸœ1ŸœŸœ˜HK˜Kšœ ™ —šžœŸœŸœ˜HK˜—K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜šžœŸœŸœ˜NK˜6K˜:K˜.K˜.K˜.K˜ K˜.K˜ K˜ K˜K˜)K˜&—˜KšœΗ™ΗKšœ'™'—š ž#œŸœŸœ ŸœŸœŸœ˜€KšŸ˜šŸœŸœ#ŸœŸœ˜8šŸ˜KšŸ˜K˜6˜6KšœD™D—K™šŸœ$Ÿœ$Ÿ˜QKšŸ˜K˜$K˜$K˜MKšŸœŸœŸœ˜"K˜MKšŸœŸœŸœ˜"KšŸœŸœŸœŸœ˜8KšŸœ ˜KšŸ˜Kš ŸœŸœ>ŸœŸœŸœŸœ˜f—KšŸœ˜——KšŸœ˜—K˜š ž%œŸœ0Ÿœ ŸœŸœŸœ˜–KšŸ˜K˜AKšŸœŸœŸœŸœ˜KšŸœŸ˜˜ KšŸ˜K˜(šŸœ%ŸœŸœ˜AKšŸœŸœ˜—KšŸœ˜—KšŸœ˜#—KšŸœ˜—K˜šžœŸœŸœ ŸœŸœŸœŸœ˜_KšœŸœŸœ˜—K˜š žœŸœŸœ ŸœŸœŸœ˜ZKšœŸœ!˜(—K˜š žœŸœŸœ ŸœŸœŸœ˜ZKšŸ˜K˜4Kš Ÿœ!ŸœŸœŸœŸœ˜\KšŸœ˜—K˜šžœŸœ%ŸœŸœ ŸœŸœŸœ ˜ƒKšŸ˜šŸœŸ˜Kšœ Ÿœ˜KšŸœŸœ" "˜R—KšŸœ˜—˜Kšœg™g—š žœŸœ&Ÿœ ŸœŸœŸœ ˜vKšŸ˜KšŸœ+ŸœŸœ˜=šŸœ.Ÿ˜4KšŸœX˜^—K˜PKšŸœ˜K˜—š žœŸœ+Ÿœ ŸœŸœŸœ ˜rKšŸ˜šŸœŸ˜šœ ˜ KšŸ˜˜-K˜ Kšœ)˜)—KšœVŸ xœ˜ΣKšŸœ˜KšŸœ˜—KšŸœŸœ ˜—KšŸœ˜—K˜K˜š žœŸœ,Ÿœ ŸœŸœŸœ ˜uKšŸ˜˜-K˜˜K˜ K˜;——K˜Kšœ-™-KšŸœ˜KšŸœ˜—K˜š žœŸœŸœ ŸœŸœŸœ ˜bKšŸ˜˜-K˜K˜4—K˜/KšŸœ˜KšŸœ˜K˜—K˜šœ₯™₯K˜Kšœ ŸœŸœ Ÿœ˜-K˜šžœŸœŸœŸœ˜-KšœŸœMŸœ˜j—K˜K˜KšžœŸœŸœ˜KKšžœŸœŸœ˜SK˜—K˜Kšœ%™%K˜Kš žœŸœŸœ!ŸœŸœŸœ˜IK˜š žœŸœŸœ0Ÿœ ŸœŸœ ˜sKšœ"˜"KšœŸœ'Ÿœ-˜_Kšœ Ÿœ'˜7šŸœŸœŸœŸœ˜KšœŸœ$˜-Kšœ8˜8—KšŸœ˜ —K˜šžœŸœŸœŸœ9˜`KšœŸœ'Ÿœ-˜_KšœŸœ*˜4Kšœ#Ÿœ˜)KšŸœ˜—K˜š žœŸœŸœŸœŸœŸœ˜6KšœŸœ'Ÿœ˜;KšœŸœ'Ÿœ˜;KšŸœ&˜,—K˜š žœŸœŸœŸœŸœŸœ˜2KšœŸœ'Ÿœ˜;KšŸœ!˜'—K˜Kš ž œŸœŸœŸœŸœ Ÿœ˜MKš ž œŸœŸœŸœŸœ Ÿœ˜KKš žœŸœŸœŸœŸœ Ÿœ˜QKšžœŸœŸœŸœ&˜HKš ž œŸœŸœŸœŸœ Ÿœ˜KKšž œŸœŸœŸœ#˜BKš ž œŸœŸœŸœŸœ Ÿœ˜KKšž œŸœŸœŸœ#˜BKš žœŸœŸœŸœŸœ Ÿœ˜UKš ž œŸœŸœŸœŸœ Ÿœ˜OKšž œŸœŸœŸœ%˜FKš ž œŸœŸœŸœŸœ Ÿœ˜OKš žœŸœŸœŸœŸœ Ÿœ˜WKšžœŸœŸœŸœ)˜NKš žœŸœŸœŸœŸœ Ÿœ˜cKš žœŸœŸœŸœŸœ Ÿœ˜[Kš žœŸœŸœŸœŸœ Ÿœ)˜fK˜K˜KšœN™N˜K˜šœύ™ύKšœΖ™ΖKšœŠ™ŠKšœΒ™ΒK™Kšœ™—K™š žœŸœ3ŸœŸœ ŸœŸœ˜›KšŸ˜KšœŸœ"˜6Kšœ Ÿœ Ÿœ5˜SK˜šŸœ ŸœŸ˜KšŸ˜Kšœ Ÿœ˜#KšŸœŸœ9Ÿœ˜XKšŸœ˜—K˜šŸœŸ˜%KšŸ˜KšŸœ!Ÿœ ˜PKšŸœ ˜KšŸœ˜—K˜šŸœŸ˜KšŸ˜K˜!K˜K˜<˜šœŸœ˜ KšŸœ  ˜&K˜—KšŸœ˜—š ž œŸœŸœŸœ Ÿœ˜DKšŸ˜Kš œ ŸœŸœŸœŸœ˜(š Ÿœ ŸœŸœŸœŸ˜3š œŸœŸœŸœŸœ ˜-KšŸœŸœ&˜1—KšŸœŸœ,˜7—KšŸœ˜—K˜šž œŸœŸœŸœŸœ ŸœŸœ˜lKšŸ˜Kš œ ŸœŸœŸœŸœ˜1š Ÿœ ŸœŸœŸœŸ˜3š œŸœŸœŸœŸœ ˜-KšŸœŸœ3˜>—KšŸœŸœ9˜D—KšŸœ˜—K˜šžœŸœŸœŸœ ŸœŸœŸœ˜TKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜9š œŸœŸœŸœŸœ ˜-KšŸœŸœ-˜8—KšŸœŸœ3˜>—KšŸœ˜—K˜šž œŸœŸœŸœ ŸœŸœŸœ˜LKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜5š œŸœŸœŸœŸœ ˜-KšŸœŸœ)˜4—KšŸœŸœ/˜:—KšŸœ˜—K˜š ž œŸœŸœŸœ Ÿœ ˜FKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜3š œŸœŸœŸœŸœ ˜-KšŸœŸœ'˜2—KšŸœŸœ-˜8—KšŸœ˜—K˜š žœŸœŸœŸœŸœ Ÿœ˜iKšŸ˜Kš œ ŸœŸœŸœŸœ ˜,š Ÿœ ŸœŸœŸœŸ˜0š œŸœŸœŸœŸœ Ÿœs˜£KšŸœŸœ*˜5—KšŸœŸœ0˜;—KšŸœ˜—K˜š ž œŸœŸœFŸœ ŸœŸœ ˜‡KšŸ˜Kš œ ŸœŸœŸœŸœ˜1š Ÿœ ŸœŸœŸœŸ˜5š œŸœŸœŸœŸœ ˜-KšŸœŸœ:˜E—KšŸœŸœ@˜K—KšŸœ˜—K˜š ž œŸœŸœFŸœ ŸœŸœ ˜‡KšŸ˜Kš œ ŸœŸœŸœŸœ˜1š Ÿœ ŸœŸœŸœŸ˜5š œŸœŸœŸœŸœ ˜-KšŸœŸœ:˜E—KšŸœŸœ@˜K—KšŸœ˜—K˜š ž œŸœŸœ&Ÿœ Ÿœ˜bšŸ˜KšžœŸœŸœ ˜,KšŸ˜Kš œ ŸœŸœŸœŸœ ˜,š Ÿœ ŸœŸœŸœŸ˜5š œŸœŸœŸœŸœ Ÿœw˜§KšŸœŸœ3˜>—KšŸœŸœ9˜D—KšŸœ˜—KšŸœ=˜CKšŸœ˜—K˜š žœŸœŸœ+Ÿœ Ÿœ˜cKšŸ˜Kš œ ŸœŸœŸœŸœ ˜.š Ÿœ ŸœŸœŸœŸ˜1š œŸœŸœŸœŸœ Ÿœn˜žKšŸœŸœ0˜;—KšŸœŸœ6˜A—KšŸœ˜—K˜š žœŸœŸœ#Ÿœ Ÿœ˜ZKšŸ˜Kš œ ŸœŸœŸœŸœ ˜-š Ÿœ ŸœŸœŸœŸ˜0š œŸœŸœŸœŸœ Ÿœl˜œKšŸœŸœ'˜2—KšŸœŸœ-˜8—KšŸœ˜K˜—š žœŸœŸœ.Ÿœ Ÿœ˜gKšŸ˜Kš œ ŸœŸœŸœŸœ ˜.š Ÿœ ŸœŸœŸœŸ˜8š œŸœŸœŸœŸœ ˜-KšŸœŸœ?˜J—KšŸœŸœE˜P—KšŸœ˜K˜—šžœŸœŸœŸœŸœŸœ Ÿœ ˜aKšŸ˜Kš œ ŸœŸœŸœŸœ˜4š Ÿœ ŸœŸœŸœŸ˜/š œŸœŸœŸœŸœ ˜-KšŸœŸœ'˜2—KšŸœŸœ-˜8—KšŸœ˜—K˜š žœŸœŸœŸœ Ÿœ ˜TKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜/š œŸœŸœŸœŸœ ˜-KšŸœŸœ˜&—KšŸœŸœ-˜8—KšŸœ˜K˜—š žœŸœŸœŸœ Ÿœ˜[KšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜;š œŸœŸœŸœŸœ ˜-KšŸœŸœ3˜>—KšŸœŸœ9˜D—KšŸœ˜K˜—š žœŸœŸœ/Ÿœ Ÿœ ˜eKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜0š œŸœŸœŸœŸœ ˜-KšŸœŸœ-˜8—KšŸœŸœ*˜5—KšŸœ˜K˜—šž œŸœŸœŸœŸœ;Ÿœ Ÿœ˜„KšŸ˜Kš œ ŸœŸœŸœŸœ ˜/š Ÿœ ŸœŸœŸœŸ˜4š œŸœŸœŸœŸœ ˜-KšŸœŸœ4˜?—KšŸœŸœ:˜E—KšŸœ˜K˜—šžœŸœŸœŸœŸœ=Ÿœ Ÿœ˜ŠKšŸ˜Kš œ ŸœŸœŸœŸœ ˜/š Ÿœ ŸœŸœŸœŸ˜8š œŸœŸœŸœŸœ ˜-KšŸœŸœ8˜C—KšŸœŸœ>˜I—KšŸœ˜—K˜š žœŸœŸœ,Ÿœ Ÿœ˜aKšŸ˜Kš œ ŸœŸœŸœŸœ˜2š Ÿœ ŸœŸœŸœŸ˜.š œŸœŸœŸœŸœ ˜-KšŸœŸœ-˜8—KšŸœŸœ3˜>—KšŸœ˜K˜—š žœŸœŸœŸœ Ÿœ ˜MKšŸ˜Kš œ ŸœŸœŸœŸœ˜2š Ÿœ ŸœŸœŸœŸ˜-š œŸœŸœŸœŸœ ˜-KšŸœŸœ%˜0—šŸ˜KšŸœ+˜1——KšŸœ˜K˜—š žœŸœŸœŸœŸœ Ÿœ ˜`KšŸ˜Kš œ ŸœŸœŸœŸœ˜1š Ÿœ ŸœŸœŸœŸ˜7š œŸœŸœŸœŸœ ˜-KšŸœŸœ7˜B—KšŸœŸœ=˜H—KšŸœ˜K˜—š ž œŸœŸœŸœŸœ Ÿœ ˜YKšŸ˜Kš œ ŸœŸœŸœŸœ ˜/š Ÿœ ŸœŸœŸœŸ˜2š œŸœŸœŸœŸœ ˜-KšŸœŸœ0˜;—KšŸœŸœ6˜A—KšŸœ˜—K˜š ž œŸœŸœŸœ"Ÿœ Ÿœ ˜gKšŸ˜Kš œ ŸœŸœŸœŸœ˜9š Ÿœ ŸœŸœŸœŸ˜6š œŸœŸœŸœŸœ ˜-KšŸœŸœ>˜I—KšŸœŸœD˜O—KšŸœ˜—K˜š ž œŸœŸœŸœ"Ÿœ Ÿœ ˜eKšŸ˜Kš œ ŸœŸœŸœŸœ˜9š Ÿœ ŸœŸœŸœŸ˜4š œŸœŸœŸœŸœ ˜-KšŸœŸœ<˜G—KšŸœŸœB˜M—KšŸœ˜—K˜š žœŸœŸœ.Ÿœ ŸœŸœ ˜hKšŸ˜Kš œ ŸœŸœŸœŸœ˜2š Ÿœ ŸœŸœŸœŸ˜.š œŸœŸœŸœŸœ ˜-KšŸœŸœ/˜:—KšŸœŸœ5˜@—KšŸœ˜—K˜š žœŸœŸœ.Ÿœ ŸœŸœ ˜hKšŸ˜Kš œ ŸœŸœŸœŸœ˜2š Ÿœ ŸœŸœŸœŸ˜.š œŸœŸœŸœŸœ ˜-KšŸœŸœ/˜:—KšŸœŸœ5˜@—KšŸœ˜—K˜šžœŸœŸœŸœ ŸœŸœŸœŸœ˜YKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœ"ŸœŸ˜>š œŸœŸœŸœŸœ ˜-KšŸœŸœ2˜=—KšŸœŸœ8˜C—šŸœ˜K˜——šž œŸœŸœŸœ ŸœŸœŸœ˜MKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜5š œŸœŸœŸœŸœ9˜[KšŸœŸœ)˜4—KšŸœŸœ/˜:—KšŸœ˜—K˜šž œŸœŸœŸœ ŸœŸœŸœ˜PKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜6š œŸœŸœŸœŸœ ˜-KšŸœŸœ*˜5—KšŸœŸœ0˜;—KšŸœ˜—K˜š ž œŸœŸœŸœ ŸœŸœ˜NKšŸ˜Kš œ ŸœŸœŸœŸœ˜)š Ÿœ ŸœŸœŸœŸ˜6š œŸœŸœŸœŸœ ˜-KšŸœŸœ*˜5—KšŸœŸœ0˜;—KšŸœ˜—K˜šžœŸœŸœŸœŸœ ŸœŸœŸœ˜lKšŸœŸœŸœ˜%Kš œŸœŸœŸœŸœ˜Kšœ6˜6KšŸœ˜—K˜šž œŸœŸœŸœŸœ&ŸœŸœ Ÿœ˜jKš œ ŸœŸœŸœŸœ˜)KšŸœŸœŸœ˜0š Ÿœ ŸœŸœŸœŸ˜2š œŸœŸœŸœŸœ ŸœT˜…KšŸœA˜E—KšŸœG˜K—Kšœ˜K˜KšœŸœŸœ˜K˜š žœŸœŸœŸœŸœ Ÿœ˜8KšŸœ ˜ Kšœ ŸœŸœ ˜KšŸœ ˜ KšŸœ˜—K˜šž œŸœŸœŸœŸœ ŸœŸœŸœ˜LKšŸœ˜Kšœ˜KšŸœ˜—K˜šžœŸœŸœŸœŸœŸœŸœŸœ Ÿœ˜xKšŸœ ˜ šœ2˜2KšœŸœŸœ ˜—KšŸœ ˜ KšŸœ˜—K˜šžœŸœŸœŸœŸœ&ŸœŸœŸœŸœ Ÿœ˜€Kšž œŸœ9˜IKšœ"˜"—K˜—š žœŸœŸœ!ŸœŸœ ˜XKšœ1˜1KšŸœ,˜2—K˜š žœŸœŸœ#Ÿœ ŸœŸœ ˜gKš œ ŸœŸœŸœŸœ˜1š Ÿœ ŸœŸœŸœŸœ˜:Kšœ9˜9KšŸœN˜T—KšŸœŸœŸœŸœF˜dKšŸœ<˜BK˜—K˜šž œŸœŸœŸœ ŸœŸœŸœ˜UKš œ ŸœŸœŸœŸœ˜1š Ÿœ ŸœŸœŸœŸœ˜2Kšœ9˜9KšŸœA˜G—šŸœŸœŸœ˜KšœŸœ$˜0KšŸœ]˜`—KšŸœ/˜5K˜——šœ™Kšœo™oK˜K˜KšœŸœŸœ˜K˜KšœΓ™ΓK™Kšœ,™,K˜Kšœ>™>K™KšŸœ„™‹—š žœŸœŸœEŸœŸœ˜|KšŸ˜K˜@Kšœ Ÿœ*˜>KšœŸœ˜=Kšœ1Ÿœ&˜ZK˜^K˜+K˜+KšŸœ#ŸœŸœ ˜9KšŸœ˜"K˜:š ŸœŸœŸ œŸœŸ˜0K˜\KšŸœ˜—KšŸœ˜ KšŸœ˜—K˜šžœŸœŸœF˜}Kšœ,˜,—K˜šžœŸœŸœ"Ÿœ ŸœŸœŸœ ˜zKšŸ˜KšœŸœ ˜/KšŸœŸ˜šœ  6˜AKšœD™DKšœ$™$K˜UK˜%šŸœ˜šœ˜Kšœ"˜"Kšœ˜—Kšœ˜——šŸœ 6˜BKšŸœm™tK˜PK˜8KšŸœ ˜—KšŸœ˜—K˜šžœŸœŸœ"Ÿœ ŸœŸœŸœ ˜xKšŸ˜KšœŸœ ˜/KšŸœŸ˜šœ  6˜AKšœD™DKšœ$™$K˜(˜-K˜=K˜.—KšŸœ,˜2—šŸœ 6˜BKšŸœm™tK˜PK˜4KšŸœ ˜—KšŸœ˜—K˜K˜šžœŸœŸœ˜WK˜0K˜*K˜—K˜š ‘œŸœŸœŸœŸœ ˜aKšŸ˜Kšœ Ÿœ"˜HKšŸœŸœŸœ˜$KšŸœŸœ*˜5KšŸœ˜—K˜š žœŸœŸœ.ŸœŸœ˜lKšŸ˜Kšœr™rKšœ Ÿœ*˜PKšœ,Ÿœ0˜_KšŸœZ˜`KšŸœ˜—K˜šžœŸœŸœŸœŸœ ŸœŸœ˜ZKšœ Ÿœ"˜HšžœŸœ Ÿœ˜'K˜Kšœ.˜.K˜KšŸœ˜—K˜Kšœ8˜8Kšœ8˜8KšœQ˜QK˜KšŸœ˜—K˜KšœŸœŸœ!˜Hšœ!ŸœŸœ˜/KšœŸœ˜ K˜—K˜šžœŸœŸœ˜TK˜!K˜#—˜Kšœ$™$—šžœŸœKŸœ˜pKšŸ˜Kšœ,Ÿœ*˜\K˜9K˜;K˜[K˜-K˜GKšŸœ˜—˜Kšœ,™,KšœS™S—šžœŸœ-ŸœŸœ˜`KšŸ˜Kšœ,Ÿœ*˜\K˜9K˜;K˜\K˜/šœ Ÿœ˜K™KšœŸœ Ÿœ]™x—˜;Kš œŸœŸœŸœ ŸœŸœ˜:—K˜KšŸœŸœŸœŸœ˜ K˜šœ/™/KšŸ˜K˜9K˜;K˜\K˜/K˜CK˜KšŸœ˜ KšŸœ˜—KšŸœ˜K˜——KšŸœ˜—…—ΉΎ(