v-TP3-DEAD-FIXTURES — Summary ============================= Tag: v-TP3-DEAD-FIXTURES Commit: 30f9fae What changed ------------ - The 9 fixtures that compiled but never executed (t08_const, t09_if, t10_while, t11_for, t12_repeat, t13_proc, t15_label, t27_localvar, t28_farparam) were rewritten to print observable results. Their `.out` files were hand-derived from the Pascal semantics, never blessed from machine output. Each now has a behavioural counterpart. Bugs found and fixed -------------------- 1. `ParseMul` used the same operator code as `+` (both 1). `*` therefore emitted ADD; constant folding hid it for constant operands. Now named `OpAdd/OpSub/OpMul` constants, so levels cannot collide. (t08 and a variable-multiply path) 2. `ParseCmp` had `>` and `>=` swapped: `9DH` = SETGE for `>` and `9FH` = SETG for `>=`. Boundary cases failed. Fixed, and each CASE arm now carries its mnemonic beside the hex. 3. `REPEAT…UNTIL` used `JNZ` to loop back (condition TRUE), so it behaved like `WHILE`. Now uses `JZ` → loop back while condition is FALSE. Verified by i:=0; repeat i:=i+1 until i>5 printing 6 (not 1). 4. Sibling procedures shared the same parameter namespace. `HideLocals` relabels a procedure's own symbols to `0FFFFH` on close (relabelled, not popped, because `symtab[old].resvar` holds an index). This prevents cross- procedure collisions and fixes the "two procedures both declare `a`" case. Scope decisions and findings ---------------------------- - Parameter lists require commas; variable lists in this compiler require separate `var` declarations. `;` between params is rejected. - A parameter may not shadow a global (DupTest rejects any name found). - Call arity capped at 16 arguments; exceeding raises `ECompOvf` = 99. - `EmJcc`/`EmSetcc` emit 386-only opcodes (`0F 8x`/`0F 9x`) on a 8086 target; invisible to qemu-i386 (which defaults to post-386). Worth trying `-cpu 8086` as a future check. Tests / harness --------------- - `run_all.sh`: 12 checks ALL PASS. - `nonvacuity.sh`: 39 ok / 0 failed (includes 5 new cases that mutate each of the four bugs back and require `run_com_exec.py` to go red on the exact fixture that pins them). - Compile matrix: 33 passed / 0 failed. - Execution: 30 passed / 0 failed. - .COM linker: 30 checked / 0 failed. - Runtime entries: 36 passed / 0 failed. - `t28_farparam` references p63/p70 to exercise disp16 encoding but does not assert their runtime values (they are unpassed due to the 16-arg cap). *(Later `v-TP3-ARGORDER` milestone: the frame now follows TP3's "last declared parameter at BP+4" rule, so the same two offsets, +128 and +142, are read through `p8` and `p1`; the encoding this row is about is unchanged.)* Tag placement ------------- `v-TP3-DEAD-FIXTURES` points to 30f9fae (the work commit). An additional tag `v-TP3-COM-IMAGE` was placed at 7dada57 (where Linker/ComTest first appeared), because the documentation for that milestone was written later; the reasoning is in the tag message. HEAD is 30f9fae, 17 commits ahead of `origin/master`, nothing pushed. What remains (next steps) ------------------------- 1. 8086 branch/compare lowering: rewrite conditional branches to TP3's `excond` + `JZ rel8` idiom (or try `qemu -cpu 8086` first to see the class turn red under an 8086 CPU model). Wide golden blast radius. 2. CmdRun (`R` key): in-process 8086 interpreter, cross-validated against qemu on the same images. 3. String variables (`s : string`, assignment, `writeln(s)`). 4. Nested procedures/recursion, `var` parameters (`SEG:OFF`), range/index checks, typed constants, array at use (`t14`), case subrange labels. 5. `readln` of a `BYTE` (separate `xrdbyte` / `TU_RdByte`). 6. Enforce the 4 KiB code window (error if `pc` reaches data start). 7. Harmonise multi-name declarations (both `,` and `;` spellings). 8. Harden program-header parameter loop against non-advancing input. 9. FreeDOS as a third opinion (untried).