Skip to main content

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}