From c487511b3aaafac30df11f567eee26336ad10b80 Mon Sep 17 00:00:00 2001 From: Daniel Covington Date: Wed, 11 Nov 2026 07:59:01 -0500 Subject: [PATCH] Fix method-label reset, hello fixture state, and harness quoting. em_reset cleared only one row of em_meth_label: ldx #$FF / dex / bpl exits after the first store because $FE is negative. Method label ids from the count pass survived into the emitting pass after fl_init had freed every flow label, so a later fl_alloc could hand the same id to another label. The loop now clears all 256 rows, and labels are stored as id + 1 so 0 means unassigned. hello-test.s never cleared em_on. Since 5489ae6 added emitter BSS, em_on lands on RAM that VICE's power-on pattern leaves non-zero, so the statement emitter ran without print vectors and reported E227 at end program. The fixture now clears em_on before parse_file, as every emitter caller must. harness.tests.ps1 embedded quotes in arguments for the call operator, which PowerShell 7.3+ escapes into the path; it now passes plain arguments and runs under both Windows PowerShell 5.1 and PowerShell 7. --- newLang/planning/claims/E04-S08.md | 44 +++++++++++++++------- newLang/src/compiler/emit.s | 24 ++++++++---- newLang/tests/compiler/hello-test.s | 2 + newLang/tests/regression/harness.tests.ps1 | 8 ++-- 4 files changed, 54 insertions(+), 24 deletions(-) diff --git a/newLang/planning/claims/E04-S08.md b/newLang/planning/claims/E04-S08.md index a0ac790..b230805 100644 --- a/newLang/planning/claims/E04-S08.md +++ b/newLang/planning/claims/E04-S08.md @@ -108,16 +108,34 @@ supply frame entry points keep their previous code shape (D156). `planning/epics-and-stories.md`, `planning/claims/E04-S08.md`. - Remaining risks: interface arguments and four-byte interface returns are not emitted (E06-S07); arguments are limited to `EM_ARG_MAX` (8) staged values; - the prologue's failure path returns without a diagnostic, so a refused frame - is currently silent; and the pre-existing `calls` suite failure described - below is unrelated but still red. - -## Known unrelated failure - -`calls` fails on a **fresh** build with `EM_ERR_LABEL` (7) and -`FL_ERR_STATE` (3), `cg_len = 0x31`, while the same test passes when the build -directory's older object files are reused. The identical signature reproduces -on pristine `8a2d8ce` (verified by `git stash` + fresh `build/calls-test`), so -it predates this story and points at emitter label state that is not -deterministically initialized. It is not caused by E04-S08 and needs its own -fix (initialize or validate the per-row method-label table before pass 2). + and the prologue's failure path returns without a diagnostic, so a refused + frame is currently silent. + +## Related label fix + +A fresh-build failure with `EM_ERR_LABEL` (7) and `FL_ERR_STATE` (3) reproduced +on pristine `8a2d8ce` and was independent of this story. Its cause was the +method-label table's `$FF` sentinel: any row whose byte was not `$FF` was taken +as an already-assigned label 0, so a later method redefined it at a different +offset. `em_reset` now clears the table to zero, `em_method_label` stores each +label as `id + 1`, and a lookup outside 1..`FL_LABELS` allocates again. Fresh +`calls` and `args` runs now pass. + +The clear loop itself was also wrong: `ldx #$FF` / `dex` / `bpl` stops after +one row because `$FE` is negative, so ids from the count pass survived into the +emitting pass after `fl_init` had freed every flow label. The loop now counts +X up from 0 until it wraps, clearing all 256 rows on every `em_reset`. + +## Hello fixture regression + +`hello` failed at HEAD with `E227 CANNOT EMIT THIS CODE YET` at `end program` +(verified passing at `221e0c5`, failing at `5489ae6`). `hello-test.s` never set +`em_on`, and the new BSS variables moved it onto RAM that VICE's power-on +pattern leaves non-zero, so the statement emitter ran without print vectors. +The fixture now clears `em_on` before `parse_file`, as the emitter contract +requires of every caller. + +The `parser` suite's verification passes, but its baseline hashes in +`tests/regression/baseline.json` predate `221e0c5` and `5489ae6`; pristine +HEAD's `parser-test.prg` already differs, so that entry needs a reviewed +refresh. diff --git a/newLang/src/compiler/emit.s b/newLang/src/compiler/emit.s index 171d615..fb1dcc4 100644 --- a/newLang/src/compiler/emit.s +++ b/newLang/src/compiler/emit.s @@ -98,10 +98,11 @@ em_reset: sta em_n_routines lda #$FF sta em_loc_next - ldx #$FF + lda #$00 ; clear all 256 rows; X wraps $00 -> $00 + tax @meth: sta em_meth_label,x - dex - bpl @meth + inx + bne @meth lda #$02 sta em_par_next rts @@ -685,17 +686,24 @@ em_method_label: sta em_nid tax lda em_meth_label,x - cmp #$FF - bne @have - lda em_nid + beq @alloc + cmp #FL_LABELS + 1 + bcs @alloc + sec + sbc #$01 + tax + clc + rts +@alloc: lda em_nid jsr fl_alloc bcs @bad ldy em_nid sta em_meth_label,y tax + lda em_meth_label,y clc - rts -@have: tax + adc #$01 + sta em_meth_label,y clc rts @bad: lda #EM_ERR_LABEL diff --git a/newLang/tests/compiler/hello-test.s b/newLang/tests/compiler/hello-test.s index 1e5aa01..0f033e2 100644 --- a/newLang/tests/compiler/hello-test.s +++ b/newLang/tests/compiler/hello-test.s @@ -27,6 +27,7 @@ .import out_byte, out_bytes, out_finish, out_abort .import out_load, out_entry, out_start, out_err .import gen_stub +.import em_on ; A conditional branch to a far error path: near branch over an absolute JMP. .macro ON_CARRY target @@ -104,6 +105,7 @@ test_entry: jsr diag_init lda #$00 ; ERR files only; keep the screen quiet sta diag_screen + sta em_on ; captured-print proof: no statement emitter jsr parse_file jsr diag_finish sta diag_count diff --git a/newLang/tests/regression/harness.tests.ps1 b/newLang/tests/regression/harness.tests.ps1 index f103e89..a56b1e7 100644 --- a/newLang/tests/regression/harness.tests.ps1 +++ b/newLang/tests/regression/harness.tests.ps1 @@ -66,9 +66,11 @@ exit 0 '@, [Text.UTF8Encoding]::new($false)) function Invoke-Harness([string[]]$Extra) { - $arguments = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", ('"' + $harness + '"'), - "-Manifest", ('"' + $manifest + '"'), "-BuildRoot", ('"' + $buildRoot + '"'), - "-Baseline", ('"' + $baseline + '"'), "-Results", ('"' + $results + '"')) + $Extra + # The call operator quotes arguments that contain spaces itself. Embedding + # quotes here breaks PowerShell 7.3+, which escapes them into the path. + $arguments = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", $harness, + "-Manifest", $manifest, "-BuildRoot", $buildRoot, + "-Baseline", $baseline, "-Results", $results) + $Extra $output = & (Get-Command powershell).Source @arguments 2>&1 | Out-String return @{ Output = $output; Code = $LASTEXITCODE } }