Skip to content

Commit c4d3ebf

Browse files
committed
Merge remote-tracking branch 'origin/main' into new/add-inferred-resources
2 parents 4491bad + 76402e3 commit c4d3ebf

24 files changed

+593
-528
lines changed

src/builder/build_traits.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use super::{
2929

3030
use crate::Hugr;
3131

32-
use crate::hugr::HugrInternalsMut;
32+
use crate::hugr::HugrMut;
3333

3434
/// Trait for HUGR container builders.
3535
/// Containers are nodes that are parents of sibling graphs.

src/builder/cfg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::{ops::handle::NodeHandle, types::Type};
1212

1313
use crate::Node;
1414
use crate::{
15-
hugr::{HugrInternalsMut, NodeType},
15+
hugr::{HugrMut, NodeType},
1616
type_row, Hugr,
1717
};
1818

src/builder/conditional.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use super::{
1515

1616
use crate::Node;
1717
use crate::{
18-
hugr::{HugrInternalsMut, NodeType},
18+
hugr::{HugrMut, NodeType},
1919
Hugr,
2020
};
2121

src/builder/dataflow.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use crate::types::{FunctionType, Signature};
1111

1212
use crate::extension::ExtensionSet;
1313
use crate::Node;
14-
use crate::{hugr::HugrInternalsMut, Hugr};
14+
use crate::{hugr::HugrMut, Hugr};
1515

1616
/// Builder for a [`ops::DFG`] node.
1717
#[derive(Debug, Clone, PartialEq)]

src/builder/module.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use super::{
44
BuildError, Container,
55
};
66

7+
use crate::hugr::hugrmut::sealed::HugrMutInternals;
78
use crate::{
89
hugr::{views::HugrView, ValidationError},
910
ops,
@@ -18,10 +19,7 @@ use crate::types::Signature;
1819
use crate::Node;
1920
use smol_str::SmolStr;
2021

21-
use crate::{
22-
hugr::{HugrInternalsMut, NodeType},
23-
Hugr,
24-
};
22+
use crate::{hugr::NodeType, Hugr};
2523

2624
/// Builder for a HUGR module.
2725
#[derive(Debug, Clone, PartialEq)]

src/extension/infer.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ mod test {
626626
use super::*;
627627
use crate::builder::{BuildError, DFGBuilder, Dataflow, DataflowHugr};
628628
use crate::extension::ExtensionSet;
629-
use crate::hugr::HugrInternalsMut;
629+
use crate::hugr::HugrMut;
630630
use crate::hugr::{validate::ValidationError, Hugr, HugrView, NodeType};
631631
use crate::ops::{self, dataflow::IOTrait, handle::NodeHandle};
632632
use crate::type_row;

src/extension/op_def.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use super::{
77
Extension, ExtensionBuildError, ExtensionId, ExtensionSet, SignatureError, TypeParametrised,
88
};
99

10-
use crate::types::{SignatureDescription, TypeRow};
10+
use crate::types::SignatureDescription;
1111

1212
use crate::types::FunctionType;
1313

@@ -31,8 +31,8 @@ pub trait CustomSignatureFunc: Send + Sync {
3131
name: &SmolStr,
3232
arg_values: &[TypeArg],
3333
misc: &HashMap<String, serde_yaml::Value>,
34-
// TODO: Make return type an FunctionType
35-
) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError>;
34+
) -> Result<FunctionType, SignatureError>;
35+
3636
/// Describe the signature of a node, given the operation name,
3737
/// values for the type parameters,
3838
/// and 'misc' data from the extension definition YAML.
@@ -48,14 +48,14 @@ pub trait CustomSignatureFunc: Send + Sync {
4848

4949
impl<F> CustomSignatureFunc for F
5050
where
51-
F: Fn(&[TypeArg]) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> + Send + Sync,
51+
F: Fn(&[TypeArg]) -> Result<FunctionType, SignatureError> + Send + Sync,
5252
{
5353
fn compute_signature(
5454
&self,
5555
_name: &SmolStr,
5656
arg_values: &[TypeArg],
5757
_misc: &HashMap<String, serde_yaml::Value>,
58-
) -> Result<(TypeRow, TypeRow, ExtensionSet), SignatureError> {
58+
) -> Result<FunctionType, SignatureError> {
5959
self(arg_values)
6060
}
6161
}
@@ -217,7 +217,7 @@ impl OpDef {
217217
/// OpDef with statically-provided [TypeArg]s.
218218
pub fn compute_signature(&self, args: &[TypeArg]) -> Result<FunctionType, SignatureError> {
219219
self.check_args(args)?;
220-
let (ins, outs, res) = match &self.signature_func {
220+
let res = match &self.signature_func {
221221
SignatureFunc::FromDecl { .. } => {
222222
// Sig should be computed solely from inputs + outputs + args.
223223
todo!()
@@ -227,7 +227,7 @@ impl OpDef {
227227
// TODO bring this assert back once resource inference is done?
228228
// https://github.com/CQCL-DEV/hugr/issues/425
229229
// assert!(res.contains(self.extension()));
230-
Ok(FunctionType::new(ins, outs).with_extension_delta(&res))
230+
Ok(res)
231231
}
232232

233233
/// Optional description of the ports in the signature.

src/hugr.rs

+68-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! The Hugr data structure, and its basic component handles.
22
3-
mod hugrmut;
3+
pub mod hugrmut;
44

55
pub mod rewrite;
66
pub mod serialize;
@@ -10,14 +10,14 @@ pub mod views;
1010
use std::collections::{HashMap, VecDeque};
1111
use std::iter;
1212

13-
pub(crate) use self::hugrmut::HugrInternalsMut;
13+
pub(crate) use self::hugrmut::HugrMut;
1414
pub use self::validate::ValidationError;
1515

1616
use derive_more::From;
1717
pub use rewrite::{Rewrite, SimpleReplacement, SimpleReplacementError};
1818

1919
use portgraph::multiportgraph::MultiPortGraph;
20-
use portgraph::{Hierarchy, PortMut, UnmanagedDenseMap};
20+
use portgraph::{Hierarchy, NodeIndex, PortMut, UnmanagedDenseMap};
2121
use thiserror::Error;
2222

2323
#[cfg(feature = "pyo3")]
@@ -251,12 +251,31 @@ impl Hugr {
251251
}
252252
}
253253

254-
/// Produce a canonical ordering of the nodes.
254+
/// Add a node to the graph, with the default conversion from OpType to NodeType
255+
pub(crate) fn add_op(&mut self, op: impl Into<OpType>) -> Node {
256+
// TODO: Default to `NodeType::open_extensions` once we can infer extensions
257+
self.add_node(NodeType::pure(op))
258+
}
259+
260+
/// Add a node to the graph.
261+
pub(crate) fn add_node(&mut self, nodetype: NodeType) -> Node {
262+
let node = self
263+
.graph
264+
.add_node(nodetype.input_count(), nodetype.output_count());
265+
self.op_types[node] = nodetype;
266+
node.into()
267+
}
268+
269+
/// Produce a canonical ordering of the descendant nodes of a root,
270+
/// following the graph hierarchy.
271+
///
272+
/// This starts with the root, and then proceeds in BFS order through the
273+
/// contained regions.
255274
///
256275
/// Used by [`HugrMut::canonicalize_nodes`] and the serialization code.
257-
fn canonical_order(&self) -> impl Iterator<Item = Node> + '_ {
276+
fn canonical_order(&self, root: Node) -> impl Iterator<Item = Node> + '_ {
258277
// Generate a BFS-ordered list of nodes based on the hierarchy
259-
let mut queue = VecDeque::from([self.root.into()]);
278+
let mut queue = VecDeque::from([root]);
260279
iter::from_fn(move || {
261280
let node = queue.pop_front()?;
262281
for child in self.children(node) {
@@ -265,6 +284,46 @@ impl Hugr {
265284
Some(node)
266285
})
267286
}
287+
288+
/// Compact the nodes indices of the hugr to be contiguous, and order them as a breadth-first
289+
/// traversal of the hierarchy.
290+
///
291+
/// The rekey function is called for each moved node with the old and new indices.
292+
///
293+
/// After this operation, a serialization and deserialization of the Hugr is guaranteed to
294+
/// preserve the indices.
295+
pub fn canonicalize_nodes(&mut self, mut rekey: impl FnMut(Node, Node)) {
296+
// Generate the ordered list of nodes
297+
let mut ordered = Vec::with_capacity(self.node_count());
298+
let root = self.root();
299+
ordered.extend(self.as_mut().canonical_order(root));
300+
301+
// Permute the nodes in the graph to match the order.
302+
//
303+
// Invariant: All the elements before `position` are in the correct place.
304+
for position in 0..ordered.len() {
305+
// Find the element's location. If it originally came from a previous position
306+
// then it has been swapped somewhere else, so we follow the permutation chain.
307+
let mut source: Node = ordered[position];
308+
while position > source.index.index() {
309+
source = ordered[source.index.index()];
310+
}
311+
312+
let target: Node = NodeIndex::new(position).into();
313+
if target != source {
314+
self.graph.swap_nodes(target.index, source.index);
315+
self.op_types.swap(target.index, source.index);
316+
self.hierarchy.swap_nodes(target.index, source.index);
317+
rekey(source, target);
318+
}
319+
}
320+
self.root = NodeIndex::new(0);
321+
322+
// Finish by compacting the copy nodes.
323+
// The operation nodes will be left in place.
324+
// This step is not strictly necessary.
325+
self.graph.compact_nodes(|_, _| {});
326+
}
268327
}
269328

270329
impl Port {
@@ -367,6 +426,9 @@ pub enum HugrError {
367426
/// An error occurred while manipulating the hierarchy.
368427
#[error("An error occurred while manipulating the hierarchy.")]
369428
HierarchyError(#[from] portgraph::hierarchy::AttachError),
429+
/// The node doesn't exist.
430+
#[error("Invalid node {0:?}.")]
431+
InvalidNode(Node),
370432
}
371433

372434
#[cfg(feature = "pyo3")]

0 commit comments

Comments
 (0)