spec/schema/zap.zap is written entirely in the whitespace-significant
form, and did not compile. Four spellings the whitespace form uses were
never rewritten into the tokens the brace grammar requires:
union content the keyword-first named union/group. Read as a
field named `union` of type `content` — silent
wherever a type of that name existed, so the
result was a differently-shaped schema rather
than a diagnostic. A header owns an indented
body and a field does not, so the offside rule
already separates them; now it does.
(name Text) method parameter and result lists omit the ':'
before each member's type for the same reason a
struct field does. Fields were rewritten; lists
were not.
extends Zap the brace form parenthesizes the superclass
list. The header was recognised but its clause
was passed through unchanged.
using X = ... at file scope the newline was not treated as the
statement terminator, though inside every block
it already was. A statement still holding an
open bracket is terminated on the line that
closes it, not on each line it spans.
The canonical schema now compiles with two errors left, both defects in
that file rather than gaps in the language: it declares no file id, and
it imports /go.capnp, which this toolchain does not ship. With those
two removed it compiles clean and generates 174 modules of Rust through
zapc, including the Gateway interface whose superclass and parameter
lists exercise three of the four rules above.
sample.ws.zap now writes its method list the way the whitespace form
reads, and still desugars byte-for-byte to sample.brace.zap.
225 + 250 tests pass, 41 of them desugar (6 new).
ZAP — C++ schema front-end
Docs: Schema language · Code generation — part of the ZAP Protocol
This repository is the canonical schema front-end for ZAP (Zero-copy
Application Protocol): the C++ implementation of the .zap schema parser and the
zap compiler binary that every language plugin (Rust, OCaml, Python, Haskell,
…) executes to read a schema. It also provides the underlying C++ runtime and KJ
support library.
It is derived from libcapnp and keeps that codebase's wire model and code-quality
bar, while ZAP adds the whitespace-significant schema grammar on top.
What it does
The zap binary parses a schema and emits a binary code-generator request on
stdout. Language plugins consume that request and emit code for their target
language — they never parse .zap text themselves. That is the contract that
keeps schema semantics identical across every binding: there is exactly one
parser, and it lives here.
ZAP schemas are whitespace-significant. Blocks are delimited by indentation (the
offside rule), there are no braces, and field ordinals are assigned automatically
in declaration order. A point.zap schema:
struct Point
x Float32
y Float32
interface PointTracker
addPoint (p Point) -> (totalPoints UInt64)
The front-end's compiler/desugar.{h,c++} lowers this indentation form to the
core grammar before the rest of the compiler runs. The legacy brace form
(x @0 :Float32;) still parses for backward compatibility — desugaring is a
no-op on it — so both surfaces produce byte-identical schemas.
Compiling schemas
# Emit a code-generator request to stdout (what a plugin reads on stdin).
zap compile -o- point.zap
# Drive a language plugin found on PATH (e.g. the Rust backend).
zap compile -orust point.zap
Plugins are resolved as zap-<lang> executables on PATH. The Rust, OCaml,
Python, and Haskell runtimes all shell out to this same zap binary; provisioning
it is how their CI builds run schema codegen.
Building
# Autotools
cd c++
autoreconf -i && ./configure && make -j check
# CMake
cmake -S c++ -B build && cmake --build build
# Bazel
bazel build //c++/...
make check builds the compiler (the zap_tool target) and runs the schema,
compiler, and runtime test suites.
Consumed by
| Plugin / runtime | Repository |
|---|---|
| Rust | zap-proto/rust |
| OCaml | zap-proto/ocaml |
| Python | zap-proto/py |
| Haskell | zap-proto/haskell |
The high-level C++ binding (client/server convenience API) is a separate
project, zap-proto/cpp; this repository is
the schema toolchain and core runtime those bindings build on.
License
MIT — see LICENSE.