Skip to main content

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 MetaLanguage implementation generated by bootstrap from mk_meta.rs.quilt.
  • runnable via quilt (uses rust-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)

GlyphExpands toResult
↑xx.qlift()A QTerm whose code reconstructs x
↓exprexpr.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 a string_literal node.
  • char — becomes a char_literal node.
  • All integer types — become integer_literal nodes.

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

AspectRustPython
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-splicesupported (via named b_)not supported

quilt invokes python3 for Python files and sets PYTHONPATH to include the quilt-python directory.

Python operators

GlyphExpands 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.