use std::fmt::{self, Debug, Formatter};
use crate::util::{AsUsize, ArrayMap, CommaSeparated};
use super::{Op, Cost, op_cost};
array_index! {
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Node(std::num::NonZeroUsize) {
debug_name: "Node",
UInt: usize,
}
}
array_index! {
#[derive(Copy, Clone, Hash, PartialEq, Eq)]
pub struct Out(std::num::NonZeroUsize) {
debug_name: "Out",
UInt: usize,
}
}
struct NodeAdapter<'a> {
dataflow: &'a Dataflow,
node: Node,
}
impl<'a> Debug for NodeAdapter<'a> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "{:?}: ({:?}) <- {:?} ({:?})",
self.node,
CommaSeparated(|| self.dataflow.outs(self.node)),
self.dataflow.op(self.node),
CommaSeparated(|| self.dataflow.ins(self.node)),
)?;
let deps = self.dataflow.deps(self.node);
if !deps.is_empty() {
write!(f, " after ({:?})", CommaSeparated(|| deps))?;
}
Ok(())
}
}
#[derive(Clone)]
struct Info {
op: Op,
cost: Option<&'static Cost>,
end_dep: usize,
end_in: usize,
end_out: usize,
}
#[derive(Clone)]
pub struct Dataflow {
nodes: Vec<Info>,
deps: Vec<Node>,
ins: Vec<Out>,
outs: Vec<Node>,
}
impl Dataflow {
pub fn new(num_inputs: usize) -> Self {
let mut ret = Dataflow {
nodes: Vec::new(),
deps: Vec::new(),
ins: Vec::new(),
outs: Vec::new(),
};
ret.add_node(Op::Convention, &[], &[], num_inputs);
ret
}
pub fn entry_node(&self) -> Node {
Node::new(0).unwrap()
}
fn info(&self, node: Node) -> &Info {
&self.nodes[node.as_usize()]
}
pub fn op(&self, node: Node) -> Op {
self.info(node).op
}
pub fn cost(&self, node: Node) -> &'static Cost {
self.info(node).cost.expect("Cannot execute Op::Convention")
}
pub fn is_entry(&self, node: Node) -> bool {
node.as_usize() == 0
}
fn prev(&self, node: Node) -> Option<&Info> {
if self.is_entry(node) {
None
} else {
Some(&self.nodes[node.as_usize() - 1])
}
}
pub fn deps(&self, node: Node) -> &[Node] {
let start_dep = self.prev(node).map_or(0, |prev| prev.end_dep);
&self.deps[start_dep .. self.info(node).end_dep]
}
pub fn ins(&self, node: Node) -> &[Out] {
let start_in = self.prev(node).map_or(0, |prev| prev.end_in);
&self.ins[start_in .. self.info(node).end_in]
}
pub fn num_outs(&self, node: Node) -> usize {
let start_out = self.prev(node).map_or(0, |prev| prev.end_out);
self.info(node).end_out - start_out
}
pub fn outs(&self, node: Node) -> impl Iterator<Item=Out> {
let start_out = self.prev(node).map_or(0, |prev| prev.end_out);
(start_out .. self.info(node).end_out).map(|index| Out::new(index).unwrap())
}
pub fn out(&self, out: Out) -> (Node, usize) {
let node = self.outs[out.as_usize()];
let start_out = self.prev(node).map_or(0, |prev| prev.end_out);
(node, out.as_usize() - start_out)
}
pub fn add_node(&mut self, op: Op, deps: &[Node], ins: &[Out], num_outs: usize) -> Node {
let node = Node::new(self.nodes.len()).unwrap();
self.deps.extend(deps);
self.ins.extend(ins);
self.outs.extend((0..num_outs).map(|_| node));
self.nodes.push(Info {
op: op,
cost: op_cost(op),
end_dep: self.deps.len(),
end_in: self.ins.len(),
end_out: self.outs.len(),
});
node
}
pub fn node_map<V: Default>(&self) -> ArrayMap<Node, V> {
ArrayMap::new(self.nodes.len())
}
pub fn out_map<V: Default>(&self) -> ArrayMap<Out, V> {
ArrayMap::new(self.outs.len())
}
pub fn all_nodes(&self) -> impl Iterator<Item=Node> {
(0..self.nodes.len()).map(|i| Node::new(i).unwrap())
}
}
impl Debug for Dataflow {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
f.write_str("Dataflow")?;
f.debug_list().entries(self.all_nodes().map(
|n| NodeAdapter {dataflow: self, node: n}
)).finish()
}
}