-- DIMed.mesa last edit: -- Bruce October 25, 1980 9:59 PM -- Sandman July 18, 1980 8:11 AM DIRECTORY Actions USING [DoRead, ReadUser], ComData USING [typeCARDINAL, typeINT, typeStringBody], DebugFormat USING [BitAddress, Foo], DebugOps USING [Foo, InvalidNumber, Lengthen, ShortCopyWRITE, ShortREAD], DI USING [ CSEIndex, dereferenced, DerefProcDesc, Err, FindField, Foo, Format, GetControlLink, GetDesc, GetLongDesc, GetNumber, GetValue, ISEIndex, LongDesc, Normalize, NotAnArray, NotAProcedure, Number, NumberType, Pad, SEIndex, SequenceSEIndex, TypeForSe], DIActions USING [ CheckLength, CheckLink, Dec, Deref, DIAbort, Inc, LengthenFob, LoopHoleWork, MakeCnt, Pop, Push, PushLongVal, PushVal, Qualify, Son, TargetTypeWork, Tos, Work], DOutput USING [Blanks, Char, EOL, Line, Text], Dump USING [ArrayHandle, ArrayInfo, CalculateAddr, Elements, ModeName], Gf USING [OldLink], DHeap USING [AllocFob, FreeLong], Init USING [CoreSwap], Inline USING [LongNumber], Lookup USING [HTIndex, HtiToString, StringToHti, XferCtx], MachineDefs USING [CallDP, WordLength], Pc USING [LinkToCbti], PrincOps USING [ControlLink, MaxParamsInStack, StateVector, SVPointer], State USING [GetGS, GSHandle], Storage USING [Node], SymbolOps USING [ BitsPerElement, FirstCtxSe, MakeNonCtxSe, NextSe, TransferTypes, TypeRoot, UnderType, VariantField, WordsForType, XferMode], SymbolPack, Symbols USING [ ArraySEIndex, bodyType, CBTIndex, CBTNull, CSEIndex, CSENull, HTIndex, HTNull, ISEIndex, ISENull, RecordSEIndex, RecordSENull, SEIndex, SENull, SERecord, seType, TransferMode, typeANY], SymbolTable USING [Base], Table USING [AddNotify, Base, DropNotify, Notifier], Tree USING [Index, Link, Null, Scan, treeType], TreeOps USING [OpName, ScanList], Types USING [Assignable, Equivalent, Handle]; DIMed: PROGRAM IMPORTS Actions, com: ComData, DebugOps, DI, DIActions, DOutput, Dump, Gf, DHeap, Init, Lookup, Pc, State, Storage, MyBase: SymbolPack, SymbolOps, Table, TreeOps, Types EXPORTS DI, DIActions = BEGIN OPEN DI, DIActions; BadTree: ERROR = CODE; BadTag: ERROR = CODE; DerefError: ERROR = CODE; data: State.GSHandle ← State.GetGS[]; seb: Table.Base; tb: Table.Base; bb: Table.Base; med: PUBLIC CARDINAL ← 0; Notify: Table.Notifier = BEGIN tb ← base[Tree.treeType]; bb ← base[Symbols.bodyType]; seb ← base[Symbols.seType]; END; Add: PROCEDURE = BEGIN IF med = 0 THEN Table.AddNotify[Notify]; med ← med + 1; END; Drop: PROCEDURE = BEGIN IF (med ← med-1) = 0 THEN Table.DropNotify[Notify]; END; Interval: PUBLIC PROC [ t: Tree.Link, type: Symbols.SEIndex, openLow, openHigh, cntOnly: BOOLEAN ← FALSE] = BEGIN index: Tree.Index ← CheckLink[t,subtree]; f1, f2: Foo; size, size2: NumberType; signed, signed2: BOOLEAN; Add[]; [f1,size,signed] ← MinimalRep[tb[index].son[1],type]; [f2,size2,signed2] ← MinimalRep[tb[index].son[2], IF cntOnly THEN Symbols.typeANY ELSE type]; Drop[]; IF cntOnly THEN RETURN; IF openLow THEN Inc[f1,size,signed]; IF openHigh THEN Dec[f2,size,signed2]; MakeCnt[f2,f1,size,signed OR signed2]; END; Size: PUBLIC PROC [f: Foo] = BEGIN IF ~f.typeOnly THEN AbortWithError[notType]; PushVal[SymbolOps.WordsForType[f.tsei],com.typeCARDINAL]; END; PushNil: PUBLIC PROC [f: Foo] = BEGIN p: POINTER TO ARRAY [0..3) OF POINTER ← Storage.Node[3]; nil: Foo ← DHeap.AllocFob[]; p↑ ← ALL[NIL]; nil.addr.base ← p; nil.words ← 1; Add[]; IF f # NIL THEN BEGIN csei: Symbols.CSEIndex ← TypeForSe[f.tsei]; nil.tsei ← csei; DO WITH seb[csei] SELECT FROM long => {nil.words ← nil.words + 1; csei ← TypeForSe[rangeType]}; arraydesc => {nil.words ← nil.words + 1; EXIT}; ENDCASE => EXIT; ENDLOOP; END ELSE nil.tsei ← Symbols.typeANY; Drop[]; Push[nil]; END; Assignable: PUBLIC PROCEDURE [f: Foo, csei: CSEIndex] = BEGIN left: Types.Handle ← [LOOPHOLE[MyBase],csei]; right: Types.Handle ← [LOOPHOLE[MyBase],TypeForSe[f.tsei]]; tSize: CARDINAL = SymbolOps.WordsForType[csei]; checkSize: BOOLEAN ← TRUE; IF ~Types.Assignable[typeL: left, typeR: right] THEN AbortWithError[typeMismatch, f.hti]; DI.GetValue[f]; -- so I can check sizes Add[]; WITH seb[TypeForSe[csei]] SELECT FROM subrange => IF CheckLength[f,1] THEN { i: LONG POINTER TO INTEGER ← LOOPHOLE[f.addr.base]; checkSize ← range # 0; i↑ ← i↑ - origin} ELSE {Drop[]; AbortWithError[invalidSubrange]}; ENDCASE; Drop[]; SELECT TRUE FROM f.tsei = csei => NULL; csei = nullProc => NULL; csei = nullSig => NULL; csei = nullError => NULL; TotalWords[f] = tSize => RETURN; tSize # 2 => AbortWithError[sizeMismatch]; ~CheckLength[f,1] => AbortWithError[sizeMismatch]; ENDCASE => LengthenFob[f]; IF checkSize AND tSize # TotalWords[f] THEN AbortWithError[sizeMismatch, f.hti]; END; DumpArray: PUBLIC PROC [array: Foo] = BEGIN cnt: CARDINAL ← GetIndex[]; start: CARDINAL ← GetIndex[]; long: BOOLEAN; [array,long,] ← SetUpApply[array]; IF long THEN DoLongDesc[array,start,start+cnt] ELSE DoDesc[array,start,start+cnt]; END; GetIndex: PROC RETURNS [c: CARDINAL] = BEGIN f: Foo ← Pop[]; n: Number; n ← GetNumber[f]; SELECT n.type FROM one => c ← n.c; ENDCASE => AbortWithError[indexTooBig]; END; Memory: PUBLIC PROC [t: Tree.Link, type: Symbols.SEIndex] = BEGIN f: Foo ← Son[t,type]; lp: LONG POINTER; n: Number ← GetNumber[f, invalidAddress]; SELECT n.type FROM one => lp ← DebugOps.Lengthen[n.p]; two => lp ← n.lp; ENDCASE; DHeap.FreeLong[f.addr.base]; f.hti ← Symbols.HTNull; f.tsei ← type; f.addr.base ← lp; f.there ← TRUE; f.words ← 1; END; TotalWords: PUBLIC PROC [f: Foo] RETURNS [cnt: CARDINAL] = BEGIN cnt ← f.words; IF f.bits # 0 THEN cnt ← cnt + 1; END; DumpMemory: PUBLIC PROCEDURE [fcnt: Foo] = BEGIN fstart: Foo ← Pop[]; start: LONG POINTER; cnt: CARDINAL; n: Number; n ← GetNumber[fstart]; SELECT n.type FROM one => start ← DebugOps.Lengthen[n.p]; two => start ← n.lp; ENDCASE => AbortWithError[invalidAddress]; n ← GetNumber[fcnt]; SELECT n.type FROM one => cnt ← n.c; two => AbortWithError[wontDump]; ENDCASE => AbortWithError[invalidNumber]; Actions.DoRead[start,cnt, Actions.ReadUser]; RETURN END; GetSize: PUBLIC PROCEDURE [index: Tree.Index, type: Symbols.SEIndex] RETURNS [size: NumberType, cnt: CARDINAL, signed: BOOLEAN] = BEGIN Process: Tree.Scan = BEGIN tosSize: NumberType; int: BOOLEAN; IF t = Tree.Null THEN ERROR BadTree; cnt ← cnt + 1; [,tosSize,int] ← GetRep[t, type]; IF int THEN signed ← TRUE; IF tosSize = size THEN RETURN; size ← two; END; cnt ← 0; size ← one; signed ← FALSE; Add[]; TreeOps.ScanList[tb[index].son[1],Process ! UNWIND => Drop[]]; Drop[]; END; MinimalRep: PUBLIC PROCEDURE [t: Tree.Link, type: Symbols.SEIndex] RETURNS [f: Foo, size: NumberType, signed: BOOLEAN] = BEGIN p: LONG POINTER TO Inline.LongNumber; [f,size,signed] ← GetRep[t,type]; IF size = one THEN RETURN; p ← f.addr.base; IF p.highbits # 0 THEN RETURN; size ← one; f.words ← 1; END; GetRep: PUBLIC PROCEDURE [t: Tree.Link, type: Symbols.SEIndex] RETURNS [f: Foo, size: NumberType, signed: BOOLEAN] = BEGIN n: Number; LoopHoleWork[t, type]; f ← Tos[]; Add[]; WITH seb[TypeForSe[f.tsei]] SELECT FROM subrange => f.tsei ← TypeForSe[rangeType]; ENDCASE; Drop[]; n ← GetNumber[f]; size ← n.type; WITH Format[f.tsei].vf SELECT FROM int => {signed ← TRUE; RETURN}; ENDCASE; SELECT size FROM one => signed ← ~n.sign; two => signed ← ~n.lsign; ENDCASE => ERROR DebugOps.InvalidNumber[f]; END; Base: PUBLIC PROC [f: Foo, sei: SEIndex] = BEGIN long: BOOLEAN; Add[]; WITH seb[TypeForSe[f.tsei]] SELECT FROM long => long ← TRUE; ENDCASE => long ← FALSE; Drop[]; IF long THEN LongBase[f,sei] ELSE ShortBase[f,sei]; END; ShortBase: PROC [f: Foo, sei: SEIndex] = BEGIN asei: Symbols.ArraySEIndex; d: LongDesc; [d,asei] ← GetDesc[f ! NotAnArray => {AbortWithError[typeMismatch,f.hti]; ERROR}]; PushLongVal[d.base,MakeLongType[MakePointerType[Symbols.typeANY]]]; END; LongBase: PROC [f: Foo, sei: SEIndex] = BEGIN asei: Symbols.ArraySEIndex; d: LongDesc; [d,asei] ← GetLongDesc[f ! NotAnArray => {AbortWithError[typeMismatch,f.hti]; ERROR}]; PushLongVal[d.base,MakeLongType[MakePointerType[Symbols.typeANY]]]; END; Length: PUBLIC PROC [f: Foo, sei: SEIndex] = BEGIN long: BOOLEAN; asei: Symbols.ArraySEIndex; Add[]; WITH seb[TypeForSe[f.tsei]] SELECT FROM long => long ← TRUE; ENDCASE => long ← FALSE; Drop[]; IF long THEN BEGIN ld: LongDesc; [ld,asei] ← GetLongDesc[f ! NotAnArray => {AbortWithError[typeMismatch,f.hti]; ERROR}]; PushVal[ld.length,com.typeCARDINAL]; END ELSE BEGIN d: LongDesc; [d,asei] ← GetDesc[f ! NotAnArray => {AbortWithError[typeMismatch,f.hti]; ERROR}]; PushVal[d.length,com.typeCARDINAL]; END; END; DerefApply: PROC [f: Foo] RETURNS [success: BOOLEAN] = BEGIN tsei: Symbols.CSEIndex ← TypeForSe[f.tsei]; DO WITH seb[tsei] SELECT FROM ref => IF basing THEN RETURN[FALSE] ELSE EXIT; long => tsei ← TypeForSe[rangeType]; ENDCASE => RETURN[FALSE]; ENDLOOP; RETURN[Deref[f]]; END; SetUpApply: PROC [f: Foo] RETURNS [newFoo: Foo, long: BOOLEAN, target: Symbols.CSEIndex] = BEGIN WHILE DerefApply[f] DO ENDLOOP; target ← TypeForSe[f.tsei]; Add[]; WITH seb[target] SELECT FROM long => {long ← TRUE; target ← TypeForSe[rangeType]}; ENDCASE => long ← FALSE; Drop[]; IF target = com.typeStringBody THEN { DIActions.Qualify[f, Lookup.StringToHti["text"L]]; newFoo ← Pop[]; target ← TypeForSe[newFoo.tsei]} ELSE newFoo ← f; END; DoApply: PUBLIC PROC [t: Tree.Link, target: Foo] = BEGIN ENABLE UNWIND => Drop[]; uniOperand: BOOLEAN ← TreeOps.OpName[t] # list; long: BOOLEAN; targetType: CSEIndex; IF target = NIL THEN RETURN; Add[]; [target, long, targetType] ← SetUpApply[target]; dereferenced ← TRUE; DO WITH seb[targetType] SELECT FROM record => { isei: Symbols.ISEIndex = SymbolOps.VariantField[targetType]; WITH seb[TypeForSe[isei]] SELECT FROM sequence => { DIActions.Qualify[target, seb[isei].hash]; target ← Pop[]; targetType ← TypeForSe[target.tsei]; LOOP}; ENDCASE; AbortWithError[constructor]}; sequence => BEGIN start: CARDINAL; start ← GetStart[t, TypeForSe[tagSei]]; DoSequence[target,tagSei,start]; END; array => BEGIN start: CARDINAL; IF ~uniOperand THEN ERROR BadTree; start ← GetStart[t, indexType]; DoArray[target,start,start]; END; arraydesc => BEGIN start: CARDINAL; asei: Symbols.ArraySEIndex; IF ~uniOperand THEN ERROR BadTree; asei ← LOOPHOLE[SymbolOps.UnderType[describedType]]; start ← GetStart[t, seb[asei].indexType]; IF long THEN DoLongDesc[target,start,start] ELSE DoDesc[target,start,start]; END; transfer => BEGIN tm: Symbols.TransferMode = SymbolOps.XferMode[targetType]; IF tm # proc THEN ApplyError[tm]; ProcedureCall[t,target]; END; ref => BEGIN tos: Foo; IF ~basing THEN ERROR DerefError; Work[t]; tos ← Tos[]; IF ~uniOperand THEN AbortWithError[notRelative,tos.hti]; Reloc[target,tos]; END; ENDCASE => AbortWithError[wrongBrackets, target.hti]; EXIT; ENDLOOP; Drop[]; END; DoSequence: PROC [f: Foo, tagSei: Symbols.ISEIndex, start: CARDINAL] = BEGIN ai: Dump.ArrayInfo; tag: Foo; ba: DebugFormat.BitAddress; sei: SequenceSEIndex = LOOPHOLE[TypeForSe[f.tsei]]; rec: Symbols.CSEIndex = SymbolOps.TypeRoot[sei]; words: CARDINAL; Add[]; tag ← DI.FindField[f, DI.Pad[f, LOOPHOLE[rec]], tagSei]; IF tag.bits + tag.addr.offset > MachineDefs.WordLength THEN ERROR BadTag; ba ← [base: tag.addr.base, offset: ]; [words, ba.offset] ← Normalize[tag.addr.offset+tag.bits]; ba.base ← tag.words + ba.base + words; DI.GetValue[tag]; ai ← [start: start, stop: start, length: tag.addr.base↑, addr: ba, packing: SymbolOps.BitsPerElement[seb[sei].componentType, seb[sei].packed], type: seb[sei].componentType]; Drop[]; GetElement[@ai]; END; DoArray: PROC [f: Foo, start, stop: CARDINAL] = BEGIN ai: Dump.ArrayInfo; d: LongDesc; sei: Symbols.ArraySEIndex; [d,sei] ← GetDesc[f]; Add[]; ai ← [ start: start, stop: stop, length: d.length, addr: f.addr, packing: SymbolOps.BitsPerElement[seb[sei].componentType, seb[sei].packed], type: seb[sei].componentType]; Drop[]; IF start = stop THEN GetElement[@ai] ELSE Dump.Elements[@ai]; END; GetElement: PUBLIC PROCEDURE [ai: Dump.ArrayHandle] = BEGIN OPEN DOutput; f: Foo ← DHeap.AllocFob[]; -- comes back zeroed f.tsei ← ai.type; f.there ← TRUE; [f.words, f.bits] ← Normalize[ai.packing]; f.addr ← Dump.CalculateAddr[ai, ai.start]; Push[f]; END; GetStart: PROC [t: Tree.Link, target: Symbols.SEIndex] RETURNS [CARDINAL] = BEGIN f: Foo; n: Number; offset: INTEGER ← 0; tsei: Symbols.CSEIndex ← TypeForSe[target]; WITH seb[tsei] SELECT FROM subrange => {offset ← origin; --IF range = 0 THEN --tsei ← TypeForSe[rangeType]}; ENDCASE; TargetTypeWork[t,tsei]; SELECT TotalWords[(f ← Pop[])] FROM 0 => AbortWithError[invalidNumber]; 1 => NULL; 2 => AbortWithError[indexTooBig]; ENDCASE => AbortWithError[invalidNumber]; n ← GetNumber[f]; RETURN[n.c-offset]; END; Reloc: PROC [base, rel: Foo] = BEGIN ENABLE UNWIND => Drop[]; csei: CSEIndex ← TypeForSe[rel.tsei]; rr: RelocRec; Add[]; WITH seb[csei] SELECT FROM relative => BEGIN lengthen, pointer: BOOLEAN; left: Types.Handle ← [LOOPHOLE[MyBase],TypeForSe[baseType]]; right: Types.Handle ← [LOOPHOLE[MyBase],TypeForSe[base.tsei]]; IF ~Types.Equivalent[left, right] THEN AbortWithError[wrongBase, base.hti]; rel.tsei ← offsetType; [rr, lengthen, pointer] ← Relocate[base,rel]; DHeap.FreeLong[rel.addr.base]; rel.tsei ← IF lengthen THEN MakeLongType[TypeForSe[resultType]] ELSE resultType; rel.addr.base ← rr.base; rel.addr.offset ← rel.bits ← 0; rel.words ← SymbolOps.WordsForType[resultType]; rel.there ← FALSE; rel.hti ← Symbols.HTNull; IF pointer AND ~Deref[rel] THEN AbortWithError[notRelative]; END; ENDCASE => AbortWithError[notRelative,rel.hti]; Drop[]; END; Relocate: PROC [f1,f2: Foo] RETURNS [rr: RelocRec, lengthen: BOOLEAN, deref: BOOLEAN] = BEGIN n: Number; lc: LONG CARDINAL; csei: Symbols.CSEIndex ← TypeForSe[f2.tsei]; long: BOOLEAN ← FALSE; lengthen ← FALSE; n ← GetNumber[f1, invalidAddress]; rr.base ← Storage.Node[SIZE[LongDesc]]; IF n.type = one THEN lc ← n.c ELSE lc ← n.lc; DO ENABLE UNWIND => DHeap.FreeLong[rr.base]; WITH seb[csei] SELECT FROM arraydesc => { IF long THEN { d: LongDesc; [d, csei] ← GetLongDesc[f2]; d.base ← d.base + lc; rr.rel↑ ← d} ELSE { d: LongDesc; [d, csei] ← GetDesc[f2]; lengthen ← TRUE; d.base ← d.base + lc; rr.rel↑ ← d}; deref ← FALSE; RETURN}; long => {long ← TRUE; csei ← TypeForSe[rangeType]; LOOP}; ENDCASE => { deref ← TRUE; n ← GetNumber[f2, notRelative]; IF n.type = one THEN lc ← lc + n.c ELSE lc ← lc + n.lc; rr.lc↑ ← lc; RETURN}; ENDLOOP; END; RelocRec: TYPE = RECORD [SELECT OVERLAID * FROM pointer => [lc: LONG POINTER TO LONG CARDINAL], relDesc => [rel: LONG POINTER TO LongDesc], foo => [base: LONG POINTER], ENDCASE]; DoLongDesc: PROC [f: Foo, start, stop: CARDINAL] = BEGIN sei: Symbols.ArraySEIndex; d: LongDesc; ai: Dump.ArrayInfo; [d,sei] ← GetLongDesc[f]; IF d.base = NIL THEN AbortWithError[nilChk]; Add[]; ai ← [start: start, stop: stop, addr: [d.base,0], length: d.length, packing: SymbolOps.BitsPerElement[seb[sei].componentType, seb[sei].packed], type: seb[sei].componentType]; Drop[]; IF start = stop THEN GetElement[@ai] ELSE Dump.Elements[@ai]; END; DoDesc: PROC [f: Foo, start, stop: CARDINAL] = BEGIN sei: Symbols.ArraySEIndex; d: LongDesc; ai: Dump.ArrayInfo; [d,sei] ← GetDesc[f]; IF d.base = NIL THEN AbortWithError[nilChk]; Add[]; ai ← [start: start, stop: stop, addr: [d.base,0], length: d.length, packing: SymbolOps.BitsPerElement[seb[sei].componentType, seb[sei].packed], type: seb[sei].componentType]; Drop[]; IF start = stop THEN GetElement[@ai] ELSE Dump.Elements[@ai]; END; ProcedureCall: PUBLIC PROCEDURE [args: Tree.Link, proc: Foo] = BEGIN OPEN SymbolOps; ENABLE UNWIND => Drop[]; cnt: CARDINAL ← 0; in: Symbols.RecordSEIndex; isei: ISEIndex ← Symbols.ISENull; cl: PrincOps.ControlLink; state: PrincOps.StateVector; cbti: Symbols.CBTIndex; sv: PrincOps.SVPointer; Collect: Tree.Scan = BEGIN f: Foo; words: CARDINAL; p: LONG POINTER TO ARRAY [0..0) OF UNSPECIFIED; isei ← IF cnt = 0 THEN FirstCtxSe[seb[in].fieldCtx] ELSE NextSe[isei]; IF isei = Symbols.ISENull THEN AbortWithError[wrongNumberArgs,proc.hti]; TargetTypeWork[t,isei]; words ← TotalWords[(f←Pop[])]; GetValue[f]; cnt ← cnt + words; IF state.stkptr + words > PrincOps.MaxParamsInStack THEN AbortWithError[tooManyArgs,proc.hti]; p ← LOOPHOLE[f.addr.base]; FOR i: CARDINAL IN [0..words) DO state.stk[state.stkptr] ← p[i]; state.stkptr ← state.stkptr + 1; ENDLOOP; END; Add[]; IF data.worryEntry THEN AbortWithError[worryCall]; in ← TransferTypes[TypeForSe[proc.tsei]].typeIn; state.instbyte ← state.stkptr ← 0; TreeOps.ScanList[args,Collect]; IF cnt#WordsForType[in] OR (cnt#0 AND NextSe[isei]#Symbols.ISENull) THEN AbortWithError[wrongNumberArgs,proc.hti]; cl ← DerefProcDesc[GetControlLink[proc ! NotAProcedure => GOTO inline] ! NotAProcedure => GOTO inline]; cbti ← Pc.LinkToCbti[cl]; IF cbti = Symbols.CBTNull THEN AbortWithError[callingInline]; state.source ← NIL; state.dest ← Gf.OldLink[cl]; sv ← @LOOPHOLE[data.ESV.parameter, MachineDefs.CallDP].sv; DebugOps.ShortCopyWRITE[ to: sv, from: @state, nwords: SIZE[PrincOps.StateVector]]; Init.CoreSwap[call]; sv ← @LOOPHOLE[data.ESV.parameter, MachineDefs.CallDP].sv; CollectResults[cbti, sv]; Drop[]; EXITS inline => AbortWithError[callingInline]; END; CollectResults: PROC [cbti: Symbols.CBTIndex, sv: PrincOps.SVPointer] = BEGIN f: DebugOps.Foo ← Lookup.XferCtx[bb[cbti].id,NIL,out]; locals: POINTER; IF f = NIL OR f.tsei = Symbols.RecordSENull THEN {Push[DHeap.AllocFob[]]; RETURN}; WITH seb[DI.TypeForSe[f.tsei]] SELECT FROM record => IF hints.unifield THEN { csei: Symbols.CSEIndex = DI.TypeForSe[SymbolOps.FirstCtxSe[fieldCtx]]; WITH seb[csei] SELECT FROM record => NULL; ENDCASE => f.tsei ← csei}; ENDCASE; f.there ← f.addr.useStack ← TRUE; locals ← IF f.words > PrincOps.MaxParamsInStack THEN DebugOps.ShortREAD[@sv.stk[0]] ELSE @sv.stk[0]; f.addr.base ← DebugOps.Lengthen[locals]; f.xfer ← FALSE; Push[f]; END; ApplyError: PROC [tm: Symbols.TransferMode] = BEGIN OPEN DOutput; Text[" can't call a"L]; IF tm = error THEN Char['n]; Blanks[1]; Dump.ModeName[tm]; Char['!]; EOL[]; ERROR DIAbort; END; LongRec: TYPE = RECORD [sei, lsei: Symbols.CSEIndex]; longs: ARRAY [0..3) OF LongRec; nullProc: PUBLIC Symbols.CSEIndex; nullError: PUBLIC Symbols.CSEIndex; nullSig: PUBLIC Symbols.CSEIndex; MakeXferType: PUBLIC PROC [mode: Symbols.TransferMode] RETURNS [csei: Symbols.CSEIndex] = BEGIN OPEN SymbolOps, Symbols; SELECT mode FROM proc => BEGIN IF nullProc # CSENull THEN RETURN[nullProc]; csei ← nullProc ← MakeNonCtxSe[SIZE[transfer cons SERecord]]; END; signal => BEGIN IF nullSig # CSENull THEN RETURN[nullSig]; csei ← nullSig ← MakeNonCtxSe[SIZE[transfer cons SERecord]]; END; error => BEGIN IF nullError # CSENull THEN RETURN[nullError]; csei ← nullError ← MakeNonCtxSe[SIZE[transfer cons SERecord]]; END; ENDCASE; Add[]; seb[csei] ← SERecord[mark3: TRUE, mark4: TRUE, body: cons[transfer[ mode: mode, inRecord: RecordSENull, outRecord: RecordSENull]]]; Drop[]; END; SetUpLongs: PROCEDURE = BEGIN longs[0] ← [com.typeINT, Symbols.CSENull]; longs[1] ← [com.typeCARDINAL, Symbols.CSENull]; longs[2] ← [Symbols.typeANY, Symbols.CSENull]; nullProc ← nullError ← nullSig ← Symbols.CSENull; END; ResetLongs: PUBLIC PROC = BEGIN i: CARDINAL; FOR i IN [0..LENGTH[longs]) DO longs[i].lsei ← Symbols.CSENull ENDLOOP; nullProc ← nullError ← nullSig ← Symbols.CSENull; END; MakeLongType: PUBLIC PROC [rType: Symbols.SEIndex] RETURNS [type: Symbols.CSEIndex] = BEGIN OPEN SymbolOps, Symbols; i: CARDINAL; sei: CSEIndex ← UnderType[rType]; Add[]; WITH seb[sei] SELECT FROM long => {Drop[]; RETURN[sei]}; ENDCASE => Drop[]; FOR i IN [0..LENGTH[longs]) DO IF longs[i].sei # sei THEN LOOP; IF longs[i].lsei # SENull THEN RETURN[longs[i].lsei]; longs[i].lsei ← type ← MakeNonCtxSe[SIZE[long cons SERecord]]; EXIT REPEAT FINISHED => type ← MakeNonCtxSe[SIZE[long cons SERecord]]; ENDLOOP; Add[]; seb[type] ← SERecord[mark3: TRUE, mark4: TRUE, body: cons[long[rangeType: rType]]]; Drop[]; RETURN END; MakePointerType: PUBLIC PROC [cType: Symbols.SEIndex] RETURNS [type: Symbols.CSEIndex] = BEGIN OPEN SymbolOps, Symbols; type ← MakeNonCtxSe[SIZE[ref cons SERecord]]; Add[]; seb[type] ← SERecord[mark3: TRUE, mark4: TRUE, body: cons[ref[ list: FALSE, counted: FALSE, ordered: FALSE, readOnly: FALSE, basing: FALSE, refType: cType]]]; Drop[]; RETURN END; AbortWithError: PUBLIC PROC [ code: Err, hti: Symbols.HTIndex ← Symbols.HTNull] = BEGIN Error[code, hti]; ERROR DIAbort END; Error: PUBLIC PROC [code: Err, hti: Symbols.HTIndex ← Symbols.HTNull] = BEGIN s: STRING ← [40]; IF hti # Symbols.HTNull THEN {Lookup.HtiToString[hti,s]; DOutput.Text[s]}; DOutput.Line[SELECT code FROM callingInline => " can't call an INLINE!"L, cantLengthen => " can't lengthen!"L, constructor => " can't make a constructor!"L, indexTooBig => " double word array index!"L, invalidAddress => " has an invalid address!"L, invalidNumber => " is an invalid number!"L, invalidPointer => " is an invalid pointer!"L, invalidSubrange => " invalid subrange!"L, nilChk => " pointer fault!"L, notFound => " not found!"L, notProcDesc => " is not a valid control link!"L, notRelative => " is not a relative pointer!"L, notType => " is not a type!"L, notUniqueField => " is not a unique field selector!"L, notValidField => " is not a valid field selector!"L, overflow => " overflow!"L, relation => " relations not implemented!"L, sizeMismatch => " size mismatch!"L, tooManyArgs => " too many arguments for stack!"L, typeMismatch => " has incorrect type!"L, unknownVariant => " unknown variant!"L, wontDump => " Won't dump that much memory!"L, worryCall => " not permitted in worry mode!"L, wrongBase => " is the wrong base!"L, wrongNumberArgs => " has the wrong number of arguments!"L, wrongBrackets => " used incorrectly with []!"L, wrongDollar => "$ is ambiguous; use frame $!"L, notArray => " is not an array!"L, ENDCASE => ERROR]; END; SetUpLongs[]; END.