-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HugrView: validate nodes, and remove Base #523
Changes from 6 commits
e28c60a
f2b64e1
17c3a30
8475d12
aa88f75
487c795
ea70450
430e4e6
c789969
6507bbc
929ecf4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,7 +18,7 @@ use itertools::{Itertools, MapInto}; | |
use portgraph::dot::{DotFormat, EdgeStyle, NodeStyle, PortStyle}; | ||
use portgraph::{multiportgraph, LinkView, MultiPortGraph, PortView}; | ||
|
||
use super::{Hugr, NodeMetadata, NodeType}; | ||
use super::{Hugr, HugrError, NodeMetadata, NodeType, DEFAULT_NODETYPE}; | ||
use crate::ops::handle::NodeHandle; | ||
use crate::ops::{FuncDecl, FuncDefn, OpName, OpTag, OpType, DFG}; | ||
use crate::types::{EdgeKind, FunctionType}; | ||
|
@@ -80,17 +80,67 @@ pub trait HugrView: sealed::HugrInternals { | |
/// Returns whether the node exists. | ||
fn contains_node(&self, node: Node) -> bool; | ||
|
||
/// Validates that a node is valid in the graph. | ||
/// | ||
/// Returns a [`HugrError::InvalidNode`] otherwise. | ||
#[inline] | ||
fn valid_node(&self, node: Node) -> Result<(), HugrError> { | ||
match self.contains_node(node) { | ||
true => Ok(()), | ||
false => Err(HugrError::InvalidNode(node)), | ||
} | ||
} | ||
|
||
/// Validates that a node is a valid root descendant in the graph. | ||
/// | ||
/// To include the root node use [`HugrView::valid_node`] instead. | ||
/// | ||
/// Returns a [`HugrError::InvalidNode`] otherwise. | ||
#[inline] | ||
fn valid_non_root(&self, node: Node) -> Result<(), HugrError> { | ||
match self.root() == node { | ||
true => Err(HugrError::InvalidNode(node)), | ||
false => self.valid_node(node), | ||
} | ||
} | ||
|
||
/// Returns the parent of a node. | ||
fn get_parent(&self, node: Node) -> Option<Node>; | ||
#[inline] | ||
fn get_parent(&self, node: Node) -> Option<Node> { | ||
self.valid_non_root(node).ok()?; | ||
self.base_hugr() | ||
.hierarchy | ||
.parent(node.index) | ||
.map(Into::into) | ||
} | ||
|
||
/// Returns the operation type of a node. | ||
fn get_optype(&self, node: Node) -> &OpType; | ||
#[inline] | ||
fn get_optype(&self, node: Node) -> &OpType { | ||
&self.get_nodetype(node).op | ||
} | ||
|
||
/// Returns the type of a node. | ||
fn get_nodetype(&self, node: Node) -> &NodeType; | ||
#[inline] | ||
fn get_nodetype(&self, node: Node) -> &NodeType { | ||
match self.contains_node(node) { | ||
true => self.base_hugr().op_types.get(node.index), | ||
false => &DEFAULT_NODETYPE, | ||
} | ||
} | ||
|
||
/// Returns the metadata associated with a node. | ||
fn get_metadata(&self, node: Node) -> &NodeMetadata; | ||
#[inline] | ||
fn get_metadata(&self, node: Node) -> &NodeMetadata { | ||
// The other way to do it - exploit the UnmanagedDenseMap's get() returning &default | ||
let md = &self.base_hugr().metadata; | ||
|
||
let idx = match self.contains_node(node) { | ||
true => node.index, | ||
false => portgraph::NodeIndex::new(md.capacity() + 1), | ||
}; | ||
md.get(idx) | ||
} | ||
|
||
/// Returns the number of nodes in the hugr. | ||
fn node_count(&self) -> usize; | ||
|
@@ -249,12 +299,12 @@ pub trait HugrView: sealed::HugrInternals { | |
} | ||
|
||
/// A common trait for views of a HUGR hierarchical subgraph. | ||
pub trait HierarchyView<'a>: HugrView { | ||
/// The base from which the subgraph is derived. | ||
type Base; | ||
|
||
pub trait HierarchyView<'a>: HugrView + Sized { | ||
/// Create a hierarchical view of a HUGR given a root node. | ||
fn new(hugr: &'a Self::Base, root: Node) -> Self; | ||
/// | ||
/// # Errors | ||
/// Returns [`HugrError::InvalidNode`] if the root isn't a node of the required [OpTag] | ||
fn new(hugr: &'a impl HugrView, root: Node) -> Result<Self, HugrError>; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, naming questions that I am not the authority on but will still give my opinion -- use it as you wish. I try to prefix function names that can fail with @aborgna-q what is your preference? You're more of a rustacean than me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, this should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good to me, done. I wonder about a utility function |
||
} | ||
|
||
impl<T> HugrView for T | ||
|
@@ -287,21 +337,6 @@ where | |
self.as_ref().graph.contains_node(node.index) | ||
} | ||
|
||
#[inline] | ||
fn get_parent(&self, node: Node) -> Option<Node> { | ||
self.as_ref().hierarchy.parent(node.index).map(Into::into) | ||
} | ||
|
||
#[inline] | ||
fn get_optype(&self, node: Node) -> &OpType { | ||
&self.as_ref().op_types.get(node.index).op | ||
} | ||
|
||
#[inline] | ||
fn get_nodetype(&self, node: Node) -> &NodeType { | ||
self.as_ref().op_types.get(node.index) | ||
} | ||
|
||
#[inline] | ||
fn node_count(&self) -> usize { | ||
self.as_ref().graph.node_count() | ||
|
@@ -386,11 +421,6 @@ where | |
None | ||
} | ||
} | ||
|
||
#[inline] | ||
fn get_metadata(&self, node: Node) -> &NodeMetadata { | ||
self.as_ref().metadata.get(node.index) | ||
} | ||
} | ||
|
||
pub(crate) mod sealed { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is a bit cryptic to me, I'm not sure what it means.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sorry, this is where I'm not sure what to do. Hopefully @aborgna-q can give a shout, I'm wondering about a PR to add something to portgraph's
UnmanagedDenseMap
....There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alan's referring to the behaviour of the metadata container, which returns a reference to the default value if it doesn't know about the node index.
I'd avoid fiddling with portgraph assumptions when you can directly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, I can use NodeMetadata::Null, indeed.
So I guess this will do for now - I don't think this have to declare
const DEFAULT_NODETYPE
etc. is a good general solution (when I know an appropriately-lifetimed default value is sitting there in the map), but it's just about OK for the specific cases here. IOW I might come back to this in another PR later...