Implement NEScript compiler Milestone 1 ("Hello Sprite")
Complete implementation of the NEScript compiler pipeline for M1:
- Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators
- Parser: recursive descent with Pratt expression parsing (M1 subset)
- Analyzer: symbol resolution, type checking, memory allocation
- 6502 Assembler: full opcode encoding table (~150 valid combinations)
- Code Generator: AST → 6502 instructions (direct, no IR for M1)
- Runtime: NES hardware init, NMI handler, controller read, OAM DMA
- Linker: NROM layout, vector table, palette loading, CHR data
- ROM Builder: iNES header generation, PRG/CHR padding
- CLI: `build` and `check` subcommands via clap
143 tests across all modules:
- 22 lexer tests (literals, keywords, operators, error recovery)
- 18 parser tests (expressions, statements, game structure, errors)
- 7 analyzer tests (symbol resolution, memory allocation, transitions)
- 30 assembler tests (every addressing mode, label resolution)
- 7 codegen tests (var init, arithmetic, buttons, draw, comparisons)
- 11 runtime tests (init sequence, NMI handler, controller read)
- 10 ROM builder tests (iNES format, mirroring, banking, validation)
- 5 linker tests (vector table, CHR data, palette loading)
- 7 integration tests (end-to-end compilation, error detection)
CI: GitHub Actions for check, fmt, clippy, test
Pre-commit: script for local fmt + clippy + test validation
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
|
|
|
use crate::lexer::Span;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct Program {
|
|
|
|
|
pub game: GameDecl,
|
|
|
|
|
pub globals: Vec<VarDecl>,
|
|
|
|
|
pub constants: Vec<ConstDecl>,
|
|
|
|
|
pub functions: Vec<FunDecl>,
|
|
|
|
|
pub states: Vec<StateDecl>,
|
2026-04-12 00:09:47 +00:00
|
|
|
pub sprites: Vec<SpriteDecl>,
|
|
|
|
|
pub palettes: Vec<PaletteDecl>,
|
|
|
|
|
pub backgrounds: Vec<BackgroundDecl>,
|
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
2026-04-12 00:22:11 +00:00
|
|
|
pub banks: Vec<BankDecl>,
|
Implement NEScript compiler Milestone 1 ("Hello Sprite")
Complete implementation of the NEScript compiler pipeline for M1:
- Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators
- Parser: recursive descent with Pratt expression parsing (M1 subset)
- Analyzer: symbol resolution, type checking, memory allocation
- 6502 Assembler: full opcode encoding table (~150 valid combinations)
- Code Generator: AST → 6502 instructions (direct, no IR for M1)
- Runtime: NES hardware init, NMI handler, controller read, OAM DMA
- Linker: NROM layout, vector table, palette loading, CHR data
- ROM Builder: iNES header generation, PRG/CHR padding
- CLI: `build` and `check` subcommands via clap
143 tests across all modules:
- 22 lexer tests (literals, keywords, operators, error recovery)
- 18 parser tests (expressions, statements, game structure, errors)
- 7 analyzer tests (symbol resolution, memory allocation, transitions)
- 30 assembler tests (every addressing mode, label resolution)
- 7 codegen tests (var init, arithmetic, buttons, draw, comparisons)
- 11 runtime tests (init sequence, NMI handler, controller read)
- 10 ROM builder tests (iNES format, mirroring, banking, validation)
- 5 linker tests (vector table, CHR data, palette loading)
- 7 integration tests (end-to-end compilation, error detection)
CI: GitHub Actions for check, fmt, clippy, test
Pre-commit: script for local fmt + clippy + test validation
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
|
|
|
pub start_state: String,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-12 00:09:47 +00:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct SpriteDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub chr_source: AssetSource,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct PaletteDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub colors: Vec<u8>,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct BackgroundDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub chr_source: AssetSource,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub enum AssetSource {
|
|
|
|
|
Chr(String),
|
|
|
|
|
Binary(String),
|
|
|
|
|
Inline(Vec<u8>),
|
|
|
|
|
}
|
|
|
|
|
|
Implement NEScript compiler Milestone 1 ("Hello Sprite")
Complete implementation of the NEScript compiler pipeline for M1:
- Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators
- Parser: recursive descent with Pratt expression parsing (M1 subset)
- Analyzer: symbol resolution, type checking, memory allocation
- 6502 Assembler: full opcode encoding table (~150 valid combinations)
- Code Generator: AST → 6502 instructions (direct, no IR for M1)
- Runtime: NES hardware init, NMI handler, controller read, OAM DMA
- Linker: NROM layout, vector table, palette loading, CHR data
- ROM Builder: iNES header generation, PRG/CHR padding
- CLI: `build` and `check` subcommands via clap
143 tests across all modules:
- 22 lexer tests (literals, keywords, operators, error recovery)
- 18 parser tests (expressions, statements, game structure, errors)
- 7 analyzer tests (symbol resolution, memory allocation, transitions)
- 30 assembler tests (every addressing mode, label resolution)
- 7 codegen tests (var init, arithmetic, buttons, draw, comparisons)
- 11 runtime tests (init sequence, NMI handler, controller read)
- 10 ROM builder tests (iNES format, mirroring, banking, validation)
- 5 linker tests (vector table, CHR data, palette loading)
- 7 integration tests (end-to-end compilation, error detection)
CI: GitHub Actions for check, fmt, clippy, test
Pre-commit: script for local fmt + clippy + test validation
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct GameDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub mapper: Mapper,
|
|
|
|
|
pub mirroring: Mirroring,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum Mapper {
|
|
|
|
|
NROM,
|
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
2026-04-12 00:22:11 +00:00
|
|
|
MMC1,
|
|
|
|
|
UxROM,
|
|
|
|
|
MMC3,
|
Implement NEScript compiler Milestone 1 ("Hello Sprite")
Complete implementation of the NEScript compiler pipeline for M1:
- Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators
- Parser: recursive descent with Pratt expression parsing (M1 subset)
- Analyzer: symbol resolution, type checking, memory allocation
- 6502 Assembler: full opcode encoding table (~150 valid combinations)
- Code Generator: AST → 6502 instructions (direct, no IR for M1)
- Runtime: NES hardware init, NMI handler, controller read, OAM DMA
- Linker: NROM layout, vector table, palette loading, CHR data
- ROM Builder: iNES header generation, PRG/CHR padding
- CLI: `build` and `check` subcommands via clap
143 tests across all modules:
- 22 lexer tests (literals, keywords, operators, error recovery)
- 18 parser tests (expressions, statements, game structure, errors)
- 7 analyzer tests (symbol resolution, memory allocation, transitions)
- 30 assembler tests (every addressing mode, label resolution)
- 7 codegen tests (var init, arithmetic, buttons, draw, comparisons)
- 11 runtime tests (init sequence, NMI handler, controller read)
- 10 ROM builder tests (iNES format, mirroring, banking, validation)
- 5 linker tests (vector table, CHR data, palette loading)
- 7 integration tests (end-to-end compilation, error detection)
CI: GitHub Actions for check, fmt, clippy, test
Pre-commit: script for local fmt + clippy + test validation
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum Mirroring {
|
|
|
|
|
Horizontal,
|
|
|
|
|
Vertical,
|
|
|
|
|
}
|
|
|
|
|
|
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
2026-04-12 00:22:11 +00:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct BankDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub bank_type: BankType,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum BankType {
|
|
|
|
|
Prg,
|
|
|
|
|
Chr,
|
|
|
|
|
}
|
|
|
|
|
|
Implement NEScript compiler Milestone 1 ("Hello Sprite")
Complete implementation of the NEScript compiler pipeline for M1:
- Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators
- Parser: recursive descent with Pratt expression parsing (M1 subset)
- Analyzer: symbol resolution, type checking, memory allocation
- 6502 Assembler: full opcode encoding table (~150 valid combinations)
- Code Generator: AST → 6502 instructions (direct, no IR for M1)
- Runtime: NES hardware init, NMI handler, controller read, OAM DMA
- Linker: NROM layout, vector table, palette loading, CHR data
- ROM Builder: iNES header generation, PRG/CHR padding
- CLI: `build` and `check` subcommands via clap
143 tests across all modules:
- 22 lexer tests (literals, keywords, operators, error recovery)
- 18 parser tests (expressions, statements, game structure, errors)
- 7 analyzer tests (symbol resolution, memory allocation, transitions)
- 30 assembler tests (every addressing mode, label resolution)
- 7 codegen tests (var init, arithmetic, buttons, draw, comparisons)
- 11 runtime tests (init sequence, NMI handler, controller read)
- 10 ROM builder tests (iNES format, mirroring, banking, validation)
- 5 linker tests (vector table, CHR data, palette loading)
- 7 integration tests (end-to-end compilation, error detection)
CI: GitHub Actions for check, fmt, clippy, test
Pre-commit: script for local fmt + clippy + test validation
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct StateDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub locals: Vec<VarDecl>,
|
|
|
|
|
pub on_enter: Option<Block>,
|
|
|
|
|
pub on_exit: Option<Block>,
|
|
|
|
|
pub on_frame: Option<Block>,
|
|
|
|
|
pub on_scanline: Vec<(u8, Block)>,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct FunDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub params: Vec<Param>,
|
|
|
|
|
pub return_type: Option<NesType>,
|
|
|
|
|
pub body: Block,
|
|
|
|
|
pub is_inline: bool,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct Param {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub param_type: NesType,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct VarDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub var_type: NesType,
|
|
|
|
|
pub init: Option<Expr>,
|
|
|
|
|
pub placement: Placement,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct ConstDecl {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub const_type: NesType,
|
|
|
|
|
pub value: Expr,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum Placement {
|
|
|
|
|
Fast,
|
|
|
|
|
Slow,
|
|
|
|
|
Auto,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
|
|
|
pub enum NesType {
|
|
|
|
|
U8,
|
|
|
|
|
I8,
|
|
|
|
|
U16,
|
|
|
|
|
Bool,
|
|
|
|
|
Array(Box<NesType>, u16),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl std::fmt::Display for NesType {
|
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
|
match self {
|
|
|
|
|
Self::U8 => write!(f, "u8"),
|
|
|
|
|
Self::I8 => write!(f, "i8"),
|
|
|
|
|
Self::U16 => write!(f, "u16"),
|
|
|
|
|
Self::Bool => write!(f, "bool"),
|
|
|
|
|
Self::Array(t, n) => write!(f, "{t}[{n}]"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct Block {
|
|
|
|
|
pub statements: Vec<Statement>,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub enum Expr {
|
|
|
|
|
IntLiteral(u16, Span),
|
|
|
|
|
BoolLiteral(bool, Span),
|
|
|
|
|
Ident(String, Span),
|
|
|
|
|
ArrayIndex(String, Box<Expr>, Span),
|
|
|
|
|
BinaryOp(Box<Expr>, BinOp, Box<Expr>, Span),
|
|
|
|
|
UnaryOp(UnaryOp, Box<Expr>, Span),
|
|
|
|
|
Call(String, Vec<Expr>, Span),
|
|
|
|
|
ButtonRead(Option<Player>, String, Span),
|
M2: Add function/array parsing, IR data structures and lowering
Parser extensions:
- Function declarations with params and return types (fun, inline fun)
- Array type syntax (u8[16]), array literal expressions ([1, 2, 3])
- fast/slow variable placement hints
- Functions stored in Program AST
IR module (new):
- IrProgram, IrFunction, IrBasicBlock, IrOp, IrTerminator types
- AST-to-IR lowering pass with:
- Expression lowering to virtual temps
- Control flow (if/else, while, loop) to basic blocks with branches
- Break/continue via loop context stack
- Short-circuit logical and/or
- Button reads, draw sprites, wait_frame
- Constants inlined as LoadImm
- State handlers lowered as separate IR functions
Tests: 6 new parser tests, 11 new IR lowering tests (153 total)
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 23:25:26 +00:00
|
|
|
ArrayLiteral(Vec<Expr>, Span),
|
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
2026-04-12 00:22:11 +00:00
|
|
|
Cast(Box<Expr>, NesType, Span),
|
Implement NEScript compiler Milestone 1 ("Hello Sprite")
Complete implementation of the NEScript compiler pipeline for M1:
- Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators
- Parser: recursive descent with Pratt expression parsing (M1 subset)
- Analyzer: symbol resolution, type checking, memory allocation
- 6502 Assembler: full opcode encoding table (~150 valid combinations)
- Code Generator: AST → 6502 instructions (direct, no IR for M1)
- Runtime: NES hardware init, NMI handler, controller read, OAM DMA
- Linker: NROM layout, vector table, palette loading, CHR data
- ROM Builder: iNES header generation, PRG/CHR padding
- CLI: `build` and `check` subcommands via clap
143 tests across all modules:
- 22 lexer tests (literals, keywords, operators, error recovery)
- 18 parser tests (expressions, statements, game structure, errors)
- 7 analyzer tests (symbol resolution, memory allocation, transitions)
- 30 assembler tests (every addressing mode, label resolution)
- 7 codegen tests (var init, arithmetic, buttons, draw, comparisons)
- 11 runtime tests (init sequence, NMI handler, controller read)
- 10 ROM builder tests (iNES format, mirroring, banking, validation)
- 5 linker tests (vector table, CHR data, palette loading)
- 7 integration tests (end-to-end compilation, error detection)
CI: GitHub Actions for check, fmt, clippy, test
Pre-commit: script for local fmt + clippy + test validation
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Expr {
|
|
|
|
|
pub fn span(&self) -> Span {
|
|
|
|
|
match self {
|
|
|
|
|
Self::IntLiteral(_, s)
|
|
|
|
|
| Self::BoolLiteral(_, s)
|
|
|
|
|
| Self::Ident(_, s)
|
|
|
|
|
| Self::ArrayIndex(_, _, s)
|
|
|
|
|
| Self::BinaryOp(_, _, _, s)
|
|
|
|
|
| Self::UnaryOp(_, _, s)
|
|
|
|
|
| Self::Call(_, _, s)
|
M2: Add function/array parsing, IR data structures and lowering
Parser extensions:
- Function declarations with params and return types (fun, inline fun)
- Array type syntax (u8[16]), array literal expressions ([1, 2, 3])
- fast/slow variable placement hints
- Functions stored in Program AST
IR module (new):
- IrProgram, IrFunction, IrBasicBlock, IrOp, IrTerminator types
- AST-to-IR lowering pass with:
- Expression lowering to virtual temps
- Control flow (if/else, while, loop) to basic blocks with branches
- Break/continue via loop context stack
- Short-circuit logical and/or
- Button reads, draw sprites, wait_frame
- Constants inlined as LoadImm
- State handlers lowered as separate IR functions
Tests: 6 new parser tests, 11 new IR lowering tests (153 total)
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 23:25:26 +00:00
|
|
|
| Self::ButtonRead(_, _, s)
|
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
2026-04-12 00:22:11 +00:00
|
|
|
| Self::ArrayLiteral(_, s)
|
|
|
|
|
| Self::Cast(_, _, s) => *s,
|
Implement NEScript compiler Milestone 1 ("Hello Sprite")
Complete implementation of the NEScript compiler pipeline for M1:
- Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators
- Parser: recursive descent with Pratt expression parsing (M1 subset)
- Analyzer: symbol resolution, type checking, memory allocation
- 6502 Assembler: full opcode encoding table (~150 valid combinations)
- Code Generator: AST → 6502 instructions (direct, no IR for M1)
- Runtime: NES hardware init, NMI handler, controller read, OAM DMA
- Linker: NROM layout, vector table, palette loading, CHR data
- ROM Builder: iNES header generation, PRG/CHR padding
- CLI: `build` and `check` subcommands via clap
143 tests across all modules:
- 22 lexer tests (literals, keywords, operators, error recovery)
- 18 parser tests (expressions, statements, game structure, errors)
- 7 analyzer tests (symbol resolution, memory allocation, transitions)
- 30 assembler tests (every addressing mode, label resolution)
- 7 codegen tests (var init, arithmetic, buttons, draw, comparisons)
- 11 runtime tests (init sequence, NMI handler, controller read)
- 10 ROM builder tests (iNES format, mirroring, banking, validation)
- 5 linker tests (vector table, CHR data, palette loading)
- 7 integration tests (end-to-end compilation, error detection)
CI: GitHub Actions for check, fmt, clippy, test
Pre-commit: script for local fmt + clippy + test validation
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum BinOp {
|
|
|
|
|
Add,
|
|
|
|
|
Sub,
|
|
|
|
|
Mul,
|
|
|
|
|
Div,
|
|
|
|
|
Mod,
|
|
|
|
|
BitwiseAnd,
|
|
|
|
|
BitwiseOr,
|
|
|
|
|
BitwiseXor,
|
|
|
|
|
ShiftLeft,
|
|
|
|
|
ShiftRight,
|
|
|
|
|
Eq,
|
|
|
|
|
NotEq,
|
|
|
|
|
Lt,
|
|
|
|
|
Gt,
|
|
|
|
|
LtEq,
|
|
|
|
|
GtEq,
|
|
|
|
|
And,
|
|
|
|
|
Or,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum UnaryOp {
|
|
|
|
|
Negate,
|
|
|
|
|
Not,
|
|
|
|
|
BitNot,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum Player {
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
P1,
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
P2,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub enum Statement {
|
|
|
|
|
VarDecl(VarDecl),
|
|
|
|
|
Assign(LValue, AssignOp, Expr, Span),
|
|
|
|
|
If(Expr, Block, Vec<(Expr, Block)>, Option<Block>, Span),
|
|
|
|
|
While(Expr, Block, Span),
|
|
|
|
|
Loop(Block, Span),
|
|
|
|
|
Break(Span),
|
|
|
|
|
Continue(Span),
|
|
|
|
|
Return(Option<Expr>, Span),
|
|
|
|
|
Draw(DrawStmt),
|
|
|
|
|
Transition(String, Span),
|
|
|
|
|
WaitFrame(Span),
|
|
|
|
|
Call(String, Vec<Expr>, Span),
|
2026-04-12 00:09:47 +00:00
|
|
|
LoadBackground(String, Span),
|
|
|
|
|
SetPalette(String, Span),
|
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
2026-04-12 00:22:11 +00:00
|
|
|
Scroll(Expr, Expr, Span),
|
Implement NEScript compiler Milestone 1 ("Hello Sprite")
Complete implementation of the NEScript compiler pipeline for M1:
- Lexer: full tokenization with hex/binary/decimal literals, all keywords, operators
- Parser: recursive descent with Pratt expression parsing (M1 subset)
- Analyzer: symbol resolution, type checking, memory allocation
- 6502 Assembler: full opcode encoding table (~150 valid combinations)
- Code Generator: AST → 6502 instructions (direct, no IR for M1)
- Runtime: NES hardware init, NMI handler, controller read, OAM DMA
- Linker: NROM layout, vector table, palette loading, CHR data
- ROM Builder: iNES header generation, PRG/CHR padding
- CLI: `build` and `check` subcommands via clap
143 tests across all modules:
- 22 lexer tests (literals, keywords, operators, error recovery)
- 18 parser tests (expressions, statements, game structure, errors)
- 7 analyzer tests (symbol resolution, memory allocation, transitions)
- 30 assembler tests (every addressing mode, label resolution)
- 7 codegen tests (var init, arithmetic, buttons, draw, comparisons)
- 11 runtime tests (init sequence, NMI handler, controller read)
- 10 ROM builder tests (iNES format, mirroring, banking, validation)
- 5 linker tests (vector table, CHR data, palette loading)
- 7 integration tests (end-to-end compilation, error detection)
CI: GitHub Actions for check, fmt, clippy, test
Pre-commit: script for local fmt + clippy + test validation
https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-11 22:07:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub struct DrawStmt {
|
|
|
|
|
pub sprite_name: String,
|
|
|
|
|
pub x: Expr,
|
|
|
|
|
pub y: Expr,
|
|
|
|
|
pub frame: Option<Expr>,
|
|
|
|
|
pub span: Span,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
pub enum LValue {
|
|
|
|
|
Var(String),
|
|
|
|
|
ArrayIndex(String, Box<Expr>),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
|
|
|
|
pub enum AssignOp {
|
|
|
|
|
Assign,
|
|
|
|
|
PlusAssign,
|
|
|
|
|
MinusAssign,
|
|
|
|
|
AmpAssign,
|
|
|
|
|
PipeAssign,
|
|
|
|
|
CaretAssign,
|
|
|
|
|
}
|