use hugr::{
HugrView, core::HugrNode, extension::simple_op::MakeExtensionOp, hugr::hugrmut::HugrMut,
ops::ExtensionOp,
};
use crate::extension::modifier::Modifier;
pub mod control;
pub mod dagger;
pub mod modifier_resolver;
pub mod power;
use crate::metadata;
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash)]
pub struct CombinedModifier {
control: usize,
accum_ctrl: Vec<usize>,
dagger: bool,
power: bool,
}
impl CombinedModifier {
pub fn push(&mut self, ext_op: &ExtensionOp) {
match Modifier::from_extension_op(ext_op) {
Ok(Modifier::ControlModifier) => {
let ctrl = ext_op.args()[0].as_nat().unwrap() as usize;
self.control += ctrl;
self.accum_ctrl.push(ctrl);
}
Ok(Modifier::DaggerModifier) => self.dagger = !self.dagger,
Ok(Modifier::PowerModifier) => self.power = !self.power,
Err(_) => {}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
struct ModifierFlags {
control: bool,
dagger: bool,
power: bool,
}
impl ModifierFlags {
fn from_metadata<N: HugrNode>(h: &impl HugrView<Node = N>, n: N) -> Option<Self> {
h.get_metadata::<metadata::Unitary>(n)
.map(|num| ModifierFlags {
dagger: (num & 1) != 0,
control: (num & 2) != 0,
power: (num & 4) != 0,
})
}
fn set_metadata<N: HugrNode>(&self, h: &mut impl HugrMut<Node = N>, n: N) {
let mut num = 0;
if self.dagger {
num |= 1;
}
if self.control {
num |= 2;
}
if self.power {
num |= 4;
}
h.set_metadata::<metadata::Unitary>(n, num);
}
fn satisfies(&self, combined: &CombinedModifier) -> bool {
(combined.control == 0 || self.control)
&& (!combined.dagger || self.dagger)
&& (!combined.power || self.power)
}
fn from_combined(combined: &CombinedModifier) -> Self {
ModifierFlags {
control: combined.control > 0,
dagger: combined.dagger,
power: combined.power,
}
}
fn or(self, other: &Option<Self>) -> Self {
match other {
None => self,
Some(other) => ModifierFlags {
control: self.control || other.control,
dagger: self.dagger || other.dagger,
power: self.power || other.power,
},
}
}
}