The defnz and defz defining forms. These macros stay thin: they
parse the form into data, hand it to the pure pipeline (signature ->
spec -> source) and the shell (compile/cache -> load -> bind), then
rebind an ordinary Clojure Var. A user can reach every stage through
the data functions without the macro.
defnz defines a Clojure function backed by a Zig body. defz
registers Zig declarations that the bodies in its namespace may call
but that are not themselves callable from Clojure.
The `defnz` and `defz` defining forms. These macros stay thin: they parse the form into data, hand it to the pure pipeline (signature -> spec -> source) and the shell (compile/cache -> load -> bind), then rebind an ordinary Clojure Var. A user can reach every stage through the data functions without the macro. `defnz` defines a Clojure function backed by a Zig body. `defz` registers Zig declarations that the bodies in its namespace may call but that are not themselves callable from Clojure.
(artifact spec body)(artifact spec body gen)Compile or reuse the native library for spec and body. Returns the
inspection data describing the build: the spec, the body, the generated
source, the library and source paths, the symbol, and whether the
library was reused (:cached) or freshly built (:compiled).
Compile or reuse the native library for `spec` and `body`. Returns the inspection data describing the build: the spec, the body, the generated source, the library and source paths, the symbol, and whether the library was reused (`:cached`) or freshly built (`:compiled`).
(build-inputs spec body)(build-inputs spec
body
{:keys [mode entry options-extra aux-files] :or {mode :inline}})The cache/compile inputs for spec and body: the generated source,
prefixed with this namespace's defz declarations, plus the toolchain
identity that the content hash includes. The Zig version in the hash is
the pinned version, not a live zig version: every machine pins the same
toolchain, so a baked library and a function built in place hash alike,
and a consumer with no toolchain reproduces the hash without running Zig.
gen selects the source shape: inline splices the body string into a
wrapper; file concatenates the user's file text and a wrapper that calls
its pub fn; raw uses the file text as-is. gen also carries any
C-interop :options-extra. Options layer by precedence: the optimize
default, then the namespace zig-deps, then the descriptor, so a function
inherits its namespace's link flags and may still override them. A file
body that imports other Zig files carries them as :aux-files, reproduced
beside the source.
The cache/compile inputs for `spec` and `body`: the generated source, prefixed with this namespace's `defz` declarations, plus the toolchain identity that the content hash includes. The Zig version in the hash is the pinned version, not a live `zig version`: every machine pins the same toolchain, so a baked library and a function built in place hash alike, and a consumer with no toolchain reproduces the hash without running Zig. `gen` selects the source shape: inline splices the body string into a wrapper; file concatenates the user's file text and a wrapper that calls its `pub fn`; raw uses the file text as-is. `gen` also carries any C-interop `:options-extra`. Options layer by precedence: the optimize default, then the namespace `zig-deps`, then the descriptor, so a function inherits its namespace's link flags and may still override them. A file body that imports other Zig files carries them as `:aux-files`, reproduced beside the source.
(c-options descriptor)The C-interop compile options a descriptor's :c/* keys carry, or nil
when it carries none. These reach zig build-lib as flags and enter the
content hash. Shared by a per-function {:zig/file ...} descriptor and a
namespace-level zig-deps.
The C-interop compile options a descriptor's `:c/*` keys carry, or nil
when it carries none. These reach `zig build-lib` as flags and enter the
content hash. Shared by a per-function `{:zig/file ...}` descriptor and a
namespace-level `zig-deps`.(declared-namespace zig-text)The namespace a .zig file asserts it belongs to via a leading
//! clj-zig: <ns> doc-comment line, or nil when it makes no such
assertion. Pure.
The namespace a `.zig` file asserts it belongs to via a leading `//! clj-zig: <ns>` doc-comment line, or nil when it makes no such assertion. Pure.
(defenumz type-name & tail)Define an enum boundary type backed by an i32. Members cross as
keywords named for each member; the Var holds the descriptor.
(defenumz ParseStatus
[ok 0
invalid 1
eof 2])
Define an enum boundary type backed by an `i32`. Members cross as
keywords named for each member; the Var holds the descriptor.
(defenumz ParseStatus
[ok 0
invalid 1
eof 2])(defnz fn-name & tail)Define a Clojure function whose body is Zig. The signature vector is
the boundary contract; the trailing form is the Zig body, a string or a
{:zig/file "name.zig"} descriptor, and may be omitted to source the
body from the namespace's co-located .zig:
(defnz add
[x :i64
y :i64
:ret :i64]
"return x + y;")
(defnz dot
[a [:slice :const :f64]
b [:slice :const :f64]
:ret :f64]
{:zig/file "dot.zig"})
;; body in app/geometry.zig's `pub fn hypotenuse`
(defnz hypotenuse
[a :f64 b :f64 :ret :f64])
;; signature inferred from app/geometry.zig's `pub fn hypotenuse`
(defnz hypotenuse)
A file holds a complete Zig pub fn the generated wrapper calls; a
bodyless form calls the pub fn of the same name in the .zig beside
the namespace's source, inferring the signature from it when the
signature is omitted too. The descriptor may also carry C-interop options
(:c/link, :c/include-path, ...), an entry name (:zig/fn), and a raw
escape hatch (:zig/raw, :zig/symbol). Redefining recompiles; a failed
recompile keeps the last good binding.
Define a Clojure function whose body is Zig. The signature vector is
the boundary contract; the trailing form is the Zig body, a string or a
`{:zig/file "name.zig"}` descriptor, and may be omitted to source the
body from the namespace's co-located `.zig`:
(defnz add
[x :i64
y :i64
:ret :i64]
"return x + y;")
(defnz dot
[a [:slice :const :f64]
b [:slice :const :f64]
:ret :f64]
{:zig/file "dot.zig"})
;; body in app/geometry.zig's `pub fn hypotenuse`
(defnz hypotenuse
[a :f64 b :f64 :ret :f64])
;; signature inferred from app/geometry.zig's `pub fn hypotenuse`
(defnz hypotenuse)
A file holds a complete Zig `pub fn` the generated wrapper calls; a
bodyless form calls the `pub fn` of the same name in the `.zig` beside
the namespace's source, inferring the signature from it when the
signature is omitted too. The descriptor may also carry C-interop options
(`:c/link`, `:c/include-path`, ...), an entry name (`:zig/fn`), and a raw
escape hatch (`:zig/raw`, `:zig/symbol`). Redefining recompiles; a failed
recompile keeps the last good binding.(defrecordz type-name & tail)Define both a Clojure record and a named boundary type sharing its layout. A signature in this namespace may name the record as an argument or return type; a record-typed return rebuilds the record on the Clojure side instead of returning a plain map.
(defrecordz Point
[x :f64
y :f64])
Define both a Clojure record and a named boundary type sharing its
layout. A signature in this namespace may name the record as an
argument or return type; a record-typed return rebuilds the record on
the Clojure side instead of returning a plain map.
(defrecordz Point
[x :f64
y :f64])(deftypez type-name & tail)Define a named boundary type with an extern struct layout. The
signatures in this namespace may name it as an argument or return type;
the Var holds the layout descriptor.
(deftypez Point
[x :f64
y :f64])
Define a named boundary type with an `extern struct` layout. The
signatures in this namespace may name it as an argument or return type;
the Var holds the layout descriptor.
(deftypez Point
[x :f64
y :f64])(defz decl-name decl-source)Register a Zig declaration usable by the defnz bodies in this
namespace. It is not callable from Clojure; the Var holds its source.
The source is a string or a {:zig/file "shared.zig"} descriptor,
the natural home for a shared @cImport block and helper fns.
Register a Zig declaration usable by the `defnz` bodies in this
namespace. It is not callable from Clojure; the Var holds its source.
The source is a string or a `{:zig/file "shared.zig"}` descriptor,
the natural home for a shared `@cImport` block and helper fns.(deps-in ns-sym)The namespace-level C-interop options registered for ns-sym, or nil.
The namespace-level C-interop options registered for `ns-sym`, or nil.
(establish! spec body)(establish! spec body gen)Build the artifact for spec and body and bind its symbol. Returns
the inspection data plus the native invoker under :invoke. Throws the
compile diagnostic when the Zig does not build.
Build the artifact for `spec` and `body` and bind its symbol. Returns the inspection data plus the native invoker under `:invoke`. Throws the compile diagnostic when the Zig does not build.
(establish-binding! the-var spec body var-meta wrap)(establish-binding! the-var spec body var-meta wrap gen)Establish the native function for the-var and rebind it. wrap turns
the raw invoker into the public fn (it carries the arglist and any
destructuring). On success the root is swapped, inspection metadata is
merged, and any stale failure is cleared. On failure the last good root
is left untouched, the failed attempt is recorded for inspection, and
the rendered diagnostic is rethrown so the REPL shows it at once.
Establish the native function for `the-var` and rebind it. `wrap` turns the raw invoker into the public fn (it carries the arglist and any destructuring). On success the root is swapped, inspection metadata is merged, and any stale failure is cleared. On failure the last good root is left untouched, the failed attempt is recorded for inspection, and the rendered diagnostic is rethrown so the REPL shows it at once.
(establish-binding-from! the-var spec descriptor defining-file var-meta wrap)Resolve a {:zig/file ...} descriptor relative to defining-file, read
the Zig source, and establish the binding for the-var. File mode
generates a wrapper that calls the user's pub fn; :zig/raw skips the
wrapper and binds :zig/symbol (or the spec's symbol) directly. The
body's relative @imports are resolved and carried along so they compile
in the cache directory. An optional //! clj-zig: <ns> header in the
file must match the using namespace. Public because the defnz
expansion calls it at load time, so re-evaluating the form re-reads the
file and its imports.
Resolve a `{:zig/file ...}` descriptor relative to `defining-file`, read
the Zig source, and establish the binding for `the-var`. File mode
generates a wrapper that calls the user's `pub fn`; `:zig/raw` skips the
wrapper and binds `:zig/symbol` (or the spec's symbol) directly. The
body's relative `@import`s are resolved and carried along so they compile
in the cache directory. An optional `//! clj-zig: <ns>` header in the
file must match the using namespace. Public because the `defnz`
expansion calls it at load time, so re-evaluating the form re-reads the
file and its imports.(namespace-zig-file defining-file)The .zig file co-located with a namespace's Clojure source: the
defining file's path with its .clj/.cljc extension replaced by
.zig. A bodyless defnz sources its body from this file's matching
pub fn. Pure; the filesystem and classpath resolution happens in
establish-binding-from!. Throws when there is no defining file, as at
the REPL, where a bodyless defnz has no co-located file to read.
The `.zig` file co-located with a namespace's Clojure source: the defining file's path with its `.clj`/`.cljc` extension replaced by `.zig`. A bodyless `defnz` sources its body from this file's matching `pub fn`. Pure; the filesystem and classpath resolution happens in `establish-binding-from!`. Throws when there is no defining file, as at the REPL, where a bodyless `defnz` has no co-located file to read.
(recompile! the-var)Force a fresh build of the-var's current spec and body, ignoring the
cached artifact, and rebind. Returns the Var. Rebuilds in the same mode
the function was defined with (inline, file, or raw).
Force a fresh build of `the-var`'s current spec and body, ignoring the cached artifact, and rebind. Returns the Var. Rebuilds in the same mode the function was defined with (inline, file, or raw).
(register-decl! ns-sym decl-name decl-source)Register or replace a defz declaration in its namespace, preserving
declaration order so the generated preamble is stable. Public because
the defz expansion calls it from the user's namespace.
Register or replace a `defz` declaration in its namespace, preserving declaration order so the generated preamble is stable. Public because the `defz` expansion calls it from the user's namespace.
(register-deps! ns-sym descriptor)Register the namespace-level C-interop options for ns-sym, replacing
any previous registration. Public because the zig-deps expansion calls
it from the user's namespace.
Register the namespace-level C-interop options for `ns-sym`, replacing any previous registration. Public because the `zig-deps` expansion calls it from the user's namespace.
(register-type! ns-sym descriptor)Register or replace a deftypez layout descriptor in its namespace.
Public because the deftypez expansion calls it from the user's
namespace.
Register or replace a `deftypez` layout descriptor in its namespace. Public because the `deftypez` expansion calls it from the user's namespace.
(resolve-decl-source decl-source defining-file)The Zig text for a defz declaration: a string as-is, or the contents
of the {:zig/file ...} it names, resolved relative to defining-file.
Public because the defz expansion calls it at load time.
The Zig text for a `defz` declaration: a string as-is, or the contents
of the `{:zig/file ...}` it names, resolved relative to `defining-file`.
Public because the `defz` expansion calls it at load time.(types-in ns-sym)The map of named-type descriptors declared in ns-sym, keyed by name.
The map of named-type descriptors declared in `ns-sym`, keyed by name.
(zig-deps descriptor)Declare the C-interop options shared by every defnz in this namespace,
so a co-located .zig may @cImport a header and link its library
without repeating the flags on each function:
(zig-deps {:c/link ["m"]})
A function descriptor still overrides these. The options enter each function's content hash, so changing them recompiles the namespace's functions.
Declare the C-interop options shared by every `defnz` in this namespace,
so a co-located `.zig` may `@cImport` a header and link its library
without repeating the flags on each function:
(zig-deps {:c/link ["m"]})
A function descriptor still overrides these. The options enter each
function's content hash, so changing them recompiles the namespace's
functions.cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |