1use std::str::FromStr;
2
3use pyo3::exceptions::PyValueError;
4use quil_rs::instruction::Instruction;
5use rigetti_pyo3::{
6 create_init_submodule, impl_repr, py_wrap_union_enum,
7 pyo3::{pymethods, types::PyDict, PyResult, Python},
8 PyWrapper,
9};
10
11use crate::{impl_eq, impl_to_quil};
12
13pub use self::{
14 calibration::{
15 PyCalibration, PyCalibrationIdentifier, PyMeasureCalibrationDefinition,
16 PyMeasureCalibrationIdentifier,
17 },
18 circuit::PyCircuitDefinition,
19 classical::{
20 PyArithmetic, PyArithmeticOperand, PyArithmeticOperator, PyBinaryLogic, PyBinaryOperand,
21 PyBinaryOperator, PyComparison, PyComparisonOperand, PyComparisonOperator, PyConvert,
22 PyExchange, PyMove, PyUnaryLogic, PyUnaryOperator,
23 },
24 control_flow::{PyJump, PyJumpUnless, PyJumpWhen, PyLabel, PyTarget, PyTargetPlaceholder},
25 declaration::{
26 ParseMemoryReferenceError, PyDeclaration, PyLoad, PyMemoryReference, PyOffset,
27 PyScalarType, PySharing, PyStore, PyVector,
28 },
29 extern_call::{
30 CallError, ExternError, PyCall, PyCallArgument, PyExternParameter, PyExternParameterType,
31 PyExternSignature,
32 },
33 frame::{
34 PyAttributeValue, PyCapture, PyFrameAttributes, PyFrameDefinition, PyFrameIdentifier,
35 PyPulse, PyRawCapture, PySetFrequency, PySetPhase, PySetScale, PyShiftFrequency,
36 PyShiftPhase, PySwapPhases,
37 },
38 gate::{
39 GateError, PyGate, PyGateDefinition, PyGateModifier, PyGateSpecification, PyPauliGate,
40 PyPauliSum, PyPauliTerm,
41 },
42 measurement::PyMeasurement,
43 pragma::{PyInclude, PyPragma, PyPragmaArgument},
44 qubit::{PyQubit, PyQubitPlaceholder},
45 reset::PyReset,
46 timing::{PyDelay, PyFence},
47 waveform::{PyWaveform, PyWaveformDefinition, PyWaveformInvocation},
48};
49
50mod calibration;
51mod circuit;
52mod classical;
53mod control_flow;
54mod declaration;
55mod extern_call;
56mod frame;
57mod gate;
58mod measurement;
59mod pragma;
60mod qubit;
61mod reset;
62mod timing;
63mod waveform;
64
65py_wrap_union_enum! {
66 #[derive(Debug, PartialEq)]
67 PyInstruction(Instruction) as "Instruction" {
68 arithmetic: Arithmetic => PyArithmetic,
69 binary_logic: BinaryLogic => PyBinaryLogic,
70 calibration_definition: CalibrationDefinition => PyCalibration,
71 call: Call => PyCall,
72 capture: Capture => PyCapture,
73 circuit_definition: CircuitDefinition => PyCircuitDefinition,
74 convert: Convert => PyConvert,
75 comparison: Comparison => PyComparison,
76 declaration: Declaration => PyDeclaration,
77 delay: Delay => PyDelay,
78 exchange: Exchange => PyExchange,
79 fence: Fence => PyFence,
80 frame_definition: FrameDefinition => PyFrameDefinition,
81 gate: Gate => PyGate,
82 gate_definition: GateDefinition => PyGateDefinition,
83 halt: Halt,
84 include: Include => PyInclude,
85 jump: Jump => PyJump,
86 jump_when: JumpWhen => PyJumpWhen,
87 jump_unless: JumpUnless => PyJumpUnless,
88 label: Label => PyLabel,
89 load: Load => PyLoad,
90 measure_calibration_definition: MeasureCalibrationDefinition => PyMeasureCalibrationDefinition,
91 measurement: Measurement => PyMeasurement,
92 move: Move => PyMove,
93 nop: Nop,
94 pragma: Pragma => PyPragma,
95 pulse: Pulse => PyPulse,
96 raw_capture: RawCapture => PyRawCapture,
97 reset: Reset => PyReset,
98 set_frequency: SetFrequency => PySetFrequency,
99 set_phase: SetPhase => PySetPhase,
100 set_scale: SetScale => PySetScale,
101 shift_frequency: ShiftFrequency => PyShiftFrequency,
102 shift_phase: ShiftPhase => PyShiftPhase,
103 store: Store => PyStore,
104 swap_phases: SwapPhases => PySwapPhases,
105 unary_logic: UnaryLogic => PyUnaryLogic,
106 waveform_definition: WaveformDefinition => PyWaveformDefinition,
107 wait: Wait
108 }
109}
110impl_repr!(PyInstruction);
111impl_to_quil!(PyInstruction);
112impl_eq!(PyInstruction);
113
114#[pymethods]
115impl PyInstruction {
116 pub fn is_quil_t(&self) -> bool {
117 self.as_inner().is_quil_t()
118 }
119
120 #[staticmethod]
121 pub fn parse(string: &str) -> PyResult<Self> {
122 match Instruction::from_str(string) {
123 Ok(instruction) => Ok(Self(instruction)),
124 Err(err) => Err(PyValueError::new_err(err.to_string())),
125 }
126 }
127
128 pub fn __copy__(&self) -> Self {
137 self.clone()
138 }
139
140 pub fn __deepcopy__(&self, py: Python<'_>, memo: &PyDict) -> PyResult<Self> {
141 match self.inner(py) {
142 Ok(inner) => Ok(PyInstruction::new(
143 py,
144 inner.call_method1(py, "__deepcopy__", (memo,))?.as_ref(py),
145 )?),
146 Err(_) => Ok(self.clone()), }
149 }
150}
151
152create_init_submodule! {
153 classes: [
154 PyInstruction,
155 PyArithmetic,
156 PyArithmeticOperand,
157 PyArithmeticOperator,
158 PyBinaryLogic,
159 PyBinaryOperand,
160 PyBinaryOperator,
161 PyCall,
162 PyCallArgument,
163 PyComparison,
164 PyComparisonOperand,
165 PyComparisonOperator,
166 PyConvert,
167 PyExchange,
168 PyExternParameter,
169 PyExternParameterType,
170 PyExternSignature,
171 PyMove,
172 PyUnaryLogic,
173 PyUnaryOperator,
174 PyCalibration,
175 PyCalibrationIdentifier,
176 PyCircuitDefinition,
177 PyMeasureCalibrationDefinition,
178 PyMeasureCalibrationIdentifier,
179 PyDeclaration,
180 PyLoad,
181 PyOffset,
182 PySharing,
183 PyStore,
184 PyScalarType,
185 PyVector,
186 PyMeasurement,
187 PyInclude,
188 PyPragma,
189 PyPragmaArgument,
190 PyAttributeValue,
191 PyCapture,
192 PyFrameDefinition,
193 PyFrameIdentifier,
194 PyPulse,
195 PyRawCapture,
196 PySetFrequency,
197 PySetPhase,
198 PySetScale,
199 PyShiftFrequency,
200 PyShiftPhase,
201 PySwapPhases,
202 PyGate,
203 PyGateDefinition,
204 PyGateModifier,
205 PyGateSpecification,
206 PyPauliGate,
207 PyPauliTerm,
208 PyPauliSum,
209 PyJump,
210 PyJumpWhen,
211 PyJumpUnless,
212 PyLabel,
213 PyTarget,
214 PyTargetPlaceholder,
215 PyMeasurement,
216 PyMemoryReference,
217 PyQubit,
218 PyQubitPlaceholder,
219 PyReset,
220 PyDelay,
221 PyFence,
222 PyWaveform,
223 PyWaveformDefinition,
224 PyWaveformInvocation
225 ],
226 errors: [ CallError, ExternError, GateError, ParseMemoryReferenceError ],
227}
228
229#[macro_export]
240macro_rules! impl_copy_for_instruction {
241 ($py_name: ident) => {
242 #[pyo3::pymethods]
243 impl $py_name {
244 pub fn __deepcopy__(
245 &self,
246 py: Python<'_>,
247 _memo: &pyo3::types::PyDict,
248 ) -> pyo3::PyResult<Self> {
249 let mut instruction = $crate::instruction::PyInstruction::new(
250 py,
251 pyo3::ToPyObject::to_object(&self, py).as_ref(py),
252 )?;
253
254 use quil_rs::instruction::{Qubit, QubitPlaceholder};
255 use std::collections::HashMap;
256 let mut placeholders: HashMap<QubitPlaceholder, QubitPlaceholder> = HashMap::new();
257
258 for qubit in
259 rigetti_pyo3::PyWrapperMut::as_inner_mut(&mut instruction).get_qubits_mut()
260 {
261 match qubit {
262 Qubit::Fixed(_) | Qubit::Variable(_) => *qubit = qubit.clone(),
263 Qubit::Placeholder(placeholder) => {
264 *qubit = Qubit::Placeholder(
265 placeholders.entry(placeholder.clone()).or_default().clone(),
266 )
267 }
268 }
269 }
270
271 Ok(instruction
272 .inner(py)
273 .unwrap()
274 .extract::<$py_name>(py)
275 .expect("a copy of a type should extract to the same type"))
276 }
277
278 pub fn __copy__(&self) -> Self {
279 self.clone()
280 }
281 }
282 };
283}