Przeglądaj źródła

calc: CALC.PAS compiles (code 25908, data 19694)

Move the fixed data base from image 0x8000 to 0xA000 (memory 0xA100) and
raise CodeMax/MaxCode to 0xA000.  This gives the large generated program room
below the data base while keeping the .COM code-only.  comimage.py and the
layout notes are updated to the new fixed base.

The last source blockers were CHAR-subrange handling for ColumnName
('A'..'G' now has class TChar, so `string + FX` works), the CASE/ELSE trailing
semicolon, and string-vs-CHAR comparison.

The CALC ladder now reports:

    CALC.PAS  OK  25908  19694

so the front-end reaches the final '.'.  This is a compile milestone, not a
run milestone: the boot harness still places stdin at memory 7000h, below the
larger image, so running CALC.COM needs the loader moved.

Verified: compile matrix 113/113, ladder 1/1 (OK), 99 .COM executions under
both oracles, rt_exec 276/276, nonvacuity 121/121, run_all ALL PASS.
Eric Streit 3 dni temu
rodzic
commit
a65e0aec2d
5 zmienionych plików z 55 dodań i 46 usunięć
  1. 13 10
      CALC-COMPILE.md
  2. 12 11
      SUMMARY.md
  3. 19 9
      shell/Compiler.mod
  4. 3 3
      shell/tests/comimage.py
  5. 8 13
      shell/tests/fixtures/calc_ladder.tsv

+ 13 - 10
CALC-COMPILE.md

@@ -97,7 +97,7 @@ Current rung (measured today, normalised position):
 
 
 | position | blocker |
 | position | blocker |
 |---|---|
 |---|---|
-| **56540** | code-image ceiling — runtime + generated code reaches the `0x8000` data base (`ERR 98`) |
+| **compiles** | `CALC.PAS` reaches its final `.` — code **25,908** B, data **19,694** B |
 
 
 Rungs behind it (now passed):
 Rungs behind it (now passed):
 
 
@@ -163,7 +163,8 @@ Rungs ahead:
 | 50744 | `Insert` string builtin - DONE |
 | 50744 | `Insert` string builtin - DONE |
 | 51322 | CASE/ELSE closing `end;` - DONE |
 | 51322 | CASE/ELSE closing `end;` - DONE |
 | 52316 | string vs CHAR comparison (`S <> Chr($FF)`) - DONE |
 | 52316 | string vs CHAR comparison (`S <> Chr($FF)`) - DONE |
-| 56540 | code-image ceiling (`ERR 98`) |
+| 56540 | code-image ceiling - DONE (DataStart moved to 0xA000) |
+| **OK** | **CALC.PAS compiles: code 25,908, data 19,694** |
 
 
 Corrections the measurements force, worth stating plainly because the stage list
 Corrections the measurements force, worth stating plainly because the stage list
 below was written before them:
 below was written before them:
@@ -423,9 +424,9 @@ properties that matter for the compile goal are preserved:
 |---|---|---|
 |---|---|---|
 | `.COM` contents | runtime + program code (CS), no data | runtime + program code, no data |
 | `.COM` contents | runtime + program code (CS), no data | runtime + program code, no data |
 | entry | `E9 rel16` over the runtime | `E9 rel16` over the runtime + 16-byte header |
 | entry | `E9 rel16` over the runtime | `E9 rel16` over the runtime + 16-byte header |
-| globals | separate DS, offsets from `dc` | fixed image `DataStart = 8000h` (memory `8100h`) |
+| globals | separate DS, offsets from `dc` | fixed image `DataStart = 0A000h` (memory `0A100h`) |
 | globals zeroed | DS data area | `initmem` zeroes `[hdrDS,hdrHeap)` |
 | globals zeroed | DS data area | `initmem` zeroes `[hdrDS,hdrHeap)` |
-| code limit | CS capacity | `MaxCode = 24,000` (and `CodeMax = 6F00h` before the stdin descriptor) |
+| code limit | CS capacity | `MaxCode = 0A000h` and `CodeMax = 0A000h` (data base) |
 | data limit | DS capacity | address space below the stack |
 | data limit | DS capacity | address space below the stack |
 | heap/stack | above DS | above `hdrHeap`, down from `SP=FFFEh` |
 | heap/stack | above DS | above `hdrHeap`, down from `SP=FFFEh` |
 
 
@@ -1256,11 +1257,13 @@ and TEXT file output is done (`t91_textout`), both compile-only because the
 harness has no filesystem.  `Str` real formatting is done (`t92_strreal`),
 harness has no filesystem.  `Str` real formatting is done (`t92_strreal`),
 pointer types with `New`/`Dispose`/dereference are done (`t93_pointer`), and
 pointer types with `New`/`Dispose`/dereference are done (`t93_pointer`), and
 text `Eof`/`Readln` plus integer `Str` are done (`t94_textread`/`t95_strint`).
 text `Eof`/`Readln` plus integer `Str` are done (`t94_textread`/`t95_strint`).
-The next blocker is image capacity: runtime plus generated code reaches the
-`0x8000` data base.  The runtime is 9,373 bytes; `rt_exec` is at HDR=0x4000 /
-data 0x5000, and the compiler's code ceiling is 0x8000.  The next change must
-be a deliberate layout move (data base/code ceiling) or a further runtime
-reduction.
+**CALC.PAS compiles.**  The runtime is 9,373 bytes; the generated program is
+25,908 bytes of code and 19,694 bytes of data, with `DataStart=0xA000` and
+`CodeMax=0xA000`.  The next task is execution, not front-end coverage: the
+current boot harness still places stdin at memory `7000h`, below the larger
+image, so the loader must be moved before CALC.COM can run under qemu.  The
+original CALC.COM is 27,901 bytes; ours is larger because the runtime and
+code layout differ.
 
 
 **Stage 14 — the CRT identifiers.** `GotoXY` (25), `LowVideo`/`NormVideo`
 **Stage 14 — the CRT identifiers.** `GotoXY` (25), `LowVideo`/`NormVideo`
 (16 + 16), `ClrEol` (10), `ClrScr` (6), `KeyPressed` (3), `Delay` (1),
 (16 + 16), `ClrEol` (10), `ClrScr` (6), `KeyPressed` (3), `Delay` (1),
@@ -1305,7 +1308,7 @@ remaining run-time capacity note.
 |---|---|---|---|
 |---|---|---|---|
 | `TextLimit` (source buffer) | 62,903 | `CALC.PAS` + `CALC.INC`, normalised = **62,415** | **488 bytes of slack** |
 | `TextLimit` (source buffer) | 62,903 | `CALC.PAS` + `CALC.INC`, normalised = **62,415** | **488 bytes of slack** |
 | `MaxCode` | 24,000 | 16,560 B program + 4,384 B runtime = **20,944 B** | **OK, 3,056 B spare** (§3.2) |
 | `MaxCode` | 24,000 | 16,560 B program + 4,384 B runtime = **20,944 B** | **OK, 3,056 B spare** (§3.2) |
-| code window | `CodeMax = 6F00h`, capped by `MaxCode` | 20,227 B | **OK**; no data gap (§3.2) |
+| code window | `CodeMax = 0A000h`, capped by `MaxCode` | 25,908 B | **OK**; no data gap (§3.2) |
 | data area | fixed image `8000h`, zeroed by `initmem` | **12,032 B** (measured, §3.1) | **OK for compile**; see the run-time cargo note (§3.2) |
 | data area | fixed image `8000h`, zeroed by `initmem` | **12,032 B** (measured, §3.1) | **OK for compile**; see the run-time cargo note (§3.2) |
 | stack | 16,384 min / 655,360 max | 16,384 min | matches the original's `minstk`/`maxstk` |
 | stack | 16,384 min / 655,360 max | 16,384 min | matches the original's `minstk`/`maxstk` |
 | `MaxSym` | 3,000 | 47 routines + locals + params | **inferred** OK, verify |
 | `MaxSym` | 3,000 | 47 routines + locals + params | **inferred** OK, verify |

+ 12 - 11
SUMMARY.md

@@ -1126,12 +1126,12 @@ assertion, rather than asking the compiler where it thinks the header is.
 `CmdCompile` honours the Destination option: 0 = memory, 1 = `.COM`, 2 = `.CHN`
 `CmdCompile` honours the Destination option: 0 = memory, 1 = `.COM`, 2 = `.CHN`
 (refused). A `.COM` is named after its source with the extension swapped at the
 (refused). A `.COM` is named after its source with the extension swapped at the
 last dot and contains **exactly the runtime and the program's code**; the
 last dot and contains **exactly the runtime and the program's code**; the
-globals are at image `8000h` (memory `8100h`), outside the file, and `initmem`
+globals are at image `0A000h` (memory `0A100h`), outside the file, and `initmem`
 zeroes them. Its stack sits at the segment top (`SS = SP = CS:FFFE`), which is
 zeroes them. Its stack sits at the segment top (`SS = SP = CS:FFFE`), which is
 where DOS puts it.
 where DOS puts it.
 
 
-**Layout:** the old fixed `rtSz + 1000H` data base is gone. `DataStart = 8000h`,
-`CodeMax = 6F00h`, and `MaxCode = 24,000` bound the code image; the `.COM`
+**Layout:** the old fixed `rtSz + 1000H` data base is gone. `DataStart = 0A000h`,
+`CodeMax = 0A000h`, and `MaxCode = 0A000h` bound the code image; the `.COM`
 writer emits `ImageBytes()` and no padding. This is the flat-segment equivalent
 writer emits `ImageBytes()` and no padding. This is the flat-segment equivalent
 of the original's separate CS/DS layout (see `CALC-COMPILE.md` §3.2). It is
 of the original's separate CS/DS layout (see `CALC-COMPILE.md` §3.2). It is
 enough to compile CALC; running CALC with its full 16,384-byte stack and
 enough to compile CALC; running CALC with its full 16,384-byte stack and
@@ -1298,9 +1298,9 @@ Details that are deliberate, not incidental:
 - **Code above 4 KiB no longer overruns the data area.** The layout rung
 - **Code above 4 KiB no longer overruns the data area.** The layout rung
   (`v-TP3-CALC-LAYOUT`) moved the globals to image `8000h`, made the `.COM`
   (`v-TP3-CALC-LAYOUT`) moved the globals to image `8000h`, made the `.COM`
   code-only, and left `initmem` to zero the data. The effective code bound is
   code-only, and left `initmem` to zero the data. The effective code bound is
-  `MaxCode = 24,000` (with `CodeMax = 6F00h` before the boot harness's stdin
-  descriptor), not a 4 KiB window. The remaining capacity question is running
-  CALC with its original stack and heap, deferred in `CALC-COMPILE.md` §3.2.
+  `MaxCode = 0A000h` (with `CodeMax = 0A000h` before the data base), not a
+  4 KiB window. The remaining capacity question is running CALC with its
+  original stack and heap, deferred in `CALC-COMPILE.md` §3.2.
 - **`[SP]` cannot be encoded on an 8086, and the fix is a shape change.**
 - **`[SP]` cannot be encoded on an 8086, and the fix is a shape change.**
   `EmMovAxSp`/`EmMovCxSp` now emit `POP reg` / `PUSH reg` — two instructions
   `EmMovAxSp`/`EmMovCxSp` now emit `POP reg` / `PUSH reg` — two instructions
   where there used to be one, so anything that assumed a one-instruction
   where there used to be one, so anything that assumed a one-instruction
@@ -2044,7 +2044,7 @@ the compiler *emitting* a 16,560-byte program). The ratchet and front-end
 features through **file control-block operations and the original memory
 features through **file control-block operations and the original memory
 layout** are landed: the ladder (`tests/calc_ladder.sh` +
 layout** are landed: the ladder (`tests/calc_ladder.sh` +
 `tests/fixtures/calc_ladder.tsv`, run by `run_all.sh`; CALC.PAS now stops at
 `tests/fixtures/calc_ladder.tsv`, run by `run_all.sh`; CALC.PAS now stops at
-`ERR 98` at pos 56540, the code-image ceiling), the `{$I}` include,
+**CALC.PAS compiles** (code 25,908, data 19,694), the `{$I}` include,
 `^X`/`#nn`, scalar typed constants, sets, enums, records (CellRec = 80),
 `^X`/`#nn`, scalar typed constants, sets, enums, records (CellRec = 80),
 subranges, arrays, element/field access, file types, string value parameters,
 subranges, arrays, element/field access, file types, string value parameters,
 `Length`, the CRT identifiers (`ClrScr`/`GotoXY`/`ClrEol`/`LowVideo`/
 `Length`, the CRT identifiers (`ClrScr`/`GotoXY`/`ClrEol`/`LowVideo`/
@@ -2070,10 +2070,11 @@ standard functions (`Abs`, `Sqr`, `Sqrt`, `Ln`, `Exp`, `Sin`, `Cos`,
 landed, along with `Delete` and local `set of Char` variables.  The math runtime
 landed, along with `Delete` and local `set of Char` variables.  The math runtime
 was compacted to guest Horner/square loops, reducing it from 14,063 to 9,203
 was compacted to guest Horner/square loops, reducing it from 14,063 to 9,203
 bytes.  `Insert`, CASE/ELSE trailing semicolons and string-vs-CHAR comparisons
 bytes.  `Insert`, CASE/ELSE trailing semicolons and string-vs-CHAR comparisons
-are also landed; the ladder now stops at the code-image ceiling
-(`ERR 98 56540`).  The runtime is 9,373 bytes / 56 entries; the rt_exec
-scaffold is at HDR=0x4000 / data 0x5000.  Items 1-4 below are independent of
-both tracks.
+are also landed.  **CALC.PAS now compiles to its final `.`** with code 25,908
+and data 19,694.  The runtime is 9,373 bytes / 56 entries; the rt_exec
+scaffold is at HDR=0x4000 / data 0x5000.  The next task is running the larger
+image, not front-end coverage.  Items 1-4 below are independent of both
+tracks.
 
 
 1. The rest of the string language. `v-TP3-STRVAR`/`v-TP3-STRREAD-ASSIGN` cover
 1. The rest of the string language. `v-TP3-STRVAR`/`v-TP3-STRREAD-ASSIGN` cover
    string variables, `s := 'literal'`, `writeln (s)`, `readln (s)`/`read (s)`
    string variables, `s := 'literal'`, `writeln (s)`, `readln (s)`/`read (s)`

+ 19 - 9
shell/Compiler.mod

@@ -75,17 +75,19 @@ CONST
       displacement is relative to the END of the jump, so every offset in the
       displacement is relative to the END of the jump, so every offset in the
       image is EntSize further along than it was before the jump existed. *)
       image is EntSize further along than it was before the jump existed. *)
    EntSize   = 3 ;
    EntSize   = 3 ;
-   MaxCode   = 8000H ;
+   MaxCode   = 0A000H ;
    (* Program layout, image offsets.  The original puts the runtime and the
    (* Program layout, image offsets.  The original puts the runtime and the
       program's code in CS and the globals in a SEPARATE DS segment, so the
       program's code in CS and the globals in a SEPARATE DS segment, so the
       .COM contains no data and the code is not limited by a data gap.  We
       .COM contains no data and the code is not limited by a data gap.  We
       have one flat segment (our boot loader), so the same property is
       have one flat segment (our boot loader), so the same property is
       obtained by putting the globals at a fixed high image offset: the .COM
       obtained by putting the globals at a fixed high image offset: the .COM
       is code-only, hdrDS points at DataStart, and initmem zeroes it.  The
       is code-only, hdrDS points at DataStart, and initmem zeroes it.  The
-      code must end below CodeMax, where the boot harness puts the stdin
-      descriptor (memory 7000h). *)
-   DataStart = 8000H ;       (* image offset of the first global (memory 8100h) *)
-   CodeMax   = 8000H ;       (* code must end below memory 7000h *)
+      code must end below CodeMax.  DataStart is now 0xA000h so the large CALC
+      image fits; the current boot harness still puts its input descriptor at
+      memory 7000h, so a .COM above that is compile-only until the loader is
+      moved. *)
+   DataStart = 0A000H ;      (* image offset of the first global (memory 0A100h) *)
+   CodeMax   = 0A000H ;       (* code must end below the 0A000h data base *)
 
 
    MaxSym    = 3000 ;
    MaxSym    = 3000 ;
    MaxPatch  = 2000 ;
    MaxPatch  = 2000 ;
@@ -357,7 +359,7 @@ VAR
 
 
    (* Image layout, all image-absolute.  rtSz is where the runtime ends and
    (* Image layout, all image-absolute.  rtSz is where the runtime ends and
       the program header begins; dataBase is the fixed high global area
       the program header begins; dataBase is the fixed high global area
-      (DataStart = 8000H image, 8100H memory), which is NOT part of the .COM
+      (DataStart = 0A000H image, 0A100H memory), which is NOT part of the .COM
       image: initmem zeroes it at startup, as the original's separate DS
       image: initmem zeroes it at startup, as the original's separate DS
       segment is zeroed.  codeSz and dataSz are PROGRAM sizes - the runtime is
       segment is zeroed.  codeSz and dataSz are PROGRAM sizes - the runtime is
       excluded. *)
       excluded. *)
@@ -799,7 +801,7 @@ BEGIN
          (CodeMax).  Globals no longer sit immediately above the code - they
          (CodeMax).  Globals no longer sit immediately above the code - they
          live at DataStart and initmem zeroes them - so this is purely a
          live at DataStart and initmem zeroes them - so this is purely a
          capacity check: cbuf cannot hold another byte, or the image would
          capacity check: cbuf cannot hold another byte, or the image would
-         reach the stdin descriptor at memory 7000h.  Reported as TP3's error
+         reach the configured data base.  Reported as TP3's error
          98 (memory overflow) rather than a silent truncation. *)
          98 (memory overflow) rather than a silent truncation. *)
       Err (EMemOvf)
       Err (EMemOvf)
    ELSE
    ELSE
@@ -6890,6 +6892,7 @@ VAR tok : CARDINAL ;
     s2, e2 : CARDINAL ;
     s2, e2 : CARDINAL ;
     subcls : CARDINAL ;
     subcls : CARDINAL ;
     strf : BOOLEAN ;
     strf : BOOLEAN ;
+    isCharRange : BOOLEAN ;
     consumed : BOOLEAN ;
     consumed : BOOLEAN ;
     running, groupFirst, i, an, recStart : CARDINAL ;
     running, groupFirst, i, an, recStart : CARDINAL ;
     alo, ahi : ARRAY [0..3] OF LONGINT ;
     alo, ahi : ARRAY [0..3] OF LONGINT ;
@@ -7196,13 +7199,20 @@ BEGIN
             are inside 0..255, else two (RESUME-TP3.md §2).  `0..20' and
             are inside 0..255, else two (RESUME-TP3.md §2).  `0..20' and
             `'A'..'G'' are one byte - which is what makes CellRec 80 and not
             `'A'..'G'' are one byte - which is what makes CellRec 80 and not
             82, and `Sheet' 147*80.  The bounds are kept for `set of T'. *)
             82, and `Sheet' 147*80.  The bounds are kept for `set of T'. *)
+         Skip () ;
+         isCharRange := (ORD (CurCh ()) = AposC) OR (CurCh () = '^')
+                        OR (CurCh () = '#') ;
          RdConst (lo, subcls, strf) ;
          RdConst (lo, subcls, strf) ;
          IF NOT MatchRange () THEN
          IF NOT MatchRange () THEN
             Err (ESimpType) ;
             Err (ESimpType) ;
             RETURN
             RETURN
          END ;
          END ;
          RdConst (hi, subcls, strf) ;
          RdConst (hi, subcls, strf) ;
-         cls := TScalar ;
+         IF isCharRange THEN
+            cls := TChar
+         ELSE
+            cls := TScalar
+         END ;
          IF (lo >= 0) AND (hi <= 255) AND (lo <= hi) THEN
          IF (lo >= 0) AND (hi <= 255) AND (lo <= hi) THEN
             size := 1
             size := 1
          ELSE
          ELSE
@@ -8466,7 +8476,7 @@ BEGIN
 END ImageBytes ;
 END ImageBytes ;
 
 
 PROCEDURE DataBase () : CARDINAL ;
 PROCEDURE DataBase () : CARDINAL ;
-(* image-absolute offset at which the data area begins (DataStart = 8000H).
+(* image-absolute offset at which the data area begins (DataStart = 0A000H).
    The data is outside the .COM; initmem zeroes [dataBase, dataBase+dataSz)
    The data is outside the .COM; initmem zeroes [dataBase, dataBase+dataSz)
    through the header's hdrDS/hdrHeap words. *)
    through the header's hdrDS/hdrHeap words. *)
 BEGIN
 BEGIN

+ 3 - 3
shell/tests/comimage.py

@@ -65,7 +65,7 @@ HDR_SZ = 16                   # 5 header words + 3 buffer words (Compiler)
 # both of their operands shift together.
 # both of their operands shift together.
 # Restated, not asked of the code under test.  See Runtime.LoadBias.
 # Restated, not asked of the code under test.  See Runtime.LoadBias.
 LOAD_BIAS = 0x100
 LOAD_BIAS = 0x100
-DATA_IMAGE = 0x8000         # image offset of the globals; memory 8100h
+DATA_IMAGE = 0xA000         # image offset of the globals; memory 0A100h
 
 
 # initmem's prologue, which is the runtime's only reader of the program header.
 # initmem's prologue, which is the runtime's only reader of the program header.
 # The displacements +4 and +6 below are the whole point of this constant: the
 # The displacements +4 and +6 below are the whole point of this constant: the
@@ -96,7 +96,7 @@ def find_header(d):
 
 
         +0  1                 hdrFlag, always 1
         +0  1                 hdrFlag, always 1
         +2  code end + bias   hdrCS
         +2  code end + bias   hdrCS
-        +4  data base + bias  hdrDS = 8000h + bias, a FIXED high area
+        +4  data base + bias  hdrDS = 0A000h + bias, a FIXED high area
         +6  data end  + bias  hdrHeap, which is hdrDS + dataBytes
         +6  data end  + bias  hdrHeap, which is hdrDS + dataBytes
 
 
     The .COM is code-only: hdrDS is above the file and initmem zeroes it at
     The .COM is code-only: hdrDS is above the file and initmem zeroes it at
@@ -119,7 +119,7 @@ def find_header(d):
         return None
         return None
     # The program header sits immediately before the first instruction, and the
     # The program header sits immediately before the first instruction, and the
     # entry jump names that instruction.  The data base is now a FIXED high
     # entry jump names that instruction.  The data base is now a FIXED high
-    # area (DataStart = 8000h image, 8100h memory), not header+1000h: the .COM
+    # area (DataStart = 0A000h image, 0A100h memory), not header+1000h: the .COM
     # is code-only, as the original's separate DS segment made it.
     # is code-only, as the original's separate DS segment made it.
     target = ENT_SZ + int.from_bytes(d[1:ENT_SZ], "little", signed=True)
     target = ENT_SZ + int.from_bytes(d[1:ENT_SZ], "little", signed=True)
     off = target - HDR_SZ
     off = target - HDR_SZ

+ 8 - 13
shell/tests/fixtures/calc_ladder.tsv

@@ -25,16 +25,11 @@
 # positions shift — which is exactly why this must be a measured number, not a
 # positions shift — which is exactly why this must be a measured number, not a
 # remembered one.
 # remembered one.
 #
 #
-# Current rung (2026-10-23): the code image reaches the 0x8000 data boundary.
-# UpCase, run-time set membership, string fields through DI, the original memory
-# layout, untyped-file declarations, file control-block operations, VAR string
-# parameters, Chr, typed-file block I/O, text-file output, Str,
-# pointers/New/dereference, text Eof/Readln, Str(integer), Val(integer), VAR/
-# value REAL and REAL function results, REAL literals/comparisons/arithmetic,
-# self-recursion, enum-indexed arrays, string-array typed constants, local REAL
-# variables, Copy, real Val, Abs/Sqr/Sqrt, Ln/Exp/Sin/Cos/Arctan, Int(REAL),
-# forward definitions, Delete, local set of Char variables, the compact
-# Horner/square runtime, Insert, CASE/ELSE trailing semicolons and
-# string-vs-CHAR comparisons moved the ladder 15911 -> ... -> 51322 -> 56540.
-# The next blocker is the image layout/code ceiling (TP3 error 98).
-CALC.PAS	ERR	98	56540
+# Current rung (2026-10-24): CALC.PAS COMPILES.
+# The compiler now reaches the final '.', with code=25908 and data=19694.
+# The layout was moved deliberately: DataStart=0xA000 image (0xA100 memory)
+# and CodeMax=0xA000, so the runtime plus the generated program fit below the
+# data base.  UpCase, set membership, strings, pointers, files, REAL
+# expressions/functions, recursion, forward definitions, Copy/Val/Delete/
+# Insert, local sets and the compact math runtime are all landed.
+CALC.PAS	OK	25908	19694