01 / Toolchain

Commands

Build the tools with make. The build/bin/ziran dispatcher accepts check, ir, build, bundle, run, and fmt. Direct binaries are listed below.

zi2zir --check-only --root DIR file.zi

Check source and imports without writing IR. Use --diagnostics=json for machine-readable diagnostics.

zi2zir --root DIR -o DIR file.zi|file.zir ...

Check and write versioned .zir modules.

zi2c --root DIR -o DIR file.zi|file.zir ...

Generate C. Optional --no-main, --plan9, and --include-dir DIR.

zi2cpp --root DIR -o DIR file.zi|file.zir ...

Generate C++. Optional --no-main.

zi2go --root DIR -o DIR file.zi|file.zir ...

Generate native Go. Optional --no-main, --pkg NAME, and --minify.

zi2zib bundle --root DIR --entry module:function -o FILE file.zi|file.zir ...

Link supported programs into a versioned .zib bundle. zi2zib run FILE validates and runs a bundle without host bindings.

zi-fmt [--check] file.zi ...

Format source with stable indentation and spacing cleanup; --check reports files that need formatting.

Repeat --module-path DIR to search for imported modules outside the root. Native tools also accept --diagnostics=text|json. The toolchain rejects --no-strict.

Toolchain source guide ↗

02 / Standard library

Text and UTF-8

Import with #import "text" or #import "utf8" and pass --module-path std. Strings are immutable UTF-8 byte sequences; .length and indexes use bytes.

std/text.zi

LowerASCII(value: u8) -> u8

Convert ASCII A–Z to lowercase; other bytes are unchanged.

StartsWithFoldASCII(value: string, prefix: string) -> bool

Test a prefix with ASCII-only case folding.

ContainsFoldASCII(value: string, needle: string) -> bool

Find a byte substring with ASCII-only case folding. Empty needle matches.

std/utf8.zi

Continuation(byte: u8) -> bool

Test whether a byte is in the UTF-8 continuation range.

Next(value: string, at: s32) -> s32

Advance to the next scalar boundary. Negative offsets return zero; offsets at or beyond the end return the length. Invalid bytes advance one byte.

Count(value: string) -> s32

Count scalars using Next; invalid bytes each count as one step.

Ziran source repository ↗

03 / Standard library

Generic value records

These are ordinary copyable records with explicit status fields. They have no hidden active variant and do not allocate.

Option($T: Type) { has_value: bool; value: T; }

Apply as Number :: Option(s32). Check has_value before reading value.

Result($T: Type, $E: Type) { is_ok: bool; value: T; error: E; }

Apply as Outcome :: Result(s32, string). Check is_ok and read the corresponding field.

Pair($A: Type, $B: Type) { first: A; second: B; }

Two-field value record. Apply as Pair(s32, string).

Owned growable Vec and a string builder are planned; they are not shipped APIs.

04 / Standard library

JSON scanner

std/json_scan.zi scans without allocating. All positions are UTF-8 byte offsets in the original input. A JsonSpan has start, end, after, and valid; a JsonNumber has value: float64, after, and valid. String spans retain their escape bytes.

Space(text: string, at: s32) -> s32

Skip ASCII JSON whitespace.

Digit(ch: u8) -> bool

Test ASCII decimal digit.

Hex(ch: u8) -> bool

Test ASCII hexadecimal digit.

ReadString(text: string, at: s32) -> JsonSpan

Validate a quoted JSON string at at and return its content span.

SpanEqualsASCII(text: string, span: JsonSpan, expected: string) -> bool

Compare a valid span to exact ASCII bytes.

SpanContainsFoldASCII(text: string, span: JsonSpan, needle: string) -> bool

Search inside a valid span with ASCII-only case folding.

ReadNumber(text: string, at: s32) -> JsonNumber

Parse a JSON decimal number into float64.

MatchLiteral(text: string, at: s32, literal: string) -> bool

Compare exact bytes at an offset.

ValueEnd(text: string, at: s32, depth: s32) -> s32

Return the offset after a valid JSON value or -1. Recursion deeper than 64 fails.

FieldAt(text: string, object_at: s32, name: string) -> s32

Find an object member’s value offset or -1. Member names match unescaped ASCII bytes.

ElementAt(text: string, array_at: s32, index: s32) -> s32

Find an array element’s value offset or -1.

Ziran source repository ↗

05 / Host capability

HTTP

std/net_http.zi specifies an HTTP request/response contract; transport and TLS are supplied by the host. SendHost is a declared host_api foreign capability, while Send is the public wrapper.

HttpRequest

Fields: method, url, token, accept, content_type, body (all strings). The host adds a Bearer authorization header when token is nonempty and must not log it.

HttpResponse

Fields: status: s32, body: string, error: string.

SendHost(request: HttpRequest) -> HttpResponse

Foreign host_api capability. Bind net_http:SendHost when running a bundle that imports it.

Send(request: HttpRequest) -> HttpResponse

Public wrapper that forwards the request to the host capability.

Ziran source repository ↗

06 / Host capability

Processes

std/process.zi defines a line-oriented child-process contract. The host owns handles and performs isolation and process I/O. The Ziran wrapper rejects more than 32 arguments.

ProcessRequest

executable, cwd, stdin, credential_name, credential_value (strings), isolate_desktop: bool, timeout_ms: s64.

ProcessStart

handle: s32, error: string.

ProcessLine

text: string, eof: bool, error: string.

ProcessExit

code: s32, stderr: string, error: string.

StartHost(request: ProcessRequest, args: []string) -> ProcessStart

Foreign host_api capability that starts the child.

NextLineHost(handle: s32) -> ProcessLine

Foreign host_api capability that reads the next output line.

WaitHost(handle: s32) -> ProcessExit

Foreign host_api capability that waits for completion.

Start(request: ProcessRequest, args: []string) -> ProcessStart

Start a child with explicit arguments. The host must honor isolate_desktop before starting it.

NextLine(handle: s32) -> ProcessLine

Read the next output line.

Wait(handle: s32) -> ProcessExit

Wait for completion; callers consume lines and wait exactly once.

Bind process:StartHost, process:NextLineHost, and process:WaitHost for bundles that import this module. Ziran source repository ↗

07 / Embedding

Portable C host API

Include ziran_host.h and link build/libziran.a. The host API validates version 7 bundles and requires every linked capability to be bound before execution.

Bundle *BundleOpen(const char *path)

Open and validate a bundle. Returns an opaque handle or failure.

void BundleClose(Bundle *bundle)

Release a bundle and its names.

size_t BundleCapabilityCount(const Bundle *bundle)

Number of required host capabilities.

const char *BundleCapabilityModule(const Bundle *bundle, size_t index)

Module name for a required capability.

const char *BundleCapabilityFunction(const Bundle *bundle, size_t index)

Function name for a required capability.

int BundleRun(const Bundle *bundle, const HostBinding *bindings, size_t count, long long *result, int *has_result)

Run with fresh globals. Integer and boolean entry values populate result; a void entry sets has_result to zero.

BundleInstance *BundleInstantiate(const Bundle *bundle, const HostBinding *bindings, size_t count)

Create an instance whose module globals persist between runs. Keep the bundle and binding contexts alive until close.

int BundleInstanceRun(BundleInstance *instance, long long *result, int *has_result)

Run one entry call. A runtime failure makes that instance unusable.

void BundleInstanceClose(BundleInstance *instance)

Release the instance.

Host values and callbacks

HostBinding contains module, function, a VmHostCall callback, and context. The callback receives typed arguments and writes a typed result. The value kinds are VM_HOST_VOID, VM_HOST_INTEGER, VM_HOST_UNSIGNED, VM_HOST_REAL, VM_HOST_STRING, VM_HOST_RECORD, and VM_HOST_SLICE.

typedef int (*VmHostCall)(void *context, const char *module,
                          const char *function, const VmHostValue *args,
                          int arg_count, VmHostValue *result);

typedef struct HostBinding {
    const char *module;
    const char *function;
    VmHostCall call;
    void *context;
} HostBinding;

VmHostValue has kind: VmHostValueKind, type: const char *, integer: int64_t, bits: uint64_t, real: double, data: const unsigned char *, length: size_t, fields: const VmHostField *, field_count: size_t, and elements: VmHostValue *. Each VmHostField has name and value.

Record fields are in declaration order and include names and types. Synchronous numeric, boolean, and string slice arguments may be edited in place; keep the element pointer and length unchanged. The VM validates and copies edits back. Host pointer, array, and slot calls are unsupported. Returned string bytes and record fields must remain valid until BundleRun returns.

Read the complete C header ↗