1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-09 01:16:12 +00:00
nescript/src
Claude f49dbce686
Fix three compiler bugs exposed by array-using examples
Landing bug A from the previous writeup plus two adjacent bugs
that the fix exposed. All three miscompile anything that uses a
u8[N] global with a literal initializer.

1. Array-literal globals are now actually initialized.
   `lower_program` only expanded `Expr::StructLiteral` into per-
   field synthetic globals — `Expr::ArrayLiteral` hit
   `eval_const`, returned `None`, and the array boot-cleared to
   zero. `IrGlobal` now carries an `init_array: Vec<u8>`
   populated by lowering, and the IR codegen startup loop emits
   one `LDA #byte; STA base+i` pair per element.

2. Local variables no longer overlap array globals.
   `IrCodeGen::new` advanced `local_ram_next` past
   `max_global_base + 1` — for an array at `$0300-$0303` it
   placed the first handler-local at `$0301`, inside the array.
   The frame handler's stores through the local then corrupted
   the array mid-frame. The allocator now walks the analyzer's
   `VarAllocation` list and advances past `address + size` for
   every RAM global, not just the base.

3. Peephole `remove_redundant_loads` honors indexed LDAs.
   The pass tracked `LDA Immediate/ZeroPage/Absolute` but let
   `LDA AbsoluteX/AbsoluteY/ZeroPageX/IndirectX/IndirectY` fall
   through the match, leaving the A-equivalence tracker
   unchanged. A later `LDA #v` that happened to match a stale
   entry from BEFORE the indexed load would then be dropped as
   "already in A" — a silent miscompile that turned every
   `draw Sprite at: (arr[i], arr[j])` pattern into garbage
   (the second array index would be computed from `arr[i]`'s
   value, reading way out of bounds). Indexed LDAs now clear
   the tracker.

Regression tests:
- `src/codegen/peephole.rs`: a synthetic
  `LDA #0; TAX; LDA AbsX(arr1); STA temp; LDA #0; TAX;
   LDA AbsX(arr2); ...` sequence asserts both `LDA #0`s survive.
- `src/ir/tests.rs`: verifies `var xs: u8[4] = [1,2,3,4]`
  populates `IrGlobal::init_array` with `[1,2,3,4]`.
- `tests/integration_test.rs`: two IR-codegen tests — one checks
  the startup instructions contain `LDA #v; STA base+i` for
  every element, the other compiles a handler-local var
  alongside an array global and asserts no post-init stores
  land inside the array.

Smoke test impact (14/14 still passing, now more visible):
- arrays_and_functions:  56 -> 104 nonBlack, now animated
- loop_break_continue:   52 -> 208 (player + 3 hazards visible)
- structs_enums_for:     52 -> 104 (player + enemy visible)

Existing examples unchanged; no remaining work for bug B
(static OAM slot allocation in loops) — that's the next PR.

https://claude.ai/code/session_014Z5y3Q9krLcAxYpZQJhZ5V
2026-04-12 19:32:22 +00:00
..
analyzer Analyzer: E0203 for bare return in typed function 2026-04-12 18:01:07 +00:00
asm Add jsnes emulator harness and fix four codegen bugs it surfaced 2026-04-12 18:46:58 +00:00
assets Language: struct types 2026-04-12 16:18:05 +00:00
codegen Fix three compiler bugs exposed by array-using examples 2026-04-12 19:32:22 +00:00
debug
errors Analyzer: E0301 error on RAM exhaustion 2026-04-12 11:05:13 +00:00
ir Fix three compiler bugs exposed by array-using examples 2026-04-12 19:32:22 +00:00
lexer Inline asm: {var} placeholder substitution 2026-04-12 17:30:21 +00:00
linker Codegen: on_scanline per-state dispatch + NMI reload 2026-04-12 16:29:15 +00:00
optimizer Language: poke() and peek() hardware intrinsics 2026-04-12 17:40:34 +00:00
parser Language: raw asm { ... } blocks 2026-04-12 17:34:17 +00:00
rom
runtime Add Player 2 controller support 2026-04-12 10:05:12 +00:00
lib.rs
main.rs CLI: --call-graph flag 2026-04-12 17:46:13 +00:00