ast-lang 1.0.0

AST node traits with visitor/fold/transform machinery.
Documentation

Installation

[dependencies]
ast-lang = "1"

Example

A language brings its own node type; ast-lang carries the traversal.

use ast_lang::{transform, walk, Arena, Flow, Id, Node, Span, Visitor};

#[derive(Clone)]
enum Expr {
    Lit(i64, Span),
    Add(Id<Expr>, Id<Expr>, Span),
}

impl Node for Expr {
    fn span(&self) -> Span {
        match self {
            Expr::Lit(_, s) | Expr::Add(_, _, s) => *s,
        }
    }
    fn each_child(&self, f: &mut dyn FnMut(Id<Self>)) {
        if let Expr::Add(a, b, _) = self {
            f(*a);
            f(*b);
        }
    }
    fn map_children(&self, f: &mut dyn FnMut(Id<Self>) -> Id<Self>) -> Self {
        match self {
            Expr::Lit(v, s) => Expr::Lit(*v, *s),
            Expr::Add(a, b, s) => Expr::Add(f(*a), f(*b), *s),
        }
    }
}

let mut arena = Arena::new();
let one = arena.alloc(Expr::Lit(1, Span::new(0, 1)));
let two = arena.alloc(Expr::Lit(2, Span::new(4, 5)));
let add = arena.alloc(Expr::Add(one, two, Span::new(0, 5)));

// Walk read-only; transform rebuilds into a fresh arena.
let mut doubled = Arena::new();
let _ = transform(&arena, add, &mut doubled, |node| match node {
    Expr::Lit(v, s) => Expr::Lit(v * 2, s),
    other => other,
});

Status

This is v1.0.0: the public API is stable and frozen under SemVer. The node trait and the iterative (stack-safe) walk / transform machinery are complete and catalogued in docs/API.md.

Contributing

See dev/DIRECTIVES.md for engineering standards and the definition of done. Before a PR: cargo fmt --all, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-features must be clean.