pub mod consts;
pub mod inline_call;
pub mod inline_dfg;
pub mod insert_cut;
pub mod insert_identity;
pub mod outline_cfg;
pub mod peel_loop;
mod port_types;
pub mod replace;
pub mod simple_replace;
use crate::HugrView;
use crate::core::HugrNode;
use crate::hugr::views::NodesIter;
use itertools::Itertools;
pub use port_types::{BoundaryPort, HostPort, ReplacementPort};
pub use simple_replace::{SimpleReplacement, SimpleReplacementError};
use super::HugrMut;
use super::views::ExtractionResult;
pub trait PatchVerification {
type Error: std::error::Error;
type Node: HugrNode;
fn verify(&self, h: &impl HugrView<Node = Self::Node>) -> Result<(), Self::Error>;
fn invalidated_nodes(
&self,
h: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node>;
}
pub trait Patch<H: NodesIter>: PatchVerification<Node = H::Node> {
type Outcome;
const UNCHANGED_ON_FAILURE: bool;
fn apply(self, h: &mut H) -> Result<Self::Outcome, Self::Error>;
}
pub trait PatchHugrMut: PatchVerification {
type Outcome;
const UNCHANGED_ON_FAILURE: bool;
fn apply_hugr_mut(
self,
h: &mut impl HugrMut<Node = Self::Node>,
) -> Result<Self::Outcome, Self::Error>;
}
impl<R: PatchHugrMut, H: HugrMut<Node = R::Node>> Patch<H> for R {
type Outcome = R::Outcome;
const UNCHANGED_ON_FAILURE: bool = R::UNCHANGED_ON_FAILURE;
fn apply(self, h: &mut H) -> Result<Self::Outcome, Self::Error> {
self.apply_hugr_mut(h)
}
}
pub struct Transactional<R> {
underlying: R,
}
impl<R: PatchVerification> PatchVerification for Transactional<R> {
type Error = R::Error;
type Node = R::Node;
fn verify(&self, h: &impl HugrView<Node = Self::Node>) -> Result<(), Self::Error> {
self.underlying.verify(h)
}
#[inline]
fn invalidated_nodes(
&self,
h: &impl HugrView<Node = Self::Node>,
) -> impl Iterator<Item = Self::Node> {
self.underlying.invalidated_nodes(h)
}
}
impl<R: PatchHugrMut> PatchHugrMut for Transactional<R> {
type Outcome = R::Outcome;
const UNCHANGED_ON_FAILURE: bool = true;
fn apply_hugr_mut(
self,
h: &mut impl HugrMut<Node = Self::Node>,
) -> Result<Self::Outcome, Self::Error> {
if R::UNCHANGED_ON_FAILURE {
return self.underlying.apply_hugr_mut(h);
}
let (backup, backup_map) = h.extract_hugr(h.module_root());
let backup_root = backup_map.extracted_node(h.module_root());
let backup_entrypoint = backup_map.extracted_node(h.entrypoint());
let r = self.underlying.apply_hugr_mut(h);
if r.is_err() {
let h_root = h.module_root();
for f in h.children(h_root).collect_vec() {
h.remove_subtree(f);
}
let insert_map = h.insert_hugr(h_root, backup).node_map;
let inserted_root = insert_map[&backup_root];
let inserted_entrypoint = insert_map[&backup_entrypoint];
h.remove_node(h_root);
h.set_module_root(inserted_root);
h.set_entrypoint(inserted_entrypoint);
}
r
}
}