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

Implement codegen for state dispatch, functions, arrays, math, scroll

State machine dispatch:
- Assign each state a numeric index, store in ZP $03
- Main loop dispatch table: CMP + BNE + JMP trampoline pattern
  (avoids branch range limits for large programs)
- on_enter/on_exit handlers generated as JSR targets
- Transition statement writes state index + JSR enter/exit handlers

Function calls:
- Function bodies emitted as labeled subroutines with RTS
- Statement::Call generates parameter passing via ZP + JSR
- Statement::Return generates RTS (with value in A if present)
- Parameter slots at ZP $04-$07

Break/continue:
- Loop stack tracks continue/break label pairs
- Break generates JMP to break_label
- Continue generates JMP to continue_label
- While and Loop push/pop the stack

Array indexing:
- LValue::ArrayIndex generates TAX + STA absolute,X
- Expr::ArrayIndex generates TAX + LDA absolute,X / ZP,X
- Compound array assignments (+=, -=, &=, |=, ^=) load-modify-store

Scroll:
- scroll(x, y) writes to PPU $2005 twice (X then Y)

Math:
- Multiply generates JSR __multiply (shift-and-add routine)
- Divide generates JSR __divide (restoring division)
- Modulo loads remainder from $03 after divide
- ShiftLeft generates ASL A, ShiftRight generates LSR A
- Math routines wired into linker

Error validations:
- E0203 for assignment to const variables
- Break/continue outside loop detection (in_loop tracking)

233 tests (8 new codegen + 2 analyzer + 2 integration), all passing.

https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
Claude 2026-04-12 02:04:49 +00:00
parent 3b1a03981b
commit 40632f192c
No known key found for this signature in database
6 changed files with 466 additions and 31 deletions

View file

@ -378,6 +378,23 @@ fn compile_with_mapper(source: &str) -> Vec<u8> {
linker.link(&instructions)
}
#[test]
fn program_with_arrays_and_math() {
let source = r#"
game "ArrayMath" { mapper: NROM }
var arr: u8[4] = [10, 20, 30, 40]
var idx: u8 = 0
var result: u8 = 0
on frame {
result = arr[idx] * 2
idx += 1
}
start Main
"#;
let rom_data = compile(source);
rom::validate_ines(&rom_data).expect("should be valid iNES");
}
#[test]
fn program_with_mmc1() {
let source = r#"