1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 08:55:38 +00:00

IR codegen: state dispatch, multi-OAM, and transition support

State machine dispatch:
- IrProgram now stores states (Vec<String>) and start_state
- Lowering captures state metadata before walking the AST
- IR codegen generates a main loop with vblank wait and CMP+BNE+JMP
  dispatch table, matching the AST codegen's layout
- Each frame handler ends with JMP __ir_main_loop
- current_state initialized to the start state's index at boot

Multi-OAM support:
- next_oam_slot counter, reset at the start of each _frame function
- Sequential allocation of 4-byte OAM entries at $0200 + slot*4
- Silently drops draws beyond slot 63 (OAM full)

Transition codegen:
- IrOp::Transition now looks up the target state's index from
  state_indices, writes it to ZP $03, and JMPs back to main loop
- Previously this was a no-op placeholder

Shared constants:
- ZP_FRAME_FLAG ($00) and ZP_CURRENT_STATE ($03) match AST codegen

Tests: 271 total (5 new IR codegen tests + 2 new integration tests)
All 7 examples compile through --use-ir, including multi-state games
and programs with transitions and functions.

https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
Claude 2026-04-12 10:33:58 +00:00
parent 7e94cf37e3
commit 5660a8b7c3
No known key found for this signature in database
5 changed files with 239 additions and 16 deletions

View file

@ -548,3 +548,47 @@ fn ir_codegen_full_pipeline() {
let rom_data = compile_with_ir_codegen(source);
rom::validate_ines(&rom_data).expect("should be valid iNES");
}
#[test]
fn ir_codegen_multi_state_dispatch() {
// Exercise the IR main-loop dispatch with multiple states and a
// transition.
let source = r#"
game "IR States" { mapper: NROM }
var timer: u8 = 0
state Title {
on frame {
if button.start { transition Play }
}
}
state Play {
on frame {
timer += 1
if timer > 60 { transition Title }
}
}
start Title
"#;
let rom_data = compile_with_ir_codegen(source);
let info = rom::validate_ines(&rom_data).expect("should be valid iNES");
assert_eq!(info.mapper, 0);
}
#[test]
fn ir_codegen_multi_oam() {
// Draw multiple sprites and verify OAM slots are allocated sequentially.
let source = r#"
game "IR MultiOAM" { mapper: NROM }
var a: u8 = 10
var b: u8 = 20
var c: u8 = 30
on frame {
draw One at: (a, a)
draw Two at: (b, b)
draw Three at: (c, c)
}
start Main
"#;
let rom_data = compile_with_ir_codegen(source);
rom::validate_ines(&rom_data).expect("should be valid iNES");
}