1
0
Fork 0
mirror of https://github.com/imjasonh/nescript synced 2026-07-08 08:55:38 +00:00
No description
Find a file
Claude 0a3e830acf
Codegen: peephole branch folding + dead JMP elimination
Two new passes that save 2 instructions per conditional:

- \`fold_branch_over_jmp\` rewrites \`BNE taken; JMP else_block;
  taken:\` into \`BEQ else_block; taken:\`. Emitted by the IR codegen
  for every \`if\` without a matching \`else\`. Bounded lookahead of
  ~60 instructions keeps the rewritten branch within the signed
  8-bit reach (-128..+127).
- \`remove_jmp_to_next_label\` drops \`JMP foo; foo:\` since the JMP
  is a no-op — execution falls through to the label anyway.

Instruction count impact (IR vs AST, lower is better):

                         before            after
    arrays_and_functions 262 vs 236   ->   243 vs 235
    bouncing_ball        135 vs 144   ->   122 vs 143
    coin_cavern          290 vs 291   ->   261 vs 289
    hello_sprite          73 vs  64   ->    64 vs  63
    mmc1_banked          261 vs 247   ->   235 vs 246
    sprites_and_palettes 121 vs 113   ->   108 vs 112
    state_machine        233 vs 229   ->   209 vs 228

IR codegen now beats the AST codegen on 5 of 7 examples and is
competitive on the other two.

https://claude.ai/code/session_01W6eQFStA66EuMKHUFo2rx3
2026-04-12 16:44:27 +00:00
.github/workflows Add example builds to CI, document sprite name behavior 2026-04-11 22:55:43 +00:00
docs docs: struct types in the language guide 2026-04-12 16:18:29 +00:00
examples Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
fuzz Add fuzz testing and parser edge case regression tests 2026-04-12 00:52:35 +00:00
scripts Implement NEScript compiler Milestone 1 ("Hello Sprite") 2026-04-11 22:07:56 +00:00
src Codegen: peephole branch folding + dead JMP elimination 2026-04-12 16:44:27 +00:00
tests Codegen: on_scanline per-state dispatch + NMI reload 2026-04-12 16:29:15 +00:00
.gitignore Implement NEScript compiler Milestone 1 ("Hello Sprite") 2026-04-11 22:07:56 +00:00
Cargo.lock M3: Asset pipeline, sprite/palette/background declarations, debug symbols 2026-04-12 00:09:47 +00:00
Cargo.toml M3: Asset pipeline, sprite/palette/background declarations, debug symbols 2026-04-12 00:09:47 +00:00
LICENSE Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
plan.md Create initial engineering design document for NEScript 2026-04-11 17:42:43 -04:00
README.md Add README, LICENSE, examples, fix draw parser lookahead 2026-04-12 00:38:19 +00:00
spec.md Add NEScript language specification draft 2026-04-11 17:42:59 -04:00

NEScript

A statically-typed, compiled programming language for NES game development.

NEScript compiles .ne source files directly into playable iNES ROM files, with no external assembler or linker dependencies. The compiler handles everything from source text to a ROM you can run in any NES emulator.

Quick Start

# Build the compiler
cargo build --release

# Compile an example
cargo run -- build examples/hello_sprite.ne

# Run the output ROM in an emulator
# (produces examples/hello_sprite.nes)

Hello World

game "Hello" {
    mapper: NROM
}

var px: u8 = 128
var py: u8 = 120

on frame {
    if button.right { px += 2 }
    if button.left  { px -= 2 }
    if button.down  { py += 2 }
    if button.up    { py -= 2 }

    draw Smiley at: (px, py)
}

start Main

Features

  • Game-aware syntax -- states, sprites, palettes, and input are first-class constructs
  • Full type system -- u8, i8, u16, bool, fixed-size arrays (u8[N])
  • Functions -- with parameters, return types, inline hint, recursion detection
  • State machines -- state with on enter, on exit, on frame handlers
  • Compile-time safety -- call depth limits, recursion detection, type checking
  • Optimizer -- constant folding, dead code elimination, strength reduction
  • Multiple mappers -- NROM, MMC1, UxROM, MMC3
  • Asset pipeline -- PNG-to-CHR conversion, palette definitions, inline tile data
  • Debug support -- --debug flag, source maps, Mesen-compatible symbol export
  • Single binary -- no dependencies on ca65, Python, or any external tools

Documentation

Examples

Example Features demonstrated
hello_sprite.ne D-pad input, sprite drawing
bouncing_ball.ne Automatic movement, edge detection
coin_cavern.ne Multi-state game, functions, constants, gravity
arrays_and_functions.ne Arrays, functions, while loops, inline functions
state_machine.ne State transitions, on enter/exit, timers
sprites_and_palettes.ne Inline CHR data, palettes, scroll, type casting
mmc1_banked.ne MMC1 mapper, bank declarations, multiply

Compiler Commands

# Compile to ROM
nescript build game.ne

# Compile with custom output path
nescript build game.ne --output my_game.nes

# Type-check only (no ROM output)
nescript check game.ne

# View generated 6502 assembly
nescript build game.ne --asm-dump

# Enable debug mode
nescript build game.ne --debug

Emulator Compatibility

Output ROMs are standard iNES format and work with any NES emulator:

Project Status

NEScript implements all five planned milestones:

Milestone Status Key Features
M1: Hello Sprite Done Full compiler pipeline, assembler, ROM builder
M2: Game Loop Done Functions, arrays, IR, optimizer, call graph analysis
M3: Asset Pipeline Done PNG-to-CHR, sprites, palettes, debug symbols
M4: Optimization Done Strength reduction, ZP promotion, type casting, asm-dump
M5: Bank Switching Done MMC1/UxROM/MMC3, bank declarations, software mul/div

210 tests across 14 modules, with CI running fmt, clippy, test, and example compilation on every push.

License

MIT