use crate::circuit::Circuit;
use crate::compile::CompilerError;
use crate::compile::transform::analysis::{CircuitAnalysis, WorkflowCircuitAnalysis};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum PassApplicability {
Run,
ProvenNoOp(&'static str),
}
pub(crate) trait WorkflowPass {
fn applicability(&self, analysis: &WorkflowCircuitAnalysis) -> PassApplicability;
}
#[derive(Debug, Clone, PartialEq)]
#[allow(clippy::large_enum_variant)] pub enum TransformOutcome {
Unchanged,
Changed(Circuit),
}
impl TransformOutcome {
pub const fn changed(&self) -> bool {
matches!(self, Self::Changed(_))
}
pub fn into_circuit(self, original: &Circuit) -> Circuit {
match self {
Self::Unchanged => original.clone(),
Self::Changed(circuit) => circuit,
}
}
}
pub trait Transformer {
fn name(&self) -> &'static str;
fn transform(
&self,
circuit: &Circuit,
analysis: Option<&CircuitAnalysis>,
) -> Result<TransformOutcome, CompilerError>;
}
#[cfg(test)]
#[derive(Debug)]
pub(crate) struct ResolvedTransform {
pub(crate) circuit: Circuit,
pub(crate) changed: bool,
}
#[cfg(test)]
pub(crate) fn resolve_transform_for_test(
outcome: TransformOutcome,
original: &Circuit,
) -> ResolvedTransform {
let changed = outcome.changed();
ResolvedTransform {
circuit: outcome.into_circuit(original),
changed,
}
}
#[cfg(test)]
pub(crate) trait TransformerTestExt: Transformer {
fn transform_resolved(
&self,
circuit: &Circuit,
analysis: Option<&CircuitAnalysis>,
) -> Result<ResolvedTransform, CompilerError> {
self.transform(circuit, analysis)
.map(|outcome| resolve_transform_for_test(outcome, circuit))
}
}
#[cfg(test)]
impl<T: Transformer + ?Sized> TransformerTestExt for T {}
#[cfg(test)]
#[path = "./transformer_test.rs"]
mod transformer_test;