diff --git a/src/algorithm/half_node.rs b/src/algorithm/half_node.rs index c6c1ed770..bef2b8e20 100644 --- a/src/algorithm/half_node.rs +++ b/src/algorithm/half_node.rs @@ -1,7 +1,7 @@ use std::hash::Hash; use super::nest_cfgs::CfgView; -use crate::hugr::view::HugrView; +use crate::hugr::views::HugrView; use crate::ops::OpTag; use crate::ops::OpTrait; use crate::{Direction, Node}; diff --git a/src/algorithm/nest_cfgs.rs b/src/algorithm/nest_cfgs.rs index b57359912..78cdbcb15 100644 --- a/src/algorithm/nest_cfgs.rs +++ b/src/algorithm/nest_cfgs.rs @@ -43,7 +43,7 @@ use std::hash::Hash; use itertools::Itertools; -use crate::hugr::view::HugrView; +use crate::hugr::views::HugrView; use crate::ops::OpTag; use crate::ops::OpTrait; use crate::{Direction, Node}; @@ -398,7 +398,7 @@ impl EdgeClassifier { pub(crate) mod test { use super::*; use crate::builder::{BuildError, CFGBuilder, Container, DataflowSubContainer, HugrBuilder}; - use crate::hugr::hierarchical_views::{HierarchyView, SiblingGraph}; + use crate::hugr::views::{HierarchyView, SiblingGraph}; use crate::ops::handle::{BasicBlockID, ConstID, NodeHandle}; use crate::ops::Const; use crate::types::{ClassicType, SimpleType}; @@ -447,7 +447,7 @@ pub(crate) mod test { let (split, merge, head, tail) = (split.node(), merge.node(), head.node(), tail.node()); // There's no need to use a FlatRegionView here but we do so just to check // that we *can* (as we'll need to for "real" module Hugr's). - let v = SiblingGraph::new(&h, h.root()); + let v: SiblingGraph = SiblingGraph::new(&h, h.root()); let edge_classes = EdgeClassifier::get_edge_classes(&SimpleCfgView::new(&v)); let [&left,&right] = edge_classes.keys().filter(|(s,_)| *s == split).map(|(_,t)|t).collect::>()[..] else {panic!("Split node should have two successors");}; diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index 2c58793ae..14932d7e2 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -1,5 +1,5 @@ use crate::hugr::validate::InterGraphEdgeError; -use crate::hugr::view::HugrView; +use crate::hugr::views::HugrView; use crate::hugr::{Node, NodeMetadata, Port, ValidationError}; use crate::ops::{self, LeafOp, OpTrait, OpType}; diff --git a/src/builder/cfg.rs b/src/builder/cfg.rs index 574f32eea..f6396f386 100644 --- a/src/builder/cfg.rs +++ b/src/builder/cfg.rs @@ -5,7 +5,7 @@ use super::{ BasicBlockID, BuildError, CfgID, Container, Dataflow, HugrBuilder, Wire, }; -use crate::hugr::view::HugrView; +use crate::hugr::views::HugrView; use crate::ops::handle::NodeHandle; use crate::ops::{self, BasicBlock, OpType}; use crate::types::AbstractSignature; diff --git a/src/builder/conditional.rs b/src/builder/conditional.rs index 7b9c7e213..32f854ef3 100644 --- a/src/builder/conditional.rs +++ b/src/builder/conditional.rs @@ -1,4 +1,4 @@ -use crate::hugr::view::HugrView; +use crate::hugr::views::HugrView; use crate::types::{AbstractSignature, ClassicRow, SimpleRow}; use crate::ops; diff --git a/src/builder/module.rs b/src/builder/module.rs index a93b91af4..f4b771602 100644 --- a/src/builder/module.rs +++ b/src/builder/module.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{ - hugr::{view::HugrView, ValidationError}, + hugr::{views::HugrView, ValidationError}, ops, types::{simple::TypeTag, PrimType, SimpleType}, }; diff --git a/src/builder/tail_loop.rs b/src/builder/tail_loop.rs index 5bd05a614..85f35fa4c 100644 --- a/src/builder/tail_loop.rs +++ b/src/builder/tail_loop.rs @@ -1,6 +1,6 @@ use crate::ops::{self, OpType}; -use crate::hugr::{view::HugrView, NodeType}; +use crate::hugr::{views::HugrView, NodeType}; use crate::types::{AbstractSignature, ClassicRow, SimpleRow}; use crate::{Hugr, Node}; diff --git a/src/hugr.rs b/src/hugr.rs index 2b57459bb..93b4264b4 100644 --- a/src/hugr.rs +++ b/src/hugr.rs @@ -2,11 +2,10 @@ mod hugrmut; -pub mod hierarchical_views; pub mod rewrite; pub mod serialize; pub mod validate; -pub mod view; +pub mod views; use std::collections::VecDeque; use std::iter; @@ -24,7 +23,7 @@ use thiserror::Error; #[cfg(feature = "pyo3")] use pyo3::prelude::*; -pub use self::view::HugrView; +pub use self::views::HugrView; use crate::ops::{OpTag, OpTrait, OpType}; use crate::resource::ResourceSet; use crate::types::{AbstractSignature, Signature}; diff --git a/src/hugr/rewrite/simple_replace.rs b/src/hugr/rewrite/simple_replace.rs index 6b941b76c..57df3cc1d 100644 --- a/src/hugr/rewrite/simple_replace.rs +++ b/src/hugr/rewrite/simple_replace.rs @@ -209,7 +209,7 @@ mod test { BuildError, Container, DFGBuilder, Dataflow, DataflowHugr, DataflowSubContainer, HugrBuilder, ModuleBuilder, }; - use crate::hugr::view::HugrView; + use crate::hugr::views::HugrView; use crate::hugr::{Hugr, Node}; use crate::ops::OpTag; use crate::ops::{LeafOp, OpTrait, OpType}; diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index cdc73a511..ede91d4be 100644 --- a/src/hugr/validate.rs +++ b/src/hugr/validate.rs @@ -18,8 +18,7 @@ use crate::resource::validate::{ResourceError, ResourceValidator}; use crate::types::{ClassicType, EdgeKind, SimpleType}; use crate::{Direction, Hugr, Node, Port}; -use super::hierarchical_views::{HierarchyView, SiblingGraph}; -use super::view::HugrView; +use super::views::{HierarchyView, HugrView, SiblingGraph}; use super::NodeType; /// Structure keeping track of pre-computed information used in the validation @@ -76,7 +75,7 @@ impl<'a> ValidationContext<'a> { /// The results of this computation should be cached in `self.dominators`. /// We don't do it here to avoid mutable borrows. fn compute_dominator(&self, parent: Node) -> Dominators { - let region = SiblingGraph::new(self.hugr, parent); + let region: SiblingGraph = SiblingGraph::new(self.hugr, parent); let entry_node = self.hugr.children(parent).next().unwrap(); dominators::simple_fast(®ion, entry_node) } @@ -336,7 +335,7 @@ impl<'a> ValidationContext<'a> { return Ok(()); }; - let region = SiblingGraph::new(self.hugr, parent); + let region: SiblingGraph = SiblingGraph::new(self.hugr, parent); let entry_node = self.hugr.children(parent).next().unwrap(); let postorder = DfsPostOrder::new(®ion, entry_node); diff --git a/src/hugr/view.rs b/src/hugr/views.rs similarity index 98% rename from src/hugr/view.rs rename to src/hugr/views.rs index 72be245c8..59aa965df 100644 --- a/src/hugr/view.rs +++ b/src/hugr/views.rs @@ -1,10 +1,10 @@ -#![allow(unused)] -//! A Trait for "read-only" HUGRs. +//! Read-only access into HUGR graphs and subgraphs. -use std::iter::FusedIterator; -use std::ops::Deref; +pub mod hierarchy; -use context_iterators::{ContextIterator, IntoContextIterator, MapCtx, MapWithCtx, WithCtx}; +pub use hierarchy::{DescendantsGraph, HierarchyView, SiblingGraph}; + +use context_iterators::{ContextIterator, IntoContextIterator, MapWithCtx}; use itertools::{Itertools, MapInto}; use portgraph::dot::{DotFormat, EdgeStyle, NodeStyle, PortStyle}; use portgraph::{multiportgraph, LinkView, MultiPortGraph, PortView}; @@ -299,7 +299,6 @@ where #[inline] fn get_io(&self, node: Node) -> Option<[Node; 2]> { let op = self.get_nodetype(node); - let dfp = OpTag::DataflowParent; if op.tag().is_superset(OpTag::DataflowParent) { self.children(node).take(2).collect_vec().try_into().ok() } else { diff --git a/src/hugr/hierarchical_views.rs b/src/hugr/views/hierarchy.rs similarity index 86% rename from src/hugr/hierarchical_views.rs rename to src/hugr/views/hierarchy.rs index 4d7567a0a..307cd7ea2 100644 --- a/src/hugr/hierarchical_views.rs +++ b/src/hugr/views/hierarchy.rs @@ -23,10 +23,11 @@ use context_iterators::{ContextIterator, IntoContextIterator, MapWithCtx}; use itertools::{Itertools, MapInto}; use portgraph::{LinkView, PortIndex, PortView}; +use crate::ops::handle::NodeHandle; +use crate::ops::OpTrait; use crate::{hugr::NodeType, hugr::OpType, Direction, Hugr, Node, Port}; -use super::view::sealed::HugrInternals; -use super::{HugrView, NodeMetadata}; +use super::{sealed::HugrInternals, HugrView, NodeMetadata}; type FlatRegionGraph<'g, Base> = portgraph::view::FlatRegion<'g, ::Portgraph>; @@ -36,7 +37,7 @@ type FlatRegionGraph<'g, Base> = /// Includes only the root node and its direct children. /// /// For a view that includes all the descendants of the root, see [`DescendantsGraph`]. -pub struct SiblingGraph<'g, Base = Hugr> +pub struct SiblingGraph<'g, Root = Node, Base = Hugr> where Base: HugrInternals, { @@ -48,10 +49,14 @@ where /// The rest of the HUGR. hugr: &'g Base, + + /// The operation type of the root node. + _phantom: std::marker::PhantomData, } -impl<'g, Base> Clone for SiblingGraph<'g, Base> +impl<'g, Root, Base> Clone for SiblingGraph<'g, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView + Clone, { fn clone(&self) -> Self { @@ -59,8 +64,9 @@ where } } -impl<'g, Base> HugrView for SiblingGraph<'g, Base> +impl<'g, Root, Base> HugrView for SiblingGraph<'g, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type Nodes<'a> = iter::Chain, MapInto, Node>> @@ -200,7 +206,7 @@ type RegionGraph<'g, Base> = portgraph::view::Region<'g, /// For a view that includes only the direct children of the root, see /// [`SiblingGraph`]. Prefer using [`SiblingGraph`] over this type when /// possible, as it is more efficient. -pub struct DescendantsGraph<'g, Base> +pub struct DescendantsGraph<'g, Root = Node, Base = Hugr> where Base: HugrInternals, { @@ -212,10 +218,14 @@ where /// The node hierarchy. hugr: &'g Base, + + /// The operation handle of the root node. + _phantom: std::marker::PhantomData, } -impl<'g, Base: Clone> Clone for DescendantsGraph<'g, Base> +impl<'g, Root, Base: Clone> Clone for DescendantsGraph<'g, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { fn clone(&self) -> Self { @@ -223,8 +233,9 @@ where } } -impl<'g, Base> HugrView for DescendantsGraph<'g, Base> +impl<'g, Root, Base> HugrView for DescendantsGraph<'g, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type Nodes<'a> = MapInto< as PortView>::Nodes<'a>, Node> @@ -345,7 +356,7 @@ where } } -/// A common trait for views of a hugr region. +/// A common trait for views of a HUGR hierarchical subgraph. pub trait HierarchyView<'a>: HugrView + pv::GraphBase @@ -359,20 +370,26 @@ pub trait HierarchyView<'a>: where for<'g> &'g Self: pv::IntoNeighborsDirected + pv::IntoNodeIdentifiers, { - /// The base from which the region is derived. + /// The base from which the subgraph is derived. type Base; - /// Create a region view of a HUGR given a root node. + /// Create a hierarchical view of a HUGR given a root node. fn new(hugr: &'a Self::Base, root: Node) -> Self; } -impl<'a, Base> HierarchyView<'a> for SiblingGraph<'a, Base> +impl<'a, Root, Base> HierarchyView<'a> for SiblingGraph<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type Base = Base; fn new(hugr: &'a Base, root: Node) -> Self { + let root_tag = hugr.get_optype(root).tag(); + if !Root::TAG.is_superset(root_tag) { + // TODO: Return an error + panic!("Root node must have the correct operation type tag.") + } Self { root, graph: FlatRegionGraph::::new_flat_region( @@ -381,17 +398,24 @@ where root.index, ), hugr, + _phantom: std::marker::PhantomData, } } } -impl<'a, Base> HierarchyView<'a> for DescendantsGraph<'a, Base> +impl<'a, Root, Base> HierarchyView<'a> for DescendantsGraph<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type Base = Base; fn new(hugr: &'a Base, root: Node) -> Self { + let root_tag = hugr.get_optype(root).tag(); + if !Root::TAG.is_superset(root_tag) { + // TODO: Return an error + panic!("Root node must have the correct operation type tag.") + } Self { root, graph: RegionGraph::::new_region( @@ -400,12 +424,14 @@ where root.index, ), hugr, + _phantom: std::marker::PhantomData, } } } -impl<'g, Base> super::view::sealed::HugrInternals for SiblingGraph<'g, Base> +impl<'g, Root, Base> super::sealed::HugrInternals for SiblingGraph<'g, Root, Base> where + Root: NodeHandle, Base: HugrInternals, { type Portgraph = FlatRegionGraph<'g, Base>; @@ -421,8 +447,9 @@ where } } -impl<'g, Base> super::view::sealed::HugrInternals for DescendantsGraph<'g, Base> +impl<'g, Root, Base> super::sealed::HugrInternals for DescendantsGraph<'g, Root, Base> where + Root: NodeHandle, Base: HugrInternals, { type Portgraph = RegionGraph<'g, Base>; @@ -490,7 +517,7 @@ mod test { fn flat_region() -> Result<(), Box> { let (hugr, def, inner) = make_module_hgr()?; - let region = SiblingGraph::new(&hugr, def); + let region: SiblingGraph = SiblingGraph::new(&hugr, def); assert_eq!(region.node_count(), 5); assert!(region @@ -505,7 +532,7 @@ mod test { fn full_region() -> Result<(), Box> { let (hugr, def, inner) = make_module_hgr()?; - let region = DescendantsGraph::new(&hugr, def); + let region: DescendantsGraph = DescendantsGraph::new(&hugr, def); assert_eq!(region.node_count(), 7); assert!(region.nodes().all(|n| n == def diff --git a/src/hugr/hierarchical_views/petgraph.rs b/src/hugr/views/hierarchy/petgraph.rs similarity index 72% rename from src/hugr/hierarchical_views/petgraph.rs rename to src/hugr/views/hierarchy/petgraph.rs index 41060f5a3..29de1506f 100644 --- a/src/hugr/hierarchical_views/petgraph.rs +++ b/src/hugr/views/hierarchy/petgraph.rs @@ -1,8 +1,9 @@ //! Implementations of petgraph's traits for Hugr Region views. use super::{DescendantsGraph, SiblingGraph}; -use crate::hugr::view::sealed::HugrInternals; +use crate::hugr::views::sealed::HugrInternals; use crate::hugr::HugrView; +use crate::ops::handle::NodeHandle; use crate::ops::OpType; use crate::types::EdgeKind; use crate::{Node, Port}; @@ -13,23 +14,26 @@ use portgraph::NodeIndex; macro_rules! impl_region_petgraph_traits { ($hugr:ident) => { - impl<'a, Base> pv::GraphBase for $hugr<'a, Base> + impl<'a, Root, Base> pv::GraphBase for $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type NodeId = Node; type EdgeId = ((Node, Port), (Node, Port)); } - impl<'a, Base> pv::GraphProp for $hugr<'a, Base> + impl<'a, Root, Base> pv::GraphProp for $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type EdgeType = petgraph::Directed; } - impl<'a, Base> pv::NodeCount for $hugr<'a, Base> + impl<'a, Root, Base> pv::NodeCount for $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { fn node_count(&self) -> usize { @@ -37,8 +41,9 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Base> pv::NodeIndexable for $hugr<'a, Base> + impl<'a, Root, Base> pv::NodeIndexable for $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { fn node_bound(&self) -> usize { @@ -54,8 +59,9 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Base> pv::EdgeCount for $hugr<'a, Base> + impl<'a, Root, Base> pv::EdgeCount for $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { fn edge_count(&self) -> usize { @@ -63,33 +69,36 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Base> pv::Data for $hugr<'a, Base> + impl<'a, Root, Base> pv::Data for $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type NodeWeight = OpType; type EdgeWeight = EdgeKind; } - impl<'g, 'a, Base> pv::IntoNodeIdentifiers for &'g $hugr<'a, Base> + impl<'g, 'a, Root, Base> pv::IntoNodeIdentifiers for &'g $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { - type NodeIdentifiers = <$hugr<'a, Base> as HugrView>::Nodes<'g>; + type NodeIdentifiers = <$hugr<'a, Root, Base> as HugrView>::Nodes<'g>; fn node_identifiers(self) -> Self::NodeIdentifiers { self.nodes() } } - impl<'g, 'a, Base> pv::IntoNodeReferences for &'g $hugr<'a, Base> + impl<'g, 'a, Root, Base> pv::IntoNodeReferences for &'g $hugr<'a, Root, Base> where + Root: NodeHandle, 'g: 'a, Base: HugrInternals + HugrView, { type NodeRef = HugrNodeRef<'a>; type NodeReferences = - MapWithCtx<<$hugr<'a, Base> as HugrView>::Nodes<'a>, Self, HugrNodeRef<'a>>; + MapWithCtx<<$hugr<'a, Root, Base> as HugrView>::Nodes<'a>, Self, HugrNodeRef<'a>>; fn node_references(self) -> Self::NodeReferences { self.nodes() @@ -98,22 +107,24 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'g, 'a, Base> pv::IntoNeighbors for &'g $hugr<'a, Base> + impl<'g, 'a, Root, Base> pv::IntoNeighbors for &'g $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { - type Neighbors = <$hugr<'a, Base> as HugrView>::Neighbours<'g>; + type Neighbors = <$hugr<'a, Root, Base> as HugrView>::Neighbours<'g>; fn neighbors(self, n: Self::NodeId) -> Self::Neighbors { self.output_neighbours(n) } } - impl<'g, 'a, Base> pv::IntoNeighborsDirected for &'g $hugr<'a, Base> + impl<'g, 'a, Root, Base> pv::IntoNeighborsDirected for &'g $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { - type NeighborsDirected = <$hugr<'a, Base> as HugrView>::Neighbours<'g>; + type NeighborsDirected = <$hugr<'a, Root, Base> as HugrView>::Neighbours<'g>; fn neighbors_directed( self, @@ -124,8 +135,9 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Base> pv::Visitable for $hugr<'a, Base> + impl<'a, Root, Base> pv::Visitable for $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type Map = std::collections::HashSet; @@ -139,8 +151,9 @@ macro_rules! impl_region_petgraph_traits { } } - impl<'a, Base> pv::GetAdjacencyMatrix for $hugr<'a, Base> + impl<'a, Root, Base> pv::GetAdjacencyMatrix for $hugr<'a, Root, Base> where + Root: NodeHandle, Base: HugrInternals + HugrView, { type AdjMatrix = std::collections::HashSet<(Self::NodeId, Self::NodeId)>;