DIRECTORY ConvertUnsafe USING [EqualSubStrings, SubString], SymbolOps USING [FindMdi, FindString, FirstCtxSe, NextSe, SearchContext, STB, SubStringForName, TypeForm, UnderType], Symbols USING [CSEIndex, CTXIndex, FirstStandardCtx, ISEIndex, ISENull, LastStandardCtx, MDIndex, MDNull, Name, nullName, nullType, OwnMdi, RecordSEIndex, RecordSENull, SEIndex, typeANY, typeTYPE], SymbolTable USING [], SymbolTablePrivate USING [SymbolTableBaseRep], Types USING [Handle]; TypesImpl: PROGRAM IMPORTS ConvertUnsafe, SymbolOps EXPORTS SymbolTable, Types = { OPEN Symbols; STB: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; NameHandle: TYPE = RECORD [ stb: STB, name: Name]; EqualIds: PROC [id1, id2: NameHandle] RETURNS [BOOL] = { IF id1 = id2 THEN RETURN [TRUE] ELSE { ss1: ConvertUnsafe.SubString ¬ SymbolOps.SubStringForName[id1.stb, id1.name]; ss2: ConvertUnsafe.SubString ¬ SymbolOps.SubStringForName[id2.stb, id2.name]; RETURN [ConvertUnsafe.EqualSubStrings[ss1, ss2]]; }; }; CTXHandle: TYPE = RECORD [ stb: STB, ctx: CTXIndex]; EqContexts: PROC [context1, context2: CTXHandle] RETURNS [BOOL] = { b1: STB ¬ context1.stb; b2: STB ¬ context2.stb; ctx1, ctx2: CTXIndex; mdi1, mdi2: MDIndex; IF context1 = context2 THEN RETURN [TRUE]; IF context1.ctx IN [FirstStandardCtx .. LastStandardCtx] THEN RETURN [context1.ctx = context2.ctx]; -- predefined types WITH c1: b1.ctxb[context1.ctx] SELECT FROM simple => {mdi1 ¬ OwnMdi; ctx1 ¬ context1.ctx}; included => {mdi1 ¬ c1.module; ctx1 ¬ c1.map}; ENDCASE => ERROR; WITH c2: b2.ctxb[context2.ctx] SELECT FROM simple => {mdi2 ¬ OwnMdi; ctx2 ¬ context2.ctx}; included => {mdi2 ¬ c2.module; ctx2 ¬ c2.map}; ENDCASE => ERROR; RETURN [ctx1 = ctx2 AND b1.mdb[mdi1].stamp = b2.mdb[mdi2].stamp]; }; OpaqueValue: PUBLIC PROC [type: Types.Handle, base: STB] RETURNS [val: Types.Handle] = { b1: STB ¬ type.stb; val ¬ type; -- the default WITH t1: b1.seb[type.sei] SELECT FROM opaque => { mdi1: MDIndex = WITH c1: b1.ctxb[b1.seb[t1.id].idCtx] SELECT FROM included => c1.module, imported => b1.ctxb[c1.includeLink].module, ENDCASE => OwnMdi; mdi2: MDIndex = SymbolOps.FindMdi[base, b1.mdb[mdi1].stamp]; IF mdi2 # MDNull AND base.mdb[mdi2].exported THEN { ss: ConvertUnsafe.SubString; sei2: ISEIndex; ss ¬ SymbolOps.SubStringForName[b1, b1.seb[t1.id].hash]; sei2 ¬ SymbolOps.SearchContext[base, SymbolOps.FindString[base, ss], base.mainCtx]; IF sei2 # ISENull AND base.seb[sei2].idType = typeTYPE AND base.seb[sei2].public AND base.seb[sei2].constant THEN val ¬ [base, SymbolOps.UnderType[base, sei2]]; }; }; ENDCASE; }; Equivalent: PUBLIC PROC [type1, type2: Types.Handle] RETURNS [BOOL] = { IF type1 = type2 THEN RETURN [TRUE]; RETURN [EqualTypes[type1, type2 ! Resolved => {RESUME[FALSE]}; Matched => {RESUME[FALSE]}] ] }; EquivalentUnder: PUBLIC PROC [type1, type2: SEHandle] RETURNS [BOOL] = { IF type1 = type2 THEN RETURN [TRUE] ELSE { ut1: Types.Handle = [type1.stb, SymbolOps.UnderType[type1.stb, type1.sei]]; ut2: Types.Handle = [type2.stb, SymbolOps.UnderType[type2.stb, type2.sei]]; IF ut1 = ut2 THEN RETURN [TRUE]; RETURN [EqualTypes[ut1, ut2 ! Resolved => {RESUME[FALSE]}; Matched => {RESUME[FALSE]}] ]; }; }; Matched: SIGNAL [m1, m2: Types.Handle] RETURNS [BOOL] = CODE; EqualTypes: PROC [type1, type2: Types.Handle] RETURNS [BOOL] = { b1: STB = type1.stb; b2: STB = type2.stb; sei1: CSEIndex = type1.sei; sei2: CSEIndex = type2.sei; IF b1 = b2 AND sei1 = sei2 THEN RETURN [TRUE]; IF sei1 = typeANY OR sei2 = typeANY THEN RETURN [TRUE]; IF (b1.seb[sei1].typeTag = opaque) # (b2.seb[sei2].typeTag = opaque) THEN { nt1: Types.Handle = OpaqueValue[type1, b2]; nt2: Types.Handle = OpaqueValue[type2, b1]; IF nt1 # type1 OR nt2 # type2 THEN RETURN [EqualTypes[nt1, nt2]]; }; WITH t1: b1.seb[sei1] SELECT FROM basic => WITH t2: b2.seb[sei2] SELECT FROM basic => RETURN [t1.code = t2.code]; ENDCASE; enumerated => WITH t2: b2.seb[sei2] SELECT FROM enumerated => { painted: BOOL = t1.painted; IF painted # t2.painted THEN RETURN [FALSE]; IF painted THEN RETURN [EqContexts[[b1, t1.valueCtx], [b2, t2.valueCtx]]]; RETURN [MatchConstants[[b1, t1.valueCtx], [b2, t2.valueCtx]]]; }; ENDCASE; record => WITH t2: b2.seb[sei2] SELECT FROM record => { painted: BOOL = t1.painted; IF painted # t2.painted THEN RETURN [FALSE]; IF t1.bitOrder # t2.bitOrder THEN RETURN [FALSE]; IF painted THEN RETURN [EqContexts[[b1, t1.fieldCtx], [b2, t2.fieldCtx]]]; IF t1.argument # t2.argument THEN RETURN [FALSE]; RETURN [ (SIGNAL Matched[type1, type2]) OR MatchFields[ [b1, LOOPHOLE[sei1]], [b2, LOOPHOLE[sei2]] ! Matched => {IF m1 = type1 AND m2 = type2 THEN RESUME[TRUE]} ]]; }; ENDCASE; ref => WITH t2: b2.seb[sei2] SELECT FROM ref => RETURN [(t1.counted = t2.counted) AND (t1.var = t2.var) AND (t1.readOnly = t2.readOnly) AND (t1.ordered = t2.ordered) AND Equal[[b1, t1.refType], [b2, t2.refType]]]; ENDCASE; array => WITH t2: b2.seb[sei2] SELECT FROM array => { IF t1.packed # t2.packed THEN RETURN [FALSE]; IF t1.bitOrder # t2.bitOrder THEN RETURN [FALSE]; RETURN [Equal[[b1, t1.componentType], [b2, t2.componentType]] AND Equal[[b1, t1.indexType], [b2, t2.indexType]]]; }; ENDCASE; arraydesc => WITH t2: b2.seb[sei2] SELECT FROM arraydesc => IF t1.readOnly = t2.readOnly THEN RETURN [Equal[[b1, t1.describedType], [b2, t2.describedType]]]; ENDCASE; transfer => WITH t2: b2.seb[sei2] SELECT FROM transfer => RETURN [(t1.mode = t2.mode) AND (t1.safe = t2.safe) AND EqualTypes[[b2, t2.typeIn], [b1, t1.typeIn]] AND EqualTypes[[b1, t1.typeOut], [b2, t2.typeOut]]]; ENDCASE; union => WITH t2: b2.seb[sei2] SELECT FROM union => RETURN [EqContexts[[b1, t1.caseCtx], [b2, t2.caseCtx]]]; ENDCASE; sequence => WITH t2: b2.seb[sei2] SELECT FROM sequence => RETURN [t1.packed = t2.packed AND t1.controlled = t2.controlled AND Equal[[b1, t1.componentType], [b2, t2.componentType]] AND MatchTags[[b1, t1.tagSei], [b2, t2.tagSei]]]; ENDCASE; relative => WITH t2: b2.seb[sei2] SELECT FROM relative => RETURN [Equal[[b1, t1.baseType], [b2, t2.baseType]] AND Equal[[b1, t1.offsetType], [b2, t2.offsetType]]]; ENDCASE; opaque => WITH t2: b2.seb[sei2] SELECT FROM opaque => RETURN [EqContexts[[b1, b1.seb[t1.id].idCtx], [b2, b2.seb[t2.id].idCtx]] AND EqualIds[[b1, b1.seb[t1.id].hash], [b2, b2.seb[t2.id].hash]]]; ENDCASE; zone => WITH t2: b2.seb[sei2] SELECT FROM zone => RETURN [(t1.mds = t2.mds AND t1.counted = t2.counted)]; ENDCASE; subrange => WITH t2: b2.seb[sei2] SELECT FROM subrange => RETURN [Equal[[b1, t1.rangeType], [b2, t2.rangeType]] AND (~t1.filled OR ~t2.filled OR (t1.origin = t2.origin AND t1.empty = t2.empty AND (t1.empty OR t1.range = t2.range)))]; ENDCASE; real => WITH t2: b2.seb[sei2] SELECT FROM real => RETURN [t1.length = t2.length]; ENDCASE; signed => WITH t2: b2.seb[sei2] SELECT FROM signed => RETURN [t1.length = t2.length]; ENDCASE; unsigned => WITH t2: b2.seb[sei2] SELECT FROM unsigned => RETURN [t1.length = t2.length]; ENDCASE; any => WITH t2: b2.seb[sei2] SELECT FROM any => RETURN [TRUE]; ENDCASE; nil => RETURN [sei1 = sei2]; ENDCASE; RETURN [FALSE] }; SEHandle: TYPE = RECORD [ stb: STB, sei: SEIndex]; Resolved: SIGNAL [se1, se2: SEHandle] RETURNS [BOOL] = CODE; Equal: PROC [type1, type2: SEHandle] RETURNS [BOOL] = { b1: STB = type1.stb; b2: STB = type2.stb; sei1: SEIndex = type1.sei; sei2: SEIndex = type2.sei; IF b1 = b2 AND sei1 = sei2 THEN RETURN [TRUE]; IF b1.seb[sei1].seTag = id AND b2.seb[sei2].seTag = id THEN RETURN [((SIGNAL Resolved[type1, type2]) OR EqualTypes[ [b1, SymbolOps.UnderType[b1, sei1]], [b2, SymbolOps.UnderType[b2, sei2]] ! Resolved => {IF se1 = type1 AND se2 = type2 THEN RESUME[TRUE]}])]; RETURN [EqualTypes[ [b1, SymbolOps.UnderType[b1, sei1]], [b2, SymbolOps.UnderType[b2, sei2]]]]; }; Assignable: PUBLIC PROC [typeL, typeR: Types.Handle] RETURNS [BOOL] = { IF typeL = typeR OR typeL.sei = typeANY OR typeR.sei = typeANY THEN RETURN [TRUE] ELSE { ENABLE {Resolved => {RESUME[FALSE]}; Matched => {RESUME[FALSE]}}; IF FreeAssignable[typeL, typeR, $val] THEN RETURN [TRUE]; SELECT SymbolOps.TypeForm[typeL.stb, typeL.sei] FROM record, opaque => RETURN [ConformingVariant[typeL, typeR]]; ENDCASE; RETURN [FreeAssignable[FullRangeType[typeL], FullRangeType[typeR], $val]]; }; }; Mode: TYPE = {val, ref}; FreeAssignable: PROC [typeL, typeR: Types.Handle, mode: Mode] RETURNS [BOOL] = { bL: STB ¬ typeL.stb; bR: STB ¬ typeR.stb; seiL: CSEIndex = typeL.sei; seiR: CSEIndex = typeR.sei; IF typeL = typeR OR seiL = typeANY OR seiR = typeANY THEN RETURN [TRUE]; IF (bL.seb[seiL].typeTag = opaque) # (bR.seb[seiR].typeTag = opaque) THEN { nt1: Types.Handle = OpaqueValue[typeL, bR]; nt2: Types.Handle = OpaqueValue[typeR, bL]; IF nt1 # typeL OR nt2 # typeR THEN RETURN [FreeAssignable[nt1, nt2, mode]]; }; IF Equivalent[typeL, typeR] THEN RETURN [TRUE]; WITH tR: bR.seb[seiR] SELECT FROM record => WITH tL: bL.seb[seiL] SELECT FROM record => { IF tL.painted OR tR.painted THEN RETURN [FALSE]; IF tL.bitOrder # tR.bitOrder THEN RETURN [FALSE]; IF tL.argument # tR.argument THEN RETURN [FALSE]; RETURN [ (SIGNAL Matched[typeL, typeR]) OR CheckFields[ [bL, LOOPHOLE[seiL]], [bR, LOOPHOLE[seiR]], mode ! Matched => {IF m1 = typeL AND m2 = typeR THEN RESUME[TRUE]} ]]; }; ENDCASE; ref => WITH tL: bL.seb[seiL] SELECT FROM ref => { IF tL.counted # tR.counted THEN RETURN [FALSE]; IF tL.var # tR.var THEN RETURN [FALSE]; IF tL.ordered AND NOT tR.ordered THEN RETURN [FALSE]; IF tR.readOnly AND NOT tL.readOnly THEN RETURN [FALSE]; { uL: CSEIndex = SymbolOps.UnderType[bL, tL.refType]; uR: CSEIndex = SymbolOps.UnderType[bR, tR.refType]; IF Equivalent[[bL, uL], [bR, uR]] THEN RETURN [TRUE]; IF tL.readOnly THEN IF Conformable[[bL, uL], [bR, uR], $ref] THEN RETURN [TRUE]; WITH xL: bL.seb[uL] SELECT FROM record, opaque => IF ConformingVariant[[bL, uL], [bR, uR]] THEN RETURN [TRUE]; any => RETURN [TRUE]; array => WITH xR: bR.seb[uR] SELECT FROM array => { IF tL.counted THEN RETURN [FALSE]; IF xL.packed # xR.packed THEN RETURN [FALSE]; IF xL.bitOrder # xR.bitOrder THEN RETURN [FALSE]; IF NOT EquivalentUnder[ [bL, xL.componentType], [bR, xR.componentType]] THEN RETURN [FALSE]; { indexL: CSEIndex = SymbolOps.UnderType[bL, xL.indexType]; indexR: CSEIndex = SymbolOps.UnderType[bR, xR.indexType]; IF FreeAssignable[ [bR, indexR], [bL, indexL], $val] THEN RETURN [TRUE]; }; }; ENDCASE; ENDCASE; }; }; ENDCASE; array => WITH tL: bL.seb[seiL] SELECT FROM array => { packed: BOOL = tL.packed; IF packed # tR.packed THEN RETURN [FALSE]; IF tL.bitOrder # tR.bitOrder THEN RETURN [FALSE]; IF EquivalentUnder[[bL, tL.indexType], [bR, tR.indexType]] THEN { cL: SEIndex = tL.componentType; cR: SEIndex = tR.componentType; IF EquivalentUnder[[bL, cL], [bR, cR]] THEN RETURN [TRUE]; IF NOT packed THEN IF Conformable[[bL, cL], [bR, cR], mode] THEN RETURN [TRUE]; }; }; ENDCASE; arraydesc => WITH tL: bL.seb[seiL] SELECT FROM arraydesc => RETURN [(tL.readOnly OR ~tR.readOnly) AND Covering[ [bL, SymbolOps.UnderType[bL, tL.describedType]], [bR, SymbolOps.UnderType[bR, tR.describedType]]]]; ENDCASE; transfer => WITH tL: bL.seb[seiL] SELECT FROM transfer => { SELECT tL.mode FROM tR.mode => {}; error => IF tR.mode # signal THEN RETURN [FALSE]; ENDCASE => RETURN [FALSE]; IF SymbolOps.TypeForm[bL, tL.typeIn] # any THEN IF NOT FreeAssignable[[bR, tR.typeIn], [bL, tL.typeIn], mode] THEN RETURN [FALSE]; IF SymbolOps.TypeForm[bL, tL.typeOut] # any THEN IF NOT FreeAssignable[[bL, tL.typeOut], [bR, tR.typeOut], mode] THEN RETURN [FALSE]; IF tL.safe AND NOT tR.safe THEN { IF tL.typeIn = nullType AND tL.typeOut = nullType THEN SELECT tL.mode FROM process => RETURN [TRUE]; ENDCASE; RETURN [FALSE]; }; RETURN [TRUE]; }; ENDCASE; relative => WITH tL: bL.seb[seiL] SELECT FROM relative => RETURN [EquivalentUnder[[bL, tL.baseType], [bR, tR.baseType]] AND FreeAssignable[ FullRangeType[[bL, SymbolOps.UnderType[bL, tL.offsetType]]], FullRangeType[[bR, SymbolOps.UnderType[bR, tR.offsetType]]], mode]]; ENDCASE; subrange => RETURN [ FreeAssignable[FullRangeType[typeL], FullRangeType[typeR], mode] AND (WITH tL: bL.seb[seiL] SELECT FROM subrange => ~tL.filled OR ~tR.filled OR (tL.origin = tR.origin AND (tR.empty OR (~tL.empty AND tL.range >= tR.range))), ENDCASE => (~tR.filled OR tR.origin = 0))]; real => WITH tL: bL.seb[seiL] SELECT FROM real => RETURN [tL.length = tR.length]; ENDCASE; signed => WITH tL: bL.seb[seiL] SELECT FROM signed => RETURN [tL.length = tR.length]; unsigned => RETURN [tL.length = tR.length]; ENDCASE; unsigned => WITH tL: bL.seb[seiL] SELECT FROM unsigned => RETURN [tL.length = tR.length]; signed => RETURN [tL.length = tR.length]; ENDCASE; ENDCASE; RETURN [FALSE]; }; Conformable: PROC [type1, type2: SEHandle, mode: Mode] RETURNS [BOOL] = { b1: STB = type1.stb; b2: STB = type2.stb; sei1: SEIndex = type1.sei; sei2: SEIndex = type2.sei; IF sei1 = sei2 AND b1 = b2 THEN RETURN [TRUE]; IF b1.seb[sei1].seTag = id AND b2.seb[type2.sei].seTag = id THEN { IF SIGNAL Resolved[type1, type2] THEN RETURN [TRUE]; RETURN [FreeAssignable[ [b1, SymbolOps.UnderType[b1, sei1]], [b2, SymbolOps.UnderType[b2, sei2]], mode ! Resolved => {IF se1 = type1 AND se2 = type2 THEN RESUME[TRUE]}]]; }; RETURN [FreeAssignable[ [b1, SymbolOps.UnderType[b1, sei1]], [b2, SymbolOps.UnderType[b2, sei2]], mode]]; }; ConformingVariant: PROC [typeL, typeR: Types.Handle] RETURNS [BOOL] = { DO IF Equivalent[typeL, typeR] THEN RETURN [TRUE]; WITH tR: typeR.stb.seb[typeR.sei] SELECT FROM record => WITH tV: tR SELECT FROM linked => {typeR.sei ¬ SymbolOps.UnderType[typeR.stb, tV.linkType]; LOOP}; ENDCASE; ENDCASE; RETURN [FALSE]; ENDLOOP; }; RecordHandle: TYPE = RECORD [ stb: STB, sei: RecordSEIndex]; MatchFields: PROC [rec1, rec2: RecordHandle] RETURNS [BOOL] = { b1: STB = rec1.stb; b2: STB = rec2.stb; SELECT TRUE FROM rec1.sei = RecordSENull OR rec2.sei = RecordSENull => RETURN [rec1.sei = rec2.sei]; EqContexts[[b1, b1.seb[rec1.sei].fieldCtx], [b2, b2.seb[rec2.sei].fieldCtx]] => RETURN [TRUE]; ENDCASE => { sei1: ISEIndex ¬ SymbolOps.FirstCtxSe[b1, b1.seb[rec1.sei].fieldCtx]; sei2: ISEIndex ¬ SymbolOps.FirstCtxSe[b2, b2.seb[rec2.sei].fieldCtx]; UNTIL sei1 = ISENull OR sei2 = ISENull DO IF NOT EqualIds[[b1, b1.seb[sei1].hash], [b2, b2.seb[sei2].hash]] THEN RETURN [FALSE]; IF NOT Equal[[b1, b1.seb[sei1].idType], [b2, b2.seb[sei2].idType]] THEN RETURN [FALSE]; sei1 ¬ SymbolOps.NextSe[b1, sei1]; sei2 ¬ SymbolOps.NextSe[b2, sei2]; ENDLOOP; RETURN [sei1 = sei2]; }; }; CheckFields: PROC [rec1, rec2: RecordHandle, mode: Mode] RETURNS [BOOL] = { b1: STB = rec1.stb; b2: STB = rec2.stb; SELECT TRUE FROM rec1.sei = RecordSENull OR rec2.sei = RecordSENull => RETURN [rec1.sei = rec2.sei]; EqContexts[[b1, b1.seb[rec1.sei].fieldCtx], [b2, b2.seb[rec2.sei].fieldCtx]] => RETURN [TRUE]; ENDCASE => { checkIds: BOOL = NOT (b1.seb[rec1.sei].hints.unifield OR b2.seb[rec2.sei].hints.unifield); sei1: ISEIndex ¬ SymbolOps.FirstCtxSe[b1, b1.seb[rec1.sei].fieldCtx]; sei2: ISEIndex ¬ SymbolOps.FirstCtxSe[b2, b2.seb[rec2.sei].fieldCtx]; UNTIL sei1 = ISENull OR sei2 = ISENull DO IF NOT Conformable[[b1, b1.seb[sei1].idType], [b2, b2.seb[sei2].idType], mode] THEN RETURN [FALSE]; IF checkIds AND b1.seb[sei1].hash # nullName AND b2.seb[sei2].hash # nullName AND NOT EqualIds[[b1, b1.seb[sei1].hash], [b2, b2.seb[sei2].hash]] THEN RETURN [FALSE]; sei1 ¬ SymbolOps.NextSe[b1, sei1]; sei2 ¬ SymbolOps.NextSe[b2, sei2]; ENDLOOP; RETURN [sei1 = sei2]; }; }; MatchConstants: PROC [context1, context2: CTXHandle] RETURNS [BOOL] = { b1: STB = context1.stb; b2: STB = context2.stb; sei1, sei2: ISEIndex; IF EqContexts[context1, context2] THEN RETURN [TRUE]; sei1 ¬ SymbolOps.FirstCtxSe[b1, context1.ctx]; sei2 ¬ SymbolOps.FirstCtxSe[b2, context2.ctx]; UNTIL sei1 = ISENull OR sei2 = ISENull DO IF NOT EqualIds[[b1, b1.seb[sei1].hash], [b2, b2.seb[sei2].hash]] THEN RETURN [FALSE]; sei1 ¬ SymbolOps.NextSe[b1, sei1]; sei2 ¬ SymbolOps.NextSe[b2, sei2]; ENDLOOP; RETURN [sei1 = sei2]; }; ISEHandle: TYPE = RECORD [ stb: STB, sei: ISEIndex]; MatchTags: PROC [tag1, tag2: ISEHandle] RETURNS [BOOL] = { b1: STB = tag1.stb; b2: STB = tag2.stb; RETURN [ EqualIds[[b1, b1.seb[tag1.sei].hash], [b2, b2.seb[tag2.sei].hash]] AND Equal[[b1, b1.seb[tag1.sei].idType], [b2, b2.seb[tag2.sei].idType]]] }; Covering: PROC [typeL, typeR: Types.Handle] RETURNS [BOOL] = { IF Equivalent[typeL, typeR] THEN RETURN [TRUE] ELSE { bL: STB = typeL.stb; bR: STB = typeR.stb; WITH tL: bL.seb[typeL.sei] SELECT FROM array => WITH tR: bR.seb[typeR.sei] SELECT FROM array => { packed: BOOL = tL.packed; IF packed # tR.packed THEN RETURN [FALSE]; IF tL.bitOrder # tR.bitOrder THEN RETURN [FALSE]; IF NOT EquivalentUnder[ [bL, tL.componentType], [bR, tR.componentType]] THEN RETURN [FALSE]; RETURN [Conformable[[bL, tL.indexType], [bR, tR.indexType], $val]]; }; ENDCASE; ENDCASE; RETURN [FALSE]; }; }; FullRangeType: PROC [type: Types.Handle] RETURNS [Types.Handle] = { sei: CSEIndex ¬ type.sei; DO WITH type.stb.seb[sei] SELECT FROM subrange => sei ¬ SymbolOps.UnderType[type.stb, rangeType]; ENDCASE => EXIT; ENDLOOP; RETURN [[type.stb, sei]]; }; }. p TypesImpl.mesa Copyright Σ 1985, 1986, 1987, 1989, 1991 by Xerox Corporation. All rights reserved. Russ Atkinson (RRA) May 22, 1989 3:00:25 pm PDT Satterthwaite, June 18, 1986 10:54:56 am PDT Sweet June 4, 1986 9:44:22 am PDT Internal utilities note: must resample b1 & b2 if any table allocations occur (none do now) note: must resample if any table allocations occur At this point we know what the exported type is. We must be careful (the test for constant) to not try to take the undertype before there really is a type! Type relations SAFE PROCESS and UNSAFE PROCESS really are equivalent Auxiliary predicates ΚΫ•NewlineDelimiter –(cedarcode) style™codešœ™Kšœ ΟeœI™TJ™/JšΟy,™,Jšž!™!—˜šΟk ˜ KšœŸœ˜1Kšœ Ÿœ:Ÿœ)˜uKšœŸœΈ˜ΕKšœ Ÿœ˜KšœŸœ˜.KšœŸœ ˜——headšΟn œŸ˜KšŸœ˜ KšŸœ˜KšŸœ ˜ K˜KšŸœŸœŸœ˜#KšœŸœŸœ)˜H—šœ™šœ ŸœŸœ˜KšœŸœ˜ K˜ K˜—š œŸœŸœŸœ˜8šŸœ ˜ KšŸœŸœŸœ˜šŸœ˜KšœM˜MKšœM˜MKšŸœ+˜1K˜——Kšœ˜K˜—šœ ŸœŸœ˜KšœŸœ˜ K˜K˜—š  œŸœ!ŸœŸœ˜CKšœŸœ˜šœŸœ˜KšœH™H—K˜K˜KšŸœŸœŸœŸœ˜*šŸœŸœ'Ÿ˜=KšŸœ Οc˜9—šŸœŸœŸ˜*K˜/K˜.KšŸœŸœ˜—šŸœŸœŸ˜*K˜/K˜.KšŸœŸœ˜—KšŸœŸœ*˜AKšœ˜K˜—š  œŸ œŸœŸœ˜XšœŸœ ˜K™2—Kšœ ‘˜šŸœŸœŸ˜%˜ šœŸœ"ŸœŸ˜AK˜K˜+KšŸœ ˜—K˜<šŸœŸœŸœ˜3K˜K˜K˜8K˜Sš ŸœŸœ"ŸœŸœŸ˜qK™œK˜.—K˜—K˜—KšŸœ˜—Kšœ˜K˜——šœ™š   œŸœŸœŸœŸœ˜GKšŸœŸœŸœŸœ˜$šŸœ˜Kš œŸœŸœŸœŸœ˜<—šœ˜K˜——š  œŸœŸœŸœŸœ˜HšŸœ˜KšŸœŸœŸœ˜šŸœ˜KšœK˜KKšœK˜KKšŸœ ŸœŸœŸœ˜ šŸœ˜Kš œŸœŸœŸœŸœ˜=—K˜——šœ˜K˜——Kš œ ŸœŸœŸœŸœ˜=K˜š  œŸœŸœŸœ˜@KšœŸœ ˜KšœŸœ ˜Kšœ˜Kšœ˜Kš Ÿœ Ÿœ ŸœŸœŸœ˜.Kš ŸœŸœŸœŸœŸœ˜7šŸœCŸœ˜KKšœ+˜+Kšœ+˜+KšŸœ Ÿœ ŸœŸœ˜AK˜—šŸœŸœŸ˜!˜šŸœŸœŸ˜!Kšœ Ÿœ˜$KšŸœ˜——˜ šŸœŸœŸ˜!˜Kšœ Ÿœ˜KšŸœŸœŸœŸœ˜,KšŸœ Ÿ œ4˜JKšŸœ8˜>K˜—KšŸœ˜——˜ šŸœŸœŸ˜!˜ Kšœ Ÿœ˜KšŸœŸœŸœŸœ˜,KšŸœŸœŸœŸœ˜1KšŸœ Ÿ œ4˜JKšŸœŸœŸœŸœ˜1šŸœ˜šœŸœ˜KšŸ˜—˜ šœŸœŸœ˜*Kš œŸœ Ÿœ ŸœŸœŸœ˜=—Kšœ˜——K˜—KšŸœ˜——˜šŸœŸœŸ˜!˜šŸœŸœ˜7KšŸœŸœ˜=KšŸœ,˜/——KšŸœ˜——˜šŸœŸœŸ˜!˜ KšŸœŸœŸœŸœ˜-KšŸœŸœŸœŸœ˜1šŸœ7˜=KšŸœ0˜3—Kšœ˜—KšŸœ˜——˜ šŸœŸœŸ˜!˜ šŸœŸ˜!KšŸœ9˜?——KšŸœ˜——˜ šŸœŸœŸ˜!˜ šŸœŸœ˜3KšŸœ-˜0KšŸœ1˜4——KšŸœ˜——˜šŸœŸœŸ˜!Kšœ Ÿœ2˜AKšŸœ˜——˜ šŸœŸœŸ˜!˜ šŸœŸœ˜@KšŸœ6˜9KšŸœ.˜1——KšŸœ˜——˜ šŸœŸœŸ˜!˜ KšŸœ/Ÿœ2˜j—KšŸœ˜——˜ šŸœŸœŸ˜!˜ KšŸœDŸœ?˜Œ—KšŸœ˜——˜šŸœŸœŸ˜!KšœŸœŸœ˜?KšŸœ˜——˜ šŸœŸœŸ˜!˜ šŸœ/˜5šŸœ˜šœ Ÿœ ˜šŸœŸœ˜1KšŸœ Ÿœ˜)—————KšŸœ˜——˜šŸœŸœŸ˜!KšœŸœ˜'KšŸœ˜——˜ šŸœŸœŸ˜!Kšœ Ÿœ˜)KšŸœ˜——˜ šŸœŸœŸ˜!Kšœ Ÿœ˜+KšŸœ˜——˜šŸœŸœŸ˜!KšœŸœŸœ˜KšŸœ˜——KšœŸœ˜KšŸœ˜—KšŸœŸœ˜šœ˜K˜——šœ ŸœŸœ˜KšœŸœ˜ K˜K˜—Kš œ ŸœŸœŸœŸœ˜KšŸœŸœŸœ˜šŸœ˜Kš ŸœŸœŸœŸœŸœ˜AKšŸœ$ŸœŸœŸœ˜9šŸœ*Ÿ˜4KšœŸœ#˜;KšŸœ˜—KšŸœD˜JK˜——šœ˜K˜——KšœŸœ˜K˜š œŸœ*ŸœŸœ˜PKšœŸœ ˜KšœŸœ ˜Kšœ˜Kšœ˜šŸœŸœŸœŸ˜9KšŸœŸœ˜—šŸœCŸœ˜KKšœ+˜+Kšœ+˜+KšŸœ Ÿœ ŸœŸœ"˜KK˜—KšŸœŸœŸœŸœ˜/šŸœŸœŸ˜!šœ ˜ šŸœŸœŸ˜!˜ Kš Ÿœ Ÿœ ŸœŸœŸœ˜0KšŸœŸœŸœŸœ˜1KšŸœŸœŸœŸœ˜1šŸœ˜KšœŸœŸ˜!˜ šœŸœŸœ ˜0Kš œŸœ Ÿœ ŸœŸœŸœ˜=—Kšœ˜——K˜—KšŸœ˜——šœ˜šŸœŸœŸ˜!˜KšŸœŸœŸœŸœ˜/KšŸœŸœŸœŸœ˜'Kš Ÿœ ŸœŸœ ŸœŸœŸœ˜5Kš Ÿœ ŸœŸœ ŸœŸœŸœ˜7˜Kšœ3˜3Kšœ3˜3KšŸœ ŸœŸœŸœ˜5šŸœ Ÿ˜KšŸœ'ŸœŸœŸœ˜<—šŸœŸœŸ˜šœ˜KšŸœ'ŸœŸœŸœ˜<—KšœŸœŸœ˜šœ ŸœŸœŸ˜(˜ KšŸœ ŸœŸœŸœ˜"KšŸœŸœŸœŸœ˜-KšŸœŸœŸœŸœ˜1Kš ŸœŸœBŸœŸœŸœ˜\˜Kšœ9˜9Kšœ9˜9šŸœ3Ÿ˜9KšŸœŸœ˜—K˜—K˜—KšŸœ˜—KšŸœ˜—K˜—K˜—KšŸœ˜——šœ ˜ šŸœŸœŸ˜!˜ KšœŸœ ˜KšŸœŸœŸœŸœ˜*KšŸœŸœŸœŸœ˜1šŸœ9Ÿœ˜AKšœ˜Kšœ˜šŸœ%Ÿ˜+KšŸœŸœ˜—šŸœŸœŸ˜šŸœ'Ÿ˜-KšŸœŸœ˜——K˜—K˜—KšŸœ˜——šœ ˜ šŸœŸœŸ˜!˜ šŸœŸœ˜%šŸœ ˜ K˜1K˜2———KšŸœ˜——šœ ˜ šŸœŸœŸ˜!˜ šŸœ Ÿ˜Kšœ˜Kš œ ŸœŸœŸœŸœ˜1KšŸœŸœŸœ˜—šŸœ)Ÿ˜/šŸœŸœ8Ÿ˜BKšŸœŸœ˜——šŸœ*Ÿ˜0šŸœŸœ:Ÿ˜DKšŸœŸœ˜——šŸœ ŸœŸœ Ÿœ˜!šŸœŸœŸ˜6KšŸœŸœŸœŸœ™5šŸœ Ÿ˜Kšœ ŸœŸœ˜KšŸœ˜——KšŸœŸœ˜K˜—KšŸœŸœ˜K˜—KšŸœ˜——šœ ˜ šŸœŸœŸ˜!˜ šŸœ7˜=šŸœ˜K˜=K˜šŸœ˜KšŸœŸœŸœ˜šŸœ˜KšœŸœ ˜KšœŸœ ˜šŸœŸœŸ˜&˜šŸœŸœŸ˜&˜ KšœŸœ ˜KšŸœŸœŸœŸœ˜*KšŸœŸœŸœŸœ˜1Kš ŸœŸœBŸœŸœŸœ˜\KšŸœ=˜CK˜—KšŸœ˜——KšŸœ˜—KšŸœŸœ˜K˜——šœ˜K˜——š  œŸœŸœ˜CKšœ˜šŸ˜šŸœŸœŸ˜"Kšœ;˜;KšŸœŸœ˜—KšŸœ˜—KšŸœ˜Kšœ˜K˜——K˜K˜—…—Bš\ε