用纯 Rust 打造的 Lua 运行时。
单个二进制里容纳五种 Lua 方言与 MacroLua。一个零依赖的解释器核心、一个基于 Cranelift 的 trace JIT、提前编译成原生二进制,以及一个为嵌入不受信任脚本而设计的沙箱。
一个运行时,覆盖你要嵌入的每一种 Lua。
luna 用安全的 Rust 从头实现了整个 Lua 语言家族——没有 C,嵌入方接触到的表层也没有 unsafe。按需选择依赖体量,再随工作负载增长逐步用上 JIT 与 AOT 两层。
5.1 – 5.5 + MacroLua
所有主线 Lua 方言都在同一构建里,在构造 Vm 时逐一选定。同一进程可并发承载多种方言而互不干扰。MacroLua 在 5.4 表层之上加入编译期 @macro 展开。
零依赖核心
luna-core 只引入一个 crate——它自己。每次提交都由 cargo deny 关卡强制保证。这意味着极小的审计面、以秒计的构建,以及无需 mmap RWX 的干净 wasm32 目标。
Cranelift trace JIT
一个 LuaJIT 血统的 trace 式编译器。热循环被记录成带类型的 IR,经 Cranelift 降级后作为原生机器码运行——通过 trait 接入,使解释器路径永不依赖具体后端。
提前编译的二进制
luna-aot 把一份 Lua 源码变成自包含的原生可执行文件——字节码、预热的 trace、静态运行时全部链接进同一个二进制,宿主上无需安装 luna 即可运行。
顺手的嵌入体验
一个 mlua 风格的 Lua 门面、自动解析参数的类型化原生函数、表构造器、通过 derive 宏暴露的 userdata、Rust 侧的协程与调试钩子,以及结构化的 LuaError。
为约束脚本而建
安全边界由宿主掌握。精选的标准库白名单、指令预算、近似内存上限,以及默认关闭的字节码加载——脚本能看到的每一项能力,都是 Rust 主动放行的。
每种方言能做什么。
特性的可用性由 src/version.rs 中的能力判定驱动。luna 生成的按方言字节码与 PUC 编译器格式一致,因此 PUC 编译出的 .luac 文件可直接加载。
| 特性 | 5.1 | 5.2 | 5.3 | 5.4 | 5.5 | MacroLua |
|---|---|---|---|---|---|---|
| 数值 | ||||||
| 整数子类型 Int | – | – | ✓ | ✓ | ✓ | ✓ |
| // 向下取整除 | – | – | ✓ | ✓ | ✓ | ✓ |
| 位运算 & | ~ << >> | – | – | ✓ | ✓ | ✓ | ✓ |
| 十六进制浮点 0x1p4 | – | ✓ | ✓ | ✓ | ✓ | ✓ |
| 语法 | ||||||
| goto / ::label:: | – | ✓ | ✓ | ✓ | ✓ | ✓ |
| 空语句 ; | – | ✓ | ✓ | ✓ | ✓ | ✓ |
| 字符串 | ||||||
| \xXX / \z 转义 | – | ✓ | ✓ | ✓ | ✓ | ✓ |
| \u{XXXX} Unicode 转义 | – | – | ✓ | ✓ | ✓ | ✓ |
| 5.4+ 属性 | ||||||
| local <const> | – | – | – | ✓ | ✓ | ✓ |
| local <close> | – | – | – | ✓ | ✓ | ✓ |
| 5.5 独有 | ||||||
| global 关键字 | – | – | – | – | ✓ | – |
| 具名变参 function f(...name) | – | – | – | – | ✓ | – |
| MacroLua 独有 | ||||||
| @name(args) 编译期宏 | – | – | – | – | – | ✓ |
完整矩阵、标准库覆盖与 C API 表面见 兼容性参考。
自己决定依赖表面。
luna 以一个含五个可发布 crate 的 Cargo 工作区形式交付。解释器核心独立成立;JIT 与 AOT 两层通过 trait 边界叠加其上,因此移除或替换后端都不会触碰核心 API。
解释器
词法、语法、按方言的编译器、分派器、运行时、标准库、NaN 装箱的值、侵入式标记-清除 GC、PUC 模式引擎,以及 JIT trait 表面。零第三方 crate。
JIT 与 C ABI
Cranelift 后端、以 cdylib / staticlib 形式暴露的 lua.h 兼容 C ABI、luna CLI,以及 Lua 嵌入门面。
AOT 编译器
一个构建期工具:Lua 源码 → 独立原生二进制。它不是所产物的运行时依赖。
JIT 流水线
源码分类
每个文件都落在三类之一,各有各的改动纪律与 review 深度:
- 石头 —— 与业务无关的地基(模式引擎、堆、值布局)。做 fuzz、做 bench、semver 严格。
- 钢筋 —— Lua 领域原语(编译器、分派器、JIT 后端)。逐方言与 PUC 交叉校验。
- 水泥 —— 宿主胶水(CLI、C ABI、标准库绑定、AOT)。随嵌入方需求自由演化。
要么诚实的数字,要么不给数字。
luna 刻意不发布一个精挑细选的头条比率。一个恰好胜出的 microbench 单元只是营销产物;真正值得追的信号,是那个落后的离群点。我们发布的是可复现的基线,以及产出它们的方法论。
方法论、调优旋钮与热路径计数器详见 性能参考。
三行就能嵌入。
加一个 crate,打开你要的库,求值即可。需要时再逐步用上沙箱、原生函数与 userdata。
# 完整解释器 + Cranelift JIT + C ABI
[dependencies]
luna-jit = "2"# 最小表面 —— 纯解释器,零依赖,对 wasm 友好
[dependencies]
luna-core = "2"cargo install luna-jit # 安装 `luna` REPL 与脚本运行器
luna -e "print('hello, world')"
luna path/to/script.luause luna_jit::vm::Vm;
use luna_jit::version::LuaVersion;
let mut vm = Vm::new(LuaVersion::Lua55);
let out = vm.eval("return 1 + 2")?;
// out[0] == Value::Int(3)use luna_jit::Lua;
use luna_jit::version::LuaVersion;
let mut lua = Lua::sandbox(LuaVersion::Lua54)
.open_base().open_math().open_string()
.with_instr_budget(1_000_000)
.with_memory_cap(8 * 1024 * 1024)
.build();
let add = lua.create_function(|a: i64, b: i64| a + b);
lua.set_global("add", add)?;
let r: i64 = lua.eval("return add(40, 2)")?;