<> <> <> <> <> DIRECTORY AMTypes USING [Error], Atom USING [MakeAtom], BcdDefs USING [NullVersion, VersionStamp], BrandXSymbolDefs USING [contextLevelZero, nullHandle, PreDefinedSEI, StandardSymbolContextIndex, SymbolContextIndex, SymbolIndex, SymbolTableBase], BrandYSymbolDefs USING [contextLevelZero, nullHandle, PreDefinedSEI, StandardSymbolContextIndex, SymbolContextIndex, SymbolIndex, SymbolTableBase], ConvertUnsafe USING [EqualSubStrings, SubString, SubStringToRope], RCMap USING [Index], RCMapOps USING [Acquire], Rope USING [ROPE], RTSymbolDefs USING [nullBase, nullHandle, SymbolConstructorIndex, SymbolIdIndex, SymbolIndex, symbolIndexForANY, SymbolNameIndex, SymbolRecordIndex, SymbolTableBase, SymbolTableHandle], RTSymbolOps USING [EnumerateCtxIseis, PeelAllButLast, SEUnderType, SETagIDP, NullISEI, SubStringForName, IsSequence, NullStb, NullSth, ISEName], RTSymbols USING [AcquireSTB, AcquireSTBFromMDI, BaseToHandle, GetSTHForModule, OuterFromMDI, ReleaseSTB], RTSymbolsPrivate USING [AcquireSTHFromSTX], RTTypesBasicPrivate USING [Enter, FindCanonicalPTD, FindPTD, FindSTI, GetLastTypeIndex, MakeNewType, MapStiStd, MapTiTd, PTypeDesc, STDesc, SymbolAccess, SymbolTableIndex, UniqueTypeFinger], RuntimeError USING [UNCAUGHT], SafeStorage USING [anyType, nullType, Type, TypeIndex, unspecType], TypeStrings USING [Create, TypeString], UnsafeStorage USING [GetSystemUZone]; RTTSupportImpl: PROGRAM IMPORTS AMTypes, Atom, ConvertUnsafe, RCMapOps, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RTTypesBasicPrivate, RuntimeError, TypeStrings, UnsafeStorage EXPORTS RTSymbolOps, RTSymbols = BEGIN OPEN bx: BrandXSymbolDefs, by: BrandYSymbolDefs, XRCMapOps: RCMapOps, YRCMapOps: RCMapOps, XTypeStrings: TypeStrings, YTypeStrings: TypeStrings, RTSymbolDefs, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RuntimeError, SafeStorage, TypeStrings; ROPE: TYPE = Rope.ROPE; standardXSTH: SymbolTableHandle _ [x[bx.nullHandle]]; standardYSTH: SymbolTableHandle _ [y[by.nullHandle]]; typeStringZone: UNCOUNTED ZONE = UnsafeStorage.GetSystemUZone[]; <<*****************************>> <> AcquireType: PUBLIC PROC [stb: SymbolTableBase, seIndex: SymbolIndex, canonicalize: BOOL _ FALSE, rcmi: RCMap.Index _ LAST[RCMap.Index]] RETURNS [type: Type] = { inner: PROC = { ptd: RTTypesBasicPrivate.PTypeDesc; utf: RTTypesBasicPrivate.UniqueTypeFinger; ustb: SymbolTableBase; usei: SymbolIndex; csei: SymbolConstructorIndex = SEUnderType[stb, seIndex]; isConsType: BOOL = NOT SETagIDP[stb, seIndex]; MakePredefinedType: PROC [preType: Type] = { utf: RTTypesBasicPrivate.UniqueTypeFinger; ustb: SymbolTableBase; usei: SymbolIndex; std: RTTypesBasicPrivate.STDesc; [utf, ustb, usei] _ ComputeUTF[stb, seIndex]; std _ STDescFromSTB[ustb]; IF stb # ustb THEN ReleaseSTB[ustb]; IF rcmi = LAST[RCMap.Index] THEN { rcmi _ WITH stb SELECT FROM t: SymbolTableBase.x => XRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.x].e], t: SymbolTableBase.y => YRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.y].e], ENDCASE => ERROR; }; [] _ RTTypesBasicPrivate.MakeNewType[ utf, std, usei, WITH stb SELECT FROM t: SymbolTableBase.x => XTypeStrings.Create [t.e, NARROW[csei, SymbolConstructorIndex.x].e, typeStringZone], t: SymbolTableBase.y => YTypeStrings.Create [t.e, NARROW[csei, SymbolConstructorIndex.y].e, typeStringZone], ENDCASE => ERROR, rcmi, FALSE, FALSE, preType]; }; IF NullISEI[LOOPHOLE[seIndex]] THEN ERROR; IF csei = symbolIndexForANY THEN { IF RTTypesBasicPrivate.MapTiTd[unspecType] = NIL THEN MakePredefinedType[unspecType]; type _ unspecType; RETURN}; IF isConsType THEN { WITH stb SELECT FROM t: SymbolTableBase.x => WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.x].e] SELECT FROM any => GO TO isAny; ENDCASE; t: SymbolTableBase.y => WITH ser: t.e.seb[NARROW[csei, SymbolConstructorIndex.y].e] SELECT FROM any => GO TO isAny; ENDCASE; ENDCASE => ERROR; EXITS isAny => { IF RTTypesBasicPrivate.MapTiTd[anyType] = NIL THEN MakePredefinedType[anyType]; type _ anyType; RETURN; }; }; IF canonicalize THEN { ts: TypeString; [ptd, ts, utf] _ FindCanonicalType[stb, csei]; -- ts new storage only if ptd = NIL IF ptd # NIL THEN {type _ ptd.equivalentType; RETURN} ELSE { std: RTTypesBasicPrivate.STDesc = STDescFromSTB[stb]; IF rcmi = LAST[RCMap.Index] THEN rcmi _ WITH stb SELECT FROM t: SymbolTableBase.x => XRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.x].e], t: SymbolTableBase.y => YRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.y].e], ENDCASE => ERROR; type _ RTTypesBasicPrivate.MakeNewType[utf, std, LOOPHOLE[csei, SymbolIndex], ts, rcmi, TRUE]; RETURN}} ELSE { IF NOT isConsType THEN seIndex _ LOOPHOLE[PeelAllButLast[stb, LOOPHOLE[seIndex, SymbolIdIndex]], SymbolIndex]; [ptd, utf, ustb, usei] _ FindUTF[stb, seIndex]; IF ptd # NIL THEN { IF stb # ustb THEN ReleaseSTB[ustb]; type _ ptd.myType; RETURN} ELSE { std: RTTypesBasicPrivate.STDesc = STDescFromSTB[ustb]; IF stb # ustb THEN ReleaseSTB[ustb]; IF rcmi = LAST[RCMap.Index] THEN rcmi _ WITH stb SELECT FROM t: SymbolTableBase.x => XRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.x].e], t: SymbolTableBase.y => YRCMapOps.Acquire[t.e, NARROW[csei, SymbolConstructorIndex.y].e], ENDCASE => ERROR; type _ RTTypesBasicPrivate.MakeNewType [utf, std, usei, WITH stb SELECT FROM t: SymbolTableBase.x => XTypeStrings.Create[t.e, NARROW[csei, SymbolConstructorIndex.x].e, typeStringZone], t: SymbolTableBase.y => YTypeStrings.Create[t.e, NARROW[csei, SymbolConstructorIndex.y].e, typeStringZone], ENDCASE => ERROR, rcmi]; RETURN}}}; RTTypesBasicPrivate.Enter[inner ! AMTypes.Error => REJECT; UNWIND => NULL; UNCAUGHT => GOTO unwind]; EXITS unwind => ERROR; }; AcquireSequenceType: PUBLIC PROC [stb: SymbolTableBase, sei: SymbolIndex, recordSTB: SymbolTableBase, recordSEIndex: SymbolRecordIndex] RETURNS [type: Type] = { inner: PROC = { ptd: RTTypesBasicPrivate.PTypeDesc; utf: RTTypesBasicPrivate.UniqueTypeFinger; ustb: SymbolTableBase; usei: SymbolIndex; csei: SymbolConstructorIndex = SEUnderType[stb, sei]; IF NOT IsSequence[stb, sei] THEN ERROR; IF SETagIDP[stb, sei] THEN sei _ LOOPHOLE[PeelAllButLast[stb, LOOPHOLE[sei, SymbolIdIndex]], SymbolIndex]; [ptd, utf, ustb, usei] _ FindUTF[stb, sei]; IF ptd # NIL THEN { IF stb # ustb THEN ReleaseSTB[ustb]; type _ ptd.myType} ELSE { std: RTTypesBasicPrivate.STDesc = STDescFromSTB[ustb]; rcmi: RCMap.Index _ WITH recordSTB SELECT FROM t: SymbolTableBase.x => XRCMapOps.Acquire[t.e, NARROW[recordSEIndex, SymbolRecordIndex.x].e], t: SymbolTableBase.y => YRCMapOps.Acquire[t.e, NARROW[recordSEIndex, SymbolRecordIndex.y].e], ENDCASE => ERROR; IF stb # ustb THEN ReleaseSTB[ustb]; type _ RTTypesBasicPrivate.MakeNewType [ utf, std, usei, WITH recordSTB SELECT FROM t: SymbolTableBase.x => XTypeStrings.Create[t.e, NARROW[recordSEIndex, SymbolRecordIndex.x].e, typeStringZone], t: SymbolTableBase.y => YTypeStrings.Create[t.e, NARROW[recordSEIndex, SymbolRecordIndex.y].e, typeStringZone], ENDCASE => ERROR, rcmi]}}; RTTypesBasicPrivate.Enter[inner ! AMTypes.Error => REJECT; UNWIND => NULL; UNCAUGHT => GOTO unwind]; EXITS unwind => ERROR; }; AcquireRope: PUBLIC PROC [stb: SymbolTableBase, hti: SymbolNameIndex] RETURNS [ROPE] = { RETURN[ConvertUnsafe.SubStringToRope[SubStringForName[stb, hti]]]; }; AcquireAtom: PUBLIC PROC [stb: SymbolTableBase, hti: SymbolNameIndex] RETURNS [atom: ATOM] ={ RETURN[Atom.MakeAtom[AcquireRope[stb, hti]]]; }; EnumerateTypes: PROC [p: PROC [Type] RETURNS [stop: BOOL]] RETURNS [stopped: BOOL _ FALSE] = { FOR t: TypeIndex IN [FIRST[TypeIndex]..RTTypesBasicPrivate.GetLastTypeIndex[]] DO IF p[[t]] THEN RETURN[TRUE]; ENDLOOP; }; ErrorRecord: TYPE = RECORD [type: Type, name: ROPE]; errList: LIST OF ErrorRecord _ NIL; GetTypeSymbols: PUBLIC PROC [type: Type] RETURNS [stb: SymbolTableBase, sei: SymbolIndex] = { IF type = nullType THEN ERROR AMTypes.Error[reason: typeFault, type: type]; [stb, sei,] _ DoGetTypeSymbols[type]; }; GetOriginalTypeSymbols: PUBLIC PROC [type: Type] RETURNS [stb: SymbolTableBase, sei: SymbolIndex] = { IF type = nullType THEN ERROR AMTypes.Error[reason: typeFault, type: type]; [stb, sei,] _ DoGetTypeSymbols[type, TRUE]; }; IsPreDefinedSEI: PROC [sei: SymbolIndex] RETURNS [BOOL] = { RETURN [WITH sei SELECT FROM t: SymbolIndex.x => LOOPHOLE[t.e, CARDINAL] IN bx.PreDefinedSEI, t: SymbolIndex.y => LOOPHOLE[t.e, CARDINAL] IN by.PreDefinedSEI, ENDCASE => ERROR]; }; DoGetTypeSymbols: PROC [type: Type, originalOnly: BOOL _ FALSE] RETURNS [stb: SymbolTableBase, sei: SymbolIndex, moduleName: ROPE _ NIL] = { ptd: RTTypesBasicPrivate.PTypeDesc = RTTypesBasicPrivate.MapTiTd[type]; stInfo: RTTypesBasicPrivate.SymbolAccess _ ptd.symbolAccess; sth: SymbolTableHandle _ IF originalOnly THEN nullHandle ELSE RTTypesBasicPrivate.MapStiStd[stInfo.sti].sth; mn: ROPE _ NIL; anySTHWillDo: BOOL _ (ptd.utf.umid = BcdDefs.NullVersion AND IsPreDefinedSEI[ptd.utf.seIndex]); originalUTF: BOOL _ NOT(ptd.utf.umid = BcdDefs.NullVersion OR IsPreDefinedSEI[ptd.utf.seIndex]); sei _ IF originalOnly AND originalUTF THEN ptd.utf.seIndex ELSE stInfo.sei; IF NullSth[sth] THEN IF anySTHWillDo THEN { <> IF NOT (IF sei.brand = x THEN NullSth[standardXSTH] ELSE NullSth[standardYSTH]) THEN sth _ (IF sei.brand = x THEN standardXSTH ELSE standardYSTH) ELSE FOR i: RTTypesBasicPrivate.SymbolTableIndex IN [1..RTTypesBasicPrivate.MapStiStd.length) DO IF RTTypesBasicPrivate.MapStiStd[i] = NIL THEN LOOP; IF NOT NullSth[RTTypesBasicPrivate.MapStiStd[i].sth] THEN { sth _ RTTypesBasicPrivate.MapStiStd[i].sth; EXIT}; <> [sth: sth, moduleName: mn] _ AcquireSTHFromSTX[i]; IF moduleName = NIL THEN moduleName _ mn; RTTypesBasicPrivate.MapStiStd[i].sth _ sth; IF NOT NullSth[sth] THEN EXIT; -- found one ENDLOOP; } ELSE { <> IF originalOnly AND originalUTF THEN sth _ GetSTHForModule[ptd.utf.umid, NIL, NIL ! AMTypes.Error => CONTINUE] ELSE { [sth: sth, moduleName: moduleName] _ AcquireSTHFromSTX[stInfo.sti]; RTTypesBasicPrivate.MapStiStd[stInfo.sti].sth _ sth; IF NullSth[sth] AND originalUTF THEN { <> std: RTTypesBasicPrivate.STDesc = [symbolsStamp: ptd.utf.umid, bcd: RTTypesBasicPrivate.MapStiStd[stInfo.sti].bcd]; sei _ ptd.utf.seIndex; IF anySTHWillDo THEN { IF NOT (IF sei.brand = x THEN NullSth[standardXSTH] ELSE NullSth[standardYSTH]) THEN sth _ (IF sei.brand = x THEN standardXSTH ELSE standardYSTH) ELSE FOR i: RTTypesBasicPrivate.SymbolTableIndex IN [1..RTTypesBasicPrivate.MapStiStd.length) DO IF RTTypesBasicPrivate.MapStiStd[i] = NIL THEN LOOP; IF NOT NullSth[RTTypesBasicPrivate.MapStiStd[i].sth] THEN { sth _ RTTypesBasicPrivate.MapStiStd[i].sth; EXIT}; <> [sth: sth, moduleName: mn] _ AcquireSTHFromSTX[i]; IF moduleName = NIL THEN moduleName _ mn; RTTypesBasicPrivate.MapStiStd[i].sth _ sth; IF NOT NullSth[sth] THEN EXIT; -- found one ENDLOOP; } ELSE { [sth: sth, moduleName: mn] _ AcquireSTHFromSTX[RTTypesBasicPrivate.FindSTI[std]]; IF moduleName = NIL THEN moduleName _ mn; }; }; }; }; IF NullSth[sth] THEN stb _ nullBase ELSE { WITH sth SELECT FROM t: SymbolTableHandle.x => IF NullSth[standardXSTH] THEN standardXSTH _ sth; t: SymbolTableHandle.y => IF NullSth[standardYSTH] THEN standardYSTH _ sth; ENDCASE => ERROR; stb _ AcquireSTB[sth]; }; IF NullStb[stb] THEN { FOR each: LIST OF ErrorRecord _ errList, each.rest WHILE each # NIL DO IF each.first.type = type THEN GO TO gleep; ENDLOOP; errList _ CONS[[type, moduleName], errList]; GO TO gleep; EXITS gleep => ERROR AMTypes.Error[reason: noSymbols, msg: moduleName]; }; }; <> FindCanonicalType: PROC [stb: SymbolTableBase, csei: SymbolConstructorIndex] RETURNS [ptd: RTTypesBasicPrivate.PTypeDesc, ts: TypeString, utf: RTTypesBasicPrivate.UniqueTypeFinger] = { <> ts _ WITH stb SELECT FROM t: SymbolTableBase.x => XTypeStrings.Create [t.e, NARROW[csei, SymbolConstructorIndex.x].e, typeStringZone], t: SymbolTableBase.y => YTypeStrings.Create [t.e, NARROW[csei, SymbolConstructorIndex.y].e, typeStringZone], ENDCASE => ERROR; ptd _ RTTypesBasicPrivate.FindCanonicalPTD[ts]; IF ptd # NIL THEN {typeStringZone.FREE[@ts]; RETURN[ptd, NIL, ptd.utf]} ELSE {[utf,,] _ ComputeUTF[stb, LOOPHOLE[csei, SymbolIndex]]; RETURN[NIL, ts, utf]}; }; <> < TypeIndex>> FindUTF: PROC [stb: SymbolTableBase, sei: SymbolIndex] RETURNS [ptd: RTTypesBasicPrivate.PTypeDesc, utf: RTTypesBasicPrivate.UniqueTypeFinger, ustb: SymbolTableBase, usei: SymbolIndex] = { [utf, ustb, usei] _ ComputeUTF[stb, sei]; RETURN[RTTypesBasicPrivate.FindPTD[utf], utf, ustb, usei]; }; ComputeUTF: PROC [outerSTB: SymbolTableBase, sei: SymbolIndex] RETURNS [utf: RTTypesBasicPrivate.UniqueTypeFinger, ustb: SymbolTableBase, usei: SymbolIndex] = { <> WITH outerSTB SELECT FROM t: SymbolTableBase.x => [utf, ustb, usei] _ ComputeUTFX[t.e, NARROW[sei, SymbolIndex.x].e]; t: SymbolTableBase.y => [utf, ustb, usei] _ ComputeUTFY[t.e, NARROW[sei, SymbolIndex.y].e]; ENDCASE => ERROR; }; ComputeUTFX: PROC [outerSTB: bx.SymbolTableBase, sei: bx.SymbolIndex] RETURNS [utf: RTTypesBasicPrivate.UniqueTypeFinger, ustb: SymbolTableBase, usei: SymbolIndex] = { ustb _ [x[outerSTB]]; usei _ [x[sei]]; WITH ser: outerSTB.seb[sei] SELECT FROM id => IF ser.idCtx IN bx.StandardSymbolContextIndex THEN utf _ [umid: BcdDefs.NullVersion, seIndex: usei] -- a primitive type ELSE WITH ctxr: outerSTB.ctxb[ser.idCtx] SELECT FROM included => IF ctxr.level # bx.contextLevelZero THEN utf _ [umid: outerSTB.mdb[ctxr.module].stamp, seIndex: [x[LOOPHOLE[ser.idValue, bx.SymbolIndex]]]] ELSE { inner: PROC [stb: SymbolTableBase] = { p: PROC [stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS [stop: BOOL] = { ssd1: ConvertUnsafe.SubString = SubStringForName[[x[outerSTB]], [x[ser.hash]]]; ssd2: ConvertUnsafe.SubString = SubStringForName[stb, ISEName[stb, isei]]; IF (stop _ ConvertUnsafe.EqualSubStrings[ssd1, ssd2]) THEN { utf _ [umid: NARROW[stb, SymbolTableBase.x].e.stHandle.version, seIndex: LOOPHOLE[isei, SymbolIndex]]; usei _ LOOPHOLE[isei, SymbolIndex]; } }; IF NOT EnumerateCtxIseis[stb: stb, ctx: [x[ctxr.map]], proc: p] THEN ERROR; }; OuterFromMDI[stb: [x[outerSTB]], mdi: [x[ctxr.module]], inner: inner]; ustb _ AcquireSTBFromMDI[[x[outerSTB]], [x[ctxr.module]]]; RETURN }; ENDCASE => utf _ [umid: outerSTB.stHandle.version, seIndex: [x[sei]]]; cons => utf _ [umid: (IF IsPreDefinedSEI[[x[sei]]] THEN BcdDefs.NullVersion ELSE outerSTB.stHandle.version), -- NOTE seIndex: [x[sei]]]; ENDCASE => ERROR; }; ComputeUTFY: PROC [outerSTB: by.SymbolTableBase, sei: by.SymbolIndex] RETURNS [utf: RTTypesBasicPrivate.UniqueTypeFinger, ustb: SymbolTableBase, usei: SymbolIndex] = { ustb _ [y[outerSTB]]; usei _ [y[sei]]; WITH ser: outerSTB.seb[sei] SELECT FROM id => IF ser.idCtx IN by.StandardSymbolContextIndex THEN utf _ [umid: BcdDefs.NullVersion, seIndex: usei] -- a primitive type ELSE WITH ctxr: outerSTB.ctxb[ser.idCtx] SELECT FROM included => IF ctxr.level # by.contextLevelZero THEN utf _ [umid: outerSTB.mdb[ctxr.module].stamp, seIndex: [y[LOOPHOLE[ser.idValue, by.SymbolIndex]]]] ELSE { inner: PROC [stb: SymbolTableBase] = { p: PROC [stb: SymbolTableBase, isei: SymbolIdIndex] RETURNS [stop: BOOL] = { ssd1: ConvertUnsafe.SubString = SubStringForName[[y[outerSTB]], [y[ser.hash]]]; ssd2: ConvertUnsafe.SubString = SubStringForName[stb, ISEName[stb, isei]]; IF (stop _ ConvertUnsafe.EqualSubStrings[ssd1, ssd2]) THEN { utf _ [umid: NARROW[stb, SymbolTableBase.y].e.stHandle.version, seIndex: LOOPHOLE[isei, SymbolIndex]]; usei _ LOOPHOLE[isei, SymbolIndex]; } }; IF NOT EnumerateCtxIseis[stb: stb, ctx: [y[ctxr.map]], proc: p] THEN ERROR; }; OuterFromMDI[stb: [y[outerSTB]], mdi: [y[ctxr.module]], inner: inner]; ustb _ AcquireSTBFromMDI[[y[outerSTB]], [y[ctxr.module]]]; RETURN }; ENDCASE => utf _ [umid: outerSTB.stHandle.version, seIndex: [y[sei]]]; cons => utf _ [umid: (IF IsPreDefinedSEI[[y[sei]]] THEN BcdDefs.NullVersion ELSE outerSTB.stHandle.version), -- NOTE seIndex: [y[sei]]]; ENDCASE => ERROR; }; STDescFromSTB: PROC [stb: SymbolTableBase] RETURNS [RTTypesBasicPrivate.STDesc] = { version: BcdDefs.VersionStamp = (WITH stb SELECT FROM t: SymbolTableBase.x => t.e.stHandle.version, t: SymbolTableBase.y => t.e.stHandle.version ENDCASE => ERROR); RETURN[[symbolsStamp: version, sth: RTSymbols.BaseToHandle[stb]]]; }; END. <<>>