use crate::{Error, Graph, GraphBuilder, Limits, Op, Source, ValueId};
use std::sync::Arc;
pub(crate) struct Rebuilder<'g> {
graph: &'g Graph,
builder: GraphBuilder,
map: Vec<Option<ValueId>>,
}
impl<'g> Rebuilder<'g> {
pub(crate) fn new(graph: &'g Graph, limits: &Limits) -> Self {
Self {
graph,
builder: GraphBuilder::new(limits.clone()),
map: vec![None; graph.values().len()],
}
}
pub(crate) fn mapped(&self, old: ValueId) -> ValueId {
self.map[old.index()].expect("a value is rebuilt before any value that uses it")
}
pub(crate) fn alias(&mut self, old: ValueId, new: ValueId) {
self.map[old.index()] = Some(new);
}
pub(crate) fn copy(&mut self, old: ValueId) -> Result<ValueId, Error> {
let value = self.graph.value(old);
let name = self.graph.label(old);
let new = match &value.source {
Source::Input => self.builder.input(&name, value.ty.shape.clone())?,
Source::Constant(data) => {
self.builder
.constant_shared(&name, value.ty.shape.clone(), Arc::clone(data))?
}
Source::Node { op, inputs } => {
let inputs: Vec<ValueId> = inputs.iter().map(|&id| self.mapped(id)).collect();
self.builder.node(&name, op.clone(), &inputs)?
}
};
self.alias(old, new);
Ok(new)
}
pub(crate) fn replace_with_node(
&mut self,
old: ValueId,
op: Op,
inputs: &[ValueId],
) -> Result<ValueId, Error> {
let name = self.graph.label(old);
let new = self.builder.node(&name, op, inputs)?;
self.alias(old, new);
Ok(new)
}
pub(crate) fn replace_with_constant(
&mut self,
old: ValueId,
data: Arc<[f32]>,
) -> Result<ValueId, Error> {
let name = self.graph.label(old);
let shape = self.graph.value(old).ty.shape.clone();
let new = self.builder.constant_shared(&name, shape, data)?;
self.alias(old, new);
Ok(new)
}
pub(crate) fn finish(self) -> Result<Graph, Error> {
let outputs = self
.graph
.output_names()
.iter()
.zip(self.graph.outputs())
.map(|(name, &id)| (name.clone(), self.mapped(id)))
.collect();
self.builder.finish_named(outputs)
}
}