Tape.
A small language with a dual backend from one source. Tape is how LeivOS scripts itself, automates itself, and — in large part — how the Uusi kernel is written.
Tape is the language we built for LeivOS. It is not a general-purpose ecosystem play; it is a tool. It exists because we wanted scripting and code generation inside the operating system without dragging in someone else's runtime, and because we wanted to write large parts of the kernel in something safer than C without giving up speed.
The Uusi kernel is written in Assembly (the early boot path and a handful of CPU primitives), C (the parts that need to live close to the metal), and Tape (the rest, and increasingly more of it). Tape's freestanding profile — the kernel profile — has no allocator and no host calls, so the same compiler that builds LeivOS application scripts also produces kernel-side code.
A complete Tape file.
Tape's surface is intentionally small: functions, locals, structs, conditionals, loops, imports. No surprises.
@profile(t1);
import io from "io";
import string from "string";
fn greet(who: string) {
io.print("hello ");
io.println(who);
}
fn main() -> i32 {
greet("world");
return 0;
} Interpret it or compile it to native code.
The same Tape source compiles to a linear three-address-code IR and runs through either backend. Differential tests assert both produce identical results.
VM interpreter
Compiles source to TAC bytecode and interprets it. Boots in microseconds. Used for scripting, the REPL, and inside the kernel.
Native AOT
Compiles the same TAC IR directly to x86-64 machine code. Tape ships its own ELF and PE writers — no LLVM, no Cranelift, no external linker.
Profiles
Every Tape file declares a profile at the top. Profiles gate features by trust level — smaller profiles get smaller code.
Freestanding
No allocator, no host calls. Used inside the Uusi kernel itself.
Typed userspace
Static types, native callable. The everyday profile for system glue and applications.
Dynamic / scripting
Adds the `any` type, top-level statements, and full REPL-style scripting.
Static where it pays off.
Tape has integers (i8..u64),
floats (f32, f64),
bool,
string, structs, slices, fixed arrays, pointers,
and optionals. No implicit narrowing. No silent coercions between integer and float.
Pointer constness and non-null are compile-time attributes. *const T
forbids writes; *!T forbids null.
?T optionals make null-handling explicit.
No borrow checker — ownership is move-by-default with compiler-inserted drops at scope exit.
struct Point {
x: i32;
y: i32;
}
fn distance_sq(a: *const Point, b: *const Point) -> i32 {
let dx: i32 = b.x - a.x;
let dy: i32 = b.y - a.y;
return dx*dx + dy*dy;
} Standard library
The standard library is enough. Three modules cover the everyday cases.
- io
- print, println, print_i64, print_u64, print_f64, read_line
- string
- len, eq, concat, slice (UTF-8 boundary checked), from_i64, from_u64, parse_i64
- dyn
- type_name, to_string, print, println — dynamic value formatting
- ...
- many others for networking, cryptography, file formats
Larger libraries — net, fs, gfx — are exposed through the LeivOS UDSO surface and called from Tape via the same import syntax.
Tape REPL.
Run tape repl to evaluate Tape lines
interactively. Each line is wrapped in a fresh @profile(t2)
context, so a bare expression prints its value and a statement runs for its side effect.
A malformed line surfaces a parse error pointing at the column it failed on. The REPL keeps going.
> 1 + 2
3
> "hi"
hi
> var xs: [3]i64 = [10, 20, 30];
> xs[1] * 2
40 One source. Two build modes.
Bytecode bundle
Compact bytecode-encoded TAC. Run with tape run. Distributable without source.
Native executable
Self-contained x86-64 binary. PE for Windows, ELF for Uusi. Tape's own emitters; no external linker required.
What Tape is not
- Not a package-manager ecosystem. Tape ships with a small standard library and a fixed surface.
- Not a closure language. Tape has no closures — typed events and function pointers cover callbacks explicitly.
- Not a generics language. Compile-time code execution (
@tape) replaces generics entirely. - Not a Tape-only world. Tape interoperates with C at library boundaries via platform-ABI trampolines.
For developers and integrators evaluating LeivOS: Tape example sources are available with your Pro license.
For the full language specification, design decisions, and standalone usage outside LeivOS, visit tapelang.org.