Grindlang: a small JIT language
A new in-house language for embedding calculations and dialog decisions into Grindshell: statically typed and compiled to native code with Cranelift.
Grindlang is a small language built for one job: embedding calculations and dialog-tree decisions into Grindshell. It borrows Lua’s surface syntax but is a constrained, statically-typed subset that’s closer in spirit to Starlark than to full Lua.
A Grindlang script is not a standalone program. It compiles to a module of exported functions and constants. The game compiles a script once and calls its exports many times. There’s no hidden state between calls; anything that needs to persist is handed in by the host.
Check out the source on GitHub.
Why a new language
Grindshell already runs Luau for dialog and scripting, and that stays. Grindlang solves a different problem: fast, predictable math and decision logic that the game can call in tight loops. Static types mean errors show up at compile time with clear messages, not mid-run. f64-only numbers and an arena with no garbage collector keep the runtime simple and predictable.
How it works
Grindlang compiles to native code with Cranelift. Numbers and booleans flow unboxed, so arithmetic, comparisons, branches, and loops are genuinely native. Heavier values like tables and arrays are handled through a shared runtime.
Correctness rests on three independent executors that must always agree on every program: a tree-walking interpreter, an interpreter for the lowered intermediate representation, and the Cranelift-compiled native backend. If any two disagree, that’s a bug — and we have differential, fuzz, and property tests that hunt for exactly that.
The front end (lexer, parser, resolver, type checker, lowering), the runtime and host API, the JIT backend, and a CLI runner are all in place, along with closures and first-class functions. What’s left is mostly polish — method-call syntax and a fuller native arena.