QTerm IR
File: quilt/src/qterm.rs
QTerm is the central intermediate representation. Every parsed .quilt file becomes a tree of Arc<QTerm> nodes; expansion transforms that tree into a flat QTerm (no Quote/Unquote variants) ready for serialization.
Variants
pub enum QTerm {
Quote { tag, index, lang, term: Arc<QTerm>, cmds, span: Option<Span> },
Unquote { tag, index, lang, term: Arc<QTerm>, cmds, span: Option<Span> },
Tuple { tag, terms: Box<[Arc<QTerm>]>, cmds },
}
Tuple
The workhorse. Represents any parsed AST node: an expression, statement, block, or leaf token.
tag— the tree-sitter node kind:"block","binary_expression","integer_literal","identifier", etc.terms— zero or more childQTerms (zero for leaf nodes).cmds— aBox<[CmdOrHole]>that interleavesStrCmdprinting instructions withHolemarkers.Holeat position i means "print the i-th child here". This is how whitespace and punctuation are stored.
Quote
Wraps a fragment to be treated as data.
tag— the tree-sitter node kind of the hole where this quote appears in the outer language (e.g."expression_statement","let_declaration").index— quasi-quote nesting depth (always 1 after parsing; can increment if quotes are nested inside quotes).lang— the language of the quoted content (e.g."rs","wgsl").term— the quotedQTerm.cmds— the surrounding serialization commands (includes the↖…↗glyphs).span— byte range of theanno↖…↗in the original source when the term came from parsing (build_nodesattaches it),Nonefor constructed terms. Diagnostic metadata only: it is ignored byPartialEq, and errors like "unquote depth too high" use it to point at the offending source.
Unquote
A splice site.
tag— the hole kind in the outer language.index— depth at which this unquote escapes (1 = escape one level of quoting).lang— the language being unquoted into.- Same
term,cmds, andspanfields asQuote.
Constructor functions
// Arc-returning constructors (most common)
leaf(tag, code) // childless node with a Write cmd
sym(s) // leaf where tag == code
tuple(tag, &terms, &cmds)
quote(tag, index, lang, term, &cmds)
unquote(tag, index, lang, term, &cmds)
// QTerm-returning (no Arc) — used internally
qleaf, qsym, qtuple, qquote, qunquote
// span-carrying variants (used by the parser and span-preserving rewrites)
qquote_at(tag, index, lang, term, &cmds, span)
qunquote_at(tag, index, lang, term, &cmds, span)
leaf("integer_literal", "42") is the typical way to create a literal token. sym("{") creates a token where the tag is also the printed text (punctuation, keywords).
Serialization: StrCmd and CmdOrHole
StrCmd drives output generation:
pub enum StrCmd {
Write(Box<str>), // emit this string (ignores prefix)
NewLine, // emit newline then re-emit the current indent prefix
Push(Box<str>), // push an extra prefix level
Pop, // pop the top prefix level
}
CmdOrHole is either a StrCmd or a Hole marker. The cmds field of every QTerm variant is Box<[CmdOrHole]>.
PrefixWriter (strcmd.rs) maintains the prefix stack and interprets StrCmds when writing to any std::io::Write.
The constants NL, POP, and the functions write(s), push(s), cmd(c), HOLE are re-exported from prelude.
The QTermBuilder API
Builder for constructing terms with an ergonomic fluent interface.
// Constructors for builders
tb(tag) // Tuple builder
qb(tag, index, lang) // Quote builder
ub(tag, index, lang) // Unquote builder
// Fluent methods (each returns Self for chaining)
.w(s) // Write(s)
.n() // NewLine
.p(s) // Push(s)
.x() // Pop
.c(&child) // insert child at this Hole position
.e(x) // emit — calls x.emit(&mut self)
.b() // build and return Arc<QTerm>
The Emit trait allows any type that "emits" things into a builder:
Arc<QTerm>emits itself as a child.Vec<T: Emit>emits each element.()emits nothing.&stremits aWrite.StrCmdemits itself as a cmd.
Example
let expr = tb("binary_expression")
.c(&leaf("integer_literal", "1"))
.w(" + ")
.c(&leaf("integer_literal", "2"))
.b();
Utility methods
| Method | Description |
|---|---|
qterm.sexp() | Debug-friendly s-expression string |
qterm.squash() | If exactly one child, absorb its cmds into the parent's |
qterm.rewrite_naive(find, replace) | Recursive structural substitution |
qterm.coparse() | Serialize to a String using the embedded cmds |
qterm.dump(path) | Write to a file |
qterm.dump_with_cmds(path, prefix_cmds, suffix_cmds) | Write with extra leading/trailing cmds |
QTermTag
A tag value that identifies a QTerm variant without its children:
pub enum QTermTag {
Quote(Box<str>, Index, Box<str>),
Unquote(Box<str>, Index, Box<str>),
Tuple(Box<str>),
}
Used by QTermBuilder::new(tag) and the Term trait.