use crate::circuit::{Instruction, Operation, Parameter, ParameterValue, Qubit, ValueOperation};
use crate::compile::CompilerError;
use crate::compile::transform::rebuild::ClassicalRemap;
use smallvec::SmallVec;
#[derive(Debug, Clone)]
pub(super) struct LowerableOperation {
pub(super) instruction: Instruction,
pub(super) qubits: SmallVec<[Qubit; 3]>,
pub(super) params: SmallVec<[ParameterValue; 1]>,
pub(super) label: Option<Box<str>>,
}
impl LowerableOperation {
pub(super) fn gphase_param(&self) -> Result<Parameter, CompilerError> {
self.params.first().map(Parameter::from).ok_or_else(|| {
CompilerError::InvariantViolation(
"GPhase operation must contain one parameter".to_string(),
)
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum LoweringScope {
TopLevel,
ControlFlowBody,
}
pub(crate) struct LoweringTarget<'a> {
output: &'a mut Vec<ValueOperation>,
phase_delta: &'a mut Parameter,
scope: LoweringScope,
}
impl<'a> LoweringTarget<'a> {
pub(crate) fn top_level(
output: &'a mut Vec<ValueOperation>,
phase_delta: &'a mut Parameter,
) -> Self {
Self {
output,
phase_delta,
scope: LoweringScope::TopLevel,
}
}
pub(crate) fn control_flow_body(
output: &'a mut Vec<ValueOperation>,
phase_delta: &'a mut Parameter,
) -> Self {
Self {
output,
phase_delta,
scope: LoweringScope::ControlFlowBody,
}
}
pub(crate) const fn is_top_level(&self) -> bool {
matches!(self.scope, LoweringScope::TopLevel)
}
pub(crate) fn push(&mut self, operation: ValueOperation) {
self.output.push(operation);
}
pub(crate) fn accumulate_phase(&mut self, phase: Parameter) {
*self.phase_delta = &*self.phase_delta + &phase;
}
}
pub(crate) trait OperationSequenceLowerer {
fn lower_one_operation(
&mut self,
operation: &Operation,
classical_remap: &ClassicalRemap,
target: &mut LoweringTarget<'_>,
) -> Result<(), CompilerError>;
fn lower_sequence(
&mut self,
operations: &[Operation],
classical_remap: &ClassicalRemap,
mut target: LoweringTarget<'_>,
) -> Result<(), CompilerError> {
for operation in operations {
self.lower_one_operation(operation, classical_remap, &mut target)?;
}
Ok(())
}
}