|
|
@@ -33,7 +33,7 @@
|
|
|
|
|
|
IMPLEMENTATION MODULE SymTab;
|
|
|
IMPORT Compiler, Loader, Texts, Errors, Scanner, CodeGen; (* Files comes via DEF import (leak rule); re-listing is a hard error *)
|
|
|
-FROM SYSTEM IMPORT ADR, MOVE; (* ADDRESS/WORD come via DEF import (leak rule) *)
|
|
|
+FROM SYSTEM IMPORT ADR, MOVE, FILL; (* ADDRESS/WORD come via DEF import (leak rule); FILL is a real M-code builtin (042e) *)
|
|
|
|
|
|
(* ---- heap model (groups B + C) ---- *)
|
|
|
(* MCode words are untyped; CARDINAL()/T1()/ADDRESS() punning mirrors the
|
|
|
@@ -42,11 +42,18 @@ FROM SYSTEM IMPORT ADR, MOVE; (* ADDRESS/WORD come via DEF import (leak rule) *)
|
|
|
kind <= 1, 10 for kind <= 6, 12 for kind <= 11, else 16). *)
|
|
|
TYPE Words = POINTER TO ARRAY [0..7] OF CARDINAL;
|
|
|
|
|
|
+(* 10-byte module-name slot (group C names). Moved up: ownNamePtr uses it. *)
|
|
|
+TYPE ModuleSymPtr = POINTER TO ModuleSym;
|
|
|
+ ModuleSym = RECORD
|
|
|
+ name: ARRAY [0..7] OF CHAR;
|
|
|
+ tag: CARDINAL;
|
|
|
+ END;
|
|
|
+
|
|
|
(* Implementation-module globals (words 10..27). NOT exported: putting them
|
|
|
in the DEF overflows the compiler name table (proven on real hardware).
|
|
|
Numbering: DEF vars occupy words 2..9, these follow. *)
|
|
|
VAR
|
|
|
- (* word 10 *) ownNamePtr: ADDRESS;
|
|
|
+ (* word 10 *) ownNamePtr: ModuleSymPtr;
|
|
|
(* word 11 *) spare11: CARDINAL; (* use TBD *)
|
|
|
(* word 12 *) symHeap: ADDRESS;
|
|
|
(* word 13 *) scpHeap: ADDRESS;
|
|
|
@@ -89,11 +96,22 @@ TYPE ScopeEntryPtr = POINTER TO ScopeEntry;
|
|
|
aux1, aux2, aux3: CARDINAL;
|
|
|
END;
|
|
|
|
|
|
-(* 10-byte module-name slot (group C names). *)
|
|
|
-TYPE ModuleSymPtr = POINTER TO ModuleSym;
|
|
|
- ModuleSym = RECORD
|
|
|
- name: ARRAY [0..7] OF CHAR;
|
|
|
- tag: CARDINAL;
|
|
|
+(* Module-name table entry view (10 bytes: name + word). *)
|
|
|
+TYPE SymbolPtr = POINTER TO Symbol;
|
|
|
+
|
|
|
+(* 8-word heap/scope entry view (group C names). Field TYPES serve the
|
|
|
+ dominant use (numerics as CARDINAL/WORD, pointers via transfer); all
|
|
|
+ 1-word loads/stores are byte-identical regardless of declared type. *)
|
|
|
+TYPE EntryPtr = POINTER TO Entry;
|
|
|
+ Entry = RECORD
|
|
|
+ w0: CARDINAL;
|
|
|
+ w1: CARDINAL; (* slot/memo/count *)
|
|
|
+ w2: CARDINAL; (* link/address (passed on as T1 via transfer) *)
|
|
|
+ w3: BITSET;
|
|
|
+ w4: CARDINAL; (* kind *)
|
|
|
+ w5: CARDINAL; (* pointer-ish (link/subtype); passed on as T1 *)
|
|
|
+ w6: CARDINAL;
|
|
|
+ w7: CARDINAL; (* numeric use (arm102 copy); all loads/stores 1 word *)
|
|
|
END;
|
|
|
|
|
|
(* Import record: same 7-word layout as Compiler.Record; names document use. *)
|
|
|
@@ -122,23 +140,16 @@ TYPE ScopePtr = POINTER TO ScopeDesc;
|
|
|
idents: Scanner.List; (* word 1: identifier list *)
|
|
|
END;
|
|
|
|
|
|
-CONST symReadError = 790; (* RAISE code in LibRead {/*0497*/} *)
|
|
|
+(* NOTE: LibRead raises EXCEPTION SYMREADERROR (declared in LoadSymFile);
|
|
|
+ v1.00 assigns the code — verified 790 against the MCD below. *)
|
|
|
|
|
|
(* ---- FORWARDs for the PutAttr/GetAttr <-> EnterChained/AllocSym/
|
|
|
UnlinkScope/EnterIdent recursion cycle (group B) ---- *)
|
|
|
(* SymbolAssert/DefineDefinitionModule are DEF-declared: no FORWARD (v1.00 rejects
|
|
|
a FORWARD duplicating a DEF declaration, proven on hardware). *)
|
|
|
-PROCEDURE CheckNode(node: T1); FORWARD;
|
|
|
PROCEDURE EnterChained(scope: ADDRESS; node: T1); FORWARD;
|
|
|
-PROCEDURE AllocSym(scope: Words; node: T1); FORWARD;
|
|
|
+PROCEDURE AllocSym(scope: EntryPtr; node: T1); FORWARD;
|
|
|
PROCEDURE UnlinkScope(scope: ADDRESS; idx: CARDINAL); FORWARD;
|
|
|
-PROCEDURE EnterIdent(scope: Words; idx: CARDINAL); FORWARD;
|
|
|
-PROCEDURE PutAttr(VAR slot: CARDINAL; src: Words); FORWARD;
|
|
|
-PROCEDURE GetAttr(VAR node: T1; idx: CARDINAL); FORWARD;
|
|
|
-PROCEDURE LookupChain(scopeNo: CARDINAL; key: CARDINAL): T1; FORWARD;
|
|
|
-PROCEDURE InitHeaps; FORWARD;
|
|
|
-PROCEDURE EnterStandards; FORWARD;
|
|
|
-PROCEDURE ImportOne(anchor: ADDRESS; symIdx: CARDINAL); FORWARD;
|
|
|
|
|
|
(* ================= group A: module/scope search (@0001-00d4) ================= *)
|
|
|
|
|
|
@@ -153,27 +164,30 @@ PROCEDURE FindModule(slot: CARDINAL): CARDINAL;
|
|
|
VAR i: CARDINAL;
|
|
|
key: ModuleSymPtr;
|
|
|
BEGIN
|
|
|
+ i := 0; (*{/*000e*/} init first (original order) *)
|
|
|
+ key := ADDRESS(modStage) + slot * 10; (*{/*0010*/} &modStage^[slot]; ADDRESS arith, no temp needed *)
|
|
|
(*{/*0016*/} key.name = ownNamePtr^ -> self *)
|
|
|
- key := ownNamePtr; (* ADDRESS->pointer assignment is legal on v1.00; transfer-call deref is not *)
|
|
|
- IF modStage^[slot].name = key^.name THEN RETURN 16 END;
|
|
|
- i := 0;
|
|
|
+ IF key^.name = ownNamePtr^.name THEN RETURN 16 END;
|
|
|
WHILE i < moduleCount DO
|
|
|
- IF modStage^[slot].name = moduleTable^[i].name THEN RETURN i END;
|
|
|
+ IF key^.name = moduleTable^[i].name THEN RETURN i END;
|
|
|
INC(i); (*{/*0036*/}*)
|
|
|
END;
|
|
|
RETURN 17; (*{/*003b*/}*)
|
|
|
END FindModule;
|
|
|
|
|
|
PROCEDURE EnterModule(slot: CARDINAL): CARDINAL;
|
|
|
-(* proc10 @0040: FindModule(slot); add if absent *)
|
|
|
+(* proc10 @0040: FindModule(slot); add if absent.
|
|
|
+ ent caches &modStage^[slot] (original computes once, reuses twice). *)
|
|
|
VAR found: CARDINAL;
|
|
|
+ ent: SymbolPtr;
|
|
|
BEGIN
|
|
|
found := FindModule(slot); (*{/*0042*/}*)
|
|
|
IF found <= 16 THEN
|
|
|
+ ent := ADR(modStage^[slot]);
|
|
|
(*{/*0051*/} ghost check on Symbol.word fields *)
|
|
|
- IF (modStage^[slot].word # 0)
|
|
|
- AND (moduleTable^[found].word # modStage^[slot].word) THEN
|
|
|
- Errors.ReportErrorWithText(12, modStage^[slot].name); (*{/*0061*/}*)
|
|
|
+ IF (ent^.word # 0)
|
|
|
+ AND (moduleTable^[found].word # ent^.word) THEN
|
|
|
+ Errors.ReportErrorWithText(12, ent^.name); (*{/*0061*/}*)
|
|
|
END;
|
|
|
RETURN found; (*{/*0066*/}*)
|
|
|
END;
|
|
|
@@ -188,11 +202,12 @@ PROCEDURE LookupChain(scopeNo: CARDINAL; key: CARDINAL): T1;
|
|
|
(* proc11 @0083 *)
|
|
|
VAR p: T1;
|
|
|
BEGIN
|
|
|
- IF scopeNo > 16 THEN RETURN NIL END; (*{/*0085*/}*)
|
|
|
- p := scopeChain^[scopeNo]; (*{/*008b*/}*)
|
|
|
- WHILE p # NIL DO (*{/*008f*/}*)
|
|
|
- IF CARDINAL(p^.link1) = key THEN RETURN p^.link2 END; (*{/*0093*/}*)
|
|
|
- p := p^.link0; (*{/*009d*/}*)
|
|
|
+ IF scopeNo <= 16 THEN (*{/*0085*/} single-exit shape (original falls through to one end RETURN) *)
|
|
|
+ p := scopeChain^[scopeNo]; (*{/*008b*/}*)
|
|
|
+ WHILE p # NIL DO (*{/*008f*/}*)
|
|
|
+ IF CARDINAL(p^.link1) = key THEN RETURN p^.link2 END; (*{/*0093*/}*)
|
|
|
+ p := p^.link0; (*{/*009d*/}*)
|
|
|
+ END;
|
|
|
END;
|
|
|
RETURN NIL; (*{/*00a2*/}*)
|
|
|
END LookupChain;
|
|
|
@@ -206,11 +221,25 @@ END MatchSym;
|
|
|
|
|
|
(* ================= group B: allocators + attrs (@00bd-03c9) ================= *)
|
|
|
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+(* NOTE (group B): the brief asked for AllocSym(nodeKind): T1, but the MCode
|
|
|
+ (proc14 @01d7, ProcLeave(2), uses param1+param2) is a 2-param PROCEDURE
|
|
|
+ chaining a 14-byte entry onto scope and filling it from node. *)
|
|
|
+PROCEDURE AllocSym(scope: EntryPtr; node: T1);
|
|
|
+(* proc14 @01d7 — chain-allocate a 14-byte symbol-table entry from node.
|
|
|
+ Entry/Record views only (LSW shapes); node used directly as T1. *)
|
|
|
+VAR se: EntryPtr; n: T1; sv: Compiler.RecordPtr;
|
|
|
+(* ---- nested in AllocSym (original ec-downward calls) ---- *)
|
|
|
PROCEDURE CheckNode(node: T1);
|
|
|
-(* proc15 @00bd — guard before chaining through word5/word6 fields *)
|
|
|
+(* proc15 @00bd — guard before chaining through word5/word6 fields.
|
|
|
+ Local EXCEPTION: v1.00 assigns the code — verify 272 against MCD. *)
|
|
|
+EXCEPTION NodeErr;
|
|
|
BEGIN
|
|
|
IF (node <> NIL) AND (CARDINAL(node^.link0) - 1 < 64) THEN (*{/*00bf*/}*)
|
|
|
- HALT; (* MCode Raise(272,0,0) {/*00cb*/} *)
|
|
|
+ RAISE NodeErr; (*{/*00cb*/}*)
|
|
|
END;
|
|
|
END CheckNode;
|
|
|
|
|
|
@@ -229,71 +258,119 @@ BEGIN
|
|
|
END;
|
|
|
END NewString;
|
|
|
|
|
|
-PROCEDURE GetName(VAR name: ADDRESS; off: CARDINAL);
|
|
|
-(* proc21 @0268 — inverse of NewString: heap copy of pooled string *)
|
|
|
-VAR cs: StringPtr;
|
|
|
-BEGIN
|
|
|
- IF off <> 0 THEN (*{/*026a*/}*)
|
|
|
- cs := strHeap + off; (* ADDRESS arithmetic into pointer; transfer-deref is not a VAR actual *)
|
|
|
- Scanner.CopyStr(name, cs^); (*{/*026e*/}*)
|
|
|
- ELSE
|
|
|
- name := NIL; (*{/*027b*/}*)
|
|
|
- END;
|
|
|
-END GetName;
|
|
|
-
|
|
|
-PROCEDURE PutAttr(VAR slot: CARDINAL; src: Words);
|
|
|
-(* proc18 @0106 — store a type/attr node into the scope-descriptor table.
|
|
|
- src is Words-typed (not T1): v1.00 rejects indexing a transfer result,
|
|
|
- so callers transfer (zero-cost, W-probes) and the body indexes directly. *)
|
|
|
-VAR i: CARDINAL; e: Words; sw: Words;
|
|
|
+PROCEDURE PutAttr(VAR slot: CARDINAL; src: T1);
|
|
|
+(* proc18 @0106, nested in AllocSym — store a type/attr node into the
|
|
|
+ scope-descriptor table. Views are RECORD fields (LSW shapes), never
|
|
|
+ Words indexes (LXW): original threads pointers on the M-stack. *)
|
|
|
+VAR i: CARDINAL; e: EntryPtr; sv: Compiler.RecordPtr; sw7: Words;
|
|
|
BEGIN
|
|
|
slot := 0; (*{/*0108*/}*)
|
|
|
- IF src = NIL THEN RETURN END; (*{/*010b*/}*)
|
|
|
- slot := src^[1]; (*{/*010f*/}*)
|
|
|
- IF slot <> 0 THEN RETURN END; (* named: referenced by name, no entry *)
|
|
|
- IF CARDINAL(src) < CARDINAL(symHeap) THEN (* static node: dedup {/*0118*/} *)
|
|
|
- (* group B read this bound as global word2; reconciled to symHeapBase:
|
|
|
- word2 is symOptions: BITSET per SYMTAB.SYM, and the heap base is the
|
|
|
- only agreed boundary for "points outside the dynamic heap". *)
|
|
|
+ IF src = NIL THEN RETURN END; (*{/*010b*/} orig emits not_zero here (v2 peephole); v1.00 emits eq0 *)
|
|
|
+ slot := CARDINAL(src^.link1); (*{/*010f*/} word1 via link1 field *)
|
|
|
+ IF slot <> 0 THEN RETURN END; (*{/*0116*/} named: referenced by name, no entry *)
|
|
|
+ IF CARDINAL(src) < CARDINAL(symOptions) THEN (* static node: dedup {/*0118*/} word2 bound *)
|
|
|
i := 1; (*{/*011d*/}*)
|
|
|
WHILE i <= scopeTop DO
|
|
|
- e := Words(scpHeap + 16 * i); (* temp: transfer results can't be indexed *)
|
|
|
- IF e^[1] = CARDINAL(src) THEN (*{/*011f*/}*)
|
|
|
+ e := EntryPtr(scpHeap + i * 16);
|
|
|
+ IF e^.w1 = CARDINAL(src) THEN (*{/*011f*/}*)
|
|
|
slot := i; RETURN;
|
|
|
END;
|
|
|
INC(i); (*{/*012e*/}*)
|
|
|
END;
|
|
|
SymbolAssert(i <= scopeCap, 86); (*{/*0137*/}*)
|
|
|
scopeTop := i;
|
|
|
- e := Words(scpHeap + 16 * scopeTop);
|
|
|
- e^[1] := CARDINAL(src); (*{/*0141*/}*)
|
|
|
+ e := EntryPtr(scpHeap + scopeTop * 16);
|
|
|
+ e^.w1 := CARDINAL(src); (*{/*0141*/}*)
|
|
|
slot := scopeTop; (*{/*0149*/}*)
|
|
|
RETURN;
|
|
|
END;
|
|
|
SymbolAssert(scopeTop < scopeCap, 86); (*{/*014f*/}*)
|
|
|
INC(scopeTop);
|
|
|
slot := scopeTop; (*{/*015c*/}*)
|
|
|
- e := Words(scpHeap + 16 * scopeTop);
|
|
|
- sw := src;
|
|
|
- e^[1] := 0; (*{/*016b*/}*)
|
|
|
- PutAttr(e^[2], Words(sw^[2])); (* copy link2 chain {/*016e*/} *)
|
|
|
- e^[3] := sw^[3]; (*{/*0176*/}*)
|
|
|
- e^[4] := sw^[4]; (* kind {/*017a*/} *)
|
|
|
- CASE sw^[4] OF (* kind switch {/*01b3*/} *)
|
|
|
+ e := EntryPtr(scpHeap + scopeTop * 16);
|
|
|
+ sv := Compiler.RecordPtr(src);
|
|
|
+ sw7 := Words(src);
|
|
|
+ e^.w1 := 0; (*{/*016b*/}*)
|
|
|
+ i := e^.w2; PutAttr(i, T1(e^.w2)); (* copy link2 chain {/*016e*/} i reuses dead loop var *)
|
|
|
+ e^.w3 := src^.word3; (*{/*0176*/} BITSET direct *)
|
|
|
+ e^.w4 := src^.word4; (* kind {/*017a*/} *)
|
|
|
+ CASE src^.word4 OF (* kind switch {/*01b3*/} *)
|
|
|
| 90, 91:
|
|
|
- e^[5] := sw^[5]; e^[6] := sw^[6]; (*{/*0182*/}*)
|
|
|
+ e^.w5 := CARDINAL(sv^.word5); e^.w6 := CARDINAL(sv^.high); (*{/*0182*/} CARDINAL() zero-cost views *)
|
|
|
| 99, 100:
|
|
|
- CheckNode(T1(sw^[5])); (*{/*0192*/}*)
|
|
|
- EnterChained(ADR(e^[5]), T1(sw^[5])); (*{/*0197*/}*)
|
|
|
+ CheckNode(T1(sv^.word5)); (*{/*0192*/}*)
|
|
|
+ EnterChained(ADR(e^.w5), T1(sv^.word5)); (*{/*0197*/}*)
|
|
|
| 101:
|
|
|
- PutAttr(e^[5], Words(sw^[5])); (*{/*0189*/}*)
|
|
|
+ i := e^.w5; PutAttr(i, T1(e^.w5)); (*{/*0189*/}*)
|
|
|
| 102:
|
|
|
- PutAttr(e^[5], Words(sw^[5])); (*{/*019e*/}*)
|
|
|
- PutAttr(e^[6], Words(sw^[6]));
|
|
|
- e^[7] := sw^[7];
|
|
|
+ i := e^.w5; PutAttr(i, T1(e^.w5)); (*{/*019e*/}*)
|
|
|
+ i := e^.w6; PutAttr(i, T1(e^.w6));
|
|
|
+ e^.w7 := sw7^[7];
|
|
|
ELSE (* 92..98: name/link/attr words suffice *)
|
|
|
END;
|
|
|
END PutAttr;
|
|
|
+
|
|
|
+BEGIN
|
|
|
+ SymbolAssert(symTop < symCap, 87); (*{/*01d9*/}*)
|
|
|
+ INC(symTop);
|
|
|
+ se := EntryPtr(symHeap + symTop * 14); (*{/*01e3*/}*)
|
|
|
+ n := T1(se); sv := Compiler.RecordPtr(node);
|
|
|
+ se^.w0 := scope^.w0; (*{/*01e9*/}*)
|
|
|
+ scope^.w0 := symTop; (*{/*01ed*/}*)
|
|
|
+ NewString(se^.w1, node^.link1); (*{/*01f0*/}*)
|
|
|
+ PutAttr(se^.w2, node^.link2); (*{/*01f7*/} T1 direct, no view needed *)
|
|
|
+ n^.word3 := node^.word3; (*{/*01fe*/}*)
|
|
|
+ se^.w5 := CARDINAL(sv^.word5); se^.w6 := CARDINAL(sv^.high); (* dword {/*0202*/} *)
|
|
|
+ n^.word4 := node^.word4; (* kind {/*0208*/} *)
|
|
|
+ IF CARDINAL(node^.link2) = CARDINAL(Compiler.charArrayDesc) THEN (* COMPILER.word12 {/*020c*/}; CARDINAL compare: T1 vs RecordPtr rejected *)
|
|
|
+ NewString(se^.w5, ADDRESS(sv^.word5)); (*{/*0213*/}*)
|
|
|
+ ELSIF n^.word4 >= 5 THEN (*{/*021c*/}*)
|
|
|
+ CheckNode(T1(sv^.high)); (*{/*0222*/}*)
|
|
|
+ se^.w6 := 0; (*{/*0226*/}*)
|
|
|
+ EnterChained(ADR(se^.w6), T1(sv^.high)); (*{/*0229*/}*)
|
|
|
+ ELSIF (n^.word4 = 1) AND (CARDINAL(node^.link2) = CARDINAL(Compiler.LongrealType)) THEN
|
|
|
+ (* COMPILER.word11: 8-byte real value {/*0231*/} *)
|
|
|
+ SymbolAssert(strTop + 8 <= strCap, 85); (*{/*023e*/}*)
|
|
|
+ MOVE(ADDRESS(sv^.word5), strHeap + strTop, 8); (*{/*0248*/}*)
|
|
|
+ INC(strTop, 8); (*{/*0251*/}*)
|
|
|
+ END;
|
|
|
+END AllocSym;
|
|
|
+
|
|
|
+PROCEDURE EnterChained(scope: ADDRESS; node: T1);
|
|
|
+(* proc13 @0259 — append a link0 node chain to scope (oldest first) *)
|
|
|
+BEGIN
|
|
|
+ IF node <> NIL THEN (*{/*025b*/}*)
|
|
|
+ EnterChained(scope, node^.link0); (*{/*025f*/}*)
|
|
|
+ AllocSym(EntryPtr(scope), node); (*{/*0263*/}*)
|
|
|
+ END;
|
|
|
+END EnterChained;
|
|
|
+
|
|
|
+PROCEDURE EnterIdent(scope: Words; idx: CARDINAL);
|
|
|
+(* proc20 @0305 — declare symbol-table entry idx into scope (dup check + attrs).
|
|
|
+ scope is Words-typed (same transfer-index rule as PutAttr/AllocSym). *)
|
|
|
+VAR sentry: Words; (* symHeapBase + idx*14 *)
|
|
|
+ new: T1; nw: Words;
|
|
|
+ mark: ADDRESS;
|
|
|
+ nm, nm2: ADDRESS; (* heap names via GetName *)
|
|
|
+ nmt: StringPtr;
|
|
|
+ vw: Words; (* temp for T1-field views *)
|
|
|
+ rp: Compiler.RecordPtr; (* temp: transfer results can't be dereferenced; also FindIden result *)
|
|
|
+(* ---- nested in EnterIdent (original ec-downward calls) ---- *)
|
|
|
+PROCEDURE GetName(VAR name: ADDRESS; off: CARDINAL);
|
|
|
+(* proc21 @0268 — inverse of NewString: heap copy of pooled string.
|
|
|
+ View is [0..128] (HIGH 128 pushes 8d 80, proven vs orig 0274): heap
|
|
|
+ strings are NUL-terminated well below, so behavior is identical. *)
|
|
|
+TYPE CS129 = POINTER TO ARRAY [0..128] OF CHAR;
|
|
|
+VAR cs: CS129;
|
|
|
+BEGIN
|
|
|
+ IF off <> 0 THEN (*{/*026a*/}*)
|
|
|
+ cs := strHeap + off; (* ADDRESS arithmetic into pointer; transfer-deref is not a VAR actual *)
|
|
|
+ Scanner.CopyStr(name, cs^); (*{/*026e*/}*)
|
|
|
+ ELSE
|
|
|
+ name := NIL; (*{/*027b*/}*)
|
|
|
+ END;
|
|
|
+END GetName;
|
|
|
+
|
|
|
PROCEDURE GetAttr(VAR node: T1; idx: CARDINAL);
|
|
|
(* proc22 @0281 — load a scope entry back into a heap node (inverse of PutAttr).
|
|
|
Entry word1 = static node pointer or memoized node (returned as-is). *)
|
|
|
@@ -327,59 +404,6 @@ BEGIN
|
|
|
END;
|
|
|
END GetAttr;
|
|
|
|
|
|
-(* NOTE (group B): the brief asked for AllocSym(nodeKind): T1, but the MCode
|
|
|
- (proc14 @01d7, ProcLeave(2), uses param1+param2) is a 2-param PROCEDURE
|
|
|
- chaining a 14-byte entry onto scope and filling it from node. *)
|
|
|
-PROCEDURE AllocSym(scope: Words; node: T1);
|
|
|
-(* proc14 @01d7 — chain-allocate a 14-byte symbol-table entry from node.
|
|
|
- scope is Words-typed (not ADDRESS): v1.00 rejects indexing a transfer
|
|
|
- result; callers transfer (zero-cost). *)
|
|
|
-VAR s: Words; n: T1; nw: Words; sw: Words;
|
|
|
-BEGIN
|
|
|
- SymbolAssert(symTop < symCap, 87); (*{/*01d9*/}*)
|
|
|
- INC(symTop);
|
|
|
- s := Words(symHeap + 14 * symTop); (*{/*01e3*/}*)
|
|
|
- n := T1(s); nw := s; sw := Words(node);
|
|
|
- s^[0] := scope^[0]; (*{/*01e9*/}*)
|
|
|
- scope^[0] := symTop; (*{/*01ed*/}*)
|
|
|
- NewString(s^[1], node^.link1); (*{/*01f0*/}*)
|
|
|
- PutAttr(s^[2], Words(node^.link2)); (*{/*01f7*/}*)
|
|
|
- n^.word3 := node^.word3; (*{/*01fe*/}*)
|
|
|
- nw^[5] := sw^[5]; nw^[6] := sw^[6]; (* dword {/*0202*/} *)
|
|
|
- n^.word4 := node^.word4; (* kind {/*0208*/} *)
|
|
|
- IF CARDINAL(node^.link2) = CARDINAL(Compiler.charArrayDesc) THEN (* COMPILER.word12 {/*020c*/}; CARDINAL compare: T1 vs RecordPtr rejected *)
|
|
|
- NewString(nw^[5], ADDRESS(sw^[5])); (*{/*0213*/}*)
|
|
|
- ELSIF nw^[4] >= 5 THEN (*{/*021c*/}*)
|
|
|
- CheckNode(T1(sw^[6])); (*{/*0222*/}*)
|
|
|
- nw^[6] := 0; (*{/*0226*/}*)
|
|
|
- EnterChained(ADR(nw^[6]), T1(sw^[6])); (*{/*0229*/}*)
|
|
|
- ELSIF (nw^[4] = 1) AND (CARDINAL(node^.link2) = CARDINAL(Compiler.LongrealType)) THEN
|
|
|
- (* COMPILER.word11: 8-byte real constant {/*0231*/} *)
|
|
|
- SymbolAssert(strTop + 8 <= strCap, 85); (*{/*023e*/}*)
|
|
|
- MOVE(ADDRESS(sw^[5]), strHeap + strTop, 8); (*{/*0248*/}*)
|
|
|
- INC(strTop, 8); (*{/*0251*/}*)
|
|
|
- END;
|
|
|
-END AllocSym;
|
|
|
-
|
|
|
-PROCEDURE EnterChained(scope: ADDRESS; node: T1);
|
|
|
-(* proc13 @0259 — append a link0 node chain to scope (oldest first) *)
|
|
|
-BEGIN
|
|
|
- IF node <> NIL THEN (*{/*025b*/}*)
|
|
|
- EnterChained(scope, node^.link0); (*{/*025f*/}*)
|
|
|
- AllocSym(Words(scope), node); (*{/*0263*/}*)
|
|
|
- END;
|
|
|
-END EnterChained;
|
|
|
-
|
|
|
-PROCEDURE EnterIdent(scope: Words; idx: CARDINAL);
|
|
|
-(* proc20 @0305 — declare symbol-table entry idx into scope (dup check + attrs).
|
|
|
- scope is Words-typed (same transfer-index rule as PutAttr/AllocSym). *)
|
|
|
-VAR sentry: Words; (* symHeapBase + idx*14 *)
|
|
|
- new: T1; nw: Words;
|
|
|
- mark: ADDRESS;
|
|
|
- nm, nm2: ADDRESS; (* heap names via GetName *)
|
|
|
- nmt: StringPtr;
|
|
|
- vw: Words; (* temp for T1-field views *)
|
|
|
- rp: Compiler.RecordPtr; (* temp: transfer results can't be dereferenced; also FindIden result *)
|
|
|
BEGIN
|
|
|
sentry := Words(symHeap + 14 * idx); (*{/*0307*/}*)
|
|
|
new := Scanner.NewNode(sentry^[4]); (* kind; always 14 bytes {/*030d*/} *)
|
|
|
@@ -500,6 +524,7 @@ END EnterStandards;
|
|
|
|
|
|
PROCEDURE LoadSymFile(VAR modName: ARRAY OF CHAR);
|
|
|
(* proc26 @04a0 *)
|
|
|
+EXCEPTION SYMREADERROR;
|
|
|
VAR
|
|
|
libFile: Loader.LibFile; (* 292-byte handle {/*04a8*/}; see LOADER.DEF *)
|
|
|
header: ARRAY [0..7] OF CARDINAL; (* 16-byte .SYM header {/*04ad*/} *)
|
|
|
@@ -510,7 +535,7 @@ VAR
|
|
|
(* proc27 @048a, nested: libFile via parent frame *)
|
|
|
BEGIN
|
|
|
IF NOT Loader.LibRead(libFile, buf, n) THEN
|
|
|
- RAISE symReadError; (* 790 {/*0497*/} *)
|
|
|
+ RAISE SYMREADERROR; (* 790 {/*0497*/} — code verified against MCD below *)
|
|
|
END;
|
|
|
END LibRead;
|
|
|
|
|
|
@@ -530,7 +555,7 @@ BEGIN
|
|
|
savSym := header[5]; (*{/*04ef*/}*)
|
|
|
savStr := header[6]; (*{/*04f3*/}*)
|
|
|
LibRead(modStage, namTotal * 10); (* module-name directory {/*04f7*/} *)
|
|
|
- dest := modStage + 160; (* slot 16 {/*04fe*/} *)
|
|
|
+ dest := ADR(modStage^[16]); (* slot 16 {/*04fe*/} — ADDRESS of element, not pointer arithmetic *)
|
|
|
FOR i := 0 TO 7 DO dest^.name[i] := 0C END; (*{/*0505*/}*)
|
|
|
i := 0;
|
|
|
WHILE (i <= 7) AND (modName[i] # 0C) DO (*{/*050e*/}*)
|
|
|
@@ -562,6 +587,7 @@ VAR
|
|
|
s: ScopeEntryPtr;
|
|
|
ch: ChainPtr;
|
|
|
matched: CARDINAL;
|
|
|
+ sp: StringPtr; (* temp for VAR-array actuals (transfer-deref banned) *)
|
|
|
|
|
|
PROCEDURE FindExport(start: CARDINAL; name: ADDRESS): CARDINAL;
|
|
|
(* proc29 @0553, nested *)
|
|
|
@@ -570,8 +596,8 @@ VAR
|
|
|
idx := start;
|
|
|
WHILE idx # 0 DO
|
|
|
e := symHeap + idx * 14; (*{/*0559*/}*)
|
|
|
- IF Scanner.StrCmp(StringPtr(symHeap + strHeap + e^.nameOff)^,
|
|
|
- StringPtr(name)^, 9 IN Scanner.scanOpt) THEN (*{/*0568*/}*)
|
|
|
+ IF Scanner.StrCmp(symHeap + strHeap + e^.nameOff,
|
|
|
+ name, 9 IN Scanner.scanOpt) THEN (*{/*0568*/} StrCmp takes ADDRESS: no view needed *)
|
|
|
RETURN idx;
|
|
|
END;
|
|
|
idx := e^.link; (*{/*0570*/}*)
|
|
|
@@ -581,7 +607,7 @@ VAR
|
|
|
|
|
|
PROCEDURE ListExports(first: CARDINAL);
|
|
|
(* proc30 @0579, nested: colCount via parent frame *)
|
|
|
- VAR e: SymEntryPtr;
|
|
|
+ VAR e: SymEntryPtr; sp: StringPtr;
|
|
|
BEGIN
|
|
|
IF first # 0 THEN
|
|
|
e := symHeap + first * 14;
|
|
|
@@ -591,7 +617,8 @@ VAR
|
|
|
Texts.WriteLn(3); colCount := 0;
|
|
|
END;
|
|
|
Texts.SetCol(3, colCount * 16); (*{/*05a0*/}*)
|
|
|
- Texts.WriteString(3, StringPtr(strHeap + e^.nameOff)^); (*{/*05af*/}*)
|
|
|
+ sp := strHeap + e^.nameOff;
|
|
|
+ Texts.WriteString(3, sp^); (*{/*05af*/}*)
|
|
|
INC(colCount); (*{/*05b4*/}*)
|
|
|
END;
|
|
|
END;
|
|
|
@@ -616,30 +643,31 @@ BEGIN
|
|
|
caseFlag := 9 IN Scanner.scanOpt;
|
|
|
importEvery := 10 IN imp^.flags;
|
|
|
sysAdr := ADDRESS(Compiler.systemModule); sysImp := sysAdr;
|
|
|
- IF Scanner.StrCmp(StringPtr(imp^.name)^, StringPtr(sysImp^.name)^, caseFlag) THEN (*{/*05e9*/}*)
|
|
|
+ IF Scanner.StrCmp(imp^.name, sysImp^.name, caseFlag) THEN (*{/*05e9*/} StrCmp takes ADDRESS *)
|
|
|
IF importEvery THEN (*{/*05f5*/}*)
|
|
|
imp^.flags := sysImp^.flags; (*{/*05f8*/}*)
|
|
|
imp^.anchor := sysImp^.anchor; (*{/*0604*/}*)
|
|
|
Compiler.compilationActive := FALSE; (* word 26 {/*0608*/} *)
|
|
|
ELSE
|
|
|
- DefineDefinitionModule(Compiler.systemScopeDesc); (* proc2 {/*060a*/} *)
|
|
|
+ DefineDefinitionModule(CARDINAL(Compiler.systemScopeDesc)); (* proc2 {/*060a*/}: word23 = systemScopeDesc slot *)
|
|
|
END;
|
|
|
RETURN; (*{/*060e*/}*)
|
|
|
END;
|
|
|
sysAdr := ADDRESS(Compiler.storageModule); stoImp := sysAdr;
|
|
|
- IF Scanner.StrCmp(StringPtr(imp^.name)^, StringPtr(stoImp^.name)^, caseFlag) THEN (*{/*0611*/}*)
|
|
|
+ IF Scanner.StrCmp(imp^.name, stoImp^.name, caseFlag) THEN (*{/*0611*/} StrCmp takes ADDRESS *)
|
|
|
IF importEvery THEN (*{/*061d*/}*)
|
|
|
imp^.flags := stoImp^.flags;
|
|
|
imp^.anchor := stoImp^.anchor;
|
|
|
Compiler.compilationActive := FALSE;
|
|
|
ELSE
|
|
|
- DefineDefinitionModule(Compiler.storageScopeDesc); (*{/*062e*/}*)
|
|
|
+ DefineDefinitionModule(CARDINAL(Compiler.storageScopeDesc)); (*{/*062e*/}: word24 *)
|
|
|
END;
|
|
|
RETURN;
|
|
|
END;
|
|
|
stgFlag := 1; (* word 25 {/*0635*/}; group C reads compileActive *)
|
|
|
InitHeaps; (*{/*0638*/}*)
|
|
|
- LoadSymFile(StringPtr(imp^.name)^);
|
|
|
+ sp := imp^.name;
|
|
|
+ LoadSymFile(sp^);
|
|
|
modIdx := EnterModule(16); (*{/*0640*/}*)
|
|
|
SymbolAssert(modIdx # 16, 48); (*{/*0644*/}*)
|
|
|
expIdx := expHead; (*{/*064b*/}*)
|