sweet to write, fast to run

Scopes own every value, so memory frees on time, every time. No garbage collector, no borrow checker, no cleanup to forget. One rnx binary checks, runs, tests, and ships it. The workbench below is live — type and watch the compiler check it.

Try it in your browser

01 - LIVE WORKBENCH

src/shade.rnx
—.———— ms

+ source — click to edit

+ compiler output — real check, off-thread

Hit Re-JIT to download the compiler engine and check your code.

02 - HOW IT FLOWS

Follow one file from keystroke to binary — through every tool, pass, and backend.

act 1 - make it right

fn shade(sun: Vec4f): Float {
    defer { print("shade done"); }
    let acc = Vec4f.splat(0.0);
    let i = 0;
    while i < 4 {
        acc = acc + sun;
        i = i + 1;
    }
    return acc.x();
}

01 - write

Your editor already speaks rnx

Keywords, types, and strings light up as you type. Brackets match, blocks fold, docs peek on hover.

fn shade(sun:Vec4f):Float{
let acc=Vec4f.splat(0.0);
    let i=0;
while i<4{
acc=acc+sun;i=i+1;}
return acc.x();}
fn shade(sun: Vec4f): Float {
    defer { print("shade done"); }
    let acc = Vec4f.splat(0.0);
    let i = 0;
    while i < 4 {
        acc = acc + sun;
        i = i + 1;
    }
    return acc.x();
}

rnx fmt - 0 diffs on second pass

02 - fmt

One true style, applied not argued

rnx fmt normalizes spacing and indentation across the whole file. Idempotent: the second pass changes nothing.

fn double(x: Int): Int => x * 2;

fn triple(x: Int): Int => x * 3;

print(double(21) + triple(14));
error[E105] :1 invalid lambda syntax — named functions need a block
error[E105] :3 invalid lambda syntax — named functions need a block

03 - check

Every error, one pass, with a span

The checker reports all syntax errors at once — each with a caret you can click, not one-at-a-time whack-a-mole.

class B {
    init() { this.cb = () => this.flush(); }
    fn flush() { }
}
class B {
    init() { this.cb = fn decay(this) { this.flush() } }
    fn flush() { }
}

W104 - capture with fn decay(this)

04 - lint + fix

Lints that fix themselves

A closure stored on its own owner trips W104. Rewrite it with fn decay(this) to capture GenRef(this) instead.

let v = Vec4f.splat(1.0);
print(v.x());

hover - splat

fn Vec4f.splat(v: Float): Vec4f

Broadcast one scalar to all four lanes. No allocation, no ARC traffic.

05 - lsp

Hover, jump, complete

The language server answers hover, go-to-definition, and completions for any editor speaking the protocol.

act 2 - make it run

let total = (x) => x * 2;
lettotal=(x)=>x*2;

06 - parse

Characters become a tree

The lexer cuts source into tokens; the parser grows them into a typed tree. Desugar lowers the surface syntax first.

Module
Fn shade(sun: Vec4f): Float decl
Block
- Defer stmt
- Let acc = Vec4f.splat(0.0) stmt
While i < 4 stmt
- Assign acc stmt
- Assign i stmt
- Return acc.x() stmt

07 - tree

The shape of the program

Expand the nodes. This is exactly what the later passes walk — nothing hidden, nothing inferred.

fn shade:
				  v0 = splat 0.0
				  v1 = call Vec4f.splat
				loop:
				  v2 = add v0, sun
				  v3 = lt i, 4
				  br v3, loop, done
				done:
				  ret v2
				

08 - lower

One IR, every backend

The checked tree lowers to LIR — simplified below. The interpreter, Cranelift, and LLVM all read this same text.

0

instructions - illustrative example

fn shade:
				  v0 = splat 0.0
				  v1 = call Vec4f.splat
				  v9 = call debug_format
				  v10 = alloc tmp_buf
				loop:
				  v2 = add v0, sun
				  v11 = retain v2
				  v3 = lt i, 4
				  br v3, loop, done
				done:
				  ret v2
				

simplified LIR - inline, DCE, TCO, ARC motion

09 - optimize

Dead code fades out

Inline, dead-code removal, tail calls, and ARC motion run to fixed point. Unused functions simply stop existing.

LIR Cranelift running

JIT compiles each function on first call. Edit, save, new code live in milliseconds.

  • ~ms - incremental function compile
  • 0 - link step, runs in place

PLANNED - HOT RELOAD

edit recompile state kept

LIR LLVM O3 strip ship

Full optimization, per-symbol sections, symbols stripped for the binary you ship.

  • O3 - cross-function optimization
  • ~360KB - stripped release binary, measured
  • C ABI - static lib + header for hosts

10 - two backends

Pick your hurry

Flip the switch. Dev compiles in milliseconds; release takes seconds and flies. Same checksum either way.

$ rnx build --release

built target/shade (ok)

$ ./shade

shade done

42

checksum match

11 - run

Keystroke to binary

Dev runs it now through the JIT; release ships a stripped binary. Either way the output agrees bit-for-bit.

03 - BROWSER PROVING GROUND

Seven workloads, seven toolchains, one log-log plot. Bottom-left wins: fastest execution with the smallest footprint. Turn the dial and check the methodology below.

Loading benchmark data...

04 - TRADEOFF SWITCHBOARD

Every tool charges a tax. Flip through the ones you have paid and see what Rasmalai does instead.

switchboard - pick the tax you know

+ chamber 1 - the tax you pay

The tax: puzzles and waiting

A thirty-minute borrow-checker negotiation over a circular graph, then a five-minute cold build to find out if you won. Real safety, billed hourly.

+ chamber 2 - the rasmalai bypass

The bypass: the closing brace is the free point

Lexical scopes do the job lifetimes did — no annotations on linear logic, no refactors to satisfy the checker. This loop compiles in milliseconds and frees itself.

fn total(xs: Array<Int>): Int {
    let sum = 0;
    for x in xs { sum = sum + x; }
    return sum;
}

05 - TOOLCHAIN STATION

One binary does it all. Switch modes and poke at it — the lint fixer and the test runner respond.

toolchain station - one binary: rnx

$ rnx check src/bad.rnx — demo output loads with site data.

tree-hook diagnostics point at the exact column and suggest the fix. Try it above in the workbench — edit the source until it breaks.

Take it for a spin

Free, open source (MIT), and built in the open. Hit a rough edge? Open an issue — we read every one.

curl -fsSL https://rnx.dev/install.sh | sh

showing Linux instructions — switch above if that is wrong

Made by people who got tired of waiting on compilers. Star the repo, file the bug, shape the language.