use super::{VarId, Vtree, VtreeIdx, VtreeNode};
#[derive(Default)]
pub(crate) struct VtreeArena {
nodes: Vec<VtreeNode>,
}
impl VtreeArena {
pub(crate) fn new() -> Self {
VtreeArena { nodes: Vec::new() }
}
pub(crate) fn with_capacity(cap: usize) -> Self {
VtreeArena {
nodes: Vec::with_capacity(cap),
}
}
pub(crate) fn leaf(&mut self, var: VarId) -> VtreeIdx {
let idx = VtreeIdx(self.nodes.len() as u32);
self.nodes.push(VtreeNode::Leaf { var, parent: None });
idx
}
pub(crate) fn internal(&mut self, left: VtreeIdx, right: VtreeIdx) -> VtreeIdx {
let idx = VtreeIdx(self.nodes.len() as u32);
self.nodes.push(VtreeNode::Internal {
left,
right,
parent: None,
});
idx
}
pub(crate) fn graft(&mut self, sub: &Vtree, var: impl Fn(VarId) -> VarId) -> VtreeIdx {
let offset = self.nodes.len() as u32;
for node in &sub.nodes {
match *node {
VtreeNode::Leaf { var: local, .. } => {
self.leaf(var(local));
}
VtreeNode::Internal { left, right, .. } => {
self.internal(VtreeIdx(left.0 + offset), VtreeIdx(right.0 + offset));
}
}
}
VtreeIdx(sub.root.0 + offset)
}
pub(crate) fn len(&self) -> usize {
self.nodes.len()
}
pub(crate) fn truncate(&mut self, len: usize) {
self.nodes.truncate(len);
}
pub(crate) fn nodes(&self) -> &[VtreeNode] {
&self.nodes
}
pub(crate) fn into_nodes(self) -> Vec<VtreeNode> {
self.nodes
}
}