RinneScript (.rg) #
A dual-mode systems and AI programming language written in pure Zig — zero third-party dependencies.
RinneScript pairs an instant-start bytecode VM for scripting and prototyping
with native compilation backends — C11 for a broad subset, plus a linked
x86-64 backend (--native, libc + -l/-L libs and @libcall bindings) and
a freestanding --no-libc static ELF — for dependency-free binaries, and
ships a first-class AI/tensor ecosystem: tensors with SIMD-style kernels,
zero-copy GGUF/SafeTensors readers, a CPU transformer forward pass, a package
manager, TCP networking, and dlopen-based C FFI.
@import = .{ std };
fn fib(n: int) int {
if n < 2 { return n; }
return fib(n - 1) + fib(n - 2);
}
pub fn main(args: []str) int {
std.print("fib(20) = {}\n", .{fib(20)});
return 0;
}
Quick start #
zig build
./zig-out/bin/rinne run examples/basics.rg # variables, control flow, functions
./zig-out/bin/rinne run examples/types_demo.rg # std import + @as casts
./zig-out/bin/rinne run examples/utilities.rg # std.math/strings/io/json/collections
./zig-out/bin/rinne run examples/tensor_simd.rg # @tensor + apply_simd ReLU
./zig-out/bin/rinne build --native examples/native.rg # -> a native x86-64 binary
./zig-out/bin/rinne version
zig build test # full test suite
CLI #
| Command | Description |
|---|---|
rinne run <script.rg> [args...] |
Execute a script on the bytecode VM |
rinne check <file.rg>... |
Parse + compile without running (CI-friendly); -q/--quiet |
rinne count <file.rg>... |
Source metrics: lines / code / comments / functions |
rinne build <entry.rg> [-o out] |
Native compilation → <name>.rgx (C11 default, or --native x86-64 linked against libc, --native --no-libc freestanding, -l/-L link libs, @libcall bindings) |
rinne fmt [--check] <file.rg> |
Format a script (or check with --check) |
rinne lint <file.rg>... |
Static analysis |
rinne init <name> |
Scaffold main.rg + .gitignore into a new directory |
rinne repl |
Interactive read-eval-print loop (each snippet runs standalone) |
rinne completions bash|zsh|fish |
Emit a shell completion script |
rinne help [topic] |
Per-command help topics |
rinne version |
Version + target triple |
Global options: --quiet (suppress non-essential output) and
--color auto|always|never (diagnostics coloring; auto keys off $TERM).
Global options may appear before or after the command.
Exit codes: 0 success · 64 usage error · 69 not implemented ·
70 parse/compile/runtime failure. A script's exit code is the value its
pub fn main returns.
Language tour #
@import = .{ std };
// Functions with typed params and return types.
fn sum_to(n: int) int {
var total: int = 0;
var i: int = 1;
while i <= n {
total = total + i;
i = i + 1;
}
return total;
}
// Explicit casts with @as; type annotations accept std/types.rg aliases.
const x: float = @as(float, 7); // 7.0
const label: str = @as(str, x); // "7"
var v: vec16f = std.vec.splat(16, 1.5); // vec16f is an alias from std/types.rg
pub fn main(args: []str) int {
std.print("{} {} {}\n", .{sum_to(100), x, label});
return 0;
}
Notes on the surface:
- Formatted output:
std.print("x={}\n", .{x})— the format string plus a tuple of values ({{/}}are literal-brace escapes). The tuple form is required. - Imports register namespaces:
@import = .{ std };enablesstd.print,std.stderr, etc. Unknown modules fail at compile time. - Casts go through
@as(int|float|str|bool, value)(aliases likei32,u64,f32map onto those four paths). - defer runs LIFO at scope exit. In v1 a deferred body cannot capture enclosing locals — call globals/builtins only, or deinit explicitly.
Libraries #
Every library has a runnable-example guide under docs/libs/:
| Library | Entry points | Guide |
|---|---|---|
| std | @import = .{std}, @as, std.print/std.stderr; std.strings.*, std.math.*, std.io.* (fs), std.json.*, std.collections.* |
docs/libs/std.md |
| tensor | @tensor(f32,[6],.{.device=.cpu,.fill=0}), .apply_simd(kernel), indexing, deinit/shape/numel/dtype/fill/data |
docs/libs/tensor.md |
| ai | ai.load_safetensors(path), ai.load_gguf(path) → named read-only tensor views (mmap, zero-copy) |
docs/libs/ai.md |
| llm | llm.llm_load(path) → transformer model; model.forward(ids) → last-token logits (CPU) |
docs/libs/llm.md |
| pkg | module-level @fetch(url_or_repo, .{ .version, .sha256 }) → cached, checksum-pinned dependencies |
docs/libs/pkg.md |
| net | net.tcp_listen(port), net.tcp_connect(host, port); accept/read/write/shutdown/close |
docs/libs/net.md |
| c | c.load_lib("libc.so.6") → dlopen handle; lib.call_int(sym, args), lib.call_float(sym, args), lib.deinit() |
docs/libs/c.md |
A taste of each:
// tensor: element-wise kernel over every cell (in place)
@import = .{ std };
var t: []f32 = @tensor(f32, [6], .{ .device = .cpu, .fill = -1.5 });
t[3] = 4.25;
t.apply_simd(fn(x: @vector(8, f32)) f32 {
if x < 0.0 { return 0.0; }
return x;
}); // relu in place
std.print("{}\n", .{t.data()}); // [0, 0, 0, 4.25, 0, 0]
t.deinit();
@import = .{ std, net };
// net: loopback echo — half-close (shutdown) frames messages
const l = net.tcp_listen(0);
const c = net.tcp_connect("127.0.0.1", l.port());
c.write("ping");
c.shutdown(); // signals end-of-message
const s = l.accept();
std.print("{}\n", .{s.read(64)}); // "ping" (read returns early at EOF)
s.write("pong");
s.shutdown();
std.print("{}\n", .{c.read(64)}); // "pong"
@import = .{ std };
// pkg: fetch a dependency (module level), then call it
@fetch("github.com/user/lib", .{ .version = "v1.2.0", .sha256 = "..." });
pub fn main(args: []str) int {
std.print("{}\n", .{lib_add(2, 3)});
return 0;
}
Platform notes:
c.load_libaccepts sonames or full paths — resolution goes through the system loader (libc.so.6works; notefabslives in libm).- AI loaders memory-map model files (Windows unsupported for mmap loaders).
@import_cstays gated in v1 by design — dlopen FFI viac.load_libis the supported C interop story.- Tensor devices other than
.cpudegrade with a clear runtime error in this build (no CUDA linking yet).
Development #
zig build # build the rinne binary
zig build test # unit + end-to-end tests (144)
zig build -Doptimize=ReleaseFast # optimized binary
python3 scripts/build_site.py # docs website into site/
Layout:
src/
main.zig # CLI entry (run/build/check/count/init/repl/fmt/lint/lsp/completions)
root.zig # module exports + aggregate tests
lsp.zig # language server (LSP over stdio)
script/
lexer.zig # O(1) tokenizer (@directives, escapes)
parser.zig # AST + recursive-descent parser
compiler.zig # bytecode emitter, phase-gated directives
vm.zig # stack VM, frames, defers, builtins, e2e tests
value.zig # dynamic values, TensorObj/LlmModel/LibObj/NetObj
type_checker.zig # dormant static checker (tooling phases)
mmap.zig # cross-platform file mapping (std.Io)
ai_safetensors.zig # SafeTensors header parser -> tensor views
ai_gguf.zig # GGUF v2/v3 parser (+ numeric kv capture)
llm.zig # transformer forward pass (RMSNorm/RoPE/GQA/SwiGLU)
pkg.zig # @fetch package manager (cache/sha256/tar.gz)
loader.zig # resolves module-level @fetch before compile
codegen/
c_emitter.zig # C11 emitter powering `rinne build`
tools/
fmt.zig # formatter core (rinne fmt)
lint.zig # linter (rinne lint)
examples/ # runnable .rg programs
selfhost/ # RinneScript lexer/parser/eval written in .rg
std/types.rg # core type aliases
editors/ # Neovim / VS Code / Emacs integrations (+ tree-sitter)
test/ # test corpus
docs/libs/*.md # library guides with runnable examples
docs/man/ # rinne(1), rinne-libs(7)
scripts/build_site.py # markdown -> HTML site generator
PIVOT.md # pivot spec & phase roadmap
v1.md # v1.0 release execution plan
Roadmap #
From PIVOT.md and the v1.md masterplan:
Remaining / future work: CUDA/ROCm allocators (devices currently degrade),
LLVM backend, tokenizer for end-to-end text generation, @import_c native
decls (kept gated), first-class function values, utility libraries
(crypto/log/test; csv + shell-completion CLI helpers landed in std.json
and rinne completions).
Design principles #
- Dual-mode: prototype on the VM (<10 ms startup), ship native via codegen — same language, same semantics.
- Explicit over implicit: manual memory with
defer, explicit types, no hidden control flow. - AI-native: tensors and SIMD as first-class intrinsics, not libraries.
- Small, auditable core: pure Zig, zero third-party dependencies.