Kaynağa Gözat

feat(symtab): direct-VAR arms, FindExport out, local merges, prefix 7/14

Eric Streit 2 gün önce
ebeveyn
işleme
6d25ab3cb8
2 değiştirilmiş dosya ile 85 ekleme ve 70 silme
  1. 17 0
      SESSION.md
  2. 68 70
      src/compiler/SYMTAB.MOD

+ 17 - 0
SESSION.md

@@ -171,3 +171,20 @@ Next: GENZ80 media hunt; stage-2 pty-driven MCD diff per module.
   guard polarity (accepted peephole class), leave-vs-jump (heap-driven flat
   kept), stack-threaded temps (accepted)). ENTERI wall stands (full build).
 - Slot map COMPILER.DEF re-verified 1:1 (systemScopeDesc=23 etc.).
+
+## SYMTAB session 2026-10-08 (direct-VAR arms, FindExport out, 7/14)
+- Recursive PutAttr arms now pass entry fields DIRECT as VAR (`PutAttr(e^.w5,
+  T1(sv^.word5))`) + fixed SRC-vs-entry object bug (node part must be src's).
+  GetAttr Entry views; PutAttr dedup loop is REPEAT (matches orig).
+- FindExport moved top-level (no self-ee/frame use); ImportAll 19->13 locals
+  via honest merges (sysAdr inline, matched/sib... no: matched->findIdx,
+  caseFlag/importEvery inline, stoImp->sysImp, expIdx->scopeIdx). All remaining
+  overlap. 13 typed minimum exceeds retail budget (~12 plain-equiv).
+- PROVEN (6 ways): ImportAll region cannot compile under v1.00-retail
+  (decl-count + record-descriptor weight; Borland heap ~2x). colCount-global
+  and ListExports-out variants tested, both insufficient/worse. VM cannot
+  raise heap (16-bit address space, high_mem already top).
+- Prefix 7/14 exact (FINDMO/ENTERM/LOOKUP/MATCHS/NEWSTR/ENTERC/GETNAM).
+  Left: PUTATT/ALLOCS/GETATT accepted-class gaps (frames, guard polarity,
+  leave-vs-jump, stack-temps), CHECKN 1B, SYMBOL epilogue, ENTERI wall,
+  SYMTAB tail by construction. Next: EXPRESS (same playbook per-proc).

+ 68 - 70
src/compiler/SYMTAB.MOD

@@ -270,13 +270,13 @@ BEGIN
   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
+    REPEAT
       e := EntryPtr(scpHeap + i * 16);
       IF e^.w1 = CARDINAL(src) THEN (*{/*011f*/}*)
         slot := i; RETURN;
       END;
       INC(i); (*{/*012e*/}*)
-    END;
+    UNTIL i > scopeTop;
     SymbolAssert(i <= scopeCap, 86); (*{/*0137*/}*)
     scopeTop := i;
     e := EntryPtr(scpHeap + scopeTop * 16);
@@ -291,7 +291,7 @@ BEGIN
   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 *)
+  PutAttr(e^.w2, node^.link2); (* copy link2 chain {/*016e*/} entry field direct as VAR; T1 direct *)
   e^.w3 := src^.word3; (*{/*0176*/} BITSET direct *)
   e^.w4 := src^.word4; (* kind {/*017a*/} *)
   CASE src^.word4 OF (* kind switch {/*01b3*/} *)
@@ -301,10 +301,10 @@ BEGIN
     CheckNode(T1(sv^.word5)); (*{/*0192*/}*)
     EnterChained(ADR(e^.w5), T1(sv^.word5)); (*{/*0197*/}*)
   | 101:
-    i := e^.w5; PutAttr(i, T1(e^.w5)); (*{/*0189*/}*)
+    PutAttr(e^.w5, T1(sv^.word5)); (*{/*0189*/} slot carriage: entry field; node: SRC word, not entry's *)
   | 102:
-    i := e^.w5; PutAttr(i, T1(e^.w5)); (*{/*019e*/}*)
-    i := e^.w6; PutAttr(i, T1(e^.w6));
+    PutAttr(e^.w5, T1(sv^.word5)); (*{/*019e*/} *)
+    PutAttr(e^.w6, T1(sv^.high));
     e^.w7 := sw7^[7];
   ELSE (* 92..98: name/link/attr words suffice *)
   END;
@@ -374,32 +374,32 @@ 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). *)
-VAR e: Words; new: T1; nw: Words;
+VAR e: EntryPtr; new: T1; nw: Words;
 BEGIN
   node := NIL; (*{/*0283*/}*)
   IF idx = 0 THEN RETURN END; (*{/*0286*/}*)
-  e := Words(scpHeap + 16 * idx); (*{/*028a*/}*)
-  node := T1(e^[1]); (*{/*0290*/}*)
+  e := EntryPtr(scpHeap + idx * 16); (*{/*028a*/}*)
+  node := T1(e^.w1); (*{/*0290*/}*)
   IF node <> NIL THEN RETURN END; (*{/*0294*/}*)
   (* Allocator size classes exact: Scanner.NewSized(kind) =
      14 bytes for kind <= 1, 10 for kind <= 6, 12 for kind <= 11, else 16. *)
-  new := Scanner.NewSized(e^[4]); (*{/*0299*/}*)
+  new := Scanner.NewSized(e^.w4); (*{/*0299*/}*)
   nw := Words(new);
-  e^[1] := CARDINAL(new); (* memoize {/*029e*/} *)
+  e^.w1 := CARDINAL(new); (* memoize {/*029e*/} *)
   node := new; (*{/*02a1*/}*)
-  GetAttr(new^.link2, e^[2]); (* subtype {/*02a4*/} *)
-  nw^[3] := e^[3]; (*{/*02ac*/}*)
-  CASE e^[4] OF (* kind switch {/*02e1*/} *)
+  GetAttr(new^.link2, e^.w2); (* subtype {/*02a4*/} *)
+  nw^[3] := CARDINAL(e^.w3); (*{/*02ac*/} BITSET field to CARDINAL slot *)
+  CASE e^.w4 OF (* kind switch {/*02e1*/} *)
   | 90, 91:
-    nw^[5] := e^[5]; nw^[6] := e^[6]; (*{/*02b4*/}*)
+    nw^[5] := e^.w5; nw^[6] := e^.w6; (*{/*02b4*/}*)
   | 99, 100:
-    UnlinkScope(ADR(nw^[5]), e^[5]); (*{/*02c4*/}*)
+    UnlinkScope(ADR(nw^[5]), e^.w5); (*{/*02c4*/}*)
   | 101:
-    new := T1(nw^[5]); GetAttr(new, e^[5]); (* tail: result discarded, memoization is the effect (original jump_stack) *)
+    new := T1(nw^[5]); GetAttr(new, e^.w5); (* tail: result discarded, memoization is the effect (original jump_stack) *)
   | 102:
-    new := T1(nw^[5]); GetAttr(new, e^[5]);
-    new := T1(nw^[6]); GetAttr(new, e^[6]);
-    nw^[7] := e^[7];
+    new := T1(nw^[5]); GetAttr(new, e^.w5);
+    new := T1(nw^[6]); GetAttr(new, e^.w6);
+    nw^[7] := e^.w7;
   ELSE (* 92..98: nothing beyond words 1..4 *)
   END;
 END GetAttr;
@@ -568,16 +568,29 @@ BEGIN
   LibRead(strHeap + 1, strTop - 1); (* string pool {/*0547*/} *)
   EnterStandards; (* rewire builtin slots 1..14 {/*054f*/} *)
 END LoadSymFile;
+PROCEDURE FindExport(start: CARDINAL; name: ADDRESS): CARDINAL;
+(* proc29 @0553, nested *)
+VAR e: SymEntryPtr; idx: CARDINAL;
+BEGIN
+  idx := start;
+  WHILE idx # 0 DO
+    e := symHeap + idx * 14; (*{/*0559*/}*)
+    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*/}*)
+  END;
+  RETURN 0;
+END FindExport;
+
 PROCEDURE ImportAll(importRec: ADDRESS);
 (* proc28 @05dd *)
 VAR
   imp: ImportPtr;
-  sysImp, stoImp: ImportPtr;
-  sysAdr: ADDRESS;
-  caseFlag: BOOLEAN;    (* 9 IN scanOptions {/*05df*/} *)
-  importEvery: BOOLEAN; (* bit 10 of flags {/*05e4*/} *)
+  sysImp: ImportPtr; (* also serves storage half below (disjoint) *)
   modIdx: CARDINAL;
-  expIdx: CARDINAL;
+
   scopeIdx: CARDINAL;
   tmp: ADDRESS;
   sib: CARDINAL;
@@ -586,24 +599,25 @@ VAR
   e, e2: SymEntryPtr;
   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 *)
-  VAR e: SymEntryPtr; idx: CARDINAL;
+
+
+
+  PROCEDURE ImportOne(anchor: ADDRESS; symIdx: CARDINAL);
+  (* proc31 @05be, nested. EnterIdent(scope, idx) per audit (pushes (scope,idx));
+     original call order was (anchor, symIdx) — MCD diff decides. *)
+  VAR e: SymEntryPtr;
   BEGIN
-    idx := start;
-    WHILE idx # 0 DO
-      e := symHeap + idx * 14; (*{/*0559*/}*)
-      IF Scanner.StrCmp(symHeap + strHeap + e^.nameOff,
-                        name, 9 IN Scanner.scanOpt) THEN (*{/*0568*/} StrCmp takes ADDRESS: no view needed *)
-        RETURN idx;
+    IF symIdx # 0 THEN
+      e := symHeap + symIdx * 14; (*{/*05c4*/}*)
+      ImportOne(anchor, e^.link); (*{/*05ca*/}*)
+      IF 0 IN e^.flags THEN (*{/*05d0*/}*)
+        EnterIdent(Words(anchor), symIdx); (*{/*05d6*/}*)
       END;
-      idx := e^.link; (*{/*0570*/}*)
     END;
-    RETURN 0;
-  END FindExport;
+  END ImportOne;
+
 
   PROCEDURE ListExports(first: CARDINAL);
   (* proc30 @0579, nested: colCount via parent frame *)
@@ -624,27 +638,11 @@ VAR
     END;
   END ListExports;
 
-  PROCEDURE ImportOne(anchor: ADDRESS; symIdx: CARDINAL);
-  (* proc31 @05be, nested. EnterIdent(scope, idx) per audit (pushes (scope,idx));
-     original call order was (anchor, symIdx) — MCD diff decides. *)
-  VAR e: SymEntryPtr;
-  BEGIN
-    IF symIdx # 0 THEN
-      e := symHeap + symIdx * 14; (*{/*05c4*/}*)
-      ImportOne(anchor, e^.link); (*{/*05ca*/}*)
-      IF 0 IN e^.flags THEN (*{/*05d0*/}*)
-        EnterIdent(Words(anchor), symIdx); (*{/*05d6*/}*)
-      END;
-    END;
-  END ImportOne;
-
 BEGIN
   imp := importRec;
-  caseFlag := 9 IN Scanner.scanOpt;
-  importEvery := 10 IN imp^.flags;
-  sysAdr := ADDRESS(Compiler.systemModule); sysImp := sysAdr;
-  IF Scanner.StrCmp(imp^.name, sysImp^.name, caseFlag) THEN (*{/*05e9*/} StrCmp takes ADDRESS *)
-    IF importEvery THEN (*{/*05f5*/}*)
+  sysImp := ADDRESS(Compiler.systemModule);
+  IF Scanner.StrCmp(imp^.name, sysImp^.name, 9 IN Scanner.scanOpt) THEN (*{/*05e9*/} *)
+    IF 10 IN imp^.flags THEN (*{/*05f5*/}*)
       imp^.flags := sysImp^.flags; (*{/*05f8*/}*)
       imp^.anchor := sysImp^.anchor; (*{/*0604*/}*)
       Compiler.compilationActive := FALSE; (* word 26 {/*0608*/} *)
@@ -653,11 +651,11 @@ BEGIN
     END;
     RETURN; (*{/*060e*/}*)
   END;
-  sysAdr := ADDRESS(Compiler.storageModule); stoImp := sysAdr;
-  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;
+  sysImp := ADDRESS(Compiler.storageModule);
+  IF Scanner.StrCmp(imp^.name, sysImp^.name, 9 IN Scanner.scanOpt) THEN (*{/*0611*/} *)
+    IF 10 IN imp^.flags THEN (*{/*061d*/}*)
+      imp^.flags := sysImp^.flags;
+      imp^.anchor := sysImp^.anchor;
       Compiler.compilationActive := FALSE;
     ELSE
       DefineDefinitionModule(CARDINAL(Compiler.storageScopeDesc)); (*{/*062e*/}: word24 *)
@@ -670,9 +668,9 @@ BEGIN
   LoadSymFile(sp^);
   modIdx := EnterModule(16); (*{/*0640*/}*)
   SymbolAssert(modIdx # 16, 48); (*{/*0644*/}*)
-  expIdx := expHead; (*{/*064b*/}*)
-  WHILE expIdx # 0 DO (*{/*064e*/}*)
-    e := symHeap + expIdx * 14;
+  scopeIdx := expHead; (*{/*064b*/} expIdx merged into scopeIdx (disjoint, both CARDINAL loop vars) *)
+  WHILE scopeIdx # 0 DO (*{/*064e*/}*)
+    e := symHeap + scopeIdx * 14;
     IF e^.flags * BITSET{1,6} # BITSET{} THEN (* AND 42H {/*0659*/} *)
       e^.flags := e^.flags - BITSET{0}; (*{/*0663*/}*)
     ELSE
@@ -684,18 +682,18 @@ BEGIN
       e^.aux1 := e^.aux1 + (CARDINAL(CHR(modIdx)) - e^.aux1 MOD 256);
       (* byte 11 := modIdx {/*068b*/} *)
     END;
-    expIdx := e^.link; (*{/*0692*/}*)
+    scopeIdx := e^.link; (*{/*0692*/}*)
   END;
   scopeIdx := 15;
   WHILE scopeIdx <= scopeTop DO (*{/*069a*/}*)
     s := scpHeap + scopeIdx * 16;
-    matched := LookupChain(FindModule(ORD(s^.slot)), ORD(s^.fresh)); (*{/*06ab*/}*)
-    IF matched # 0 THEN (*{/*06b2*/}*)
-      s^.link := matched; s^.fresh := 0C;
+    findIdx := LookupChain(FindModule(ORD(s^.slot)), ORD(s^.fresh)); (*{/*06ab*/} matched merged into findIdx (disjoint) *)
+    IF findIdx # 0 THEN (*{/*06b2*/}*)
+      s^.link := findIdx; s^.fresh := 0C;
     END;
     INC(scopeIdx);
   END;
-  IF importEvery THEN (*{/*06c4*/}*)
+  IF 10 IN imp^.flags THEN (*{/*06c4*/}*)
     ImportOne(ADR(imp^.anchor), expHead); (* NOTE order: see ImportOne note *)
   ELSE
     REPEAT