Thanks for your interest in lua-rs — a pure-Rust Lua interpreter that runs Lua
5.1 through 5.5 from one core (5.4 is the stable baseline). This guide covers how
to build it, how to run the tests, the project layout, and the code-style rules
the project enforces. For the agent-facing operational guide (the iteration
ladder, the multi-version oracle, benchmarks), see CLAUDE.md.
- A recent stable Rust toolchain (
rustuprecommended; the workspace pinsrust-version = "1.77"). - A POSIX shell for the harness scripts.
cargo build --bin lua-rs # debug build of the CLI
cargo build --release --bin lua-rs # optimized build
cargo build --workspace --bins # everythingThe debug binary lands at target/debug/lua-rs.
target/debug/lua-rs script.lua # run a source file
target/debug/lua-rs -e 'print(1 + 2)' # run a one-liner
target/debug/lua-rs 'print("bare source")' # a bare argument is treated as source
target/debug/lua-rs # REPL (no arguments)
target/debug/lua-rs - # read a script from stdin
LUA_RS_VERSION=5.1 target/debug/lua-rs s.lua # select a Lua version (5.1–5.5; default 5.4)A change is unverified until an oracle says it behaves like reference C. Build success is not signal.
One command runs everything CI runs (it builds its own binary, so there is no stale-binary trap):
make test # build + Rust tests + full conformance suiteThe other Makefile targets:
make rust # workspace unit/integration tests + embedding doctests
make conformance # official Lua 5.4 suite only
make perf # benchmark vs reference C Lua (measurement, not a gate)
make scaling # flag superlinear (O(n^2)) behavior in hot operations
make setup # recreate the reference/lua-c/testes symlink if missingmake scaling and make perf are how you check a change for complexity or
throughput regressions. make scaling runs each operation in
harness/bench/scaling/ at growing sizes and fails if any goes superlinear;
that is the gate that catches O(n^2) bugs.
Under the hood, the conformance harness:
# Full upstream Lua 5.4.7 suite (the headline gate)
TEST_TIMEOUT_S=90 ./harness/run_official_all.sh
# A single official test
./harness/run_one_test.sh reference/lua-c/testes/strings.lua
# Inspect a failure
tail -120 harness/impl/official/<test>.outharness/impl/official/run_all.tsv is the canonical scoring artifact. Do not
commit harness/impl/official/*.out — they regenerate on every run.
GC-sensitive changes should also run the canaries:
./harness/canaries/gc/run_canaries.shcrates/
lua-lex, lua-parse, lua-code # front end: lexer, parser, bytecode compiler
lua-vm # the register VM and core runtime
lua-types # LuaValue, tables, strings, errors
lua-gc # garbage collector (budgeted unsafe)
lua-stdlib # standard library
lua-coro # coroutines
lua-cli # the `lua-rs` binary + dynamic-load backend
harness/ # oracles, benchmarks, enforcement gates
docs/ # architecture, performance, and porting docs
reference/ # pinned upstream Lua 5.4.7 (the oracle; not edited)
These rules are mechanically checked by hooks in .claude/hooks/ and will fail a
commit/Stop event if violated:
- No inline
//comments. If something is worth explaining, put it in a doc string. (// SAFETY:justifications onunsafeblocks are the exception and are required.) - No fallback patterns (
x || y || z). Use a single source of truth; if data might be missing, fix the data path rather than papering over it. - No
String/&strfor Lua data. Lua strings are byte strings — use&[u8]/Vec<u8>/LuaString. unsafeis budgeted. The workspace defaults to#![forbid(unsafe_code)]. Onlylua-gcandlua-clicarry a budget; everyunsafeblock needs a// SAFETY:comment and must stay under the per-crate ceiling inharness/unsafe-budgets.toml. Run.claude/hooks/unsafe-budget.shto check.- Never edit
reference/lua-c/testes/. The upstream tests are the oracle. - Every
crates/**/*.rscarries a PORT STATUS trailer. SeePORTING.md§12.
- Reproduce the target behavior as a tiny
lua-rs -e '...'snippet first. - Patch the smallest cause; don't normalize a whole subsystem for one assertion.
- Re-run the test that exposed the issue plus its adjacent gates.
- Build before final verification:
cargo build --bin lua-rs. - Keep temporary debugging (
eprintln!, scratch files) out of the final diff.
The full debugging playbook lives in CLAUDE.md.
- CLAUDE.md — the operational guide: iteration ladder, multi-version oracle, benchmarks, debugging playbook.
- README.md — what the project is and where it stands.
- specs/MULTIVERSION_PLAYBOOK.md — how to add or fix a Lua version (and the harness/enforcement model).
- PORTING.md — the original C→Rust translation rules (historical; the port is complete, but the PORT STATUS trailer convention is still in use).
- docs/LUA_SYSTEM_DEEP_DIVE.md — architecture, GC, and the unsafe model.
By contributing, you agree that your contributions are licensed under the project's MIT license.