Bladeren bron

fix(labels): true CASE labels = printed-90; scorer compares case tables

Eric Streit 2 weken geleden
bovenliggende
commit
5f90a8fc4e
5 gewijzigde bestanden met toevoegingen van 74 en 31 verwijderingen
  1. 28 0
      SESSION.md
  2. 6 2
      src/compiler/EXPRESS.DEF
  3. 17 16
      src/compiler/EXPRESS.MOD
  4. 12 12
      src/compiler/SYMTAB.MOD
  5. 11 1
      tools/score.py

+ 28 - 0
SESSION.md

@@ -349,3 +349,31 @@ Next: GENZ80 media hunt; stage-2 pty-driven MCD diff per module.
   CheckAndStore runs only for 92/default (restructure proven by jumps);
   jump_stack=bare RETURN (59×, 1 push in file); nested-proper leave long-form;
   T1 param; CopyStr fits frozen DEF; LONGINT(REAL) free; BITSET{0..8} folds.
+- MAJOR: unassemble prints case labels +90 (subtracts 32678, should be 32768;
+  both toolchains emit raw = label+32768, interpreter adds 8000H). TRUE label
+  = printed - 90, universally. Proof: retail recompile of TypeKindOf labels
+  94/97/98 emits cd 5e 80, orig has cd 04 80 -> orig labels are 4/7/8.
+  score.py now attaches case-table lines to the cd op (they were INVISIBLE
+  before: all CASE verifications missed table bytes). Re-scored TypeKindOf
+  29/29 SAME incl. tables (stronger than old 24/24); proc50 tables match too
+  (verdict unchanged: NOT/DWORD/last-arm-layout deltas).
+- Relabeled to TRUE labels: TypeKindOf 8/7/4, Proc50 identKd 0-5 (arm 1 =
+  const, consistent with Scanner identKd:=1), ParseSetCons draft 0-8/11,
+  SYMTAB PutAttr/GetAttr 0/1/9-12 (ELSE 2..8). CODEGEN/SCANNER labels were
+  hand-written small — unaffected. Widened Head DEF variant (rl REAL arm)
+  for proc49 real_mul/compare (byte-neutral, T8-probe pattern).
+- kind scale settled 0..5 (CARD/INT/LONG/REAL/SET/LONGREAL): MUL/DIV/ADD
+  switches true 0-4 + kind-5 fall-through (qmul/qdiv/qadd+spill); SUB switch
+  true 2-5 + kinds 0-1 fall-through (INT-vs-CARD select + typ:=IntType).
+  DIV-neg: eq0 (CARD), real_compare+equal (LONG/REAL bit-trick), qcp+equal.
+- Proc49 fully decoded, not yet written/scored. Open items: (1) quad-load
+  spelling LRPtr(buf^.value)^ rejected (T(x)^ parses as T(x^)); needs pq-view
+  or heapLR staging; (2) FIXME-QCP: `qcp = 0L` emits call+dword0+dcompare+equal
+  vs MCD call+equal (+2 ops x3 sites: 11df, 15dd, 15f0); (3) LONGREAL-zero arg
+  spelling (dword0+dword0): 0.0 is REAL (rejected), DOUBLE() misresolves to
+  DoubleToStr; (4) $O scope: proc-wide $O+ breaks x-const folds (WHILE sub 51,
+  op-52 af 34) -> narrow $O+ wraps around MUL-90/ADD-90/ADD-91/SUB-01 only;
+  (5) e8 FIXME-BOOL (all conversions cost 1 op: not_zero). Calibrated:
+  qmul=8, qcp=5, qdiv=9, qadd=6, qsub=7, qneg=11 (hidden-proc0 +1 shift);
+  EmitTypedOp=6, EmitExtendedOp=7, OpenFixup=12, InsertFixup=14,
+  EmitSystemCall=17, EmitExtCall3=18. BITSET() transfer free; op2: 404/272/132.

+ 6 - 2
src/compiler/EXPRESS.DEF

@@ -50,7 +50,8 @@ TYPE DescPtr = POINTER TO Desc;
      END;
      Head = RECORD (* 5-word descriptor head (MCD global word2 accesses
        fields 0-4 only); typ: NodePtr so typ^.w0(T1)/w2(DescPtr) reach;
-       value+extra overlay lv LONGINT (proc2 QueueLongConst dword-load) *)
+       value+extra overlay lv LONGINT (proc2 QueueLongConst dword-load);
+       rl REAL arm shares offset 2 (proc49 real_mul/compare) *)
        typ: NodePtr;
        mode: CARDINAL;
        CASE : BOOLEAN OF
@@ -58,7 +59,10 @@ TYPE DescPtr = POINTER TO Desc;
          value: CharBufPtr;
          extra: CARDINAL;
        | FALSE:
-         lv: LONGINT;
+         CASE : BOOLEAN OF
+         | TRUE: lv: LONGINT;
+         | FALSE: rl: REAL;
+         END;
        END;
        kind: CARDINAL;
      END;

+ 17 - 16
src/compiler/EXPRESS.MOD

@@ -111,6 +111,7 @@ PROCEDURE ParseFuncCall(idx: CARDINAL): ADDRESS; FORWARD;
 PROCEDURE Proc43(code: BOOLEAN); FORWARD;
 PROCEDURE Proc44(p1: WalkPtr); FORWARD;
 PROCEDURE Proc50; FORWARD;
+PROCEDURE Proc49; FORWARD;
 PROCEDURE Proc18; FORWARD;
 PROCEDURE Proc19; FORWARD;
 PROCEDURE ExpandStdProc45(std: CARDINAL); FORWARD; (* FIXME: 0-arg call site *)
@@ -185,9 +186,9 @@ END IsPointer;
 PROCEDURE TypeKindOf(): CARDINAL;
 BEGIN
   CASE curDesc^.typ^.w4 OF
-    98: RETURN (CARDINAL(curDesc^.typ^.w3) DIV 2) + 1;
-  | 97: RETURN 2;
-  | 94: RETURN 4;
+    8: RETURN (CARDINAL(curDesc^.typ^.w3) DIV 2) + 1;
+  | 7: RETURN 2;
+  | 4: RETURN 4;
   ELSE RETURN ORD(RecordPtr(curDesc^.typ) = Compiler.IntType);
   END;
 END TypeKindOf;
@@ -372,12 +373,12 @@ BEGIN
       Scanner.GetSym;
     ELSE
       CASE Scanner.identKd OF
-        91: curDesc^.mode := 0;
+        1: curDesc^.mode := 0;
             curDesc^.value := ADDRESS(CARDINAL(Scanner.curNode^.word5)); (* FIXME-DWORD *)
             curDesc^.extra := CARDINAL(Scanner.curNode^.high);
             PushOperand(curDesc);
             Scanner.GetSym;
-      | 93: Scanner.GetSym;
+      | 3: Scanner.GetSym;
             Scanner.TestSet(BITSET{3,5});
             IF Scanner.AcceptSy(45) THEN
               MatchOpClass(BITSET{4}, 45);
@@ -393,7 +394,7 @@ BEGIN
               curDesc^.mode := 2;
               Scanner.ExpectSy(5);
             END;
-      | 94: ParseDesignatorTail;
+      | 4: ParseDesignatorTail;
             IF Scanner.curSym = 43 THEN
               Scanner.GetSym;
               MatchOpClass(BITSET{9}, 43);
@@ -402,10 +403,10 @@ BEGIN
             ELSE
               PushOperand(curDesc);
             END;
-      | 95: CentralError(CARDINAL(NodePtr(t2)) <> 0, 60);
+      | 5: CentralError(CARDINAL(NodePtr(t2)) <> 0, 60);
             Proc18;
-      | 90: Errors.ReportErrorWithText(0, Scanner.tokBuf);
-      | 92: Errors.ReportError(22);
+      | 0: Errors.ReportErrorWithText(0, Scanner.tokBuf);
+      | 2: Errors.ReportError(22);
       END;
       CheckAndStore(curDesc);
     END;
@@ -979,18 +980,18 @@ BEGIN
     CodeGen.EmitSystemCall(20); PushOperand(curDesc); (*FIXME-ARG*) (*{0781-0786}*)
     IF flag THEN BoolCondHelper ELSE ParseDesignatorTail END; (*{09e0}*)
     NormalizeOperand(curDesc); (*FIXME-ARG*) op := 2; m := 7; k1 := mod; Proc6; (*{09e9} *)
-    CASE curDesc^.typ^.w4 OF (*{09f0} callswitch; labels TBD by audit *)
-      90, 91:
-      | 92: bad := RecordPtr(curDesc^.typ) # Compiler.CharType; m := 1; (*{07a1-07a5}*)
-        | 93..96: m := m+3; ParseTypeCast(6); (*{07a6-07af}*)
-      | 97: m := 5; ParseTypeCast(11); (*{07b2-07b5}*)
-      | 98: IF RecordPtr(curDesc^.typ) = Compiler.LongrealType THEN (*{07b8-07bc} LONGREAL *)
+    CASE curDesc^.typ^.w4 OF (*{09f0} callswitch; TRUE labels = printed-90 *)
+    | 0, 1:
+      | 2: bad := RecordPtr(curDesc^.typ) # Compiler.CharType; m := 1; (*{07a1-07a5}*)
+        | 3..6: m := m+3; ParseTypeCast(6); (*{07a6-07af}*)
+      | 7: m := 5; ParseTypeCast(11); (*{07b2-07b5}*)
+      | 8: IF RecordPtr(curDesc^.typ) = Compiler.LongrealType THEN (*{07b8-07bc} LONGREAL *)
           ParseTypeCast(22); ParseTypeCast(65523);
           mod := Scanner.EnterMod("DOUBLES", 6); (*{07c8-07d5}*)
           aux := mod; m := 14; k1 := 1; (*{07d6-07dc}*)
         ELSE ParseTypeCast(13); ParseTypeCast(65531); m := 6; (*{07df-07e6}*)
         END;
-      | 101: IF ~ IsPointer(RecordPtr(curDesc^.typ)) THEN bad := TRUE END; (*{07ea-07ef}*)
+      | 11: IF ~ IsPointer(RecordPtr(curDesc^.typ)) THEN bad := TRUE END; (*{07ea-07ef}*)
         EmitAddress(curDesc); (*FIXME-ARG*) op := 3; m := 2; (*{07f0-07f6}*)
       ELSE bad := TRUE; (*{0817}*)
     END;

+ 12 - 12
src/compiler/SYMTAB.MOD

@@ -294,19 +294,19 @@ BEGIN
   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*/} *)
-  | 90, 91:
+  CASE src^.word4 OF (* kind switch {/*01b3*/} TRUE labels = printed-90 *)
+  | 0, 1:
     e^.w5 := CARDINAL(sv^.word5); e^.w6 := CARDINAL(sv^.high); (*{/*0182*/} CARDINAL() zero-cost views *)
-  | 99, 100:
+  | 9, 10:
     CheckNode(T1(sv^.word5)); (*{/*0192*/}*)
     EnterChained(ADR(e^.w5), T1(sv^.word5)); (*{/*0197*/}*)
-  | 101:
+  | 11:
     PutAttr(e^.w5, T1(sv^.word5)); (*{/*0189*/} slot carriage: entry field; node: SRC word, not entry's *)
-  | 102:
+  | 12:
     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 *)
+  ELSE (* 2..8: name/link/attr words suffice *)
   END;
 END PutAttr;
 
@@ -389,18 +389,18 @@ BEGIN
   node := new; (*{/*02a1*/}*)
   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:
+  CASE e^.w4 OF (* kind switch {/*02e1*/} TRUE labels = printed-90 *)
+  | 0, 1:
     nw^[5] := e^.w5; nw^[6] := e^.w6; (*{/*02b4*/}*)
-  | 99, 100:
+  | 9, 10:
     UnlinkScope(ADR(nw^[5]), e^.w5); (*{/*02c4*/}*)
-  | 101:
+  | 11:
     new := T1(nw^[5]); GetAttr(new, e^.w5); (* tail: result discarded, memoization is the effect (original jump_stack) *)
-  | 102:
+  | 12:
     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 *)
+  ELSE (* 2..8: nothing beyond words 1..4 *)
   END;
 END GetAttr;
 

+ 11 - 1
tools/score.py

@@ -8,10 +8,20 @@ def procs(path, mod):
     heads = [(m.group(1), int(m.group(2), 16))
              for m in re.finditer(r'(?m)^;? ?' + mod + r'\.(\w+)\s*: ([0-9a-f]{4})$', txt)]
     ops = []
+    cur = None
     for line in txt.splitlines():
         m = re.match(r'^\s*([0-9a-f]{4})\s+((?:[0-9a-f]{2}\s*)+?)(?:\s{2,}|\t+|$)(.*)$', line)
         if m:
-            ops.append((int(m.group(1), 16), m.group(2).split(), m.group(3).strip()))
+            cur = int(m.group(1), 16)
+            ops.append((cur, m.group(2).split(), m.group(3).strip()))
+            continue
+        # case-table lines carry no address: attach to preceding cd op so
+        # CASE bounds/labels participate in comparison (else invisible).
+        # NOTE: unassemble prints labels +90 (subtracts 32678 not 32768);
+        # the shift applies equally to both sides, so comparison stays valid.
+        c = re.match(r'^\s*case (\d+) => ([0-9a-f]{4})$', line)
+        if c and cur is not None:
+            ops.append((cur, ['cd'], 'case %d => %s' % (int(c.group(1)), c.group(2))))
     out = {}
     addrs = sorted(set(a for _, a in heads))
     for name, a in heads: