mirror of
https://github.com/imjasonh/nescript
synced 2026-07-10 01:37:45 +00:00
M4+M5: Optimizer passes, type casting, bank switching, math runtime
Milestone 4 — Optimization & Polish: - Strength reduction: multiply by power-of-2 → shift left - Zero-page promotion analysis: rank variables by access frequency - `as` type casting expression in parser/AST/analyzer - `scroll(x, y)` statement - `--asm-dump` flag for viewing generated assembly - Extended optimizer tests (strength reduction, frequency analysis) Milestone 5 — Bank Switching & Release: - Mapper support: MMC1 (1), UxROM (2), MMC3 (4) in parser and ROM builder - Bank declarations: `bank Name: prg` / `bank Name: chr` - Linker::with_mapper for mapper-aware ROM generation - Software multiply (8x8→16, shift-and-add algorithm) - Software divide (8÷8→8, restoring division algorithm) - ROM tests for mapper encoding round-trip - Integration test for MMC1 compilation 210 tests total (18 new), all pre-commit checks pass. https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
This commit is contained in:
parent
058f7a87b6
commit
5434dda114
15 changed files with 865 additions and 13 deletions
|
|
@ -289,6 +289,26 @@ fn error_test_recursion_detected() {
|
|||
);
|
||||
}
|
||||
|
||||
// ── M4 Tests ──
|
||||
|
||||
#[test]
|
||||
fn program_with_scroll_and_cast() {
|
||||
let source = r#"
|
||||
game "M4 Test" { mapper: NROM }
|
||||
var px: u8 = 0
|
||||
var py: u8 = 0
|
||||
var wide: u16 = 0
|
||||
on frame {
|
||||
if button.right { px += 1 }
|
||||
wide = px as u16
|
||||
scroll(px, py)
|
||||
}
|
||||
start Main
|
||||
"#;
|
||||
let rom_data = compile(source);
|
||||
rom::validate_ines(&rom_data).expect("should be valid iNES");
|
||||
}
|
||||
|
||||
// ── M3 Tests ──
|
||||
|
||||
#[test]
|
||||
|
|
@ -329,3 +349,46 @@ fn program_with_sprites_and_palette() {
|
|||
let rom_data = compile(source);
|
||||
rom::validate_ines(&rom_data).expect("should be valid iNES");
|
||||
}
|
||||
|
||||
// ── M5 Tests ──
|
||||
|
||||
/// Compile a source string using the mapper-aware linker.
|
||||
fn compile_with_mapper(source: &str) -> Vec<u8> {
|
||||
let (program, diags) = nescript::parser::parse(source);
|
||||
assert!(
|
||||
diags.is_empty(),
|
||||
"unexpected parse errors: {diags:?}\nsource:\n{source}"
|
||||
);
|
||||
let program = program.expect("parse should succeed");
|
||||
|
||||
let analysis = analyzer::analyze(&program);
|
||||
assert!(
|
||||
analysis.diagnostics.iter().all(|d| !d.is_error()),
|
||||
"unexpected analysis errors: {:?}",
|
||||
analysis.diagnostics
|
||||
);
|
||||
|
||||
let mut ir_program = ir::lower(&program, &analysis);
|
||||
nescript::optimizer::optimize(&mut ir_program);
|
||||
|
||||
let codegen = nescript::codegen::CodeGen::new(&analysis.var_allocations, &program.constants);
|
||||
let instructions = codegen.generate(&program);
|
||||
|
||||
let linker = Linker::with_mapper(program.game.mirroring, program.game.mapper);
|
||||
linker.link(&instructions)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn program_with_mmc1() {
|
||||
let source = r#"
|
||||
game "MMC1 Game" { mapper: MMC1 }
|
||||
var px: u8 = 128
|
||||
on frame {
|
||||
if button.right { px += 2 }
|
||||
}
|
||||
start Main
|
||||
"#;
|
||||
let rom_data = compile_with_mapper(source);
|
||||
let info = rom::validate_ines(&rom_data).expect("should be valid iNES");
|
||||
assert_eq!(info.mapper, 1, "should be MMC1 (mapper 1)");
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue