====================================================== ZEPHYR(1) — the manual · v0.2 ====================================================== a small, statically-typed, memory-safe language that compiles to native x86-64 — as readable as a scripting language, as fast as C, with a compiler written in itself. sections below: overview, getting started, language, stdlib, toolchain.
malloc/free, no null. A GC reclaims memory, indexing is bounds-checked, every variable is initialized. Use-after-free, double-free, overruns and null derefs cannot be written.zc.exe is written in Zephyr, carries its own assembler and PE linker, and depends only on kernel32.dll.and/or/not, string interpolation, no semicolons, and a clear let vs var.struct Point { x: float, y: float } fn dist(a: Point, b: Point) -> float { let dx = a.x - b.x let dy = a.y - b.y return sqrt(dx * dx + dy * dy) } let b = Point{x: 3.0, y: 4.0} print("distance is {dist(a, b)}") // 5 print(b.dist(a)) // UFCS
Best-of-7, Windows x86-64, Zen5, same algorithm with a verified checksum:
| Workload | Zephyr | C −O2 | Rust −O | Result |
|---|---|---|---|---|
| integer SIMD (matmul) | 42 | 72 | 70 | wins both |
| rasterization (cube) | 8 | 10 | 11 | wins both |
| bignum (pi) | 66 | 84 | 91 | wins both |
| sorting | 139 | 276 | 43 | 2× faster than C |
| recursion (fib) | 21 | 12 | 21 | ties Rust |
| float compute (mandel) | 109 | 88 | 90 | within 1.2× |
Requirements: Windows x86-64 and zc.exe — a single self-contained file with the runtime and standard library embedded. No separate runtime, no linker to configure, no C toolchain.
fn main() { print("Hello from Zephyr!") }
$ .\zc.exe --rt hello.zeph hello.exe $ .\hello.exe Hello from Zephyr!
hello.exe is a standalone Windows executable that imports only kernel32.dll. --rt links Zephyr's own runtime; end the output path in .s to emit Intel-syntax assembly instead.
// math.zeph fn square(n: int) -> int { return n * n } // main.zeph import "math.zeph" fn main() { print(square(9)) } // 81
import resolves relative to the importing file, then the compiler's directory. Each file is included once — diamond imports are fine.
let is immutable, var is mutable; locals infer their type and every variable is initialized. int widens to float implicitly; every other conversion is explicit with as.
| Type | Notes |
|---|---|
| int | 64-bit signed integer |
| float | 64-bit floating point |
| bool | true / false |
| str | immutable string, UTF-8 bytes |
Operators: arithmetic + - * / %, comparison == != < > <= >=, short-circuiting and or not, bitwise & | ^ << >>. Control flow is if / else if / else, while with break/continue, and for x in xs / for i in 0..n (half-open).
impl Point { fn new(x: float, y: float) -> Point { // constructor return Point{x: x, y: y} } fn len(self) -> float { // method return sqrt(self.x*self.x + self.y*self.y) } } let p = Point.new(3.0, 4.0) print(p.len()) // 5 print(p.dist(a)) // UFCS: same as dist(p, a)
interface Shape { fn area(self) -> float fn name(self) -> str } fn describe(s: Shape) { print("{s.name()}: {s.area()}") } enum Color { Red, Green, Blue } print(Color.Green) // Green — prints its member name
fn find(xs: [int], target: int) -> int? { for v in xs { if v == target { return v } } return none } let v = find(xs, 9).or(0) // default if absent
[] cannot infer its element type — annotate the binding: var xs: [int] = [].fn contains[T](xs: [T], x: T) -> bool { for v in xs { if v == x { return true } } return false } print(contains([1, 2, 3], 2)) // T = int fn make_adder(n: int) -> fn(int) -> int { return fn(x: int) -> int { return x + n } } print(make_adder(5)(10)) // 15
Functionality splits between a small set of compiler built-ins and a standard library written in Zephyr (std/) — ordinary generic code, not special-cased.
| Built-in | Purpose |
|---|---|
| print(x) | Print a value (any type) + newline |
| panic(msg) | Abort with a message |
| assert(cond, msg) | Abort if cond is false |
| args() | Command-line arguments as [str] |
| read_file / write_file | File I/O |
import "std/list.zeph" print(xs.contains(2)) // generic Zephyr, UFCS
load64, store64, addr, win(...) for Win64 FFI) exist for the runtime and FFI — most code never touches them.zc.exe — written in Zephyr — is one self-contained binary: lexer, recursive-descent parser, type checker, optimizer, x86-64 code generator, its own assembler, and its own PE linker. No gcc, no ld, no external assembler.
lexer -> parser -> type checker -> inliner -> optimizer passes -> x86-64 codegen -> peephole -> assembler -> PE linker -> app.exe // imports: kernel32.dll
The runtime is itself written in Zephyr (runtime.zeph): allocation, strings, collections, formatting, and a conservative mark-sweep GC — a contiguous reserved heap with an object-start bitmap for O(1) pointer identification, size-segregated free lists, roots scanned from the machine stack and globals, and a live-proportional collection trigger.
The production compiler selfhost/zc.zeph compiles itself; a one-time C seed produced the first binary, and gcc has been out of the loop ever since. Any change to codegen is promoted through a three-stage bootstrap to a byte-identical fixpoint.
$ .\selfbuild.ps1 # recompiles zc.zeph; checks the fixpoint
xmm6–xmm11).idiv, bit-identical, exact idiv fallback).