1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
//! The trait every AST node implements.
use Id;
use Span;
/// The contract a language's syntax-tree node satisfies so the generic traversals
/// in this crate can walk and rebuild it.
///
/// ast-lang owns no grammar: a language defines its own node type — almost always
/// a single `enum` with a variant per syntactic form — stores its nodes in an
/// [`Arena`](arena_lang::Arena), and wires the tree with [`Id`] handles. Implementing
/// `Node` for that type is what lets [`walk`](crate::walk) and
/// [`transform`](crate::transform) operate on it without knowing what the variants
/// are.
///
/// The contract is three operations, and nothing more:
///
/// - [`span`](Node::span) — the byte range of source this node covers.
/// - [`each_child`](Node::each_child) — report the node's direct child handles, in
/// source order. Read traversal is built on this.
/// - [`map_children`](Node::map_children) — rebuild the node with each child handle
/// replaced by another, preserving everything else. Rewriting is built on this.
///
/// The two traversal operations are kept separate so a leaf node — one with no
/// children — is an empty `each_child` and a plain clone in `map_children`.
///
/// # Examples
///
/// A minimal expression tree. The node carries its span and its child handles; the
/// three methods just thread those handles through.
///
/// ```
/// use ast_lang::{Id, Node, Span};
///
/// enum Expr {
/// Lit(i64, Span),
/// Neg(Id<Expr>, Span),
/// Add(Id<Expr>, Id<Expr>, Span),
/// }
///
/// impl Node for Expr {
/// fn span(&self) -> Span {
/// match self {
/// Expr::Lit(_, s) | Expr::Neg(_, s) | Expr::Add(_, _, s) => *s,
/// }
/// }
///
/// fn each_child(&self, f: &mut dyn FnMut(Id<Self>)) {
/// match self {
/// Expr::Lit(..) => {}
/// Expr::Neg(a, _) => f(*a),
/// Expr::Add(a, b, _) => {
/// 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::Neg(a, s) => Expr::Neg(f(*a), *s),
/// Expr::Add(a, b, s) => Expr::Add(f(*a), f(*b), *s),
/// }
/// }
/// }
/// ```