Skip to content

Formatter

The Mighty formatter is a Wadler/Lindig pretty-printer that operates over the rowan CST. It lives in crates/mty-fmt/.

In slice 1 the formatter is an identity pass: it parses the source, walks the CST, and re-emits the text verbatim. The combinator engine is fully built — slice 2 replaces the per-node stub with real format rules.

Entry point

pub fn format(green: GreenNode) -> String;

Doc combinators

doc.rs defines Doc, the abstract document description:

pub enum Doc {
    Nil,
    Text(Rc<str>),
    Line,
    SoftLine,
    Nest(usize, Box<Doc>),
    Group(Box<Doc>),
    Concat(Box<Doc>, Box<Doc>),
}

Constructor methods: Doc::nil(), Doc::text(s), Doc::line(), Doc::softline(), Doc::nest(n, d), Doc::group(d), Doc::concat(a, b), Doc::concat_all(parts), Doc::join(sep, parts).

Printer

printer.rs implements the standard Wadler/Lindig layout algorithm:

pub struct Layout { pub width: usize }   // default 100
pub fn pretty(doc: &Doc, layout: &Layout) -> String;

The printer walks the tree with an explicit stack, tracking the current column. When a Group is encountered it uses a fits lookahead to decide whether the whole group renders on the current line in Flat mode; otherwise the group switches to Break mode and its Lines become newlines.

Per-node rules

fmt/ is the per-node dispatch. Submodules:

Module Productions
items.rs fn, struct, enum, use, mod, type, impl, trait, const, extern, export, macro
agents.rs agent, protocol, supervisor
concurrency.rs arena, task scope, budget, sandbox
exprs.rs every expression
patterns.rs every pattern
types.rs every type expression

fmt::file(node) -> Doc is the top-level entry. In slice 1 it returns Doc::text(node.text().to_string()); slice 2 will dispatch by kind.

Trivia

trivia.rs tracks comments and blank lines that the per-node formatter must preserve. Real formatting needs to attach trivia to its nearest node and re-emit it in the right place. Slice 2 wires this into the per-node rules.

Round-trip tests

tests/fmt/ feeds every example file through mty fmt and asserts byte-identity. This is how slice 1 proves the identity pass actually preserves source — and how slice 2 will prove the real formatter is idempotent.

See also