Concrete Languages
Directory: quilt/src/langs/
Each language lives in its own subdirectory and contributes (at minimum) a lang.rs implementing Language and optionally a meta.rs implementing MetaLanguage.
Rust (rs) — host + meta
Files: langs/rust/lang.rs, langs/rust/meta.rs (generated), langs/rust/ops.rs
The Rust language is the primary host language. It supports:
- Parsing via the forked
tree-sitter-rust(hole placeholder{}). - Full
MetaLanguageimplementation generated by bootstrap frommk_meta.rs.quilt. - runnable via
quilt(usesrust-script).
Variadic nodes
"block" and "source_file" have Arity::Variadic. Inside a block quote, each child is emitted with .emit(&mut b_); into an imperative QTermBuilder block:
{
let mut b_ = tb("block");
b_.write("{");
child1.emit(&mut b_);
child2.emit(&mut b_);
b_.write("}");
b_.b()
}
Key operators (Rust meta-language)
| Glyph | Expands to | Result |
|---|---|---|
↑x | x.qlift() | A QTerm whose code reconstructs x |
↓expr | expr.reduce() | Evaluate expr at generation time via rust-script |
⟨N⟩ | name("ident") | An identifier node |
QLift trait (ops.rs)
QLift is implemented for:
Arc<QTerm>— recursively builds constructor code.str/String— becomes astring_literalnode.char— becomes achar_literalnode.- All integer types — become
integer_literalnodes.
reduce (ops.rs)
QTerm::reduce::<T>() compiles the term via rust-script, runs it, and deserializes the returned value via postcard. The script is given a cargo manifest in its frontmatter that points back to the local quilt crate.
Python (py) — host + meta
Files: langs/python/lang.rs, langs/python/meta.rs, langs/python/ops.rs
Python uses the forked tree-sitter-python (hole placeholder __HOLE__). Its MetaLanguage emits Python code targeting the quilt Python runtime (see Python Bindings).
Differences from the Rust meta-language
| Aspect | Rust | Python |
|---|---|---|
| Builder method | .c(&child) | .c(child) (no &) |
| Cmd sequences | &[..] Rust slice literal | [..] Python list |
| Variadic block | { let mut b_ = tb(..); b_.emit(..); b_.b() } | fluent chain .e(child1).e(child2).b() |
| Statement-splice | supported (via named b_) | not supported |
quilt invokes python3 for Python files and sets PYTHONPATH to include the quilt-python directory.
Python operators
| Glyph | Expands to |
|---|---|
↑(x) | qlift(x) into Python; qlift_html(x) into an HTML quote |
⟨N⟩ | name("ident") |
Python's lift is written prefix (↙↑(x)↘), unlike Rust's postfix x.↑: the spelling is a free function because a qlift method can't hang off builtin ints and strings.
Python also has a LiftTo marker type (Python in lift.rs), so a Rust host can lift values into quoted Python (python↖ … ↙x.↑↘ … ↗): integers, floats, bools, and strings lift to the corresponding literals, and slices/Vecs lift element-wise to list literals.
HTML (html) — target only
Files: langs/html/lang.rs, langs/html/mod.rs
HTML is a target-only language: it can appear inside quotes (html↖<p>Hello</p>↗) but is never the ground host and has no MetaLanguage. The Rust or Python host's meta-language drives expansion.
The HTML grammar is based on the forked tree-sitter-html with hole support.
Usage in a *.rs.quilt file:
let frag: Arc<QTerm> = html↖<div class="foo">↙content↘</div>↗;
WGSL (wgsl) — target only
Files: langs/wgsl/lang.rs, langs/wgsl/mod.rs
WebGPU Shading Language — used in *.wgsl.rs.quilt files where the extension chain is ["rs", "wgsl"]. Bare quotes inside such a file default to WGSL, while the ground language is Rust.
WGSL is target-only: no MetaLanguage.
Usage in shaders.wgsl.rs.quilt:
// Bare ↖…↗ defaults to WGSL here:
let shader = ↖
@vertex
fn vs_main(@builtin(position) pos: vec4<f32>) -> @builtin(position) vec4<f32> {
return pos;
}
↗;
Zsh (zsh) and Bash (bash) — target only
Files: langs/zsh/lang.rs, langs/zsh/mod.rs, langs/bash/lang.rs, langs/bash/mod.rs
Shell languages, parsed via the forked tree-sitter-zsh / tree-sitter-bash grammars. Both are target-only: they can appear inside quotes (zsh↖…↗, bash↖…↗) but have no MetaLanguage. Both also have LiftTo marker types (Zsh, Bash in lift.rs) so Rust values can be lifted into shell fragments.
Nix (nix) — target and host
Files: langs/nix/lang.rs, langs/nix/meta.rs, langs/nix/ops.rs, langs/nix/mod.rs
The Nix expression language, parsed via the forked tree-sitter-nix grammar. Nix is purely expression-oriented — a whole file is a single expression — so every fragment is an Expr and unquotes splice into expression positions; there are no statements.
The hole token is __QUILT_HOLE__, a plain Nix identifier (so it parses as a variable_expression in any expression position; the range-based hole detection in treesitter.rs recognises it).
As a target
Quote and splice Nix fragments inside another host (nix↖…↗). Nix has a LiftTo marker type (Nix in lift.rs): strings lift to double-quoted string_expressions (with ${ escaped to keep them inert), integers/floats to integer_expression/float_expression, booleans to the true/false builtins, and slices/Vecs to space-separated list_expressions. See examples/nix_module.rs.quilt:
let drv = nix↖
pkgs.stdenv.mkDerivation {
pname = ↙pname.↑↘;
buildInputs = ↙build_inputs↘;
}
↗;
As a host (string-based meta)
NixMetaLanguage makes Nix drive generation. Unlike the Rust/Python hosts, which emit builder calls into a QTerm runtime, the Nix host has no runtime library: meta.rs/ops.rs represent generated code as plain Nix strings. A quote ↖…↗ becomes a Nix string literal, a host unquote ↙x↘ becomes Nix's own ${x} antiquotation, and ↑ spells toString. So a .nix.quilt file expands to a Nix metaprogram that, evaluated (nix eval), yields the generated code as a string. Static sub-structure is flattened inline, so a literal fragment is one flat string, not a tower of ${"…"}.
The string model is language-agnostic (a Nix host can generate any target), but has no b_ accumulator, so emit/splice in ground loops is unsupported — build sequences functionally (map, concatStringsSep). See examples/nix_host.nix.quilt:
let
attr = "enabled";
package = "hello";
in
nix↖{
↙attr↘ = true;
default = ↙package↘;
}↗
expands to the Nix metaprogram let … in "{\n ${attr} = true;\n default = ${package};\n}".
Text (txt) — target only
Files: langs/text/lang.rs, langs/text/mod.rs, langs/text/meta.rs
Plain text. Useful when you want to quote an arbitrary string fragment without language-specific parsing. Has a MetaLanguage but only for text-level operations (the expand methods produce identity output).
Bootstrap (bs) — internal only
Files: langs/bootstrap/lang.rs, langs/bootstrap/meta.rs, langs/bootstrap/strlift.rs
The bootstrap language is used exclusively during the self-hosting step that generates langs/rust/meta.rs. It does not use tree-sitter; instead it parses Rust code using the production RustLanguage, then lifts by building strings (strlift.rs) and re-parsing them. This is slower but avoids the chicken-and-egg problem of needing meta.rs to generate meta.rs.
See Bootstrap for details.
Feature flags
Each language is gated behind a Cargo feature with the same name (quilt/Cargo.toml):
[features]
default = ["python", "rust", "text", "bootstrap", "wgsl", "html", "zsh", "bash"]
parse = ["dep:tree-sitter", "dep:tree-sitter-quilt", "dep:tree-sitter-rust", "dep:tree-sitter-python"]
bash = ["dep:tree-sitter-bash", "parse"]
html = ["dep:tree-sitter-html", "parse"]
wgsl = ["dep:tree-sitter-wgsl", "parse"]
zsh = ["dep:tree-sitter-zsh", "parse"]
python = []
rust = []
text = []
bootstrap = ["parse"]
The parse feature gates everything that needs tree-sitter (the Quilt-source parser, the Language providers, Omni, Multi's parse path). With default-features = false the crate is runtime-only (the QTerm builders, qlift, coparse) and builds for wasm32-unknown-unknown — this is how nanobots-codegen consumes it.
The Omni type is built only from features that are enabled, via #[cfg(feature = "…")] gates throughout langs/omni.rs.