luna
A Lua runtime in pure Rust. Full Lua 5.1 / 5.2 / 5.3 / 5.4 / 5.5 dialect support in a single binary, with a Cranelift-backed JIT that hits 2× faster than PUC across the cross-dialect bench and competitive with LuaJIT 2.1 on numeric workloads.
use Lua;
let mut lua = new;
lua.open_base;
lua.open_math;
let r: i64 = lua.eval?;
assert_eq!;
Status
- v1.0.0 shipped 2026-06-23 (commit
ae7795c). - v1.1 sprint in progress: ergonomic embedder API
(
Lua::eval/set_global/native_typed/LuaTable/ etc.), workspace split (luna-coreis zero-dep), MSRV declaration, structuredLuaError, host userdata payloads, Rust-side coroutine + debug hook APIs, and async embedder integration (seeCHANGELOG.mdfor the full unreleased section).
Correctness
- 910 tests / 0 failures across the v1.0 baseline (242 lib unit, 123 PUC official-suite files × 5 dialects, 40 e2e programs × 5 dialects byte-diff vs installed PUC, 64 method-JIT audit, 28 trace-JIT audit, 13 capi conformance, 10 sandbox embedding, etc.)
- v1.1 adds 60+ new integration tests for the embedder ergo
surface (
sandbox_builder,table_builder,native_typed,lua_facade,userdata_host,rust_debug_hook,rust_coroutine,lua_error_structured).
Performance
Master gate is vs.X ≤ 0.50 — luna at least 2× faster than the
reference — on every cross-dialect cell:
| cells | pass | |
|---|---|---|
| vs PUC 5.1-5.5 (7 cells × 5 dialects) | 35 | 35 ✓ |
| vs LuaJIT 2.1 (7 cells) | 7 | 6 ✓ (1 within 0.83×) |
See docs/performance.md for the full table
and the Redis-Lua-shape (D1) corpus.
Install
luna ships as a Cargo workspace with two publishable crates:
# Most embedders — full interp + Cranelift JIT + capi.
[]
= "1.1"
# Minimum surface — pure interpreter, zero third-party deps,
# wasm32-friendly.
[]
= "1.1"
cargo tree -p luna-core shows exactly one crate. The full luna
adds 6 Cranelift crates and their transitive deps for the JIT side.
For the CLI binary:
# or, for the polished REPL (tab completion against globals + Lua
# syntax highlighting; pulls rustyline as a dep):
Embedding (quick demo)
The sandbox builder + ergo APIs collapse the v1.0 dance into a handful of lines:
use Lua;
use LuaVersion;
let mut lua = sandbox
.open_base
.open_math
.open_string
.with_instr_budget
.with_memory_cap
.build;
// Register a typed Rust function:
let add = lua.create_function;
lua.set_global?;
// Build a table and expose it:
let cfg = lua.create_table;
cfg.set?;
cfg.set?;
lua.set_global?;
// Run a script:
let result: i64 = lua.eval?;
assert_eq!;
Full walkthrough: docs/embedding.md (12
sections covering install, sandbox, set_global, tables, native
functions, userdata, coroutines, debug hooks, errors, the Lua
newtype facade, and threading).
Threading model
luna_jit::Vm is !Send + !Sync — pin one Vm per OS thread (or per
single-thread Tokio worker). For async embedders, use Tokio's
current_thread runtime flavor or wrap Vm access in a LocalSet.
See docs/threading.md for canonical patterns
(single-thread Tokio, LocalSet on multi-thread, Vm-per-OS-thread
- channels) and the post-v1.1
feature = "send"roadmap.
Standalone CLI
luna --version-of <51|52|53|54|55> selects the dialect.
Linking from C
luna ships a cdylib / staticlib exposing a lua.h-compatible
subset under crates/luna-jit/src/capi.rs. Existing C / C++ hosts that
need a drop-in PUC replacement can link against it.
Build
Architecture in 30 seconds
crates/luna-core/ # 0 third-party deps; pure interp + types
├── src/vm/ # dispatcher + sandbox + ergo (eval, native_typed, ...)
├── src/runtime/ # heap (NonNull-based mark-sweep GC), value, table, userdata
├── src/compiler/ # bytecode emit per dialect
├── src/frontend/ # lexer + parser
├── src/pattern.rs # PUC pattern engine
├── src/jit/ # IntChunkCompiler + TraceCompiler trait surface
│ # (NullJitBackend lives here; embedders compose
│ # their own implementations against this contract)
└── src/lib.rs # module roots
crates/luna-jit/ # depends on luna-core + cranelift × 6
├── src/jit_backend/ # Cranelift-backed CraneliftBackend implementations
├── src/capi.rs # lua.h-compatible C ABI
├── src/lua_facade.rs # `Lua` newtype mlua-shape facade
├── src/bin/luna.rs # CLI binary
└── src/lib.rs # pub use luna_core::*; + JIT + Vm::new_minimal_with_jit
See docs/architecture.md for the full
breakdown (crate boundary, source classification, JIT pipeline,
sandbox surface).
Documentation
docs/embedding.md— cookbookdocs/architecture.md— crate layout + JIT pipelinedocs/threading.md— async + multi-thread patternsdocs/compatibility.md— per-dialect feature matrixdocs/performance.md— bench numbersCHANGELOG.md— release notescargo doc --open— full API reference
License
Dual MIT / Apache-2.0 (see LICENSE-MIT and
LICENSE-APACHE).