|
@@ -28,6 +28,7 @@ manual, not guessed.
|
|
|
| Image layout in one file; a check's sweep region measured, not restated | `v-TP3-IMAGELAYOUT` | done, **every reader of a linked `.COM` imports `tests/comimage.py`, and the region `check_framedisp` sweeps is two readings of the file required to agree** |
|
|
| Image layout in one file; a check's sweep region measured, not restated | `v-TP3-IMAGELAYOUT` | done, **every reader of a linked `.COM` imports `tests/comimage.py`, and the region `check_framedisp` sweeps is two readings of the file required to agree** |
|
|
|
| Arguments pushed as they are parsed; the parameter frame read from BP+4 backwards | `v-TP3-ARGORDER` | done, **`t36_argclobber` runs: a computed argument survives the parse of the next one, and the callee's slots match the order they were pushed in** |
|
|
| Arguments pushed as they are parsed; the parameter frame read from BP+4 backwards | `v-TP3-ARGORDER` | done, **`t36_argclobber` runs: a computed argument survives the parse of the next one, and the callee's slots match the order they were pushed in** |
|
|
|
| A `byte` reader of its own, and bug 36's four sites proved re-derivable | `v-TP3-NONVACUITY-RDBYTE` | done, **`readln (b)` of a `byte` prints the byte and leaves the variable beside it alone; reverting any one of the argument-order fix's four sites turns `t36_argclobber` red** |
|
|
| A `byte` reader of its own, and bug 36's four sites proved re-derivable | `v-TP3-NONVACUITY-RDBYTE` | done, **`readln (b)` of a `byte` prints the byte and leaves the variable beside it alone; reverting any one of the argument-order fix's four sites turns `t36_argclobber` red** |
|
|
|
|
|
+| A `BOOLEAN` read refused with TP3's own error 66 | `v-TP3-BOOLREAD` | done, **`readln (b)` of a boolean is an error, not a word store into a one-byte variable — exactly TPSRC8 `prderrtp`; the compile matrix demands `ERR 66` at the character after the variable, and the accepting dispatch is one of the in-suite reverts** |
|
|
|
|
|
|
|
|
Every row that names a tag has one, and every tag points at a commit on
|
|
Every row that names a tag has one, and every tag points at a commit on
|
|
|
`master`; verified by diffing the rows against `git tag -l`, which is how
|
|
`master`; verified by diffing the rows against `git tag -l`, which is how
|
|
@@ -121,11 +122,11 @@ needing a squint. It was checked for vacuousness by reverting the string
|
|
|
scanner fix: the suite went red with exit 1, and came back green only when the
|
|
scanner fix: the suite went red with exit 1, and came back green only when the
|
|
|
fix was restored.
|
|
fix was restored.
|
|
|
|
|
|
|
|
-**35 of 38 fixtures compile clean**, up from 1 (the empty program) when the
|
|
|
|
|
|
|
+**35 of 39 fixtures compile clean**, up from 1 (the empty program) when the
|
|
|
direct harness was first built.
|
|
direct harness was first built.
|
|
|
|
|
|
|
|
```
|
|
```
|
|
|
-compile matrix: 38 passed, 0 failed (of 38)
|
|
|
|
|
|
|
+compile matrix: 39 passed, 0 failed (of 39)
|
|
|
```
|
|
```
|
|
|
|
|
|
|
|
Compiling: `t01` minimal · `t04` var+assign+`writeln` · `t06` two args ·
|
|
Compiling: `t01` minimal · `t04` var+assign+`writeln` · `t06` two args ·
|
|
@@ -146,8 +147,10 @@ arguments are computed in various positions, each one keeping its own value. ·
|
|
|
|
|
|
|
|
Failing, all deliberately: `t14` `array [1..5] of integer` at its point of use
|
|
Failing, all deliberately: `t14` `array [1..5] of integer` at its point of use
|
|
|
and `t25` a string literal used as a *value* (`s := 'hi'`) both → `ENoLib`
|
|
and `t25` a string literal used as a *value* (`s := 'hi'`) both → `ENoLib`
|
|
|
-(102), the original's "not implemented" path; `uierror` is a deliberate syntax
|
|
|
|
|
-error (41) used by the UI test.
|
|
|
|
|
|
|
+(102), the original's "not implemented" path; `t38` `readln (b)` of a
|
|
|
|
|
+`boolean` → error 66, TP3's "I/O not allowed here" (TPSRC8 `prderrtp`), which
|
|
|
|
|
+refuses the whole class because the runtime has no boolean reader at all; and
|
|
|
|
|
+`uierror` is a deliberate syntax error (41) used by the UI test.
|
|
|
|
|
|
|
|
`run_com_tests.sh` additionally links **all 35 that compile** to a real `.COM`
|
|
`run_com_tests.sh` additionally links **all 35 that compile** to a real `.COM`
|
|
|
and re-verifies the bytes with an independent Python checker that *measures*
|
|
and re-verifies the bytes with an independent Python checker that *measures*
|
|
@@ -440,16 +443,22 @@ goes red before a single instruction has run.
|
|
|
|
|
|
|
|
### Non-vacuity — `tests/nonvacuity.sh`
|
|
### Non-vacuity — `tests/nonvacuity.sh`
|
|
|
|
|
|
|
|
-Every assertion in this file is proved able to fail: **66 deliberate
|
|
|
|
|
|
|
+Every assertion in this file is proved able to fail: **67 deliberate
|
|
|
breakages, each asserted to turn exactly one named check red for the stated
|
|
breakages, each asserted to turn exactly one named check red for the stated
|
|
|
-reason, then restored and re-asserted green** — `non-vacuity: 66 ok, 0 failed`.
|
|
|
|
|
|
|
+reason, then restored and re-asserted green** — `non-vacuity: 67 ok, 0 failed`.
|
|
|
They cover the runtime's emitter audit and its restored source, the mod=11
|
|
They cover the runtime's emitter audit and its restored source, the mod=11
|
|
|
table (including restoring the exact wrong table this project once shipped),
|
|
table (including restoring the exact wrong table this project once shipped),
|
|
|
the `[BP+off]` rule, the behavioural bugs, the emitter-name audit of
|
|
the `[BP+off]` rule, the behavioural bugs, the emitter-name audit of
|
|
|
`Compiler.mod`, the BP contract, the `.COM` layout checker, the image-layout
|
|
`Compiler.mod`, the BP contract, the `.COM` layout checker, the image-layout
|
|
|
helper and the three checks that read it, the 8086 lowering, the interpreter
|
|
helper and the three checks that read it, the 8086 lowering, the interpreter
|
|
|
itself, the `R` key, and — since `v-TP3-NONVACUITY-RDBYTE` — the four
|
|
itself, the `R` key, and — since `v-TP3-NONVACUITY-RDBYTE` — the four
|
|
|
-independent sites of the argument-order fix.
|
|
|
|
|
|
|
+independent sites of the argument-order fix. Since `v-TP3-BOOLREAD` there is
|
|
|
|
|
+also one whose checker is neither an execution nor a disassembly but the
|
|
|
|
|
+**compile matrix** itself: `IoCall`'s refusing arm for a boolean read is
|
|
|
|
|
+reverted to the accepting dispatch it replaced, and `run_compile_tests.sh`
|
|
|
|
|
+must come back red on `t38`'s `ERR 66` row. Nothing that runs programs could
|
|
|
|
|
+see that one — an `ERR` fixture is never executed, so the refusal has to be
|
|
|
|
|
+asserted where the refusal happens.
|
|
|
|
|
|
|
|
Those four replace a proof that could only be quoted. `t36_argclobber`'s
|
|
Those four replace a proof that could only be quoted. `t36_argclobber`'s
|
|
|
`.out` had been compiled and run against the compiler as it stood **before**
|
|
`.out` had been compiled and run against the compiler as it stood **before**
|
|
@@ -1097,9 +1106,10 @@ Details that are deliberate, not incidental:
|
|
|
prove the *path* exists (compile → poke → run → report → no file written),
|
|
prove the *path* exists (compile → poke → run → report → no file written),
|
|
|
which it does with eight assertions. The other 34 are covered by
|
|
which it does with eight assertions. The other 34 are covered by
|
|
|
`run_exec86.py`, which calls the same interpreter directly.
|
|
`run_exec86.py`, which calls the same interpreter directly.
|
|
|
-- **Every fixture that compiles is now also run.** 35 of 38 execute; the 3 that
|
|
|
|
|
- do not are `t14` and `t25` (`ENoLib`, by design) and `uierror` (a deliberate
|
|
|
|
|
- syntax error). The gap this replaces was nine fixtures that compiled and were
|
|
|
|
|
|
|
+- **Every fixture that compiles is now also run.** 35 of 39 execute; the 4 that
|
|
|
|
|
+ do not are `t14` and `t25` (`ENoLib`, by design), `t38` (a boolean read,
|
|
|
|
|
+ refused with TP3's error 66, by design) and `uierror` (a deliberate syntax
|
|
|
|
|
+ error). The gap this replaces was nine fixtures that compiled and were
|
|
|
*never executed* — `t08` const, `t09` if/then/else, `t10` while, `t11` for/to,
|
|
*never executed* — `t08` const, `t09` if/then/else, `t10` while, `t11` for/to,
|
|
|
`t12` repeat/until, `t13` procedure + value param, `t15` label + goto,
|
|
`t12` repeat/until, `t13` procedure + value param, `t15` label + goto,
|
|
|
`t27` five locals, `t28` the 70-parameter declaration — and all nine
|
|
`t27` five locals, `t28` the 70-parameter declaration — and all nine
|
|
@@ -1205,11 +1215,13 @@ Details that are deliberate, not incidental:
|
|
|
still said OK.
|
|
still said OK.
|
|
|
- **Comma-separated names are not supported.** `var i, c : integer;` is a
|
|
- **Comma-separated names are not supported.** `var i, c : integer;` is a
|
|
|
parse error. Pre-existing, unrelated to any of the above, and still open.
|
|
parse error. Pre-existing, unrelated to any of the above, and still open.
|
|
|
-- **`readln` of a `BOOLEAN` still stores a word into a one-byte variable.**
|
|
|
|
|
- This is bug 37's shape, unfixed: the BYTE half now has its own `rdbyte`
|
|
|
|
|
- entry, but a boolean read still dispatches to `rdbool`, which stores `CX`.
|
|
|
|
|
- TP3 refuses a boolean read with error 66 rather than implementing it, so the
|
|
|
|
|
- honest options are to refuse it too or to add the one-byte entry.
|
|
|
|
|
|
|
+- **`readln` of a `BOOLEAN` is refused, exactly as TP3 refuses it.** It used to
|
|
|
|
|
+ dispatch to `rdbool`, which stores a word (`CX`) into a one-byte variable —
|
|
|
|
|
+ bug 37's shape, unclaimed only because no fixture read a boolean. TPSRC8
|
|
|
|
|
+ `prderrtp` errors 66 ("I/O not allowed here") for the whole class, and the
|
|
|
|
|
+ original runtime has no `xrdbool` at all, so `IoCall` now does the same and
|
|
|
|
|
+ never emits a boolean read. `rdbool` stays a runtime entry that `rt_exec`
|
|
|
|
|
+ still probes directly; only the compiler stopped reaching it.
|
|
|
- **The program-header parameter loop is unguarded against non-advancing
|
|
- **The program-header parameter loop is unguarded against non-advancing
|
|
|
input.** `program p(1;)` would loop forever. The fix needs a `BOOLEAN` flag
|
|
input.** `program p(1;)` would loop forever. The fix needs a `BOOLEAN` flag
|
|
|
and **must not** use `EXIT`, which ICEs gm2 in pass 3 (see the pitfalls
|
|
and **must not** use `EXIT`, which ICEs gm2 in pass 3 (see the pitfalls
|
|
@@ -1761,6 +1773,31 @@ reason for existing.
|
|
|
just past the variable and require it to survive, and the fixture's `.out`
|
|
just past the variable and require it to survive, and the fixture's `.out`
|
|
|
is the same assertion at the level of a whole program.
|
|
is the same assertion at the level of a whole program.
|
|
|
|
|
|
|
|
|
|
+### Then a boolean read was refused the way TP3 refuses it
|
|
|
|
|
+
|
|
|
|
|
+38. **A `readln` of a `BOOLEAN` was accepted, and `rdbool` stored a *word*
|
|
|
|
|
+ into a one-byte variable.** The byte half of bug 37 got its own reader,
|
|
|
|
|
+ but a boolean read still went through the word-storing `rdbool`, so the
|
|
|
|
|
+ only thing between the compiler and the same overflow again was that no
|
|
|
|
|
+ fixture read a boolean.
|
|
|
|
|
+
|
|
|
|
|
+ TP3 refuses the whole class: TPSRC8 `prdlp2` ends at `prderrtp`, which
|
|
|
|
|
+ errors 66 (`B $42` is "I/O not allowed here"), and the load-to-type list
|
|
|
|
|
+ in TPSRC8's `prdnum` has `xrdreal`, `xrdchar`, `xrdint`, `xrdbyte` and
|
|
|
|
|
+ the rest but no `xrdbool` at all — a boolean read is not something the
|
|
|
|
|
+ original runtime can answer. So the fix is to do what TP3 does rather
|
|
|
|
|
+ than to invent the missing entry: `IoCall` now refuses a boolean argument
|
|
|
|
|
+ to `read`/`readln` with `EIoHere = 66`. The new `t38_readbool` fixture
|
|
|
|
|
+ pins error 66 at the character after the variable, and the matrix row was
|
|
|
|
|
+ red before the fix landed — the accepting compiler answered `OK 43 5`
|
|
|
|
|
+ (a word store plus the `readln` tail) instead of `ERR 66 659`.
|
|
|
|
|
+
|
|
|
|
|
+ The refusal happens after the argument is fully parsed, which is the same
|
|
|
|
|
+ point TP3's `varptr2` check stands: the atom parser's `Skip` has already
|
|
|
|
|
+ run, so the pinned position is the `)` that closes `readln (b)`.
|
|
|
|
|
+ `rdbool` stays in the runtime and `rt_exec` still probes it; the compiler
|
|
|
|
|
+ simply no longer reaches it.
|
|
|
|
|
+
|
|
|
## The bug family, stated once
|
|
## The bug family, stated once
|
|
|
|
|
|
|
|
Nine of the bugs recorded here are the *same* bug in different clothes: **loading the
|
|
Nine of the bugs recorded here are the *same* bug in different clothes: **loading the
|
|
@@ -1840,30 +1877,25 @@ independently-scanned inventory at all.
|
|
|
|
|
|
|
|
## Next steps
|
|
## Next steps
|
|
|
|
|
|
|
|
-1. **`readln` of a `BOOLEAN`** is bug 37's shape with the fix not yet written:
|
|
|
|
|
- `rdbool` stores a word (`CX`) into a one-byte variable. TP3 itself refuses a
|
|
|
|
|
- boolean read with error 66 rather than implementing it, so the choice is to
|
|
|
|
|
- refuse it the same way or to add the one-byte entry. Fixture first, so the
|
|
|
|
|
- bug is red before the fix.
|
|
|
|
|
-2. **String *variables*** — `s : string`, `s := 'hi'`, `writeln(s)`. The
|
|
|
|
|
|
|
+1. **String *variables*** — `s : string`, `s := 'hi'`, `writeln(s)`. The
|
|
|
encoding blocker is gone (`EmBpDisp`); what is left is a length word, an
|
|
encoding blocker is gone (`EmBpDisp`); what is left is a length word, an
|
|
|
assignment path, and a `WrStr` entry (TPSRC4 `xwrtstr`). `IoCall` currently
|
|
assignment path, and a `WrStr` entry (TPSRC4 `xwrtstr`). `IoCall` currently
|
|
|
refuses with `ENoLib`.
|
|
refuses with `ENoLib`.
|
|
|
-3. Nested procedures / recursion, `var` parameters (the `SEG:OFF` push from
|
|
|
|
|
|
|
+2. Nested procedures / recursion, `var` parameters (the `SEG:OFF` push from
|
|
|
RESUME-TP3.md §3.11), range/index checks (`TU_RANGE_CHECK`,
|
|
RESUME-TP3.md §3.11), range/index checks (`TU_RANGE_CHECK`,
|
|
|
`TU_INDEX_CHECK`), typed constants (RESUME-TP3.md §3.14), `array` at its
|
|
`TU_INDEX_CHECK`), typed constants (RESUME-TP3.md §3.14), `array` at its
|
|
|
point of use (`t14`), `case` with subrange labels.
|
|
point of use (`t14`), `case` with subrange labels.
|
|
|
-4. Make the 4 KiB code window an enforced limit rather than a documented one:
|
|
|
|
|
|
|
+3. Make the 4 KiB code window an enforced limit rather than a documented one:
|
|
|
report an error when `pc` reaches `dc`, instead of writing over the data.
|
|
report an error when `pc` reaches `dc`, instead of writing over the data.
|
|
|
-5. Both spellings of a multi-name declaration. `var i, c : integer;` is
|
|
|
|
|
|
|
+4. Both spellings of a multi-name declaration. `var i, c : integer;` is
|
|
|
error 1 at the comma and needs two `var` lines; `procedure f (a : integer;
|
|
error 1 at the comma and needs two `var` lines; `procedure f (a : integer;
|
|
|
b : integer)` is error 1 at the semicolon and needs a comma. Neither is
|
|
b : integer)` is error 1 at the semicolon and needs a comma. Neither is
|
|
|
wrong Pascal, so a program that compiles under one compiler may not under
|
|
wrong Pascal, so a program that compiles under one compiler may not under
|
|
|
another. A parameter may also not shadow a global (`DupTest` rejects any
|
|
another. A parameter may also not shadow a global (`DupTest` rejects any
|
|
|
name `Search` finds at any level), which Pascal allows.
|
|
name `Search` finds at any level), which Pascal allows.
|
|
|
-6. Harden the program-header parameter loop against non-advancing input
|
|
|
|
|
|
|
+5. Harden the program-header parameter loop against non-advancing input
|
|
|
(`program p(1;)`) with a `BOOLEAN` flag — **not** `EXIT`, which ICEs gm2.
|
|
(`program p(1;)`) with a `BOOLEAN` flag — **not** `EXIT`, which ICEs gm2.
|
|
|
-7. FreeDOS (`freedos.qcow2`, FD14-LiveCD) is still untried. Now that `R` runs
|
|
|
|
|
|
|
+6. FreeDOS (`freedos.qcow2`, FD14-LiveCD) is still untried. Now that `R` runs
|
|
|
the image in-process, a real DOS is no longer needed for any claim above —
|
|
the image in-process, a real DOS is no longer needed for any claim above —
|
|
|
but it is still the only way to get a third opinion on the `INT 21h` shim,
|
|
but it is still the only way to get a third opinion on the `INT 21h` shim,
|
|
|
and `Exec86` deliberately implements only the three functions the runtime
|
|
and `Exec86` deliberately implements only the three functions the runtime
|