use cow_vec::CowVec;
use smallvec::SmallVec;
use crate::Shape;
use crate::op::Op;
use super::opcode::Node;
use super::{Origin, Symbol, ValueId};
use super::Operands;
#[derive(Debug, Clone)]
pub(crate) struct Structure<Data> {
pub(crate) ops: CowVec<Op<Data>>,
pub(crate) operands: CowVec<Operands>,
pub(crate) shapes: CowVec<Shape>,
}
impl<Data> Structure<Data> {
pub(crate) fn new() -> Self {
Self {
ops: CowVec::new(),
operands: CowVec::new(),
shapes: CowVec::new(),
}
}
pub(crate) fn len(&self) -> usize {
self.ops.len()
}
pub(crate) fn push(&mut self, op: Op<Data>, operands: Operands, shape: Shape) -> ValueId {
self.ops.push(op);
self.operands.push(operands);
self.shapes.push(shape);
debug_assert_eq!(self.ops.len(), self.operands.len());
debug_assert_eq!(self.ops.len(), self.shapes.len());
ValueId(self.ops.len() - 1)
}
}
impl<Data> Structure<Data> {
pub(crate) fn ancestors(&self, seeds: impl IntoIterator<Item = ValueId>) -> Vec<bool> {
let mut wanted = vec![false; self.len()];
for seed in seeds {
wanted[seed.index()] = true;
}
for index in (0..wanted.len()).rev() {
if !wanted[index] {
continue;
}
let links = self
.operands
.get(index)
.expect("operand links cover the columns");
for link in links.as_slice() {
wanted[link.index()] = true;
}
}
wanted
}
pub(crate) fn node_at(&self, origin: Origin, index: usize) -> Node {
let op = self
.ops
.get(index)
.expect("`node_at` index is in bounds for its columns");
let operands: SmallVec<[Symbol; 2]> = self
.operands
.get(index)
.expect("operand links cover the columns")
.as_slice()
.iter()
.map(|link| Symbol { origin, id: *link })
.collect();
Node {
symbol: Symbol {
origin,
id: ValueId(index),
},
opcode: op.opcode(),
shape: self
.shapes
.get(index)
.expect("shapes cover the columns")
.clone(),
operands,
}
}
}