DIRECTORY Basics USING [LongNumber], ConvertUnsafe USING [SubString], MobDefs USING [NullVersion, VersionStamp], OSMiscOps USING [Copy], SymbolOps USING [DecodeCard, FindMdi, FindString, FirstCtxSe, NameForSe, NextSe, SearchContext, STB, SubStringForName, TypeForm, UnderType], Symbols USING [Base, codeANY, codeCHAR, CSEIndex, CSENull, CTXFirst, CTXIndex, CTXNull, CTXRecord, FirstStandardCtx, HTRecord, IncludedCTXIndex, IncludedCTXNull, ISEIndex, ISENull, LastStandardCtx, MDIndex, MDNull, Name, nullName, nullType, OwnMdi, Type, TypeClass, typeTYPE], SymbolTable USING [], SymbolTablePrivate USING [SymbolTableBaseRep], Target: TYPE MachineParms USING [bitsPerLongWord, bitsPerReal, bitsPerWord, maxWord, maxLongWord], TypeStrings USING [Code, TypeString]; TypeStringsImpl: PROGRAM IMPORTS OSMiscOps, SymbolOps EXPORTS TypeStrings, SymbolTable = { OPEN Symbols, TypeStrings; STB: TYPE = REF SymbolTableBaseRep; SymbolTableBaseRep: PUBLIC TYPE = SymbolTablePrivate.SymbolTableBaseRep; stb: STB ¬ NIL; zone: UNCOUNTED ZONE ¬ NIL; ts: TypeString ¬ NIL; stackQuick: INT ¬ 0; defsQuick: INT ¬ 0; stateQuick: INT ¬ 0; listQuick: INT ¬ 0; createCalls: INT ¬ 0; Create: PUBLIC PROC [base: STB, sei: Type, z: UNCOUNTED ZONE] RETURNS [TypeString] = { IF base = NIL THEN RETURN [NIL]; stb ¬ base; zone ¬ z; ts ¬ zone.NEW[StringBody[32]]; createCalls ¬ createCalls + 1; IF stack = NIL THEN stack ¬ zone.NEW[StackVector[4]] ELSE stackQuick ¬ stackQuick + 1; IF defs = NIL THEN defs ¬ zone.NEW[DefsVector[4]] ELSE defsQuick ¬ defsQuick + 1; IF state = NIL THEN state ¬ zone.NEW[StateTable[4]] ELSE stateQuick ¬ stateQuick + 1; IF list = NIL THEN list ¬ zone.NEW[ListVector[4]] ELSE listQuick ¬ listQuick + 1; stack.index ¬ defs.index ¬ state.index ¬ list.index ¬ 0; lastName ¬ '\000; AppendTypeString[sei]; IF InsertDefinitions[] THEN Canonicalize[sei]; IF defs.len > 16 THEN zone.FREE[@defs]; IF stack.len > 16 THEN zone.FREE[@stack]; IF state.max > 16 THEN zone.FREE[@state]; IF list.max > 16 THEN zone.FREE[@list]; IF ts.length + 16 < ts.maxlength THEN { old: TypeString ¬ ts; oldLen: CARDINAL ¬ old.length; ts ¬ zone.NEW[StringBody[oldLen]]; OSMiscOps.Copy[ from: @old.text, nwords: StringBody[oldLen].WORDS - StringBody[0].WORDS, to: @ts.text]; ts.length ¬ oldLen; zone.FREE[@old]; }; RETURN [ts]; }; Expand: PROC [s: TypeString] RETURNS [new: TypeString] = { n: NAT = s.length + (s.length + 4)/2; new ¬ zone.NEW[StringBody[n]]; OSMiscOps.Copy[ from: @s.text, nwords: StringBody[s.length].WORDS - StringBody[0].WORDS, to: @new.text]; new.length ¬ s.length; zone.FREE[@s]; }; Append: PROC [c: CHAR] = { len: NAT ¬ ts.length; IF len = ts.maxlength THEN {ts ¬ Expand[ts]; len ¬ ts.length}; IF ts = NIL OR len >= ts.maxlength THEN ERROR; ts[len] ¬ c; ts.length ¬ len + 1; }; AppendByte: PROC [b: BYTE] = LOOPHOLE[Append]; AppendCode: PROC [code: Code] = LOOPHOLE[Append]; AppendCard: PROC [c: CARD32] = { encodeMod: NAT = 64; ln: Basics.LongNumber = [card[c]]; SELECT c FROM < encodeMod => AppendByte[ln.ll]; < encodeMod*256 => { AppendByte[encodeMod*1+ln.lh]; AppendByte[ln.ll]; }; < encodeMod*LONG[256]*256 => { AppendByte[encodeMod*2+ln.hl]; AppendByte[ln.lh]; AppendByte[ln.ll]; }; ENDCASE => { prefix: NAT ¬ encodeMod*3; IF ln.int < 0 AND ln.int > - encodeMod THEN { AppendByte[prefix-ln.int]; RETURN; }; AppendByte[prefix]; AppendByte[ln.hh]; AppendByte[ln.hl]; AppendByte[ln.lh]; AppendByte[ln.ll]; }; }; AppendPaint: PROC [type: CSEIndex] = { form: Symbols.TypeClass = SymbolOps.TypeForm[stb, type]; SELECT form FROM $enumerated, $definition, $record, $union, $opaque => { version: MobDefs.VersionStamp ¬ MobDefs.NullVersion; ctx: CTXIndex ¬ TypeContext[type]; mdi: MDIndex; WITH c~~stb.ctxb[ctx] SELECT FROM simple => mdi ¬ OwnMdi; included => {mdi ¬ c.module; ctx ¬ c.map}; imported => { link: Symbols.IncludedCTXIndex ¬ c.includeLink; IF link = Symbols.IncludedCTXNull THEN ERROR; mdi ¬ stb.ctxb[link].module; ctx ¬ stb.ctxb[link].map; }; ENDCASE => ERROR; IF ctx NOT IN [FirstStandardCtx..LastStandardCtx] THEN version ¬ LOOPHOLE[stb.mdb[mdi].stamp]; WITH t: stb.seb[type] SELECT FROM opaque => { AppendName[SymbolOps.NameForSe[stb, t.id]]; AppendCard[version[0]]; AppendCard[version[1]]; }; ENDCASE => { index: CARD ¬ CARD[ctx-CTXFirst]; index ¬ index * BYTES[UNIT]; AppendCard[version[0]]; AppendCard[version[1]]; AppendCard[index]; }; }; ENDCASE => ERROR; }; AppendName: PROC [name: Name] = { IF name = nullName THEN Append[VAL[0]] ELSE { offset: CARDINAL = stb.htb[name-HTRecord.SIZE].ssIndex <<+ 1>>; length: CARDINAL = stb.htb[name].ssIndex - offset; IF length >= 200b THEN ERROR; Append[VAL[length]]; FOR i: CARDINAL IN [offset..offset+length) DO Append[stb.ssb[i]]; ENDLOOP; }; }; AppendField: PROC [iSei: ISEIndex] = INLINE { AppendName[SymbolOps.NameForSe[stb, iSei]]; AppendTypeString[stb.seb[iSei].idType]; }; AppendTypeString: PROC [type: Type] = { csei: CSEIndex ¬ SymbolOps.UnderType[stb, type]; class: Code; e: StackElement; IF SymbolOps.TypeForm[stb, csei]=$opaque THEN csei ¬ OpaqueValue[csei, stb]; FOR i: CARDINAL IN [0..state.index) DO IF state[i].type = csei THEN {csei ¬ state[i].current; EXIT}; ENDLOOP; IF (e ¬ Find[csei]) # NIL THEN { IF e.name='\000 THEN e.name ¬ NewName[]; AppendCode[$name]; Append[e.name]; RETURN}; Push[csei]; SELECT (class ¬ TypeClass[csei]) FROM $definition => ERROR; $enumerated => { ctx: CTXIndex = TypeContext[csei]; IF (ctx-CTXNull) = CTXRecord.nil.SIZE + CTXRecord.simple.SIZE THEN AppendCode[$boolean] -- This is the special common case for BOOLEAN ELSE WITH t: stb.seb[csei] SELECT FROM enumerated => { IF ~t.painted THEN { AppendCode[$enumerated]; AppendCode[$leftParen]; FOR iSei: ISEIndex ¬ SymbolOps.FirstCtxSe[stb, ctx], SymbolOps.NextSe[stb, iSei] UNTIL iSei = ISENull DO AppendName[SymbolOps.NameForSe[stb, iSei]]; IF t.machineDep THEN AppendCard[SymbolOps.DecodeCard[stb.seb[iSei].idValue]]; ENDLOOP; AppendCode[$rightParen]; } ELSE { AppendCode[$paint]; AppendPaint[csei]; }; }; ENDCASE => ERROR; }; $record => { SELECT (TypeContext[csei]-CTXNull) FROM CTXRecord.nil.SIZE + 2*CTXRecord.simple.SIZE => AppendCode[$text]; CTXRecord.nil.SIZE + 3*CTXRecord.simple.SIZE => AppendCode[$stringBody]; ENDCASE => {AppendCode[$paint]; AppendPaint[csei]}; }; $structure => { ctx: CTXIndex = TypeContext[csei]; WITH c~~stb.ctxb[ctx] SELECT FROM included => IF ~c.complete THEN ERROR; ENDCASE; AppendCode[$leftParen]; FOR iSei: ISEIndex ¬ SymbolOps.FirstCtxSe[stb, ctx], SymbolOps.NextSe[stb, iSei] WHILE iSei # ISENull DO AppendField[iSei]; ENDLOOP; AppendCode[$rightParen]; }; $union => { AppendCode[$union]; AppendPaint[csei]; }; $array => { IF Packed[csei] THEN AppendCode[$packed]; AppendCode[$array]; AppendTypeString[Domain[csei]]; AppendTypeString[Range[csei]]; }; $sequence => { IF Packed[csei] THEN AppendCode[$packed]; AppendCode[$sequence]; AppendField[Tag[csei]]; AppendTypeString[Range[csei]]; }; $subrange => { AppendCode[$subrange]; AppendTypeString[Ground[csei]]; AppendCard[First[csei]]; AppendCard[Last[csei]]; }; $opaque => { WITH t~~stb.seb[csei] SELECT FROM opaque => IF stb.seb[t.id].idCtx IN [FirstStandardCtx..LastStandardCtx] THEN AppendCode[$atomRec] ELSE {AppendCode[$opaque]; AppendPaint[csei]}; ENDCASE => ERROR; }; $countedZone, $uncountedZone => { IF Mds[csei] THEN AppendCode[$mds]; AppendCode[class]; }; $list => { IF Ordered[csei] THEN AppendCode[$ordered]; IF ReadOnly[csei] THEN AppendCode[$readOnly]; AppendCode[$list]; AppendTypeString[ListArg[csei]]; }; $relativeRef => { AppendCode[$relativeRef]; AppendTypeString[Base[csei]]; AppendTypeString[Range[csei]]; }; $ref => { IF ReadOnly[csei] THEN AppendCode[$readOnly]; IF TypeClass[Range[csei]] = $any THEN AppendCode[$refAny] ELSE {AppendCode[$ref]; AppendTypeString[Range[csei]]}; }; $var => { IF ReadOnly[csei] THEN AppendCode[$readOnly]; AppendCode[$var]; AppendTypeString[Range[csei]]; }; $pointer, $longPointer => { IF Ordered[csei] THEN AppendCode[$ordered]; IF ReadOnly[csei] THEN AppendCode[$readOnly]; AppendCode[class]; AppendTypeString[Range[csei]]; }; $descriptor, $longDescriptor => { IF ReadOnly[csei] THEN AppendCode[$readOnly]; AppendCode[class]; AppendTypeString[Range[csei]]; }; $procedure, $safeProc => { AppendCode[class]; AppendTypeString[Domain[csei]]; AppendTypeString[Range[csei]]; }; $port, $program, $signal, $error => { IF Safe[csei] THEN AppendCode[$safe]; AppendCode[class]; AppendTypeString[Domain[csei]]; AppendTypeString[Range[csei]]; }; $process => { IF Safe[csei] THEN AppendCode[$safe]; AppendCode[process]; AppendTypeString[Range[csei]]; }; $nil => { AppendCode[$leftParen]; AppendCode[$rightParen]; }; $cardinal, $integer, $character, $longInteger, $longCardinal, $real, $type, $any, $unspecified, $longUnspecified, $dcard, $dint, $dreal => AppendCode[class]; $globalFrame, $localFrame => ERROR; ENDCASE => ERROR; Pop[]; }; OpaqueValue: PROC [type: CSEIndex, base: STB] RETURNS [val: CSEIndex] = { val ¬ type; WITH t1~~stb.seb[type] SELECT FROM opaque => { mdi1: MDIndex = (WITH c1~~stb.ctxb[stb.seb[t1.id].idCtx] SELECT FROM included => c1.module, imported => stb.ctxb[c1.includeLink].module, ENDCASE => OwnMdi); mdi2: MDIndex = SymbolOps.FindMdi[base, stb.mdb[mdi1].stamp]; IF mdi2 # MDNull AND base.mdb[mdi2].exported THEN { sei2: ISEIndex; ss: ConvertUnsafe.SubString = SymbolOps.SubStringForName[stb, stb.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 THEN val ¬ SymbolOps.UnderType[base, sei2]}}; ENDCASE; }; lastName: CHAR; NewName: PROC RETURNS [CHAR] = INLINE {RETURN [lastName ¬ lastName.SUCC]}; Canonicalize: PROC [type: Type] = { AddState[type]; -- gets them all recursively UNTIL ~Split[] DO NULL ENDLOOP; ts.length ¬ 0; AppendTypeString[type]; -- will make use of the equivalences [] ¬ InsertDefinitions[]; }; Split: PROC RETURNS [split: BOOL¬FALSE]= { FOR i: CARDINAL IN [0..state.index) DO found: BOOL ¬ FALSE; FOR j: CARDINAL IN [0..i) DO IF state[i].current=state[j].current THEN found ¬ TRUE; ENDLOOP; IF ~found THEN { list[0] ¬ state[i].type; list.index ¬ 1; state[i].next ¬ state[i].type; FOR j: CARDINAL IN (i..state.index) DO IF state[j].current=state[i].current THEN { -- in the class found ¬ FALSE; FOR k: CARDINAL IN [0..list.index) DO IF kEQ[state[j].type,list[k]] THEN { state[j].next ¬ list[k]; found ¬ TRUE; EXIT}; ENDLOOP; IF ~found THEN { state[j].next ¬ state[j].type; IF list.index = list.max THEN { nLen: NAT = list.index + (list.index + 4) / 2; new: LONG POINTER TO ListVector = zone.NEW[ListVector[nLen]]; OSMiscOps.Copy[ from: @list[0], nwords: ListVector[list.index].WORDS - ListVector[0].WORDS, to: @new[0]]; new.index ¬ list.index; zone.FREE[@list]; list ¬ new}; IF list.index >= list.max THEN ERROR; list[list.index]¬state[j].type; list.index ¬ list.index + 1; split ¬ TRUE}; }; ENDLOOP; }; ENDLOOP; FOR i: CARDINAL IN [0..state.index) DO state[i].current ¬ state[i].next; ENDLOOP; }; AddState: PROC [type: Type] = { class: Code; csei: CSEIndex = SymbolOps.UnderType[stb, type]; FOR i: CARDINAL IN [0..state.index) DO IF state[i].type = csei THEN RETURN; ENDLOOP; IF state.index = state.max THEN { nLen: NAT = state.index + (state.index + 4) / 2; new: LONG POINTER TO StateTable = zone.NEW[StateTable[nLen]]; OSMiscOps.Copy[ from: @state[0], nwords: StateTable[state.index].WORDS - StateTable[0].WORDS, to: @new[0]]; new.index ¬ state.index; zone.FREE[@state]; state ¬ new}; IF state.index >= state.max THEN ERROR; state[state.index] ¬ [csei, CSENull, CSENull]; state.index ¬ state.index + 1; class ¬ TypeClass[csei]; SELECT class FROM $definition => ERROR; $record => { }; $enumerated => { }; $structure => FOR iSei: ISEIndex ¬ SymbolOps.FirstCtxSe[stb, TypeContext[csei]], SymbolOps.NextSe[stb, iSei] WHILE iSei#ISENull DO AddState[stb.seb[iSei].idType]; ENDLOOP; $union => NULL; $array => { AddState[Domain[csei]]; AddState[Range[csei]]}; $sequence => { AddState[stb.seb[Tag[csei]].idType]; AddState[Range[csei]]}; $subrange => AddState[Ground[csei]]; $opaque => NULL; $countedZone, $uncountedZone => NULL; $list => AddState[ListArg[csei]]; $relativeRef => { AddState[Base[csei]]; AddState[Range[csei]]}; $ref => AddState[Range[csei]]; $var => AddState[Range[csei]]; $pointer, $longPointer, $descriptor, $longDescriptor => AddState[Range[csei]]; $procedure, $safeProc, $port, $program, $signal, $error => { AddState[Domain[csei]]; AddState[Range[csei]]}; $process => AddState[Range[csei]]; $nil => NULL; $globalFrame, $localFrame => ERROR; $cardinal, $integer, $character, $longInteger, $longCardinal, $real, $type, $any, $unspecified, $longUnspecified, $dcard, $dint, $dreal => NULL; ENDCASE => ERROR; }; kEQ: PROC [t1, t2: CSEIndex] RETURNS [BOOL] = { class1: Code = TypeClass[t1]; class2: Code = TypeClass[t2]; IF class1 # class2 THEN RETURN [FALSE]; IF t1 = t2 THEN RETURN [TRUE]; SELECT class1 FROM $definition => ERROR; $enumerated => { WITH x1: stb.seb[t1] SELECT FROM enumerated => { iSei1: ISEIndex ¬ SymbolOps.FirstCtxSe[stb, TypeContext[t1]]; WITH x2: stb.seb[t2] SELECT FROM enumerated => { iSei2: ISEIndex ¬ SymbolOps.FirstCtxSe[stb, TypeContext[t1]]; IF x1.painted OR x2.painted THEN RETURN [t1 = t2]; IF x1.range # x2.range THEN RETURN [FALSE]; UNTIL iSei1=ISENull OR iSei2=ISENull DO IF SymbolOps.NameForSe[stb, iSei1] # SymbolOps.NameForSe[stb, iSei2] THEN RETURN [FALSE]; IF stb.seb[iSei1].idValue # stb.seb[iSei2].idValue THEN RETURN [FALSE]; iSei1 ¬ SymbolOps.NextSe[stb, iSei1]; iSei2 ¬ SymbolOps.NextSe[stb, iSei2]; ENDLOOP; RETURN [iSei1=iSei2]; }; ENDCASE; }; ENDCASE; RETURN [FALSE]; }; $structure => { iSei1: ISEIndex ¬ SymbolOps.FirstCtxSe[stb, TypeContext[t1]]; iSei2: ISEIndex ¬ SymbolOps.FirstCtxSe[stb, TypeContext[t2]]; UNTIL iSei1=ISENull OR iSei2=ISENull DO IF SymbolOps.NameForSe[stb, iSei1] # SymbolOps.NameForSe[stb, iSei2] THEN RETURN [FALSE]; IF Current[stb.seb[iSei1].idType] # Current[stb.seb[iSei2].idType] THEN RETURN [FALSE]; iSei1 ¬ SymbolOps.NextSe[stb, iSei1]; iSei2 ¬ SymbolOps.NextSe[stb, iSei2]; ENDLOOP; RETURN [iSei1=iSei2]; }; $array => RETURN [Current[Domain[t1]]=Current[Domain[t2]] AND Current[Range[t1]]=Current[Range[t2]]]; $sequence => { iSei1: ISEIndex = Tag[t1]; iSei2: ISEIndex = Tag[t2]; RETURN [SymbolOps.NameForSe[stb, iSei1] = SymbolOps.NameForSe[stb, iSei2] AND Current[stb.seb[iSei1].idType]=Current[stb.seb[iSei2].idType] AND Current[Range[t1]]=Current[Range[t2]]]; }; $subrange => RETURN [Current[Ground[t1]]=Current[Ground[t2]] AND First[t1] = First[t2] AND Last[t1] = Last[t2]]; $list => RETURN [Current[ListArg[t1]]=Current[ListArg[t2]]]; $relativeRef => RETURN [Current[Base[t1]]=Current[Base[t2]] AND Current[Range[t1]]=Current[Range[t2]]]; $ref => RETURN [Current[Range[t1]]=Current[Range[t2]]]; $var => RETURN [Current[Range[t1]]=Current[Range[t2]]]; $pointer, $longPointer, $descriptor, $longDescriptor => RETURN [Current[Range[t1]]=Current[Range[t2]]]; $procedure, $safeProc, $port, $program, $signal, $error => { RETURN [Current[Domain[t1]]=Current[Domain[t2]] AND Current[Range[t1]]=Current[Range[t2]]]}; $process => RETURN [Current[Range[t1]]=Current[Range[t2]]]; $globalFrame, $localFrame => ERROR; ENDCASE => RETURN [FALSE]; }; Current: PROC [type: Type] RETURNS [CSEIndex] = { csei: CSEIndex = SymbolOps.UnderType[stb, type]; FOR i: CARDINAL IN [0..state.index) DO IF state[i].type=csei THEN RETURN [state[i].current]; ENDLOOP; ERROR; }; StateTable: TYPE = RECORD [ index: CARDINAL, elems: SEQUENCE max: CARDINAL OF RECORD[type, current, next: CSEIndex]]; state: LONG POINTER TO StateTable ¬ NIL; ListVector: TYPE = RECORD [ index: CARDINAL, elems: SEQUENCE max: CARDINAL OF CSEIndex]; list: LONG POINTER TO ListVector ¬ NIL; StackElementRecord: TYPE = RECORD[name: CHAR, type: CSEIndex, index: CARDINAL]; StackElement: TYPE = LONG POINTER TO StackElementRecord; StackVector: TYPE = RECORD [ index: CARDINAL, elems: SEQUENCE len: CARDINAL OF StackElementRecord]; stack: LONG POINTER TO StackVector ¬ NIL; DefsVector: TYPE = RECORD [ index: CARDINAL, elems: SEQUENCE len: CARDINAL OF StackElementRecord]; defs: LONG POINTER TO DefsVector ¬ NIL; Push: PROC [type: CSEIndex] = INLINE { IF stack.index = stack.len THEN { nLen: NAT = stack.index + (stack.index + 4)/2; new: LONG POINTER TO StackVector = zone.NEW[StackVector[nLen]]; OSMiscOps.Copy[ from: @stack[0], nwords: StackVector[stack.index].WORDS - StackVector[0].WORDS, to: @new[0]]; new.index ¬ stack.index; zone.FREE[@stack]; stack ¬ new}; stack[stack.index] ¬ ['\000, type, ts.length]; stack.index ¬ stack.index + 1; }; Pop: PROC = INLINE { IF stack.index = 0 THEN ERROR; stack.index ¬ stack.index - 1; IF stack[stack.index].name='\000 THEN RETURN; IF defs.index = defs.len THEN { nLen: NAT = defs.index + (defs.index+4)/2; new: LONG POINTER TO DefsVector = zone.NEW[DefsVector[nLen]]; OSMiscOps.Copy[ from: @defs[0], nwords: DefsVector[defs.index].WORDS - DefsVector[0].WORDS, to: @new[0]]; new.index ¬ defs.index; zone.FREE[@defs]; defs ¬ new}; defs[defs.index] ¬ stack[stack.index]; defs.index ¬ defs.index+1; }; Find: PROC [type: CSEIndex] RETURNS [StackElement¬NIL] = { FOR i: CARDINAL IN [0..stack.index) DO IF stack[i].type = type THEN RETURN [@stack[i]]; ENDLOOP; }; InsertDefinitions: PROC RETURNS [recursive: BOOL ¬ FALSE] = { WHILE TRUE DO index, j: CARDINAL ¬ 0; found: BOOL ¬ FALSE; FOR i: CARDINAL IN [0..defs.index) DO IF defs[i].name#'\000 AND defs[i].index>=index THEN { index ¬ defs[i].index; j ¬ i; found ¬ recursive ¬ TRUE}; ENDLOOP; IF ~found THEN EXIT; IF ts.length+2 > ts.maxlength THEN ts ¬ Expand[ts]; ts.length ¬ ts.length + 2; FOR i: CARDINAL DECREASING IN [index+2..ts.length) DO ts[i] ¬ ts[i-2] ENDLOOP; ts[index] ¬ VAL[Code.definition.ORD]; ts[index+1] ¬ defs[j].name; defs[j].name ¬ '\000; ENDLOOP; lastName ¬ '\000; defs.index ¬ 0; }; TypeContext: PROC [csei: CSEIndex] RETURNS [CTXIndex] = { WITH t: stb.seb[csei] SELECT FROM enumerated => RETURN [t.valueCtx]; record => RETURN [t.fieldCtx]; definition => RETURN [t.defCtx]; union => RETURN [t.caseCtx]; opaque => RETURN [stb.seb[t.id].idCtx]; ENDCASE => ERROR; }; ListArg: PROC [csei: CSEIndex] RETURNS [Type] = { ctx: CTXIndex = TypeContext[SymbolOps.UnderType[stb, Range[csei]]]; iSei: ISEIndex = SymbolOps.FirstCtxSe[stb, ctx]; WITH c~~stb.ctxb[ctx] SELECT FROM included => IF ~c.complete THEN ERROR; ENDCASE; RETURN [stb.seb[iSei].idType]; }; Base: PROC [csei: CSEIndex] RETURNS [Type] = INLINE { RETURN [WITH t~~stb.seb[csei] SELECT FROM relative => t.baseType, ENDCASE => ERROR] }; Range: PROC [csei: CSEIndex] RETURNS [Type] = { RETURN [WITH t~~stb.seb[csei] SELECT FROM array => t.componentType, sequence => t.componentType, transfer => t.typeOut, ref => t.refType, relative => t.offsetType, arraydesc => t.describedType, ENDCASE => ERROR] }; Domain: PROC [csei: CSEIndex] RETURNS [Type] = { RETURN [WITH t~~stb.seb[csei] SELECT FROM array => t.indexType, sequence => stb.seb[t.tagSei].idType, union => stb.seb[t.tagSei].idType, transfer => t.typeIn, ENDCASE => ERROR] }; Tag: PROC [csei: CSEIndex] RETURNS [ISEIndex] = { RETURN [WITH t~~stb.seb[csei] SELECT FROM sequence => t.tagSei, union => t.tagSei, ENDCASE => ERROR] }; First: PROC [csei: CSEIndex] RETURNS [CARD] = { RETURN [SELECT TypeClass[csei] FROM $enumerated => 0, $subrange => (WITH t~~stb.seb[csei] SELECT FROM subrange => t.origin, ENDCASE => ERROR), $cardinal => Target.maxWord, $integer => Target.maxWord - Target.maxWord/2, $character => CHAR.FIRST.ORD.LONG, $longInteger => Target.maxLongWord - Target.maxLongWord/2, $longCardinal => Target.maxLongWord, ENDCASE => ERROR] }; Last: PROC [csei: CSEIndex] RETURNS [CARD] = { RETURN [SELECT TypeClass[csei] FROM $enumerated => (WITH t~~stb.seb[csei] SELECT FROM enumerated => t.range, ENDCASE => ERROR), $subrange => (WITH t~~stb.seb[csei] SELECT FROM subrange => LOOPHOLE[t.origin + t.range], ENDCASE => ERROR), $cardinal => Target.maxWord, $integer => Target.maxWord/2, $character => CHAR.LAST.ORD.LONG, $longInteger => Target.maxLongWord/2, $longCardinal => Target.maxLongWord, ENDCASE => ERROR] }; Safe: PROC [csei: CSEIndex] RETURNS [BOOL] = INLINE { RETURN [WITH t~~stb.seb[csei] SELECT FROM transfer => t.safe, ENDCASE => ERROR] }; ReadOnly: PROC [csei: CSEIndex] RETURNS [BOOL] = { RETURN [WITH t~~stb.seb[csei] SELECT FROM ref => t.readOnly, arraydesc => t.readOnly, ENDCASE => ERROR] }; Ordered: PROC [csei: CSEIndex] RETURNS [BOOL] = { RETURN [WITH t~~stb.seb[csei] SELECT FROM ref => t.ordered, ENDCASE => ERROR] }; Packed: PROC [csei: CSEIndex] RETURNS [BOOL] = { RETURN [WITH t~~stb.seb[csei] SELECT FROM array => t.packed, sequence => t.packed, ENDCASE => ERROR] }; Mds: PROC [csei: CSEIndex] RETURNS [BOOL] = INLINE { RETURN [WITH t~~stb.seb[csei] SELECT FROM zone => t.mds, ENDCASE => ERROR] }; Ground: PROC [csei: CSEIndex] RETURNS [Type] = INLINE { RETURN [WITH t~~stb.seb[csei] SELECT FROM subrange => t.rangeType, ENDCASE => ERROR] -- NOTE relativeRef not yet }; TypeClass: PROC [sei: Type] RETURNS [code: Code] = { csei: CSEIndex; IF sei=nullType THEN RETURN [$nil]; IF stb.seb[sei].seTag = id THEN RETURN [$definition]; csei ¬ SymbolOps.UnderType[stb, sei]; WITH t~~stb.seb[csei] SELECT FROM basic => code ¬ SelectBasicClass[t.code]; record => code ¬ (IF t.painted THEN $record ELSE $structure); definition => code ¬ $record; real => code ¬ SELECT t.length FROM Target.bitsPerReal => $real, Target.bitsPerReal*2 => $dreal, ENDCASE => ERROR; signed => code ¬ SELECT t.length FROM Target.bitsPerWord => $integer, Target.bitsPerLongWord => $longInteger, Target.bitsPerWord*2 => $dint, ENDCASE => ERROR; unsigned => code ¬ SELECT t.length FROM Target.bitsPerWord => $cardinal, Target.bitsPerLongWord => $longCardinal, Target.bitsPerWord*2 => $dcard, ENDCASE => ERROR; union => code ¬ $union; array => code ¬ $array; opaque => code ¬ $opaque; sequence => code ¬ $sequence; ref => code ¬ (SELECT TRUE FROM t.var => $var, t.counted => IF t.list THEN $list ELSE $ref, ENDCASE => $pointer); arraydesc => code ¬ $descriptor; relative => code ¬ $relativeRef; enumerated => code ¬ $enumerated; subrange => code ¬ $subrange; transfer => code ¬ (SELECT t.mode FROM $proc => IF t.safe THEN $safeProc ELSE $procedure, $port => $port, $signal => $signal, $error => $error, $process => $process, $program => $program, ENDCASE => ERROR); zone => code ¬ (IF t.counted THEN $countedZone ELSE $uncountedZone); mode => code ¬ $type; any => code ¬ $any; ENDCASE => ERROR; }; SelectBasicClass: PROC [code: [0..16)] RETURNS [Code] = INLINE { RETURN [SELECT code FROM codeANY => $unspecified, codeCHAR => $character, ENDCASE => ERROR] }; }. T TypeStringsImpl.mesa Copyright Σ 1984, 1985, 1986, 1987, 1988, 1989, 1991 by Xerox Corporation. All rights reserved. Satterthwaite, June 18, 1986 11:15:31 am PDT Russ Atkinson (RRA) December 19, 1989 7:42:24 pm PST Willie-s, September 24, 1991 4:48 pm PDT Basic algorithm Allocate the various state holders if they have not been already allocated. Free the various holders if they have grown a lot. We try to hold on to little ones to reduce the cost for quick type string construction in the (hopefully common) small cases. The length is substantially less than the maxLength, so we can make the string shorter Special case for small negative numbers RRA: Opaque types do not really have their own contexts, so we can't just rely on the context index within the BCD. Therefore we add in the name. Note, must use absolute, not machine relative, units! RRA: March 11, 1989 avoid code for leftParen and rightParen substitute concrete type for opaque type replace type with its set representative check to see if type is recursive general cases RRA: Unpainted enumeration types are identified by their name/value pairs Painted enumeration types are identified by their paint alone There are a few special records. Other records are painted. CTXRecord.nil.SIZE + 4*CTXRecord.simple.SIZE => AppendCode[$condition]; CTXRecord.nil.SIZE + 5*CTXRecord.simple.SIZE => AppendCode[$lock]; a structure is an unpainted record Canonicalization build an equivalence table for the type minimize the table generate a new string iterate over all k-equivalent classes, splitting them into k+1-equivalent classes check to see if we have done this class already if not, process the class a new class is born Records and other painted types don't add state because they are unique enough For painted enumerated values there is no new state because they are unique. For unpainted enumerated types there is no new state because there are no subsidiary types (just names). For unpainted records we have to add in the states for the component types. Another place where unions are assumed to be painted. This routine is concerned with type equality. If either is painted, then type index equality suffices Both are unpainted, so use name&value equality For structures, equality is determined by name and type equivalence. Stack management Grow the stack a little Grow the defs a little to accomodate the new definition Procedures that work with the symbol table For LIST OF T returns T IF type = fhType THEN RETURN[localFrame]; IF type = nullType THEN RETURN[nil]; IF type = gfhType THEN RETURN[globalFrame]; IF type = unspecType THEN RETURN[unspecified]; Κύ–(cedarcode) style•NewlineDelimiter ™headšœ™Icodešœ ΟeœU™`LšΟy,™,L™4L™(L˜šΟk ˜ LšœŸœ˜LšœŸœ ˜ LšœŸœ˜*Lšœ Ÿœ˜Lšœ ŸœQŸœ)˜ŒLšœŸœ‡˜”Lšœ Ÿœ˜LšœŸœ˜.LšœŸœŸœC˜bLšœ Ÿœ˜%——šΟnœŸœ˜LšŸœ˜LšŸœ˜$LšŸœ˜L˜LšŸœŸœŸœ˜#LšœŸœŸœ)˜H—šœ™LšœŸœŸœ˜LšœŸ œŸœŸœ˜LšœŸœ˜L˜Lšœ Ÿœ˜Lšœ Ÿœ˜Lšœ Ÿœ˜Lšœ Ÿœ˜Lšœ Ÿœ˜L˜š œŸœŸœŸœŸ œŸœŸœ˜VLš ŸœŸœŸœŸœŸœ˜ L˜ L˜ Lšœ Ÿœ˜L˜LšœK™KLšœ˜šŸœ Ÿ˜LšŸœŸœ˜%LšŸœ˜!—šŸœŸ˜ LšŸœ Ÿœ˜#LšŸœ˜—šŸœ Ÿ˜LšŸœŸœ˜$LšŸœ˜!—šŸœŸ˜ LšŸœ Ÿœ˜#LšŸœ˜—Lšœ8˜8L˜L˜L˜LšŸœŸœ˜.L˜Lšœ±™±LšŸœŸœŸœ˜'LšŸœŸœŸœ ˜)LšŸœŸœŸœ ˜)LšŸœŸœŸœ˜'šŸœŸœ˜'L™VLšœ˜LšœŸœ˜Lšœ Ÿœ˜"šœ˜Lšœ˜LšœŸœŸœ˜7Lšœ˜—Lšœ˜LšœŸœ˜L˜—LšŸœ˜ Lšœ˜L˜—š œŸœŸœ˜:LšœŸœ˜%Lšœ Ÿœ˜šœ˜Lšœ˜LšœŸœŸœ˜9Lšœ˜—Lšœ˜LšœŸœ˜Lšœ˜L˜—š œŸœŸœ˜LšœŸœ ˜LšŸœŸœ$˜>Lš ŸœŸœŸœŸœŸœ˜.Lšœ ˜ Lšœ˜L˜L˜—š  œŸœŸœŸœ ˜.L˜—Lš  œŸœŸœ ˜1L˜š  œŸœŸœ˜ Lšœ Ÿœ˜L˜"šŸœŸ˜ šœ˜Lšœ˜—šœ˜Lšœ˜Lšœ˜L˜—šœ Ÿœ˜Lšœ˜Lšœ˜Lšœ˜L˜—šŸœ˜ LšœŸœ˜šŸœ ŸœŸœ˜-L™'Lšœ˜LšŸœ˜Lšœ˜—Lšœ˜Lšœ˜Lšœ˜Lšœ˜Lšœ˜L˜——Lšœ˜L˜—š  œŸœ˜&Lšœ8˜8šŸœŸ˜˜7Lšœ4˜4L˜"L˜ šŸœŸœŸ˜!L˜L˜*˜ Lšœ/˜/LšŸœ ŸœŸœ˜-Lšœ˜Lšœ˜L˜—LšŸœŸœ˜—šŸœŸœŸœ%Ÿ˜6Lšœ Ÿœ˜'—šŸœŸœŸ˜!šœ ˜ LšŸœlŸœ ™’Lšœ+˜+Lšœ˜Lšœ˜L˜—šŸœ˜ LšœŸœŸœ˜!šœŸœŸœ˜™5LšŸœ™——Lšœ˜Lšœ˜Lšœ˜L˜——Lšœ˜—LšŸœŸœ˜—Lšœ˜L˜—š  œŸœ˜!šŸœ˜LšŸœŸœ˜šŸœ˜LšœŸœŸœ˜?LšœŸœ"˜2šŸœŸœŸœ˜Lšœ'™'—LšœŸœ ˜Lš ŸœŸœŸœŸœŸœ˜JL˜——Lšœ˜L˜—š  œŸœŸœ˜-L˜+L˜'L˜L˜—š œŸœ˜'Lšœ0˜0L˜ L˜Lšœ(™(LšŸœ'Ÿœ˜LLšœ(™(šŸœŸœŸœŸ˜&LšŸœŸœŸœ˜=LšŸœ˜—Lšœ!™!šŸœŸœŸœ˜ LšŸœŸœ˜)Lšœ#Ÿœ˜+—Lšœ ™ L˜ šŸœŸ˜%LšœŸœ˜˜Lšœ"˜"šŸœŸœŸ˜=šŸ˜LšœΟc.˜C—šŸ˜šŸœŸœŸ˜!˜šŸœ Ÿœ˜LšœI™ILšœ˜L˜šŸœNŸœŸ˜hL˜+šŸœŸ˜Lšœ8˜8—LšŸœ˜—L˜L˜—šŸœ˜Lšœ=™=Lšœ˜Lšœ˜Lšœ˜—L˜—LšŸœŸœ˜———Lšœ˜—šœ ˜ Lšœ<™<šŸœŸ˜'L˜BL˜HLšœG™GLšœB™BLšŸœ,˜3—Lšœ˜—šœ˜Lšœ"™"L˜"šŸœŸœŸ˜!Lšœ Ÿœ ŸœŸœ˜&LšŸœ˜—L˜šŸœNŸœŸ˜hLšœ˜LšŸœ˜—L˜L˜—šœ ˜ Lšœ˜Lšœ˜Lšœ˜—˜ LšŸœŸœ˜)L˜L˜ L˜L˜—˜LšŸœŸœ˜)L˜L˜L˜L˜—šœ˜L˜L˜Lšœ˜Lšœ˜L˜—˜ šŸœŸœŸ˜!˜ šŸœŸœ$˜=LšŸœ˜LšŸœ*˜.——LšŸœŸœ˜—Lšœ˜—˜!LšŸœ Ÿœ˜#L˜L˜—šœ ˜ LšŸœŸœ˜+LšŸœŸœ˜-L˜L˜ L˜—˜L˜L˜L˜L˜—˜ LšŸœŸœ˜-šŸœ˜ LšŸœ˜LšŸœ3˜7—Lšœ˜—˜ LšŸœŸœ˜-L˜L˜L˜—˜LšŸœŸœ˜+LšŸœŸœ˜-L˜L˜L˜—˜!LšŸœŸœ˜-L˜L˜L˜—˜L˜L˜L˜L˜—˜%LšŸœ Ÿœ˜%L˜L˜L˜L˜—˜ LšŸœ Ÿœ˜%L˜L˜L˜—˜ L˜L˜L˜—˜ŠL˜—LšœŸœ˜#LšŸœŸœ˜—L˜L˜L˜—š  œŸœŸœŸœ˜IL˜ šŸœŸœŸ˜"˜ šœŸœ$ŸœŸ˜DL˜Lšœ,˜,LšŸœ ˜—Lšœ=˜=šŸœŸœŸœ˜3L˜LšœS˜SLšœS˜SšŸœŸœ ˜3LšŸœŸœ)˜G———LšŸ˜—šœ˜L˜——Lšœ Ÿœ˜L˜Lš œŸœŸœŸœŸœŸœŸœ˜J—šœ™š  œŸœ˜#Lšœ'™'Lšœ‘˜,Lšœ™LšŸœ ŸœŸœŸœ˜Lšœ™L˜Lšœ‘$˜=Lšœ˜Lšœ˜L˜—š œŸœŸœ Ÿ œ˜*Lšœ'™'Lšœ*™*šŸœŸœŸœŸ˜&Lšœ/™/LšœŸœŸœ˜šŸœŸœŸœŸœ˜LšŸœ#Ÿœ Ÿœ˜7LšŸœ˜—šŸœŸœ˜Lšœ™L˜L˜L˜šŸœŸœŸœŸ˜&šŸœ#Ÿœ‘˜˜ALšŸœ(˜+—Lšœ˜—Lšœ Ÿœ*ŸœŸœ˜pLšœ Ÿœ-˜<˜šŸœ%˜+LšŸœ(˜+——LšœŸœ)˜7LšœŸœ)˜7˜8LšŸœ)˜/—˜<šŸœ*˜0LšŸœ)˜,——Lšœ Ÿœ)˜;LšœŸœ˜#LšŸœŸœŸœ˜—šœ˜L˜——š œŸœŸœ˜1L˜0šŸœŸœŸœŸ˜&LšŸœŸœŸœ˜5LšŸœ˜—LšŸœ˜Lšœ˜L˜—šœ ŸœŸœ˜LšœŸœ˜Lš œŸœŸœŸœŸœ!˜H—Lš œŸœŸœŸœŸœ˜(L˜šœ ŸœŸœ˜LšœŸœ˜LšœŸœŸœŸœ ˜+—Lš œŸœŸœŸœŸœ˜'—šœ™Lš œŸœŸœŸœŸœ˜OLš œŸœŸœŸœŸœ˜8L˜šœ ŸœŸœ˜LšœŸœ˜LšœŸœŸœŸœ˜5—Lš œŸœŸœŸœŸœ˜)L˜šœ ŸœŸœ˜LšœŸœ˜LšœŸœŸœŸœ˜5—Lš œŸœŸœŸœŸœ˜'L˜š œŸœŸœ˜&šŸœŸœ˜!Lšœ™LšœŸœ%˜.Lš œŸœŸœŸœŸœ˜?šœ˜Lšœ˜Lšœ!ŸœŸœ˜>Lšœ ˜ —Lšœ˜LšœŸœ ˜L˜ —Lšœ.˜.Lšœ˜Lšœ˜L˜—š œŸœŸœ˜LšŸœŸœŸœ˜Lšœ˜LšŸœŸœŸœ˜-šŸœŸœ˜Lšœ7™7LšœŸœ!˜*Lš œŸœŸœŸœŸœ˜=šœ˜Lšœ˜LšœŸœŸœ˜;Lšœ ˜ —Lšœ˜LšœŸœ˜Lšœ ˜ —Lšœ&˜&Lšœ˜Lšœ˜L˜—š œŸœŸœŸœ˜:šŸœŸ œŸœŸ˜&LšŸœŸœŸœ ˜0LšŸœ˜—šœ˜L˜——š  œŸœŸœ ŸœŸœ˜=šŸœŸœŸ˜ Lšœ Ÿœ˜LšœŸœŸœ˜šŸœŸœŸœŸ˜%šŸœŸœŸœ˜5L˜LšœŸœ˜—LšŸœ˜—LšŸœŸœŸœ˜LšŸœŸœ˜3L˜Lš ŸœŸœŸ œŸœŸœŸœ˜NLšœ ŸœŸœ˜%L˜L˜LšŸœ˜—L˜Lšœ˜Lšœ˜——šœ*™*š  œŸœŸœ˜9šŸœŸœŸ˜!LšœŸœ˜"Lšœ Ÿœ˜LšœŸœ ˜ Lšœ Ÿœ ˜Lšœ Ÿœ˜'LšŸœŸœ˜—šœ˜L˜——š œŸœŸœ ˜1Lšœ™LšœC˜CL˜0šŸœŸœŸ˜!Lšœ Ÿœ ŸœŸœ˜&LšŸœ˜—LšŸœ˜Lšœ˜L˜—š œŸœŸœ Ÿœ˜5šŸœŸœŸœŸ˜)L˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœ ˜/šŸœŸœŸœŸ˜)L˜L˜L˜L˜L˜L˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœ ˜0šŸœŸœŸœŸ˜)L˜L˜%L˜"L˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœ˜1šŸœŸœŸœŸ˜)L˜L˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœŸœ˜/šŸœŸœŸ˜#L˜˜ šœŸœŸœŸ˜"Lšœ˜LšŸœŸœ˜——Lšœ˜Lšœ.˜.Lš œŸœŸœŸœŸœ˜"Lšœ:˜:Lšœ$˜$LšŸœŸœ˜—šœ˜L˜——š œŸœŸœŸœ˜.šŸœŸœŸ˜#˜šœŸœŸœŸ˜"Lšœ˜LšŸœŸœ˜——˜ šœŸœŸœŸ˜"Lšœ Ÿœ˜)LšŸœŸœ˜——Lšœ˜Lšœ˜Lš œŸœŸœŸœŸœ˜!Lšœ%˜%Lšœ$˜$LšŸœŸœ˜—šœ˜L˜——š  œŸœŸœŸœŸœ˜5šŸœŸœŸœŸ˜)L˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœŸœ˜2šŸœŸœŸœŸ˜)L˜L˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœŸœ˜1šŸœŸœŸœŸ˜)L˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœŸœ˜0šŸœŸœŸœŸ˜)L˜L˜LšŸœŸœ˜—šœ˜L˜——š  œŸœŸœŸœŸœ˜4šŸœŸœŸœŸ˜)L˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœ Ÿœ˜7šŸœŸœŸœŸ˜)L˜LšŸœŸœ‘˜.—šœ˜L˜——š  œŸœ Ÿœ˜4L˜Lšœ)™)Lšœ$™$Lšœ+™+Lšœ.™.LšŸœŸœŸœ˜#LšŸœŸœŸœ˜5L˜%šŸœŸœŸ˜!Lšœ)˜)LšœŸœ Ÿœ Ÿœ ˜=Lšœ˜šœŸœ Ÿ˜#Lšœ˜Lšœ˜LšŸœŸœ˜—šœŸœ Ÿ˜%L˜Lšœ'˜'L˜LšŸœŸœ˜—šœŸœ Ÿ˜'L˜ Lšœ(˜(L˜LšŸœŸœ˜—Lšœ˜Lšœ˜Lšœ˜Lšœ˜šœŸœŸœŸ˜L˜Lšœ ŸœŸœŸœ˜,LšŸœ˜—Lšœ ˜ Lšœ ˜ Lšœ!˜!Lšœ˜šœŸœŸ˜&Lšœ ŸœŸœ Ÿœ ˜2L˜L˜L˜L˜L˜LšŸœŸœ˜—LšœŸœ ŸœŸœ˜DLšœ˜Lšœ˜LšŸœŸœ˜—šœ˜L˜——š œŸœŸœ Ÿœ˜@šŸœŸœŸ˜L˜L˜LšŸœŸœ˜—šœ˜L˜———˜L˜L˜˜L˜L˜L˜L˜———…—X`±