A language you can read
without running it.
Ziman is small and statically typed. Its syntax and semantics are designed to be cheap for an LLM to generate correctly and cheap for a human to check by eye: no implicit coercion, no exceptions, no operator overloading, one obvious way to spell most things, and errors that say what to write instead.
A taste
use json #[derive(Json)] struct Item { name: string qty: int } fn total(items: [Item]) -> int { var sum = 0 for item in items { sum = sum + item.qty } return sum } fn summarize(text: string) -> Result<string, string> { val parsed = try json.parse(text) val item = try item_from_json(parsed) return ok(format("{} x{}", item.name, item.qty)) } fn main() { val items = [Item { name: "pen", qty: 3 }, Item { name: "ink", qty: 4 }] printf("total units: {}\n", total(items)) print(summarize("{\"name\":\"cup\",\"qty\":2}")) print(summarize("{\"name\":1}")) }
total units: 7 Ok(cup x2) Err(name: expected a string)
Errors are values. try propagates them; there is nothing to catch.
This program is tests/lang/readme_example.zm, run by the test suite on every
change — so it stays true. It is one of 1,142 fixtures that work the same way.
Errors that say what to write instead
A diagnostic is part of the language’s surface, not an afterthought. Ziman reports every error it can find rather than stopping at the first, names the file each one is in, and points a caret at the column. Where there is a right thing to write, the message says what it is.
ziman: type error at 2:19 in hello.zm: arithmetic operator requires two operands of the same numeric type, found int and float (use 'as' to cast explicitly) | 2 | val total = 3 + 2.5 | ^
No implicit coercion — and the fix is in the message.
ziman: type error at 1:1 in pick.zm: function
'pick' does not return a value on every path
|
1 | fn pick(n: int) -> string {
| ^
Checked without running: ziman --check loads and type-checks only.
--json reports each error as one JSON object for an editor or an agent.
The language at a glance
- Types.
int,float,bool,string,byte, arbitrary-precisionbigintanddecimal, arrays, structs, tagged-union enums,Option<T>,Result<T, E>,Map,Set,Channel<T>and function types. Values are immutable unless declaredvar. - Errors are values.
ResultandOptionwith a prefixtryto propagate, and a narrow bare-value auto-wrap soreturn xworks in aResultfunction. - Control flow.
if/else,while,for x in arr, an exhaustiveswitchover enums and results, anddeferfor cleanup. - Generics. Explicit type arguments with
Eq,HashandOrdbounds. No general traits. - Derives.
#[derive(Json)],#[derive(Row)]for SQL rows,#[derive(Entity)],#[derive(Ord)],#[derive(Properties)].--emit-derivedprints what each one generates. - Concurrency. Real OS threads with
spawnand thread-safe channels, in a single-writer style rather than shared memory. - Modules.
use path/to/modoruse mod.Name as alias. The standard library is bundled with the binary and needs no installation.
Standard library
Bundled with the binary, reached with use name. Every pub signature
is generated from the source into the corelib reference, and a gate fails if the committed
copy drifts.
| Modules | What they are |
|---|---|
| fs, os, process, clock, random | Files, environment and this process, starting and signalling children, time source, entropy |
| time | java.time-shaped dates, times, durations and instants, with named zones from the system’s own zone files |
| json, ndjson, csv, toml*, yaml* | JSON, and the other formats as converters to and from the same Json tree |
| xml*, markdown* | Document trees of their own, each with a reader, a writer that escapes per position, and limits where a format has no syntax errors to lean on |
| net, http, server, client, url | TCP and TLS, an HTTP/1.1 server toolkit with per-key rate limiting and connection caps, an HTTP client |
| db, sql*, eql*, sqlite, pg*, mysql*, memdb* | One database API over SQLite, PostgreSQL and MySQL, with pooling, a SQL statement tree, an entity query language, and an in-memory SQL engine written in Ziman |
| uuid, number, encoding, compress, bits | UUIDs, number formatting, base 2/8/16/32/64, deflate and gzip, bitwise helpers |
| crypto, jwt, otp | SHA-256, HMAC, PBKDF2, Argon2id, bcrypt; signed tokens; time-based one-time passwords |
| geom, shape, paint, scene, pdf, raster, font, image | A device-independent 2D drawing model, and two backends that render the same scene: PDF documents and anti-aliased raster images, with embedded TrueType text |
| properties, log, metrics, regex, schedule, locale* | Configuration, levelled logging, Prometheus-format metrics, regular expressions, cron and interval scheduling, system locale data |
* Experimental: less real-world use than the rest, so treat a gap or a protocol-conformance bug as more likely there.
Building and running
$ make
$ echo 'fn main() { print("hello, ziman") }' > hello.zm
$ ./ziman hello.zm
hello, ziman
Developed and tested on Linux (x86-64). Needs a C11 compiler, make, and
development files for SQLite, OpenSSL 3.2+, libxcrypt and zlib. macOS and the BSDs use the
same POSIX interfaces and will probably build, but nobody has tried. Windows needs WSL or a
container.
Manuals
- Tutorial Start here: the language in order, with programs you can run.
- Syntax reference The full grammar and rules — what the language is.
- Corelib reference
Every
pubsignature in the bundled library, generated from the source. - Cheatsheet One page, for when you know the idea and want the spelling.
- Design log A dated record of why each decision was made and what was tried — the reasoning behind the reference.
- Feature notes Long-form notes on individual features.
- Roadmap What is next, what was declined, and why.
Examples
One runnable program per library module, each stored with its expected output and checked by the suite — so an example that drifts from the library fails the build rather than misleading you.
- client
- clock
- compress
- crypto
- csv
- datasource
- db
- fs
- http
- json
- log
- markdown
- math
- mime
- ndjson
- net
- number
- os
- prelude
- properties
- random
- regex
- server
- sqlite
- thread
- time
- toml
- uuid
- xml
- yaml
Beyond the examples there is a whole application: health-record-backend-ziman, an HTTP backend with 27 repositories over SQLite and PostgreSQL, used as the language’s North Star and run by its test suite on every change.