Files
vercel-labs--zerolang/skill-data/language.md
T
wehub-resource-sync e7738de6d2
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
chore: import upstream snapshot with attribution
2026-07-13 12:29:30 +08:00

6.4 KiB

name, description
name description
language Compact zerolang syntax and semantics guide for agents.

zerolang Language

Use this when reading or writing Zero source. .0 files are the human-readable projection syntax, not the package compiler input: package commands compile from zero.graph and refresh it automatically after .0 edits. Read one function with zero view --fn <name> instead of whole files.

Minimal Program

pub fn main(world: World) -> Void raises {
    check world.out.write("hello from zerolang\n")
}

pub fn exports a function. World carries runtime capabilities. raises marks a fallible function. check calls a fallible operation and propagates failure.

Declarations

  • use std.mem or use helpers
  • const answer: i32 = 42 (top-level consts work in functions and tests)
  • type Point { x: i32, y: i32, }
  • enum Mode { fast, small, }
  • choice Result { ok: i32, err: String, }
  • fn answer() -> i32 { return 42 }
  • pub fn main(world: World) -> Void raises { ... }
  • test "name" { expect true }

Values, Mutation, And Control Flow

Use let by default and var only when a binding changes. Conditions are Bool; do not rely on truthy integers or strings. Operators are normal infix expressions: a + b, a % b, a == b, a < b, a && b. Comments start with //.

fn sum_odds(n: i32) -> i32 {
    var i: i32 = 0
    var total: i32 = 0
    while i < n {
        i = i + 1
        if i % 2 == 0 {
            continue
        }
        if total > 100 {
            break
        }
        total = total + i
    }
    return total
}

break exits the nearest loop and continue skips to its next iteration.

Types

Primitive and scalar types:

Bool Void String char Type
i8 i16 i32 i64 isize
u8 u16 u32 u64 usize
f32 f64

Bare integer literals adopt the other operand's integer type when in range, so i * 12 works for i: usize. Use suffixes such as _u8 or _usize only when no operand gives context, and as for intentional casts.

Core capability, resource, and helper types recognized by the compiler:

World WorldStream
Fs File ByteBuf
NullAlloc FixedBufAlloc PageAlloc GeneralAlloc
Vec Duration RandSource ProcStatus ProcChild
Address Net Conn Listener
HttpMethod HttpClient HttpServer HttpResult HttpError HttpHeaderValue
JsonDoc BufferedReader BufferedWriter FixedReader FixedWriter
Env Args Clock Rand Proc Alloc
Maybe<T> Span<T> MutSpan<T>
ref<T> mutref<T> owned<T>

Shapes, Enums, And Choices

let point: Point = Point { x: 1, y: 2 }
let result: Result = Result.ok(42)

Matches must be exhaustive unless they use the fallback arm _:

match result {
    .ok(value) {
        expect value == 42
    }
    .err(message) {
        expect true
    }
}

Errors

fn value(i: i32) -> i32 raises [Odd] {
    if i % 2 == 0 {
        return i
    }
    raise Odd
}

pub fn main(world: World) -> Void raises {
    let item: i32 = rescue value(3) err 1
    if item == 1 {
        check world.out.write("fallible ok\n")
    }
}

raises [Error] restricts the error set. Plain raises is open. Calling a fallible function requires check or rescue.

Borrowing And Memory Views

  • ref<T> is a read-only borrow, passed with &value.
  • mutref<T> is a mutable borrow, passed with &mut value. Shape parameters such as mutref<Point> work, including field mutation and nested calls.
  • [N]T is a fixed array; Span<T> is a read-only view; MutSpan<T> is a writable view.
  • Returning a span backed by local fixed-array storage is rejected; return an owned value or keep the view local.
  • Maybe<T> represents absence; read .value only inside a visible .has guard, or use check / rescue. var name: Maybe<String> = null declares an absent local to assign or return later.
  • owned<T> marks explicit resource ownership.
  • One function's fixed locals are limited to 128 KiB (MEM003). Split large buffers into smaller buffers in helper functions, or process data in fixed-size chunks.
fn bump(point: mutref<Point>) -> Void {
    point.x = point.x + 1
}

pub fn main() -> Void {
    var storage: [4]u8 = [1, 2, 3, 4]
    let view: MutSpan<u8> = storage
    let first: u8 = storage[0]
    storage[0] = 9
}

Array and span indexing is bounds-checked at runtime; an out-of-range index traps with a signal exit and no output, so exercise boundary inputs before declaring a change done.

Generics

type Box<T: Type> {
    value: T,
}

fn id<T: Type>(value: T) -> T {
    return value
}

type FixedVec<T: Type, static N: usize> {
    len: usize,
    items: [N]T,
}

Standard Library Call Shapes

Load zero skills get stdlib for the full signature catalog. Beyond the std.mem/std.parse/std.rand/std.json helpers shown below, it ships ready-made validators: std.time (RFC 3339 date/time incl. the exact leap-second rule), std.inet (IPv4/IPv6/hostname), std.regex (ECMA subset), and std.unicode (strict UTF-8). Check the catalog before hand-writing parsing or validation logic. Target-neutral helpers follow these shapes:

pub fn main() -> Void {
    let bytes: Span<u8> = std.mem.span("zero")
    let n: usize = std.mem.len(bytes)
    let same: Bool = std.mem.eql("zero", "zero")

    let parsed: Maybe<u16> = std.parse.parseU16("8080")
    if parsed.has {
        expect parsed.value == 8080
    }

    var rng: RandSource = std.rand.seed(7_u32)
    let random: u32 = std.rand.nextU32(&mut rng)
    let count: Maybe<u32> = std.json.u32("{\"count\":42}", "count")
    expect same && random == 1025555898_u32 && count.has
}

Hosted helpers are capability-gated by target. There is no stdin; hosted programs take input from std.args and files through std.fs:

pub fn main(world: World) -> Void raises {
    let first: Maybe<String> = std.args.get(1)
    if first.has {
        check world.out.write(first.value)
    }

    var path_storage: [16]u8 = [0; 16]
    let path: String = check std.path.join(path_storage, ".zero", "x")
    let fs: Fs = std.fs.host()
    var file: owned<File> = check std.fs.createOrRaise(fs, path)
    check std.fs.writeAllOrRaise(&mut file, std.mem.span("hello\n"))
}

If unsure, run zero check instead of inventing syntax, and pair behavior changes with a test block:

fn point_sum(point: Point) -> i32 {
    return point.x + point.y
}

test "shape" {
    let point: Point = Point { x: 40, y: 2 }
    expect point_sum(point) == 42
}