Skip to content
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

feat: Rewrite for inlining a single Call #1934

Merged
merged 32 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
7a3ac0b
Add InlineCall - v0 supporting recursion but no other incoming edges
acl-cqc Feb 5, 2025
6d8dfc1
fix verify to also check call target
acl-cqc Feb 5, 2025
0d5b5af
Update portgraph to 0.13.2
acl-cqc Feb 5, 2025
75f8842
Add HugrMut::copy_subtree. TODO check for invalidation?
acl-cqc Feb 5, 2025
4c345eb
InlineCall uses copy_subtree
acl-cqc Feb 5, 2025
120f17c
First test; fix copying of optypes,metadata,hierarchy
acl-cqc Feb 5, 2025
c10c81a
WIP test
acl-cqc Feb 5, 2025
45dc680
Fix recursion by changing copy_subtree => copy_descendants
acl-cqc Feb 5, 2025
d3f9c62
Validate in test
acl-cqc Feb 6, 2025
231b125
Tidy tests w/helper methods calls/extension_ops
acl-cqc Feb 6, 2025
756902a
refactor test: inline get_nonrec_call
acl-cqc Feb 7, 2025
8db58de
Fix tests for --all-features
acl-cqc Feb 7, 2025
45dd9ac
Update that comment
acl-cqc Feb 25, 2025
c995322
test errors, improve+derive InlineCallError
acl-cqc Feb 25, 2025
5a1f2f8
Use hierarchy.descendants
acl-cqc Feb 27, 2025
7f86624
oops, fix prev
acl-cqc Feb 27, 2025
b32065b
Add InlineCall::new
doug-q Feb 27, 2025
f7069c0
Add Option<Substitution> to copy_descendants
acl-cqc Mar 3, 2025
feaaace
Merge remote-tracking branch 'origin/main' into HEAD
acl-cqc Mar 3, 2025
49a5726
comment => doc comment
acl-cqc Mar 3, 2025
787773a
doc new
acl-cqc Mar 3, 2025
ee38b5b
use derive_more not thiserror
acl-cqc Mar 3, 2025
8e4bf5d
Use RootChecked to improve coverage
acl-cqc Mar 3, 2025
7f13f41
Use BTreeMap, changing translate_indices to return impl Iterator
acl-cqc Mar 3, 2025
122c751
Test nesting
acl-cqc Mar 3, 2025
99a152a
Add static edge, check it gets preserved (it doesn't)
acl-cqc Mar 3, 2025
5f47685
Preserve Order edges
acl-cqc Mar 3, 2025
eb95372
Add test of polymorphism
acl-cqc Mar 3, 2025
1a71d61
Fix by updating portgraph
acl-cqc Mar 4, 2025
acefcda
Merge remote-tracking branch 'origin/main' into acl/inline_call
acl-cqc Mar 4, 2025
1caa970
Fix --all-features test
acl-cqc Mar 4, 2025
0f78db5
common up a get_optype
acl-cqc Mar 4, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ missing_docs = "warn"
debug_assert_with_mut_call = "warn"

[workspace.dependencies]
portgraph = { version = "0.13.0" }
portgraph = { version = "0.13.3" }
insta = { version = "1.42.2" }
bitvec = "1.0.1"
capnp = "0.20.4"
Expand Down
74 changes: 68 additions & 6 deletions hugr-core/src/hugr/hugrmut.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Low-level interface for modifying a HUGR.

use core::panic;
use std::collections::HashMap;
use std::collections::{BTreeMap, HashMap};
use std::sync::Arc;

use portgraph::view::{NodeFilter, NodeFiltered};
Expand All @@ -11,6 +11,8 @@ use crate::extension::ExtensionRegistry;
use crate::hugr::views::SiblingSubgraph;
use crate::hugr::{HugrView, Node, OpType, RootTagged};
use crate::hugr::{NodeMetadata, Rewrite};
use crate::ops::OpTrait;
use crate::types::Substitution;
use crate::{Extension, Hugr, IncomingPort, OutgoingPort, Port, PortIndex};

use super::internal::HugrMutInternals;
Expand Down Expand Up @@ -146,6 +148,29 @@ pub trait HugrMut: HugrMutInternals {
self.hugr_mut().remove_node(node);
}

/// Copies the strict descendants of `root` to under the `new_parent`, optionally applying a
/// [Substitution] to the [OpType]s of the copied nodes.
///
/// That is, the immediate children of root, are copied to make children of `new_parent`.
///
/// Note this may invalidate the Hugr in two ways:
/// * Adding children of `root` may make the children-list of `new_parent` invalid e.g.
/// leading to multiple [Input](OpType::Input), [Output](OpType::Output) or
/// [ExitBlock](OpType::ExitBlock) nodes or Input/Output in the wrong positions
/// * Nonlocal edges incoming to the subtree of `root` will be copied to target the subtree under `new_parent`
/// which may be invalid if `new_parent` is not a child of `root`s parent (for `Ext` edges - or
/// correspondingly for `Dom` edges)
fn copy_descendants(
&mut self,
root: Node,
new_parent: Node,
subst: Option<Substitution>,
) -> BTreeMap<Node, Node> {
panic_invalid_node(self, root);
panic_invalid_node(self, new_parent);
self.hugr_mut().copy_descendants(root, new_parent, subst)
}

/// Connect two nodes at the given ports.
///
/// # Panics
Expand Down Expand Up @@ -294,8 +319,8 @@ pub struct InsertionResult {

fn translate_indices(
node_map: HashMap<portgraph::NodeIndex, portgraph::NodeIndex>,
) -> HashMap<Node, Node> {
HashMap::from_iter(node_map.into_iter().map(|(k, v)| (k.into(), v.into())))
) -> impl Iterator<Item = (Node, Node)> {
node_map.into_iter().map(|(k, v)| (k.into(), v.into()))
}

/// Impl for non-wrapped Hugrs. Overwrites the recursive default-impls to directly use the hugr.
Expand Down Expand Up @@ -398,7 +423,7 @@ impl<T: RootTagged<RootHandle = Node, Node = Node> + AsMut<Hugr>> HugrMut for T
);
InsertionResult {
new_root,
node_map: translate_indices(node_map),
node_map: translate_indices(node_map).collect(),
}
}

Expand All @@ -419,7 +444,7 @@ impl<T: RootTagged<RootHandle = Node, Node = Node> + AsMut<Hugr>> HugrMut for T
);
InsertionResult {
new_root,
node_map: translate_indices(node_map),
node_map: translate_indices(node_map).collect(),
}
}

Expand Down Expand Up @@ -448,7 +473,44 @@ impl<T: RootTagged<RootHandle = Node, Node = Node> + AsMut<Hugr>> HugrMut for T
self.use_extensions(exts);
}
}
translate_indices(node_map)
translate_indices(node_map).collect()
}

fn copy_descendants(
&mut self,
root: Node,
new_parent: Node,
subst: Option<Substitution>,
) -> BTreeMap<Node, Node> {
let mut descendants = self.base_hugr().hierarchy.descendants(root.pg_index());
let root2 = descendants.next();
debug_assert_eq!(root2, Some(root.pg_index()));
let nodes = Vec::from_iter(descendants);
let node_map = translate_indices(
portgraph::view::Subgraph::with_nodes(&mut self.as_mut().graph, nodes)
.copy_in_parent()
.expect("Is a MultiPortGraph"),
)
.collect::<BTreeMap<_, _>>();

for node in self.children(root).collect::<Vec<_>>() {
self.set_parent(*node_map.get(&node).unwrap(), new_parent);
}

// Copy the optypes, metadata, and hierarchy
for (&node, &new_node) in node_map.iter() {
for ch in self.children(node).collect::<Vec<_>>() {
self.set_parent(*node_map.get(&ch).unwrap(), new_node);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like the hierarchy part isn't covered, do you need a test with more nesting?

}
let new_optype = match (&subst, self.get_optype(node)) {
(None, op) => op.clone(),
(Some(subst), op) => op.substitute(subst),
};
self.as_mut().op_types.set(new_node.pg_index(), new_optype);
let meta = self.base_hugr().metadata.get(node.pg_index()).clone();
self.as_mut().metadata.set(new_node.pg_index(), meta);
}
node_map
}
}

Expand Down
1 change: 1 addition & 0 deletions hugr-core/src/hugr/rewrite.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Rewrite operations on the HUGR - replacement, outlining, etc.

pub mod consts;
pub mod inline_call;
pub mod inline_dfg;
pub mod insert_identity;
pub mod outline_cfg;
Expand Down
Loading
Loading