diff --git a/src/builder.rs b/src/builder.rs index c8c0cdc55..c0260530b 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -5,10 +5,11 @@ use thiserror::Error; #[cfg(feature = "pyo3")] use pyo3::{create_exception, exceptions::PyException, PyErr}; -use crate::hugr::{HugrError, Node, ValidationError, Wire}; +use crate::hugr::{HugrError, ValidationError}; use crate::ops::handle::{BasicBlockID, CfgID, ConditionalID, DfgID, FuncID, TailLoopID}; use crate::types::ConstTypeError; use crate::types::Type; +use crate::{Node, Wire}; pub mod handle; pub use handle::BuildHandle; diff --git a/src/builder/build_traits.rs b/src/builder/build_traits.rs index a890dcd6c..cd89bd5ce 100644 --- a/src/builder/build_traits.rs +++ b/src/builder/build_traits.rs @@ -1,8 +1,9 @@ use crate::hugr::hugrmut::InsertionResult; use crate::hugr::validate::InterGraphEdgeError; use crate::hugr::views::HugrView; -use crate::hugr::{IncomingPort, Node, NodeMetadata, OutgoingPort, Port, ValidationError}; +use crate::hugr::{NodeMetadata, ValidationError}; use crate::ops::{self, LeafOp, OpTrait, OpType}; +use crate::{IncomingPort, Node, OutgoingPort, Port}; use std::iter; diff --git a/src/builder/circuit.rs b/src/builder/circuit.rs index e42e6996e..4b45d34fc 100644 --- a/src/builder/circuit.rs +++ b/src/builder/circuit.rs @@ -2,12 +2,10 @@ use std::collections::HashMap; use thiserror::Error; -use crate::hugr::CircuitUnit; - use crate::ops::OpType; use super::{BuildError, Dataflow}; -use crate::Wire; +use crate::{CircuitUnit, Wire}; /// Builder to build regions of dataflow graphs that look like Circuits, /// where some inputs of operations directly correspond to some outputs. diff --git a/src/core.rs b/src/core.rs new file mode 100644 index 000000000..286e4baab --- /dev/null +++ b/src/core.rs @@ -0,0 +1,282 @@ +//! Definitions for the core types used in the Hugr. +//! +//! These types are re-exported in the root of the crate. + +use derive_more::From; + +#[cfg(feature = "pyo3")] +use pyo3::pyclass; + +use crate::hugr::HugrError; + +/// A handle to a node in the HUGR. +#[derive( + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, + Debug, + From, + serde::Serialize, + serde::Deserialize, +)] +#[serde(transparent)] +#[cfg_attr(feature = "pyo3", pyclass)] +pub struct Node { + index: portgraph::NodeIndex, +} + +/// A handle to a port for a node in the HUGR. +#[derive( + Clone, + Copy, + PartialEq, + PartialOrd, + Eq, + Ord, + Hash, + Default, + Debug, + From, + serde::Serialize, + serde::Deserialize, +)] +#[serde(transparent)] +#[cfg_attr(feature = "pyo3", pyclass)] +pub struct Port { + offset: portgraph::PortOffset, +} + +/// A trait for getting the undirected index of a port. +pub trait PortIndex { + /// Returns the offset of the port. + fn index(self) -> usize; +} + +/// A trait for getting the index of a node. +pub trait NodeIndex { + /// Returns the index of the node. + fn index(self) -> usize; +} + +/// A port in the incoming direction. +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Default, Debug)] +pub struct IncomingPort { + index: u16, +} + +/// A port in the outgoing direction. +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Default, Debug)] +pub struct OutgoingPort { + index: u16, +} + +/// The direction of a port. +pub type Direction = portgraph::Direction; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +/// A DataFlow wire, defined by a Value-kind output port of a node +// Stores node and offset to output port +pub struct Wire(Node, usize); + +impl Node { + /// Returns the node as a portgraph `NodeIndex`. + #[inline] + pub(crate) fn pg_index(self) -> portgraph::NodeIndex { + self.index + } +} + +impl Port { + /// Creates a new port. + #[inline] + pub fn new(direction: Direction, port: usize) -> Self { + Self { + offset: portgraph::PortOffset::new(direction, port), + } + } + + /// Creates a new incoming port. + #[inline] + pub fn new_incoming(port: impl Into) -> Self { + Self::try_new_incoming(port).unwrap() + } + + /// Creates a new outgoing port. + #[inline] + pub fn new_outgoing(port: impl Into) -> Self { + Self::try_new_outgoing(port).unwrap() + } + + /// Creates a new incoming port. + #[inline] + pub fn try_new_incoming(port: impl TryInto) -> Result { + let Ok(port) = port.try_into() else { + return Err(HugrError::InvalidPortDirection(Direction::Outgoing)); + }; + Ok(Self { + offset: portgraph::PortOffset::new_incoming(port.index()), + }) + } + + /// Creates a new outgoing port. + #[inline] + pub fn try_new_outgoing(port: impl TryInto) -> Result { + let Ok(port) = port.try_into() else { + return Err(HugrError::InvalidPortDirection(Direction::Incoming)); + }; + Ok(Self { + offset: portgraph::PortOffset::new_outgoing(port.index()), + }) + } + + /// Returns the direction of the port. + #[inline] + pub fn direction(self) -> Direction { + self.offset.direction() + } + + /// Returns the port as a portgraph `PortOffset`. + #[inline] + pub(crate) fn pg_offset(self) -> portgraph::PortOffset { + self.offset + } +} + +impl PortIndex for Port { + #[inline(always)] + fn index(self) -> usize { + self.offset.index() + } +} + +impl PortIndex for usize { + #[inline(always)] + fn index(self) -> usize { + self + } +} + +impl PortIndex for IncomingPort { + #[inline(always)] + fn index(self) -> usize { + self.index as usize + } +} + +impl PortIndex for OutgoingPort { + #[inline(always)] + fn index(self) -> usize { + self.index as usize + } +} + +impl From for IncomingPort { + #[inline(always)] + fn from(index: usize) -> Self { + Self { + index: index as u16, + } + } +} + +impl From for OutgoingPort { + #[inline(always)] + fn from(index: usize) -> Self { + Self { + index: index as u16, + } + } +} + +impl TryFrom for IncomingPort { + type Error = HugrError; + #[inline(always)] + fn try_from(port: Port) -> Result { + match port.direction() { + Direction::Incoming => Ok(Self { + index: port.index() as u16, + }), + dir @ Direction::Outgoing => Err(HugrError::InvalidPortDirection(dir)), + } + } +} + +impl TryFrom for OutgoingPort { + type Error = HugrError; + #[inline(always)] + fn try_from(port: Port) -> Result { + match port.direction() { + Direction::Outgoing => Ok(Self { + index: port.index() as u16, + }), + dir @ Direction::Incoming => Err(HugrError::InvalidPortDirection(dir)), + } + } +} + +impl NodeIndex for Node { + fn index(self) -> usize { + self.index.into() + } +} + +impl Wire { + /// Create a new wire from a node and a port. + #[inline] + pub fn new(node: Node, port: impl TryInto) -> Self { + Self(node, Port::try_new_outgoing(port).unwrap().index()) + } + + /// The node that this wire is connected to. + #[inline] + pub fn node(&self) -> Node { + self.0 + } + + /// The output port that this wire is connected to. + #[inline] + pub fn source(&self) -> Port { + Port::new_outgoing(self.1) + } +} + +/// Enum for uniquely identifying the origin of linear wires in a circuit-like +/// dataflow region. +/// +/// Falls back to [`Wire`] if the wire is not linear or if it's not possible to +/// track the origin. +#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub enum CircuitUnit { + /// Arbitrary input wire. + Wire(Wire), + /// Index to region input. + Linear(usize), +} + +impl CircuitUnit { + /// Check if this is a wire. + pub fn is_wire(&self) -> bool { + matches!(self, CircuitUnit::Wire(_)) + } + + /// Check if this is a linear unit. + pub fn is_linear(&self) -> bool { + matches!(self, CircuitUnit::Linear(_)) + } +} + +impl From for CircuitUnit { + fn from(value: usize) -> Self { + CircuitUnit::Linear(value) + } +} + +impl From for CircuitUnit { + fn from(value: Wire) -> Self { + CircuitUnit::Wire(value) + } +} diff --git a/src/extension/infer.rs b/src/extension/infer.rs index ae59d9127..f9bfdfa55 100644 --- a/src/extension/infer.rs +++ b/src/extension/infer.rs @@ -13,10 +13,9 @@ use super::{ExtensionId, ExtensionSet}; use crate::{ hugr::views::HugrView, - hugr::Node, ops::{OpTag, OpTrait, OpType}, types::EdgeKind, - Direction, + Direction, Node, }; use super::validate::ExtensionError; diff --git a/src/hugr.rs b/src/hugr.rs index ec44afa46..670967bd4 100644 --- a/src/hugr.rs +++ b/src/hugr.rs @@ -14,7 +14,6 @@ use std::iter; pub(crate) use self::hugrmut::HugrMut; pub use self::validate::ValidationError; -use derive_more::From; pub use ident::{IdentList, InvalidIdentifier}; pub use rewrite::{Rewrite, SimpleReplacement, SimpleReplacementError}; @@ -26,12 +25,14 @@ use thiserror::Error; use pyo3::{create_exception, exceptions::PyException, pyclass, PyErr}; pub use self::views::{HugrView, RootTagged}; +use crate::core::NodeIndex; use crate::extension::{ infer_extensions, ExtensionRegistry, ExtensionSet, ExtensionSolution, InferExtensionError, }; use crate::ops::custom::resolve_extension_ops; use crate::ops::{OpTag, OpTrait, OpType, DEFAULT_OPTYPE}; use crate::types::{FunctionType, Signature}; +use crate::{Direction, Node}; use delegate::delegate; @@ -167,73 +168,8 @@ impl AsMut for Hugr { } } -/// A handle to a node in the HUGR. -#[derive( - Clone, - Copy, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Debug, - From, - serde::Serialize, - serde::Deserialize, -)] -#[serde(transparent)] -#[cfg_attr(feature = "pyo3", pyclass)] -pub struct Node { - index: portgraph::NodeIndex, -} - -/// A handle to a port for a node in the HUGR. -#[derive( - Clone, - Copy, - PartialEq, - PartialOrd, - Eq, - Ord, - Hash, - Default, - Debug, - From, - serde::Serialize, - serde::Deserialize, -)] -#[serde(transparent)] -#[cfg_attr(feature = "pyo3", pyclass)] -pub struct Port { - offset: portgraph::PortOffset, -} - -/// A trait for getting the undirected index of a port. -pub trait PortIndex { - /// Returns the offset of the port. - fn index(self) -> usize; -} - -/// A trait for getting the index of a node. -pub trait NodeIndex { - /// Returns the index of the node. - fn index(self) -> usize; -} - -/// A port in the incoming direction. -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Default, Debug)] -pub struct IncomingPort { - index: u16, -} - -/// A port in the outgoing direction. -#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Default, Debug)] -pub struct OutgoingPort { - index: u16, -} - -/// The direction of a port. -pub type Direction = portgraph::Direction; +/// Arbitrary metadata for a node. +pub type NodeMetadata = serde_json::Value; /// Public API for HUGRs. impl Hugr { @@ -262,7 +198,7 @@ impl Hugr { // We only care about inferred _input_ extensions, because `NodeType` // uses those to infer the output extensions for (node, input_extensions) in solution.iter() { - let nodetype = self.op_types.try_get_mut(node.index).unwrap(); + let nodetype = self.op_types.try_get_mut(node.pg_index()).unwrap(); match &nodetype.input_extensions { None => nodetype.input_extensions = Some(input_extensions.clone()), Some(existing_ext_reqs) => { @@ -273,9 +209,6 @@ impl Hugr { } } -/// Arbitrary metadata for a node. -pub type NodeMetadata = serde_json::Value; - /// Internal API for HUGRs, not intended for use by users. impl Hugr { /// Create a new Hugr, with a single root node. @@ -357,15 +290,17 @@ impl Hugr { // Find the element's location. If it originally came from a previous position // then it has been swapped somewhere else, so we follow the permutation chain. let mut source: Node = ordered[position]; - while position > source.index.index() { - source = ordered[source.index.index()]; + while position > source.index() { + source = ordered[source.index()]; } let target: Node = portgraph::NodeIndex::new(position).into(); if target != source { - self.graph.swap_nodes(target.index, source.index); - self.op_types.swap(target.index, source.index); - self.hierarchy.swap_nodes(target.index, source.index); + let pg_target = target.pg_index(); + let pg_source = source.pg_index(); + self.graph.swap_nodes(pg_target, pg_source); + self.op_types.swap(pg_target, pg_source); + self.hierarchy.swap_nodes(pg_target, pg_source); rekey(source, target); } } @@ -378,196 +313,6 @@ impl Hugr { } } -impl Port { - /// Creates a new port. - #[inline] - pub fn new(direction: Direction, port: usize) -> Self { - Self { - offset: portgraph::PortOffset::new(direction, port), - } - } - - /// Creates a new incoming port. - #[inline] - pub fn new_incoming(port: impl Into) -> Self { - Self::try_new_incoming(port).unwrap() - } - - /// Creates a new outgoing port. - #[inline] - pub fn new_outgoing(port: impl Into) -> Self { - Self::try_new_outgoing(port).unwrap() - } - - /// Creates a new incoming port. - #[inline] - pub fn try_new_incoming(port: impl TryInto) -> Result { - let Ok(port) = port.try_into() else { - return Err(HugrError::InvalidPortDirection(Direction::Outgoing)); - }; - Ok(Self { - offset: portgraph::PortOffset::new_incoming(port.index()), - }) - } - - /// Creates a new outgoing port. - #[inline] - pub fn try_new_outgoing(port: impl TryInto) -> Result { - let Ok(port) = port.try_into() else { - return Err(HugrError::InvalidPortDirection(Direction::Incoming)); - }; - Ok(Self { - offset: portgraph::PortOffset::new_outgoing(port.index()), - }) - } - - /// Returns the direction of the port. - #[inline] - pub fn direction(self) -> Direction { - self.offset.direction() - } -} - -impl PortIndex for Port { - #[inline(always)] - fn index(self) -> usize { - self.offset.index() - } -} - -impl PortIndex for usize { - #[inline(always)] - fn index(self) -> usize { - self - } -} - -impl PortIndex for IncomingPort { - #[inline(always)] - fn index(self) -> usize { - self.index as usize - } -} - -impl PortIndex for OutgoingPort { - #[inline(always)] - fn index(self) -> usize { - self.index as usize - } -} - -impl From for IncomingPort { - #[inline(always)] - fn from(index: usize) -> Self { - Self { - index: index as u16, - } - } -} - -impl From for OutgoingPort { - #[inline(always)] - fn from(index: usize) -> Self { - Self { - index: index as u16, - } - } -} - -impl TryFrom for IncomingPort { - type Error = HugrError; - #[inline(always)] - fn try_from(port: Port) -> Result { - match port.direction() { - Direction::Incoming => Ok(Self { - index: port.index() as u16, - }), - dir @ Direction::Outgoing => Err(HugrError::InvalidPortDirection(dir)), - } - } -} - -impl TryFrom for OutgoingPort { - type Error = HugrError; - #[inline(always)] - fn try_from(port: Port) -> Result { - match port.direction() { - Direction::Outgoing => Ok(Self { - index: port.index() as u16, - }), - dir @ Direction::Incoming => Err(HugrError::InvalidPortDirection(dir)), - } - } -} - -impl NodeIndex for Node { - fn index(self) -> usize { - self.index.into() - } -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -/// A DataFlow wire, defined by a Value-kind output port of a node -// Stores node and offset to output port -pub struct Wire(Node, usize); - -impl Wire { - /// Create a new wire from a node and a port. - #[inline] - pub fn new(node: Node, port: impl TryInto) -> Self { - Self(node, Port::try_new_outgoing(port).unwrap().index()) - } - - /// The node that this wire is connected to. - #[inline] - pub fn node(&self) -> Node { - self.0 - } - - /// The output port that this wire is connected to. - #[inline] - pub fn source(&self) -> Port { - Port::new_outgoing(self.1) - } -} - -/// Enum for uniquely identifying the origin of linear wires in a circuit-like -/// dataflow region. -/// -/// Falls back to [`Wire`] if the wire is not linear or if it's not possible to -/// track the origin. -#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub enum CircuitUnit { - /// Arbitrary input wire. - Wire(Wire), - /// Index to region input. - Linear(usize), -} - -impl CircuitUnit { - /// Check if this is a wire. - pub fn is_wire(&self) -> bool { - matches!(self, CircuitUnit::Wire(_)) - } - - /// Check if this is a linear unit. - pub fn is_linear(&self) -> bool { - matches!(self, CircuitUnit::Linear(_)) - } -} - -impl From for CircuitUnit { - fn from(value: usize) -> Self { - CircuitUnit::Linear(value) - } -} - -impl From for CircuitUnit { - fn from(value: Wire) -> Self { - CircuitUnit::Wire(value) - } -} - /// Errors that can occur while manipulating a Hugr. /// /// TODO: Better descriptions, not just re-exporting portgraph errors. diff --git a/src/hugr/hugrmut.rs b/src/hugr/hugrmut.rs index 7f91752b5..a9c9357ea 100644 --- a/src/hugr/hugrmut.rs +++ b/src/hugr/hugrmut.rs @@ -6,22 +6,20 @@ use std::ops::Range; use portgraph::view::{NodeFilter, NodeFiltered}; use portgraph::{LinkMut, NodeIndex, PortMut, PortView, SecondaryMap}; +use crate::hugr::views::SiblingSubgraph; use crate::hugr::{Direction, HugrError, HugrView, Node, NodeType, RootTagged}; +use crate::hugr::{NodeMetadata, Rewrite}; use crate::ops::OpType; - -use crate::{Hugr, Port}; +use crate::{Hugr, IncomingPort, OutgoingPort, Port, PortIndex}; use self::sealed::HugrMutInternals; -use super::views::SiblingSubgraph; -use super::{IncomingPort, NodeMetadata, OutgoingPort, PortIndex, Rewrite}; - /// Functions for low-level building of a HUGR. pub trait HugrMut: HugrMutInternals { /// Returns the metadata associated with a node. fn get_metadata_mut(&mut self, node: Node) -> Result<&mut NodeMetadata, HugrError> { self.valid_node(node)?; - Ok(self.hugr_mut().metadata.get_mut(node.index)) + Ok(self.hugr_mut().metadata.get_mut(node.pg_index())) } /// Sets the metadata associated with a node. @@ -211,7 +209,7 @@ impl + AsMut> HugrMut for T { let node = self.as_mut().add_node(node); self.as_mut() .hierarchy - .push_child(node.index, parent.index)?; + .push_child(node.pg_index(), parent.pg_index())?; Ok(node) } @@ -223,7 +221,7 @@ impl + AsMut> HugrMut for T { let node = self.as_mut().add_node(nodetype); self.as_mut() .hierarchy - .insert_before(node.index, sibling.index)?; + .insert_before(node.pg_index(), sibling.pg_index())?; Ok(node) } @@ -231,7 +229,7 @@ impl + AsMut> HugrMut for T { let node = self.as_mut().add_op(op); self.as_mut() .hierarchy - .insert_after(node.index, sibling.index)?; + .insert_after(node.pg_index(), sibling.pg_index())?; Ok(node) } @@ -240,9 +238,9 @@ impl + AsMut> HugrMut for T { // TODO: Add a HugrMutError ? panic!("cannot remove root node"); } - self.as_mut().hierarchy.remove(node.index); - self.as_mut().graph.remove_node(node.index); - self.as_mut().op_types.remove(node.index); + self.as_mut().hierarchy.remove(node.pg_index()); + self.as_mut().graph.remove_node(node.pg_index()); + self.as_mut().op_types.remove(node.pg_index()); Ok(()) } @@ -254,22 +252,24 @@ impl + AsMut> HugrMut for T { dst_port: impl TryInto, ) -> Result<(), HugrError> { self.as_mut().graph.link_nodes( - src.index, + src.pg_index(), Port::try_new_outgoing(src_port)?.index(), - dst.index, + dst.pg_index(), Port::try_new_incoming(dst_port)?.index(), )?; Ok(()) } fn disconnect(&mut self, node: Node, port: Port) -> Result<(), HugrError> { - let offset = port.offset; - let port = self.as_mut().graph.port_index(node.index, offset).ok_or( - portgraph::LinkError::UnknownOffset { - node: node.index, + let offset = port.pg_offset(); + let port = self + .as_mut() + .graph + .port_index(node.pg_index(), offset) + .ok_or(portgraph::LinkError::UnknownOffset { + node: node.pg_index(), offset, - }, - )?; + })?; self.as_mut().graph.unlink_port(port); Ok(()) } @@ -296,7 +296,10 @@ impl + AsMut> HugrMut for T { let meta = other.metadata.take(node); self.as_mut().set_metadata(new_node.into(), meta).unwrap(); } - debug_assert_eq!(Some(&new_root.index), node_map.get(&other.root().index)); + debug_assert_eq!( + Some(&new_root.pg_index()), + node_map.get(&other.root().pg_index()) + ); Ok(InsertionResult { new_root, node_map: translate_indices(node_map), @@ -318,7 +321,10 @@ impl + AsMut> HugrMut for T { .set_metadata(new_node.into(), meta.clone()) .unwrap(); } - debug_assert_eq!(Some(&new_root.index), node_map.get(&other.root().index)); + debug_assert_eq!( + Some(&new_root.pg_index()), + node_map.get(&other.root().pg_index()) + ); Ok(InsertionResult { new_root, node_map: translate_indices(node_map), @@ -366,16 +372,16 @@ fn insert_hugr_internal( other: &impl HugrView, ) -> Result<(Node, HashMap), HugrError> { let node_map = hugr.graph.insert_graph(&other.portgraph())?; - let other_root = node_map[&other.root().index]; + let other_root = node_map[&other.root().pg_index()]; // Update hierarchy and optypes - hugr.hierarchy.push_child(other_root, root.index)?; + hugr.hierarchy.push_child(other_root, root.pg_index())?; for (&node, &new_node) in node_map.iter() { other .children(node.into()) .try_for_each(|child| -> Result<(), HugrError> { hugr.hierarchy - .push_child(node_map[&child.index], new_node)?; + .push_child(node_map[&child.pg_index()], new_node)?; Ok(()) })?; } @@ -416,8 +422,8 @@ fn insert_subgraph_internal( for (&node, &new_node) in node_map.iter() { let new_parent = other .get_parent(node.into()) - .and_then(|parent| node_map.get(&parent.index).copied()) - .unwrap_or(root.index); + .and_then(|parent| node_map.get(&parent.pg_index()).copied()) + .unwrap_or(root.pg_index()); hugr.hierarchy.push_child(new_node, new_parent)?; } @@ -514,12 +520,12 @@ pub(crate) mod sealed { fn set_num_ports(&mut self, node: Node, incoming: usize, outgoing: usize) { self.hugr_mut() .graph - .set_num_ports(node.index, incoming, outgoing, |_, _| {}) + .set_num_ports(node.pg_index(), incoming, outgoing, |_, _| {}) } fn add_ports(&mut self, node: Node, direction: Direction, amount: isize) -> Range { - let mut incoming = self.hugr_mut().graph.num_inputs(node.index); - let mut outgoing = self.hugr_mut().graph.num_outputs(node.index); + let mut incoming = self.hugr_mut().graph.num_inputs(node.pg_index()); + let mut outgoing = self.hugr_mut().graph.num_outputs(node.pg_index()); let increment = |num: &mut usize| { let new = num.saturating_add_signed(amount); let range = *num..new; @@ -532,37 +538,37 @@ pub(crate) mod sealed { }; self.hugr_mut() .graph - .set_num_ports(node.index, incoming, outgoing, |_, _| {}); + .set_num_ports(node.pg_index(), incoming, outgoing, |_, _| {}); range } fn set_parent(&mut self, node: Node, parent: Node) -> Result<(), HugrError> { - self.hugr_mut().hierarchy.detach(node.index); + self.hugr_mut().hierarchy.detach(node.pg_index()); self.hugr_mut() .hierarchy - .push_child(node.index, parent.index)?; + .push_child(node.pg_index(), parent.pg_index())?; Ok(()) } fn move_after_sibling(&mut self, node: Node, after: Node) -> Result<(), HugrError> { - self.hugr_mut().hierarchy.detach(node.index); + self.hugr_mut().hierarchy.detach(node.pg_index()); self.hugr_mut() .hierarchy - .insert_after(node.index, after.index)?; + .insert_after(node.pg_index(), after.pg_index())?; Ok(()) } fn move_before_sibling(&mut self, node: Node, before: Node) -> Result<(), HugrError> { - self.hugr_mut().hierarchy.detach(node.index); + self.hugr_mut().hierarchy.detach(node.pg_index()); self.hugr_mut() .hierarchy - .insert_before(node.index, before.index)?; + .insert_before(node.pg_index(), before.pg_index())?; Ok(()) } fn replace_op(&mut self, node: Node, op: NodeType) -> Result { // We know RootHandle=Node here so no need to check - let cur = self.hugr_mut().op_types.get_mut(node.index); + let cur = self.hugr_mut().op_types.get_mut(node.pg_index()); Ok(std::mem::replace(cur, op)) } } diff --git a/src/hugr/rewrite/outline_cfg.rs b/src/hugr/rewrite/outline_cfg.rs index 910ea4fcc..1cd720ef0 100644 --- a/src/hugr/rewrite/outline_cfg.rs +++ b/src/hugr/rewrite/outline_cfg.rs @@ -10,10 +10,11 @@ use crate::extension::ExtensionSet; use crate::hugr::hugrmut::sealed::HugrMutInternals; use crate::hugr::rewrite::Rewrite; use crate::hugr::views::sibling::SiblingMut; -use crate::hugr::{HugrMut, HugrView, PortIndex}; +use crate::hugr::{HugrMut, HugrView}; use crate::ops; use crate::ops::handle::{BasicBlockID, CfgID, NodeHandle}; use crate::ops::{BasicBlock, OpTrait, OpType}; +use crate::PortIndex; use crate::{type_row, Node}; /// Moves part of a Control-flow Sibling Graph into a new CFG-node diff --git a/src/hugr/serialize.rs b/src/hugr/serialize.rs index 2fdc2fb36..87eba59b3 100644 --- a/src/hugr/serialize.rs +++ b/src/hugr/serialize.rs @@ -8,17 +8,18 @@ use thiserror::Error; #[cfg(feature = "pyo3")] use pyo3::{create_exception, exceptions::PyException, PyErr}; +use crate::core::NodeIndex; use crate::extension::ExtensionSet; use crate::hugr::{Hugr, NodeType}; use crate::ops::OpTrait; use crate::ops::OpType; -use crate::Node; +use crate::{Node, PortIndex}; use portgraph::hierarchy::AttachError; -use portgraph::{Direction, LinkError, NodeIndex, PortView}; +use portgraph::{Direction, LinkError, PortView}; use serde::{Deserialize, Deserializer, Serialize}; -use super::{HugrError, HugrMut, HugrView, PortIndex}; +use super::{HugrError, HugrMut, HugrView}; /// A wrapper over the available HUGR serialization formats. /// @@ -138,7 +139,7 @@ impl TryFrom<&Hugr> for SerHugrV0 { // and ignore the copy nodes. let mut node_rekey: HashMap = HashMap::with_capacity(hugr.node_count()); for (order, node) in hugr.canonical_order(hugr.root()).enumerate() { - node_rekey.insert(node, NodeIndex::new(order).into()); + node_rekey.insert(node, portgraph::NodeIndex::new(order).into()); } let mut nodes = vec![None; hugr.node_count()]; @@ -146,7 +147,7 @@ impl TryFrom<&Hugr> for SerHugrV0 { for n in hugr.nodes() { let parent = node_rekey[&hugr.get_parent(n).unwrap_or(n)]; let opt = hugr.get_nodetype(n); - let new_node = node_rekey[&n].index.index(); + let new_node = node_rekey[&n].index(); nodes[new_node] = Some(NodeSer { parent, input_extensions: opt.input_extensions.clone(), @@ -176,12 +177,7 @@ impl TryFrom<&Hugr> for SerHugrV0 { .flat_map(move |(src_offset, port)| { let src = find_offset(node, src_offset, Direction::Outgoing, hugr); hugr.linked_ports(node, port).map(move |(tgt_node, tgt)| { - let tgt = find_offset( - tgt_node, - tgt.offset.index(), - Direction::Incoming, - hugr, - ); + let tgt = find_offset(tgt_node, tgt.index(), Direction::Incoming, hugr); [src, tgt] }) }) @@ -212,7 +208,7 @@ impl TryFrom for Hugr { input_extensions, op: root_type, } = nodes.next().unwrap(); - if root_parent.index.index() != 0 { + if root_parent.index() != 0 { return Err(HUGRSerializationError::FirstNodeNotRoot(root_parent)); } // if there are any unconnected ports or copy nodes the capacity will be @@ -234,12 +230,12 @@ impl TryFrom for Hugr { } for (node, metadata) in metadata.into_iter().enumerate() { - let node = NodeIndex::new(node).into(); + let node = portgraph::NodeIndex::new(node).into(); hugr.set_metadata(node, metadata)?; } let unwrap_offset = |node: Node, offset, dir, hugr: &Hugr| -> Result { - if !hugr.graph.contains_node(node.index) { + if !hugr.graph.contains_node(node.pg_index()) { return Err(HUGRSerializationError::UnknownEdgeNode { node }); } let offset = match offset { @@ -305,7 +301,7 @@ pub mod test { } /// Generate an optype for a node with a matching amount of inputs and outputs. - fn gen_optype(g: &MultiPortGraph, node: NodeIndex) -> OpType { + fn gen_optype(g: &MultiPortGraph, node: portgraph::NodeIndex) -> OpType { let inputs = g.num_inputs(node); let outputs = g.num_outputs(node); match (inputs == 0, outputs == 0) { diff --git a/src/hugr/validate.rs b/src/hugr/validate.rs index 57b9020c0..9d40c52fa 100644 --- a/src/hugr/validate.rs +++ b/src/hugr/validate.rs @@ -119,7 +119,9 @@ impl<'a, 'b> ValidationContext<'a, 'b> { // The Hugr can have only one root node. if node == self.hugr.root() { // The root node has no edges. - if self.hugr.graph.num_outputs(node.index) + self.hugr.graph.num_inputs(node.index) != 0 + if self.hugr.graph.num_outputs(node.pg_index()) + + self.hugr.graph.num_inputs(node.pg_index()) + != 0 { return Err(ValidationError::RootWithEdges { node }); } @@ -142,7 +144,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { for dir in Direction::BOTH { // Check that we have the correct amount of ports and edges. - let num_ports = self.hugr.graph.num_ports(node.index, dir); + let num_ports = self.hugr.graph.num_ports(node.pg_index(), dir); if num_ports != op_type.port_count(dir) { return Err(ValidationError::WrongNumberOfPorts { node, @@ -154,7 +156,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { } // Check port connections - for (i, port_index) in self.hugr.graph.ports(node.index, dir).enumerate() { + for (i, port_index) in self.hugr.graph.ports(node.pg_index(), dir).enumerate() { let port = Port::new(dir, i); self.validate_port(node, port, port_index, op_type)?; } @@ -292,7 +294,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { let op_type = &node_type.op; let flags = op_type.validity_flags(); - if self.hugr.hierarchy.child_count(node.index) > 0 { + if self.hugr.hierarchy.child_count(node.pg_index()) > 0 { if flags.allowed_children.is_empty() { return Err(ValidationError::NonContainerWithChildren { node, @@ -328,7 +330,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { } } // Additional validations running over the full list of children optypes - let children_optypes = all_children.map(|c| (c.index, self.hugr.get_optype(c))); + let children_optypes = all_children.map(|c| (c.pg_index(), self.hugr.get_optype(c))); if let Err(source) = op_type.validate_op_children(children_optypes) { return Err(ValidationError::InvalidChildren { parent: node, @@ -339,9 +341,9 @@ impl<'a, 'b> ValidationContext<'a, 'b> { // Additional validations running over the edges of the contained graph if let Some(edge_check) = flags.edge_check { - for source in self.hugr.hierarchy.children(node.index) { + for source in self.hugr.hierarchy.children(node.pg_index()) { for target in self.hugr.graph.output_neighbours(source) { - if self.hugr.hierarchy.parent(target) != Some(node.index) { + if self.hugr.hierarchy.parent(target) != Some(node.pg_index()) { continue; } let source_op = self.hugr.get_optype(source.into()); @@ -387,7 +389,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { /// Inter-graph edges are ignored. Only internal dataflow, constant, or /// state order edges are considered. fn validate_children_dag(&self, parent: Node, op_type: &OpType) -> Result<(), ValidationError> { - if !self.hugr.hierarchy.has_children(parent.index) { + if !self.hugr.hierarchy.has_children(parent.pg_index()) { // No children, nothing to do return Ok(()); }; @@ -479,7 +481,7 @@ impl<'a, 'b> ValidationContext<'a, 'b> { // Must have an order edge. self.hugr .graph - .get_connections(from.index, ancestor.index) + .get_connections(from.pg_index(), ancestor.pg_index()) .find(|&(p, _)| { let offset = self.hugr.graph.port_offset(p).unwrap(); from_optype.port_kind(offset) == Some(EdgeKind::StateOrder) @@ -858,7 +860,7 @@ mod test { // Make the hugr root not a hierarchy root { let mut hugr = b.clone(); - hugr.root = other.index; + hugr.root = other.pg_index(); assert_matches!( hugr.validate(&EMPTY_REG), Err(ValidationError::RootNotRoot { node }) => assert_eq!(node, other) @@ -900,7 +902,7 @@ mod test { let root = b.root(); let (_input, copy, _output) = b .hierarchy - .children(def.index) + .children(def.pg_index()) .map_into() .collect_tuple() .unwrap(); @@ -947,7 +949,7 @@ mod test { let (mut b, def) = make_simple_hugr(2); let (_input, output, copy) = b .hierarchy - .children(def.index) + .children(def.pg_index()) .map_into() .collect_tuple() .unwrap(); @@ -966,7 +968,7 @@ mod test { assert_matches!( b.validate(&EMPTY_REG), Err(ValidationError::InvalidChildren { parent, source: ChildrenValidationError::IOSignatureMismatch { child, .. }, .. }) - => {assert_eq!(parent, def); assert_eq!(child, output.index)} + => {assert_eq!(parent, def); assert_eq!(child, output.pg_index())} ); b.replace_op( output, @@ -983,7 +985,7 @@ mod test { assert_matches!( b.validate(&EMPTY_REG), Err(ValidationError::InvalidChildren { parent, source: ChildrenValidationError::InternalIOChildren { child, .. }, .. }) - => {assert_eq!(parent, def); assert_eq!(child, copy.index)} + => {assert_eq!(parent, def); assert_eq!(child, copy.pg_index())} ); } @@ -993,7 +995,7 @@ mod test { let (mut b, def) = make_simple_hugr(1); let (_input, _output, copy) = b .hierarchy - .children(def.index) + .children(def.pg_index()) .map_into() .collect_tuple() .unwrap(); @@ -1049,7 +1051,7 @@ mod test { assert_matches!( b.validate(&EMPTY_REG), Err(ValidationError::InvalidChildren { parent, source: ChildrenValidationError::InternalExitChildren { child, .. }, .. }) - => {assert_eq!(parent, cfg); assert_eq!(child, exit2.index)} + => {assert_eq!(parent, cfg); assert_eq!(child, exit2.pg_index())} ); b.remove_node(exit2).unwrap(); @@ -1064,7 +1066,7 @@ mod test { }), ) .unwrap(); - let mut block_children = b.hierarchy.children(block.index); + let mut block_children = b.hierarchy.children(block.pg_index()); let block_input = block_children.next().unwrap().into(); let block_output = block_children.next_back().unwrap().into(); b.replace_op(block_input, NodeType::pure(ops::Input::new(type_row![Q]))) diff --git a/src/hugr/views.rs b/src/hugr/views.rs index 231840f05..2aadbdc82 100644 --- a/src/hugr/views.rs +++ b/src/hugr/views.rs @@ -107,7 +107,7 @@ pub trait HugrView: sealed::HugrInternals { self.valid_non_root(node).ok()?; self.base_hugr() .hierarchy - .parent(node.index) + .parent(node.pg_index()) .map(Into::into) } @@ -121,7 +121,7 @@ pub trait HugrView: sealed::HugrInternals { #[inline] fn get_nodetype(&self, node: Node) -> &NodeType { match self.contains_node(node) { - true => self.base_hugr().op_types.get(node.index), + true => self.base_hugr().op_types.get(node.pg_index()), false => &DEFAULT_NODETYPE, } } @@ -130,7 +130,7 @@ pub trait HugrView: sealed::HugrInternals { #[inline] fn get_metadata(&self, node: Node) -> &NodeMetadata { match self.contains_node(node) { - true => self.base_hugr().metadata.get(node.index), + true => self.base_hugr().metadata.get(node.pg_index()), false => &NodeMetadata::Null, } } @@ -362,7 +362,7 @@ impl> HugrView for T { #[inline] fn contains_node(&self, node: Node) -> bool { - self.as_ref().graph.contains_node(node.index) + self.as_ref().graph.contains_node(node.pg_index()) } #[inline] @@ -382,18 +382,27 @@ impl> HugrView for T { #[inline] fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { - self.as_ref().graph.port_offsets(node.index, dir).map_into() + self.as_ref() + .graph + .port_offsets(node.pg_index(), dir) + .map_into() } #[inline] fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { - self.as_ref().graph.all_port_offsets(node.index).map_into() + self.as_ref() + .graph + .all_port_offsets(node.pg_index()) + .map_into() } #[inline] fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { let hugr = self.as_ref(); - let port = hugr.graph.port_index(node.index, port.offset).unwrap(); + let port = hugr + .graph + .port_index(node.pg_index(), port.pg_offset()) + .unwrap(); hugr.graph .port_links(port) .with_context(hugr) @@ -410,7 +419,7 @@ impl> HugrView for T { let hugr = self.as_ref(); hugr.graph - .get_connections(node.index, other.index) + .get_connections(node.pg_index(), other.pg_index()) .with_context(hugr) .map_with_context(|(p1, p2), hugr| { [p1, p2].map(|link| { @@ -422,22 +431,28 @@ impl> HugrView for T { #[inline] fn num_ports(&self, node: Node, dir: Direction) -> usize { - self.as_ref().graph.num_ports(node.index, dir) + self.as_ref().graph.num_ports(node.pg_index(), dir) } #[inline] fn children(&self, node: Node) -> Self::Children<'_> { - self.as_ref().hierarchy.children(node.index).map_into() + self.as_ref().hierarchy.children(node.pg_index()).map_into() } #[inline] fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { - self.as_ref().graph.neighbours(node.index, dir).map_into() + self.as_ref() + .graph + .neighbours(node.pg_index(), dir) + .map_into() } #[inline] fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { - self.as_ref().graph.all_neighbours(node.index).map_into() + self.as_ref() + .graph + .all_neighbours(node.pg_index()) + .map_into() } } diff --git a/src/hugr/views/descendants.rs b/src/hugr/views/descendants.rs index bf396b85c..0f39e0180 100644 --- a/src/hugr/views/descendants.rs +++ b/src/hugr/views/descendants.rs @@ -72,7 +72,7 @@ impl<'g, Root: NodeHandle> HugrView for DescendantsGraph<'g, Root> { #[inline] fn contains_node(&self, node: Node) -> bool { - self.graph.contains_node(node.index) + self.graph.contains_node(node.pg_index()) } #[inline] @@ -92,16 +92,19 @@ impl<'g, Root: NodeHandle> HugrView for DescendantsGraph<'g, Root> { #[inline] fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { - self.graph.port_offsets(node.index, dir).map_into() + self.graph.port_offsets(node.pg_index(), dir).map_into() } #[inline] fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { - self.graph.all_port_offsets(node.index).map_into() + self.graph.all_port_offsets(node.pg_index()).map_into() } fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { - let port = self.graph.port_index(node.index, port.offset).unwrap(); + let port = self + .graph + .port_index(node.pg_index(), port.pg_offset()) + .unwrap(); self.graph .port_links(port) .with_context(self) @@ -115,7 +118,7 @@ impl<'g, Root: NodeHandle> HugrView for DescendantsGraph<'g, Root> { fn node_connections(&self, node: Node, other: Node) -> Self::NodeConnections<'_> { self.graph - .get_connections(node.index, other.index) + .get_connections(node.pg_index(), other.pg_index()) .with_context(self) .map_with_context(|(p1, p2), hugr| { [p1, p2].map(|link| { @@ -127,25 +130,29 @@ impl<'g, Root: NodeHandle> HugrView for DescendantsGraph<'g, Root> { #[inline] fn num_ports(&self, node: Node, dir: Direction) -> usize { - self.graph.num_ports(node.index, dir) + self.graph.num_ports(node.pg_index(), dir) } #[inline] fn children(&self, node: Node) -> Self::Children<'_> { - match self.graph.contains_node(node.index) { - true => self.base_hugr().hierarchy.children(node.index).map_into(), + match self.graph.contains_node(node.pg_index()) { + true => self + .base_hugr() + .hierarchy + .children(node.pg_index()) + .map_into(), false => portgraph::hierarchy::Children::default().map_into(), } } #[inline] fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { - self.graph.neighbours(node.index, dir).map_into() + self.graph.neighbours(node.pg_index(), dir).map_into() } #[inline] fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { - self.graph.all_neighbours(node.index).map_into() + self.graph.all_neighbours(node.pg_index()).map_into() } } impl<'g, Root: NodeHandle> RootTagged for DescendantsGraph<'g, Root> { @@ -161,7 +168,7 @@ where let hugr = hugr.base_hugr(); Ok(Self { root, - graph: RegionGraph::new_region(&hugr.graph, &hugr.hierarchy, root.index), + graph: RegionGraph::new_region(&hugr.graph, &hugr.hierarchy, root.pg_index()), hugr, _phantom: std::marker::PhantomData, }) diff --git a/src/hugr/views/petgraph.rs b/src/hugr/views/petgraph.rs index 751b3ac4f..7fb3a9c84 100644 --- a/src/hugr/views/petgraph.rs +++ b/src/hugr/views/petgraph.rs @@ -3,11 +3,11 @@ use crate::hugr::HugrView; use crate::ops::OpType; use crate::types::EdgeKind; +use crate::NodeIndex; use crate::{Node, Port}; use context_iterators::{ContextIterator, IntoContextIterator, MapWithCtx}; use petgraph::visit as pv; -use portgraph::NodeIndex; /// Wrapper for a HugrView that implements petgraph's traits. /// @@ -50,11 +50,11 @@ where } fn to_index(&self, ix: Self::NodeId) -> usize { - ix.index.into() + ix.index() } fn from_index(&self, ix: usize) -> Self::NodeId { - NodeIndex::new(ix).into() + portgraph::NodeIndex::new(ix).into() } } diff --git a/src/hugr/views/sibling.rs b/src/hugr/views/sibling.rs index 4311afb2d..d5ed45865 100644 --- a/src/hugr/views/sibling.rs +++ b/src/hugr/views/sibling.rs @@ -63,7 +63,7 @@ macro_rules! impl_base_members { #[inline] fn node_count(&self) -> usize { - self.base_hugr().hierarchy.child_count(self.root.index) + 1 + self.base_hugr().hierarchy.child_count(self.root.pg_index()) + 1 } #[inline] @@ -80,7 +80,7 @@ macro_rules! impl_base_members { let children = self .base_hugr() .hierarchy - .children(self.root.index) + .children(self.root.pg_index()) .map_into(); iter::once(self.root).chain(children) } @@ -88,7 +88,7 @@ macro_rules! impl_base_members { fn children(&self, node: Node) -> Self::Children<'_> { // Same as SiblingGraph match node == self.root { - true => self.base_hugr().hierarchy.children(node.index).map_into(), + true => self.base_hugr().hierarchy.children(node.pg_index()).map_into(), false => portgraph::hierarchy::Children::default().map_into(), } } @@ -118,21 +118,24 @@ impl<'g, Root: NodeHandle> HugrView for SiblingGraph<'g, Root> { #[inline] fn contains_node(&self, node: Node) -> bool { - self.graph.contains_node(node.index) + self.graph.contains_node(node.pg_index()) } #[inline] fn node_ports(&self, node: Node, dir: Direction) -> Self::NodePorts<'_> { - self.graph.port_offsets(node.index, dir).map_into() + self.graph.port_offsets(node.pg_index(), dir).map_into() } #[inline] fn all_node_ports(&self, node: Node) -> Self::NodePorts<'_> { - self.graph.all_port_offsets(node.index).map_into() + self.graph.all_port_offsets(node.pg_index()).map_into() } fn linked_ports(&self, node: Node, port: Port) -> Self::PortLinks<'_> { - let port = self.graph.port_index(node.index, port.offset).unwrap(); + let port = self + .graph + .port_index(node.pg_index(), port.pg_offset()) + .unwrap(); self.graph .port_links(port) .with_context(self) @@ -146,7 +149,7 @@ impl<'g, Root: NodeHandle> HugrView for SiblingGraph<'g, Root> { fn node_connections(&self, node: Node, other: Node) -> Self::NodeConnections<'_> { self.graph - .get_connections(node.index, other.index) + .get_connections(node.pg_index(), other.pg_index()) .with_context(self) .map_with_context(|(p1, p2), hugr| { [p1, p2].map(|link| { @@ -158,17 +161,17 @@ impl<'g, Root: NodeHandle> HugrView for SiblingGraph<'g, Root> { #[inline] fn num_ports(&self, node: Node, dir: Direction) -> usize { - self.graph.num_ports(node.index, dir) + self.graph.num_ports(node.pg_index(), dir) } #[inline] fn neighbours(&self, node: Node, dir: Direction) -> Self::Neighbours<'_> { - self.graph.neighbours(node.index, dir).map_into() + self.graph.neighbours(node.pg_index(), dir).map_into() } #[inline] fn all_neighbours(&self, node: Node) -> Self::Neighbours<'_> { - self.graph.all_neighbours(node.index).map_into() + self.graph.all_neighbours(node.pg_index()).map_into() } } impl<'g, Root: NodeHandle> RootTagged for SiblingGraph<'g, Root> { @@ -180,7 +183,7 @@ impl<'a, Root: NodeHandle> SiblingGraph<'a, Root> { let hugr = hugr.base_hugr(); Self { root, - graph: FlatRegionGraph::new_flat_region(&hugr.graph, &hugr.hierarchy, root.index), + graph: FlatRegionGraph::new_flat_region(&hugr.graph, &hugr.hierarchy, root.pg_index()), hugr, _phantom: std::marker::PhantomData, } @@ -267,7 +270,7 @@ impl<'g, Root: NodeHandle> HugrInternals for SiblingMut<'g, Root> { FlatRegionGraph::new_flat_region( &self.base_hugr().graph, &self.base_hugr().hierarchy, - self.root.index, + self.root.pg_index(), ) } diff --git a/src/hugr/views/sibling_subgraph.rs b/src/hugr/views/sibling_subgraph.rs index 263b5c8b5..33e249dd3 100644 --- a/src/hugr/views/sibling_subgraph.rs +++ b/src/hugr/views/sibling_subgraph.rs @@ -186,7 +186,10 @@ impl SiblingSubgraph { ) -> Result { let pg = hugr.portgraph(); - let to_pg = |(n, p): (Node, Port)| pg.port_index(n.index, p.offset).expect("invalid port"); + let to_pg = |(n, p): (Node, Port)| { + pg.port_index(n.pg_index(), p.pg_offset()) + .expect("invalid port") + }; // Ordering of the edges here is preserved and becomes ordering of the signature. let subpg = Subgraph::new_subgraph( diff --git a/src/lib.rs b/src/lib.rs index 3b3f3671c..d1675d6e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ pub mod algorithm; pub mod builder; +mod core; pub mod extension; pub mod hugr; pub mod macros; @@ -23,5 +24,8 @@ pub mod types; mod utils; pub mod values; +pub use crate::core::{ + CircuitUnit, Direction, IncomingPort, Node, NodeIndex, OutgoingPort, Port, PortIndex, Wire, +}; pub use crate::extension::Extension; -pub use crate::hugr::{Direction, Hugr, HugrView, Node, Port, SimpleReplacement, Wire}; +pub use crate::hugr::{Hugr, HugrView, SimpleReplacement}; diff --git a/src/ops.rs b/src/ops.rs index ad99e26b3..4926e60b6 100644 --- a/src/ops.rs +++ b/src/ops.rs @@ -9,8 +9,8 @@ pub mod leaf; pub mod module; pub mod tag; pub mod validate; -use crate::hugr::PortIndex; use crate::types::{EdgeKind, FunctionType, SignatureDescription, Type}; +use crate::PortIndex; use crate::{Direction, Port}; use portgraph::NodeIndex; diff --git a/src/types/signature.rs b/src/types/signature.rs index 38a816092..7b3216a36 100644 --- a/src/types/signature.rs +++ b/src/types/signature.rs @@ -9,12 +9,10 @@ use smol_str::SmolStr; use std::fmt::{self, Display, Write}; -use crate::hugr::{Direction, PortIndex}; +use crate::{Direction, Port, PortIndex}; use super::{Type, TypeRow}; -use crate::hugr::Port; - use crate::extension::ExtensionSet; use delegate::delegate; diff --git a/src/types/type_row.rs b/src/types/type_row.rs index 8a2bedcf6..9cfd6b03b 100644 --- a/src/types/type_row.rs +++ b/src/types/type_row.rs @@ -8,8 +8,8 @@ use std::{ }; use super::Type; -use crate::hugr::PortIndex; use crate::utils::display_list; +use crate::PortIndex; use delegate::delegate; #[cfg(feature = "pyo3")]