1use crate::circuit::ClassicalControlOp;
44use crate::circuit::ClassicalType;
45use crate::circuit::circuit_param::{CircuitParam, ParameterValue};
46use crate::circuit::classical::{ClassicalValue, ClassicalVar};
47use crate::circuit::classical_expr::ClassicalExpr;
48use crate::circuit::control_flow::{ControlBody, validate_for_types, validate_switch};
49use crate::circuit::error::CircuitError;
50use crate::circuit::gate::directive::Directive;
51use crate::circuit::gate::instruction::Instruction;
52use crate::circuit::gate::standard_gate::StandardGate;
53use crate::circuit::operation::{Operation, ValueOperation};
54use alloc::collections::BTreeSet;
55use std::fmt;
56
57#[derive(Debug, Clone, PartialEq)]
86pub struct ValueControlBody {
87 operations: Vec<ValueOperation>,
88}
89
90impl ValueControlBody {
91 pub fn new(operations: Vec<ValueOperation>) -> Self {
93 Self { operations }
94 }
95
96 pub fn operations(&self) -> &[ValueOperation] {
98 self.operations.as_slice()
99 }
100
101 pub fn used_qubits(&self) -> BTreeSet<crate::circuit::Qubit> {
103 let mut qubits = BTreeSet::new();
104 for operation in &self.operations {
105 qubits.extend(operation.qubits.iter().copied());
106 if let ValueInstruction::ClassicalControl(control) = &operation.instruction {
107 qubits.extend(control.used_qubits());
108 }
109 }
110 qubits
111 }
112
113 pub fn has_measurement(&self) -> bool {
115 self.operations
116 .iter()
117 .any(|operation| match &operation.instruction {
118 ValueInstruction::Instruction(instruction) => instruction.has_measurement(),
119 ValueInstruction::ClassicalControl(control) => control.has_measurement(),
120 })
121 }
122
123 pub fn reads_value(&self, value: ClassicalValue) -> bool {
125 self.operations
126 .iter()
127 .any(|operation| match &operation.instruction {
128 ValueInstruction::Instruction(instruction) => instruction.reads_value(value),
129 ValueInstruction::ClassicalControl(control) => control.reads_value(value),
130 })
131 }
132}
133
134impl From<Vec<ValueOperation>> for ValueControlBody {
135 fn from(operations: Vec<ValueOperation>) -> Self {
136 Self::new(operations)
137 }
138}
139
140#[derive(Debug, Clone, PartialEq)]
145pub struct ValueSwitchCase {
146 pub value: u128,
148 pub body: ValueControlBody,
150}
151
152impl ValueSwitchCase {
153 pub fn new(value: u128, body: ValueControlBody) -> Self {
155 Self { value, body }
156 }
157}
158
159#[derive(Debug, Clone, PartialEq)]
177pub enum ValueClassicalControlOp {
178 If {
182 condition: ClassicalExpr,
184 then_body: ValueControlBody,
186 else_body: Option<ValueControlBody>,
188 },
189 While {
193 condition: ClassicalExpr,
195 body: ValueControlBody,
197 },
198 For {
203 var: ClassicalVar,
205 start: ClassicalExpr,
207 stop: ClassicalExpr,
209 step: ClassicalExpr,
211 body: ValueControlBody,
213 },
214 Switch {
218 target: ClassicalExpr,
220 cases: Vec<ValueSwitchCase>,
222 default: Option<ValueControlBody>,
224 },
225 Break,
227 Continue,
229}
230
231impl ValueClassicalControlOp {
232 pub fn new_if(
236 condition: ClassicalExpr,
237 then_body: ValueControlBody,
238 else_body: Option<ValueControlBody>,
239 ) -> Result<Self, CircuitError> {
240 if condition.ty() != ClassicalType::Bool {
241 return Err(CircuitError::InvalidOperation(format!(
242 "if condition must be Bool, got {:?}",
243 condition.ty()
244 )));
245 }
246 Ok(Self::If {
247 condition,
248 then_body,
249 else_body,
250 })
251 }
252
253 pub fn new_while(
257 condition: ClassicalExpr,
258 body: ValueControlBody,
259 ) -> Result<Self, CircuitError> {
260 if condition.ty() != ClassicalType::Bool {
261 return Err(CircuitError::InvalidOperation(format!(
262 "while condition must be Bool, got {:?}",
263 condition.ty()
264 )));
265 }
266 Ok(Self::While { condition, body })
267 }
268
269 pub fn new_for(
273 var: ClassicalVar,
274 start: ClassicalExpr,
275 stop: ClassicalExpr,
276 step: ClassicalExpr,
277 body: ValueControlBody,
278 ) -> Result<Self, CircuitError> {
279 validate_for_types(var, &start, &stop, &step)?;
280 Ok(Self::For {
281 var,
282 start,
283 stop,
284 step,
285 body,
286 })
287 }
288
289 pub fn new_switch(
293 target: ClassicalExpr,
294 cases: Vec<ValueSwitchCase>,
295 default: Option<ValueControlBody>,
296 ) -> Result<Self, CircuitError> {
297 validate_switch(&target, cases.iter().map(|case| case.value))?;
298 Ok(Self::Switch {
299 target,
300 cases,
301 default,
302 })
303 }
304
305 pub fn used_qubits(&self) -> BTreeSet<crate::circuit::Qubit> {
307 let mut qubits = BTreeSet::new();
308 match self {
309 Self::If {
310 then_body,
311 else_body,
312 ..
313 } => {
314 qubits.extend(then_body.used_qubits());
315 if let Some(else_body) = else_body {
316 qubits.extend(else_body.used_qubits());
317 }
318 }
319 Self::While { body, .. } | Self::For { body, .. } => {
320 qubits.extend(body.used_qubits());
321 }
322 Self::Switch { cases, default, .. } => {
323 for case in cases {
324 qubits.extend(case.body.used_qubits());
325 }
326 if let Some(default) = default {
327 qubits.extend(default.used_qubits());
328 }
329 }
330 Self::Break | Self::Continue => {}
331 }
332 qubits
333 }
334
335 pub fn classical_var_reads(&self) -> Vec<ClassicalVar> {
337 match self {
338 Self::If { condition, .. } | Self::While { condition, .. } => {
339 condition.vars().into_iter().collect()
340 }
341 Self::For {
342 start, stop, step, ..
343 } => {
344 let mut vars: Vec<_> = start.vars().into_iter().collect();
345 vars.extend(stop.vars());
346 vars.extend(step.vars());
347 vars
348 }
349 Self::Switch { target, .. } => target.vars().into_iter().collect(),
350 Self::Break | Self::Continue => Vec::new(),
351 }
352 }
353
354 pub fn classical_value_reads(&self) -> Vec<crate::circuit::ClassicalValue> {
356 match self {
357 Self::If { condition, .. } | Self::While { condition, .. } => {
358 condition.values().into_iter().collect()
359 }
360 Self::For {
361 start, stop, step, ..
362 } => {
363 let mut vals: Vec<_> = start.values().into_iter().collect();
364 vals.extend(stop.values());
365 vals.extend(step.values());
366 vals
367 }
368 Self::Switch { target, .. } => target.values().into_iter().collect(),
369 Self::Break | Self::Continue => Vec::new(),
370 }
371 }
372
373 pub fn classical_writes(&self) -> Vec<ClassicalVar> {
377 match self {
378 Self::For { var, .. } => vec![*var],
379 _ => Vec::new(),
380 }
381 }
382
383 pub fn has_measurement(&self) -> bool {
385 match self {
386 Self::If {
387 then_body,
388 else_body,
389 ..
390 } => {
391 then_body.has_measurement()
392 || else_body
393 .as_ref()
394 .is_some_and(|body| body.has_measurement())
395 }
396 Self::While { body, .. } | Self::For { body, .. } => body.has_measurement(),
397 Self::Switch { cases, default, .. } => {
398 cases.iter().any(|case| case.body.has_measurement())
399 || default.as_ref().is_some_and(|body| body.has_measurement())
400 }
401 Self::Break | Self::Continue => false,
402 }
403 }
404
405 pub fn reads_value(&self, value: ClassicalValue) -> bool {
407 if self.classical_value_reads().contains(&value) {
408 return true;
409 }
410 match self {
411 Self::If {
412 then_body,
413 else_body,
414 ..
415 } => {
416 then_body.reads_value(value)
417 || else_body
418 .as_ref()
419 .is_some_and(|body| body.reads_value(value))
420 }
421 Self::While { body, .. } | Self::For { body, .. } => body.reads_value(value),
422 Self::Switch { cases, default, .. } => {
423 cases.iter().any(|case| case.body.reads_value(value))
424 || default.as_ref().is_some_and(|body| body.reads_value(value))
425 }
426 Self::Break | Self::Continue => false,
427 }
428 }
429}
430
431impl fmt::Display for ValueClassicalControlOp {
432 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433 match self {
434 Self::If { .. } => write!(f, "if"),
435 Self::While { .. } => write!(f, "while"),
436 Self::For { .. } => write!(f, "for"),
437 Self::Switch { .. } => write!(f, "switch"),
438 Self::Break => write!(f, "break"),
439 Self::Continue => write!(f, "continue"),
440 }
441 }
442}
443
444#[derive(Debug, Clone, PartialEq)]
468pub enum ValueInstruction {
469 Instruction(Instruction),
472 ClassicalControl(ValueClassicalControlOp),
474}
475
476impl ValueInstruction {
477 pub fn from_instruction(inst: Instruction) -> Self {
484 debug_assert!(
485 !matches!(inst, Instruction::ClassicalControl(_)),
486 "Instruction::ClassicalControl must use ValueInstruction::ClassicalControl variant"
487 );
488 Self::Instruction(inst)
489 }
490
491 pub fn is_classical_control(&self) -> bool {
493 matches!(self, Self::ClassicalControl(_))
494 }
495
496 pub fn is_instruction(&self) -> bool {
498 matches!(self, Self::Instruction(_))
499 }
500
501 pub fn name(&self) -> String {
503 match self {
504 Self::Instruction(instruction) => instruction.name(),
505 Self::ClassicalControl(control) => control.to_string(),
506 }
507 }
508
509 pub fn instruction_type(&self) -> &'static str {
511 match self {
512 Self::Instruction(instruction) => instruction.instruction_type(),
513 Self::ClassicalControl(_) => "classical_control",
514 }
515 }
516
517 pub fn is_standard(&self) -> bool {
519 matches!(self, Self::Instruction(instruction) if instruction.is_standard())
520 }
521
522 pub fn is_mcgate(&self) -> bool {
524 matches!(self, Self::Instruction(instruction) if instruction.is_mcgate())
525 }
526
527 pub fn is_unitary(&self) -> bool {
529 matches!(self, Self::Instruction(instruction) if instruction.is_unitary())
530 }
531
532 pub fn is_circuit_gate(&self) -> bool {
534 matches!(self, Self::Instruction(instruction) if instruction.is_circuit_gate())
535 }
536
537 pub fn is_directive(&self) -> bool {
539 matches!(self, Self::Instruction(instruction) if instruction.is_directive())
540 }
541
542 pub fn is_classical_data(&self) -> bool {
544 matches!(self, Self::Instruction(instruction) if instruction.is_classical_data())
545 }
546
547 pub fn is_delay(&self) -> bool {
549 matches!(self, Self::Instruction(instruction) if instruction.is_delay())
550 }
551
552 pub fn standard_gate(&self) -> Option<StandardGate> {
554 match self {
555 Self::Instruction(Instruction::Standard(gate)) => Some(*gate),
556 _ => None,
557 }
558 }
559
560 pub fn directive(&self) -> Option<Directive> {
562 match self {
563 Self::Instruction(Instruction::Directive(directive)) => Some(*directive),
564 _ => None,
565 }
566 }
567
568 pub fn as_instruction(&self) -> Option<&Instruction> {
570 match self {
571 Self::Instruction(inst) => Some(inst),
572 Self::ClassicalControl(_) => None,
573 }
574 }
575
576 pub fn into_instruction(self) -> Option<Instruction> {
579 match self {
580 Self::Instruction(inst) => Some(inst),
581 Self::ClassicalControl(_) => None,
582 }
583 }
584}
585
586impl From<Instruction> for ValueInstruction {
587 fn from(inst: Instruction) -> Self {
593 Self::from_instruction(inst)
594 }
595}
596
597impl From<ValueClassicalControlOp> for ValueInstruction {
598 fn from(op: ValueClassicalControlOp) -> Self {
599 Self::ClassicalControl(op)
600 }
601}
602
603impl fmt::Display for ValueInstruction {
604 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
605 match self {
606 Self::Instruction(inst) => write!(f, "{}", inst),
607 Self::ClassicalControl(vcc) => write!(f, "{}", vcc),
608 }
609 }
610}
611
612pub fn storage_operation_to_value<F>(
613 operation: Operation,
614 resolve_parameter: &F,
615) -> Result<ValueOperation, CircuitError>
616where
617 F: Fn(&CircuitParam) -> Result<ParameterValue, CircuitError>,
618{
619 fn convert_operation<F>(
620 operation: Operation,
621 resolve_parameter: &F,
622 ) -> Result<ValueOperation, CircuitError>
623 where
624 F: Fn(&CircuitParam) -> Result<ParameterValue, CircuitError>,
625 {
626 let params = operation
627 .params
628 .iter()
629 .map(resolve_parameter)
630 .collect::<Result<_, _>>()?;
631 Ok(ValueOperation {
632 instruction: convert_instruction(operation.instruction, resolve_parameter)?,
633 qubits: operation.qubits,
634 params,
635 label: operation.label,
636 })
637 }
638
639 fn convert_body<F>(
640 body: &ControlBody,
641 resolve_parameter: &F,
642 ) -> Result<ValueControlBody, CircuitError>
643 where
644 F: Fn(&CircuitParam) -> Result<ParameterValue, CircuitError>,
645 {
646 body.operations()
647 .iter()
648 .cloned()
649 .map(|operation| convert_operation(operation, resolve_parameter))
650 .collect::<Result<Vec<_>, _>>()
651 .map(ValueControlBody::new)
652 }
653
654 fn convert_instruction<F>(
655 instruction: Instruction,
656 resolve_parameter: &F,
657 ) -> Result<ValueInstruction, CircuitError>
658 where
659 F: Fn(&CircuitParam) -> Result<ParameterValue, CircuitError>,
660 {
661 let Instruction::ClassicalControl(op) = instruction else {
662 return Ok(ValueInstruction::Instruction(instruction));
663 };
664
665 let op = match op {
666 ClassicalControlOp::If(op) => ValueClassicalControlOp::If {
667 condition: op.condition().clone(),
668 then_body: convert_body(op.then_body(), resolve_parameter)?,
669 else_body: op
670 .else_body()
671 .map(|body| convert_body(body, resolve_parameter))
672 .transpose()?,
673 },
674 ClassicalControlOp::While(op) => ValueClassicalControlOp::While {
675 condition: op.condition().clone(),
676 body: convert_body(op.body(), resolve_parameter)?,
677 },
678 ClassicalControlOp::For(op) => ValueClassicalControlOp::For {
679 var: op.var(),
680 start: op.start().clone(),
681 stop: op.stop().clone(),
682 step: op.step().clone(),
683 body: convert_body(op.body(), resolve_parameter)?,
684 },
685 ClassicalControlOp::Switch(op) => ValueClassicalControlOp::Switch {
686 target: op.target().clone(),
687 cases: op
688 .cases()
689 .iter()
690 .map(|case| {
691 Ok(ValueSwitchCase::new(
692 case.value(),
693 convert_body(case.body(), resolve_parameter)?,
694 ))
695 })
696 .collect::<Result<_, CircuitError>>()?,
697 default: op
698 .default()
699 .map(|body| convert_body(body, resolve_parameter))
700 .transpose()?,
701 },
702 ClassicalControlOp::Break => ValueClassicalControlOp::Break,
703 ClassicalControlOp::Continue => ValueClassicalControlOp::Continue,
704 };
705 Ok(ValueInstruction::ClassicalControl(op))
706 }
707
708 convert_operation(operation, resolve_parameter)
709}
710
711#[cfg(test)]
712mod tests {
713 use super::*;
714 use crate::circuit::ClassicalType;
715 use crate::circuit::bit::Qubit;
716 use crate::circuit::gate::{ClassicalDataOp, Directive, StandardGate};
717 use std::num::NonZeroU32;
718
719 #[test]
720 fn value_control_body_stores_value_operations() {
721 let ops = vec![ValueOperation::from_standard(
722 StandardGate::H,
723 [Qubit::new(0)],
724 [],
725 )];
726 let body = ValueControlBody::new(ops);
727 assert_eq!(body.operations().len(), 1);
728 }
729
730 #[test]
731 fn value_control_body_from_vec() {
732 let ops = vec![
733 ValueOperation::from_standard(StandardGate::X, [Qubit::new(0)], []),
734 ValueOperation::from_standard(StandardGate::Y, [Qubit::new(1)], []),
735 ];
736 let body: ValueControlBody = ops.into();
737 assert_eq!(body.operations().len(), 2);
738 }
739
740 #[test]
741 fn value_instruction_from_gate_instruction() {
742 let vi = ValueInstruction::from_instruction(Instruction::Standard(StandardGate::H));
743 assert!(vi.is_instruction());
744 assert!(!vi.is_classical_control());
745 }
746
747 #[test]
748 fn value_instruction_from_classical_control() {
749 let vcc = ValueClassicalControlOp::Break;
750 let vi = ValueInstruction::from(vcc);
751 assert!(vi.is_classical_control());
752 assert!(!vi.is_instruction());
753 }
754
755 #[test]
756 fn value_instruction_exposes_instruction_queries() {
757 let standard = ValueInstruction::from_instruction(Instruction::Standard(StandardGate::H));
758 assert_eq!(standard.name(), "H");
759 assert_eq!(standard.instruction_type(), "standard");
760 assert!(standard.is_standard());
761 assert_eq!(standard.standard_gate(), Some(StandardGate::H));
762 assert_eq!(standard.directive(), None);
763
764 let directive =
765 ValueInstruction::from_instruction(Instruction::Directive(Directive::Barrier));
766 assert_eq!(directive.name(), "barrier");
767 assert_eq!(directive.to_string(), "barrier");
768 assert_eq!(directive.instruction_type(), "directive");
769 assert!(directive.is_directive());
770 assert_eq!(directive.directive(), Some(Directive::Barrier));
771
772 let value =
773 ClassicalValue::new(crate::circuit::CircuitId::default(), 0, ClassicalType::Bit);
774 let classical_data = ValueInstruction::from_instruction(Instruction::ClassicalData(
775 ClassicalDataOp::MeasureBit { result: value },
776 ));
777 assert_eq!(classical_data.name(), "measure_bit");
778 assert_eq!(classical_data.instruction_type(), "classical_data");
779 assert!(classical_data.is_classical_data());
780
781 let control = ValueInstruction::from(ValueClassicalControlOp::Break);
782 assert_eq!(control.name(), "break");
783 assert_eq!(control.instruction_type(), "classical_control");
784 assert!(control.is_classical_control());
785
786 let delay = ValueInstruction::from_instruction(Instruction::Delay);
787 assert_eq!(delay.name(), "delay");
788 assert_eq!(delay.instruction_type(), "delay");
789 assert!(delay.is_delay());
790 }
791
792 #[test]
793 fn value_classical_control_reads_and_writes() {
794 let var = ClassicalVar::new(
795 crate::circuit::CircuitId::default(),
796 0,
797 ClassicalType::UInt(NonZeroU32::new(8).unwrap()),
798 );
799 let start = ClassicalExpr::var(var);
800 let stop = ClassicalExpr::uint_literal(8, 10).unwrap();
801 let step = ClassicalExpr::uint_literal(8, 1).unwrap();
802 let body = ValueControlBody::new(vec![]);
803
804 let vcc = ValueClassicalControlOp::For {
805 var,
806 start,
807 stop,
808 step,
809 body,
810 };
811
812 assert_eq!(vcc.classical_var_reads().len(), 1);
813 assert_eq!(vcc.classical_writes().len(), 1);
814 assert_eq!(vcc.classical_writes()[0], var);
815 }
816
817 #[test]
818 fn value_body_reports_nested_measurements() {
819 let value =
820 ClassicalValue::new(crate::circuit::CircuitId::default(), 0, ClassicalType::Bit);
821 let nested = ValueControlBody::new(vec![ValueOperation {
822 instruction: ValueInstruction::from_instruction(Instruction::ClassicalData(
823 ClassicalDataOp::MeasureBit { result: value },
824 )),
825 qubits: smallvec::smallvec![Qubit::new(0)],
826 params: smallvec::smallvec![],
827 label: None,
828 }]);
829 let body = ValueControlBody::new(vec![ValueOperation {
830 instruction: ValueInstruction::ClassicalControl(ValueClassicalControlOp::If {
831 condition: ClassicalExpr::bool_literal(true),
832 then_body: nested,
833 else_body: None,
834 }),
835 qubits: smallvec::smallvec![Qubit::new(0)],
836 params: smallvec::smallvec![],
837 label: None,
838 }]);
839
840 assert!(body.has_measurement());
841 }
842
843 #[test]
844 fn value_body_reports_nested_value_reads() {
845 let circuit_id = crate::circuit::CircuitId::default();
846 let value = ClassicalValue::new(circuit_id, 0, ClassicalType::Bit);
847 let target = ClassicalVar::new(circuit_id, 1, ClassicalType::Bit);
848 let nested = ValueControlBody::new(vec![ValueOperation {
849 instruction: ValueInstruction::from_instruction(Instruction::ClassicalData(
850 ClassicalDataOp::Store {
851 target,
852 value: value.expr(),
853 },
854 )),
855 qubits: smallvec::smallvec![],
856 params: smallvec::smallvec![],
857 label: None,
858 }]);
859 let control = ValueClassicalControlOp::While {
860 condition: ClassicalExpr::bool_literal(true),
861 body: nested,
862 };
863
864 assert!(control.reads_value(value));
865 }
866
867 #[test]
868 fn value_switch_case_construction() {
869 let body = ValueControlBody::new(vec![]);
870 let case = ValueSwitchCase::new(1, body);
871 assert_eq!(case.value, 1);
872 assert_eq!(case.body.operations().len(), 0);
873 }
874
875 #[test]
876 fn value_instructions_compare_nested_control_flow_structurally() {
877 let make_if = || {
878 ValueInstruction::ClassicalControl(ValueClassicalControlOp::If {
879 condition: ClassicalExpr::bool_literal(true),
880 then_body: ValueControlBody::new(vec![ValueOperation::from_standard(
881 StandardGate::H,
882 [Qubit::new(0)],
883 [],
884 )]),
885 else_body: None,
886 })
887 };
888
889 assert_eq!(make_if(), make_if());
890
891 let different_body = ValueInstruction::ClassicalControl(ValueClassicalControlOp::If {
892 condition: ClassicalExpr::bool_literal(true),
893 then_body: ValueControlBody::new(vec![ValueOperation::from_standard(
894 StandardGate::X,
895 [Qubit::new(0)],
896 [],
897 )]),
898 else_body: None,
899 });
900 assert_ne!(make_if(), different_body);
901
902 let with_else = ValueInstruction::ClassicalControl(ValueClassicalControlOp::If {
903 condition: ClassicalExpr::bool_literal(true),
904 then_body: ValueControlBody::new(vec![ValueOperation::from_standard(
905 StandardGate::H,
906 [Qubit::new(0)],
907 [],
908 )]),
909 else_body: Some(ValueControlBody::new(vec![])),
910 });
911 assert_ne!(make_if(), with_else);
912
913 assert_eq!(
914 ValueInstruction::from_instruction(Instruction::Standard(StandardGate::H)),
915 ValueInstruction::from_instruction(Instruction::Standard(StandardGate::H))
916 );
917 assert_ne!(
918 ValueInstruction::from_instruction(Instruction::Standard(StandardGate::H)),
919 ValueInstruction::from_instruction(Instruction::Standard(StandardGate::X))
920 );
921 }
922}