#![allow(clippy::large_enum_variant)]
#![allow(clippy::vec_init_then_push)]
use std::path::PathBuf;
use awint::awint_dag::{
triple_arena::{Advancer, Arena, ChainArena, Ptr},
triple_arena_render::{render_to_svg_file, DebugNode, DebugNodeTrait},
};
use crate::{
route::{channel::Referent, CEdge, CNode, Channeler},
Error,
};
#[derive(Debug, Clone)]
pub enum NodeKind<PCNode: Ptr, PCEdge: Ptr> {
CNode(CNode<PCNode, PCEdge>),
SubNode(PCNode, PCNode),
CEdgeIncidence(PCNode, PCEdge, Option<usize>, CEdge<PCNode>, CEdge<PCNode>),
Remove,
}
impl<PCNode: Ptr, PCEdge: Ptr> DebugNodeTrait<PCNode> for NodeKind<PCNode, PCEdge> {
fn debug_node(_p_this: PCNode, this: &Self) -> DebugNode<PCNode> {
match this {
NodeKind::CNode(cnode) => DebugNode {
sources: {
let mut v = vec![];
if let Some(p_supernode) = cnode.p_supernode {
v.push((p_supernode, "super".to_owned()));
}
v
},
center: { vec!["cnode".to_owned(), format!("{:?}", cnode.p_this_cnode)] },
sinks: vec![],
},
NodeKind::SubNode(p_back, p_back_forwarded) => DebugNode {
sources: vec![],
center: { vec!["sub".to_owned()] },
sinks: vec![(*p_back_forwarded, format!("{p_back:?}"))],
},
NodeKind::CEdgeIncidence(p_back, p_cedge, i, cedge, cedge_forwarded) => DebugNode {
sources: {
let mut v = vec![(*p_back, String::new())];
for (source, source_forwarded) in
cedge.sources().iter().zip(cedge_forwarded.sources().iter())
{
v.push((*source_forwarded, format!("{source:?}")));
}
v
},
center: {
vec![
format!("{p_cedge:?}"),
if let Some(source_i) = i {
format!("{source_i}")
} else {
"".to_owned()
},
]
},
sinks: {
let mut v = vec![];
if i.is_none() {
v.push((cedge_forwarded.sink(), "".to_owned()));
}
v
},
},
NodeKind::Remove => panic!("should have been removed"),
}
}
}
#[derive(Debug, Clone)]
pub enum LevelNodeKind<PCNode: Ptr, PCEdge: Ptr> {
CNode(CNode<PCNode, PCEdge>, CNode<PCNode, PCEdge>),
CEdge(PCEdge, CEdge<PCNode>, CEdge<PCNode>),
Remove,
}
impl<PCNode: Ptr, PCEdge: Ptr> DebugNodeTrait<PCNode> for LevelNodeKind<PCNode, PCEdge> {
fn debug_node(_p_this: PCNode, this: &Self) -> DebugNode<PCNode> {
match this {
LevelNodeKind::CNode(cnode, forwarded_cnode) => DebugNode {
sources: vec![],
center: {
let mut v = vec![
format!("{} cnode {}", cnode.lvl, cnode.internal_behavior.lut_bits),
format!("{:?}", cnode.p_this_cnode),
];
if let Some(p_supernode) = forwarded_cnode.p_supernode {
v.push(format!("sup: {:?}", p_supernode));
}
v
},
sinks: vec![],
},
LevelNodeKind::CEdge(p_cedge, cedge, cedge_forwarded) => DebugNode {
sources: {
let mut v = vec![];
for (source, source_forwarded) in
cedge.sources().iter().zip(cedge_forwarded.sources().iter())
{
v.push((*source_forwarded, format!("{source:?}")));
}
v
},
center: {
let mut v = cedge.programmability().debug_strings();
v.push(format!("{p_cedge:?}"));
v
},
sinks: { vec![(cedge_forwarded.sink(), "".to_owned())] },
},
LevelNodeKind::Remove => panic!("should have been removed"),
}
}
}
#[derive(Debug, Clone)]
pub enum HierarchyNodeKind<PCNode: Ptr, PCEdge: Ptr> {
CNode(CNode<PCNode, PCEdge>, Option<(PCNode, PCNode)>),
CEdge(PCEdge, CEdge<PCNode>, CEdge<PCNode>),
Remove,
}
impl<PCNode: Ptr, PCEdge: Ptr> DebugNodeTrait<PCNode> for HierarchyNodeKind<PCNode, PCEdge> {
fn debug_node(_p_this: PCNode, this: &Self) -> DebugNode<PCNode> {
match this {
HierarchyNodeKind::CNode(cnode, p_super) => DebugNode {
sources: if let Some((p_super, p_super_forwarded)) = p_super {
vec![(*p_super_forwarded, format!("{p_super:?}"))]
} else {
vec![]
},
center: {
vec![
format!("{} cnode {}", cnode.lvl, cnode.internal_behavior.lut_bits),
format!("{:?}", cnode.p_this_cnode),
]
},
sinks: vec![],
},
HierarchyNodeKind::CEdge(p_cedge, cedge, cedge_forwarded) => DebugNode {
sources: {
let mut v = vec![];
for (source, source_forwarded) in
cedge.sources().iter().zip(cedge_forwarded.sources().iter())
{
v.push((*source_forwarded, format!("{source:?}")));
}
v
},
center: {
let mut v = cedge.programmability().debug_strings();
v.push(format!("{p_cedge:?}"));
v
},
sinks: { vec![(cedge_forwarded.sink(), "".to_owned())] },
},
HierarchyNodeKind::Remove => panic!("should have been removed"),
}
}
}
impl<PCNode: Ptr, PCEdge: Ptr> Channeler<PCNode, PCEdge> {
pub fn to_cnode_backrefs_debug(&self) -> Arena<PCNode, NodeKind<PCNode, PCEdge>> {
let mut arena = Arena::<PCNode, NodeKind<PCNode, PCEdge>>::new();
self.cnodes
.clone_keys_to_arena(&mut arena, |p_self, referent| {
let p_cnode = self.cnodes.get_val(p_self).unwrap().clone().p_this_cnode;
match *referent {
Referent::ThisCNode => {
NodeKind::CNode(self.cnodes.get_val(p_self).unwrap().clone())
}
Referent::SubNode(p_back) => NodeKind::SubNode(p_back, p_cnode),
Referent::CEdgeIncidence(p_cedge, i) => {
let cedge = self.cedges.get(p_cedge).unwrap().clone();
let mut cedge_forwarded = cedge.clone();
for source in cedge_forwarded.sources_mut() {
*source = self.cnodes.get_val(*source).unwrap().p_this_cnode;
}
if i.is_none() {
*cedge_forwarded.sink_mut() =
self.cnodes.get_val(cedge.sink()).unwrap().p_this_cnode;
}
NodeKind::CEdgeIncidence(p_cnode, p_cedge, i, cedge, cedge_forwarded)
}
}
});
let mut adv = arena.advancer();
while let Some(p) = adv.advance(&arena) {
if let NodeKind::Remove = arena.get(p).unwrap() {
arena.remove(p).unwrap();
}
}
arena
}
pub fn to_cnode_level_debug(&self, lvl: usize) -> Arena<PCNode, LevelNodeKind<PCNode, PCEdge>> {
let mut arena = Arena::<PCNode, LevelNodeKind<PCNode, PCEdge>>::new();
self.cnodes
.clone_keys_to_arena(&mut arena, |p_self, referent| {
match *referent {
Referent::ThisCNode => {
let cnode = self.cnodes.get_val(p_self).unwrap();
if cnode.lvl == u16::try_from(lvl).unwrap() {
let mut forwarded_cnode = cnode.clone();
if let Some(ref mut p_supernode) = forwarded_cnode.p_supernode {
*p_supernode =
self.cnodes.get_val(*p_supernode).unwrap().p_this_cnode;
}
LevelNodeKind::CNode(cnode.clone(), forwarded_cnode)
} else {
LevelNodeKind::Remove
}
}
Referent::SubNode(_) => LevelNodeKind::Remove,
Referent::CEdgeIncidence(p_cedge, i) => {
if i.is_none() {
let cedge = self.cedges.get(p_cedge).unwrap().clone();
if self.cnodes.get_val(cedge.sink()).unwrap().lvl
== u16::try_from(lvl).unwrap()
{
let mut cedge_forwarded = cedge.clone();
for source in cedge_forwarded.sources_mut() {
*source = self.cnodes.get_val(*source).unwrap().p_this_cnode;
}
if i.is_none() {
*cedge_forwarded.sink_mut() =
self.cnodes.get_val(cedge.sink()).unwrap().p_this_cnode;
}
LevelNodeKind::CEdge(p_cedge, cedge, cedge_forwarded)
} else {
LevelNodeKind::Remove
}
} else {
LevelNodeKind::Remove
}
}
}
});
let mut adv = arena.advancer();
while let Some(p) = adv.advance(&arena) {
if let LevelNodeKind::Remove = arena.get(p).unwrap() {
arena.remove(p).unwrap();
}
}
arena
}
pub fn to_cnode_hierarchy_debug(&self) -> Arena<PCNode, HierarchyNodeKind<PCNode, PCEdge>> {
let mut arena = Arena::<PCNode, HierarchyNodeKind<PCNode, PCEdge>>::new();
self.cnodes
.clone_keys_to_arena(&mut arena, |p_self, referent| {
match *referent {
Referent::ThisCNode => {
let cnode = self.cnodes.get_val(p_self).unwrap();
if let Some(p) = self.get_supernode(cnode.p_this_cnode) {
let p_forwarded = self.cnodes.get_val(p).unwrap().p_this_cnode;
HierarchyNodeKind::CNode(cnode.clone(), Some((p, p_forwarded)))
} else {
HierarchyNodeKind::CNode(cnode.clone(), None)
}
}
Referent::SubNode(_) => HierarchyNodeKind::Remove,
Referent::CEdgeIncidence(p_cedge, i) => {
if i.is_none() {
let cedge = self.cedges.get(p_cedge).unwrap().clone();
let mut cedge_forwarded = cedge.clone();
for source in cedge_forwarded.sources_mut() {
*source = self.cnodes.get_val(*source).unwrap().p_this_cnode;
}
if i.is_none() {
*cedge_forwarded.sink_mut() =
self.cnodes.get_val(cedge.sink()).unwrap().p_this_cnode;
}
HierarchyNodeKind::CEdge(p_cedge, cedge, cedge_forwarded)
} else {
HierarchyNodeKind::Remove
}
}
}
});
let mut adv = arena.advancer();
while let Some(p) = adv.advance(&arena) {
if let HierarchyNodeKind::Remove = arena.get(p).unwrap() {
arena.remove(p).unwrap();
}
}
arena
}
pub fn render_to_svgs_in_dir(&self, lvl: usize, out_dir: PathBuf) -> Result<(), Error> {
let dir = match out_dir.canonicalize() {
Ok(o) => {
if !o.is_dir() {
return Err(Error::OtherStr("need a directory not a file"));
}
o
}
Err(e) => {
return Err(Error::OtherString(format!("{e:?}")));
}
};
let mut cnode_backrefs_file = dir.clone();
cnode_backrefs_file.push("cnode_backrefs.svg");
let mut cnode_level_file = dir.clone();
cnode_level_file.push("cnode_level.svg");
let mut cnode_hierarchy_file = dir;
cnode_hierarchy_file.push("cnode_hierarchy.svg");
let res = self.verify_integrity();
render_to_svg_file(&self.to_cnode_backrefs_debug(), false, cnode_backrefs_file).unwrap();
render_to_svg_file(&self.to_cnode_level_debug(lvl), false, cnode_level_file).unwrap();
render_to_svg_file(
&self.to_cnode_hierarchy_debug(),
false,
cnode_hierarchy_file,
)
.unwrap();
res
}
pub fn backrefs_to_chain_arena(&self) -> ChainArena<PCNode, Referent<PCNode, PCEdge>> {
let mut chain_arena = ChainArena::new();
self.cnodes
.clone_keys_to_chain_arena(&mut chain_arena, |_, p_lnode| *p_lnode);
chain_arena
}
pub fn eprint_debug_summary(&self) {
let chain_arena = self.backrefs_to_chain_arena();
eprintln!("chain_arena: {:#?}", chain_arena);
}
}