跳转到内容

Polyglot Genes —— 用 Rust、AssemblyScript、Go 或 C 写 Gene

Rotifer IR 协议层是 WASM-Native, Polyglot by Design(WASM 原生、生而多语言)。 CLI 当前内置一条 TypeScript → WASM 编译路径,走 Javy (QuickJS)。其他所有语言 —— Rust、AssemblyScript、Go(TinyGo)、C/C++、Zig —— 自己产出 WASM 后通过 Bring-Your-Own-WASM(BYO-WASM)通道接入:

Terminal window
# 1. 用任意工具链把 Gene 编译为 WASM
wasm-pack build --target nodejs # Rust
npx asc index.ts --outFile gene.wasm # AssemblyScript
tinygo build -target=wasi -o gene.wasm . # Go
emcc gene.c -O3 -s STANDALONE_WASM -o gene.wasm # C / Emscripten
# 2. 把 WASM 交给 Rotifer CLI
rotifer compile my-gene --wasm path/to/gene.wasm
rotifer arena submit my-gene

为什么可行。 Rotifer IR Specification §1.2 Rotifer IR 的定位 把 IR 定义为 语言无关的中间表示——多个语言前端 可以共同 target 它。CLI 的 Javy 路径只是众多前端之一。只要你的 WASM 遵守 下方的 ABI 契约,它就是一等公民 Rotifer Gene。


你的 WASM 模块必须导出 以下两种之一 的入口加上 memory

风格必需导出典型产生方式
Rotiferexpress(i32, i32) -> i32 + memoryRust(#[no_mangle] extern "C")、AssemblyScript、Zig、手写 WAT
WASI_start + memory(无参无返回)任何默认走 WASI 入口的语言

对于 Rotifer 风格,两个 i32 参数是 (input_ptr, input_len)——指向线性内存; i32 返回值是打包后的 (output_ptr << 32) | output_len。Host 通过这个 buffer 读写 JSON。

WASI 风格更简单——适合 hello-world 级 fixture 和任何带内置 WASI runtime 的语言。


配方 1 —— Rust(wasm-pack / cargo

Section titled “配方 1 —— Rust(wasm-pack / cargo)”

Cargo.toml

[package]
name = "my-rotifer-gene"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[profile.release]
lto = true
opt-level = "z"
strip = true

src/lib.rs

#[no_mangle]
pub extern "C" fn express(input_ptr: i32, input_len: i32) -> i32 {
// 真实 Gene 的逻辑:
// 1. 从线性内存 [input_ptr .. input_ptr + input_len] 读取 JSON 输入
// 2. 计算结果
// 3. 在内存里分配输出 buffer,返回打包的 (ptr, len)
0
}

构建并提交:

Terminal window
rustup target add wasm32-unknown-unknown
cargo build --release --target wasm32-unknown-unknown
rotifer compile my-rust-gene --wasm target/wasm32-unknown-unknown/release/my_rotifer_gene.wasm
rotifer arena submit my-rust-gene

可工作的最小 Rust 源码示例位于 playground 仓库 tests/fixtures/polyglot/rust-style/source/


AssemblyScript 是 TypeScript 开发者门槛最低的路径,产出的 WASM 比 Javy 小得多 (~10-50 KB vs ~700 KB)。

index.ts

export function express(inputPtr: i32, inputLen: i32): i32 {
// 真实 Gene 从内存读取输入、计算、返回打包后的 (ptr, len)
return 0;
}

asconfig.json

{
"targets": {
"release": {
"outFile": "gene.wasm",
"optimize": true,
"runtime": "stub"
}
}
}

构建并提交:

Terminal window
npm install --save-dev assemblyscript
npx asc index.ts --target release
rotifer compile my-as-gene --wasm gene.wasm
rotifer arena submit my-as-gene

可工作的最小 AssemblyScript 源码位于 tests/fixtures/polyglot/as-style/source/


Terminal window
tinygo build -target=wasi -o gene.wasm ./gene.go
rotifer compile my-go-gene --wasm gene.wasm

TinyGo 产出 WASI 风格模块;IR 流水线通过 WASI ABI 接受它。注意 TinyGo 兼容性限制——大部分 Go 标准库可用,但重度依赖反射的包(encoding/json 处理任意类型、 text/template 等)可能不工作。


Terminal window
emcc gene.c -O3 -s STANDALONE_WASM=1 -s EXPORTED_FUNCTIONS='["_express"]' -o gene.wasm
rotifer compile my-c-gene --wasm gene.wasm

STANDALONE_WASM=1 是关键——没有它 Emscripten 会产出依赖 JavaScript runtime 的 胶水层,IR 沙箱不提供这个 runtime。


当前状态:BYO-WASM 可用,内置编译路径正在评估中

Section titled “当前状态:BYO-WASM 可用,内置编译路径正在评估中”
语言状态路径
TypeScript✅ 内置(自动检测 index.tsesbuild + Javy/QuickJS
Rust✅ BYO-WASM--wasm target/.../*.wasm
AssemblyScript✅ BYO-WASM--wasm gene.wasm
Go(TinyGo)✅ BYO-WASM--wasm gene.wasm(WASI ABI)
C / C++✅ BYO-WASM--wasm gene.wasmSTANDALONE_WASM
Zig✅ BYO-WASM--wasm gene.wasm
Python❌ 不可行(Pyodide ~10 MB 超过 WASM 燃料预算)

是否把 Rust + AssemblyScript 从 BYO-WASM 升级为 内置编译路径 正在评估中。 触发是真实的社区需求——如果你需要这个能力,欢迎在 GitHub IssuesDiscord 反馈。


Python 在 WASM 中的 runtime 成本与单次调用的燃料预算不兼容:

  • Pyodide(完整 CPython on WASM)~10 MB,仅模块实例化就耗尽燃料预算
  • MicroPython-WASM(~1 MB)小到能跑,但标准库缺失,且没有支撑 AI/ML 的关键包
  • CPython-WASI(3.12+,~3 MB)是最现实的选择,但仍是 Javy QuickJS 的 4 倍大

更关键的是,让 Python 在 AI 工作中具有吸引力的库(PyTorch、NumPy、Transformers) 是 C/Fortran 扩展,无法编译到 WASM。一个”Python Gene”只能表达纯 Python 业务逻辑——而这正是 TypeScript 已经覆盖的能力,且没有 runtime 开销。

对于 Python 重度的工作负载,应使用 Wrapped Gene:在 phenotype 中声明指向已有 Python 服务的元数据指针,让 Cloud Binding 执行它。组合模式见 Hybrid Gene 指南