tidepool_repr/builder.rs
1use crate::frame::CoreFrame;
2use crate::tree::{MapLayer, RecursiveTree};
3
4/// Builds a RecursiveTree by appending nodes bottom-up.
5///
6/// Using TreeBuilder avoids manual index arithmetic when constructing CoreExpr trees.
7///
8/// # Example
9/// ```
10/// use tidepool_repr::{TreeBuilder, CoreFrame, Literal, VarId};
11///
12/// let mut b = TreeBuilder::new();
13/// let x = b.push(CoreFrame::Var(VarId(1)));
14/// let lit = b.push(CoreFrame::Lit(Literal::LitInt(42)));
15/// let app = b.push(CoreFrame::App { fun: x, arg: lit });
16/// let expr = b.build();
17/// assert_eq!(expr.nodes.len(), 3);
18/// ```
19#[derive(Debug, Clone)]
20pub struct TreeBuilder {
21 nodes: Vec<CoreFrame<usize>>,
22}
23
24impl TreeBuilder {
25 /// Create a new empty builder.
26 pub fn new() -> Self {
27 Self { nodes: Vec::new() }
28 }
29
30 /// Add a node, return its index.
31 pub fn push(&mut self, frame: CoreFrame<usize>) -> usize {
32 let idx = self.nodes.len();
33 self.nodes.push(frame);
34 idx
35 }
36
37 /// Append all nodes from another builder, offsetting indices.
38 /// Returns the offset of the first added node.
39 pub fn push_tree(&mut self, other: TreeBuilder) -> usize {
40 let offset = self.nodes.len();
41 for node in other.nodes {
42 self.nodes.push(node.map_layer(|idx| idx + offset));
43 }
44 offset
45 }
46
47 /// Finish building, return the tree.
48 pub fn build(self) -> RecursiveTree<CoreFrame<usize>> {
49 RecursiveTree { nodes: self.nodes }
50 }
51}
52
53impl Default for TreeBuilder {
54 fn default() -> Self {
55 Self::new()
56 }
57}