quil_rs/instruction/
classical.rs

1#[cfg(feature = "stubs")]
2use pyo3_stub_gen::derive::{
3    gen_stub_pyclass, gen_stub_pyclass_complex_enum, gen_stub_pyclass_enum,
4};
5
6use super::MemoryReference;
7
8use crate::{floating_point_eq, pickleable_new, quil::Quil};
9
10#[derive(Clone, Debug, Hash, PartialEq)]
11#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
12#[cfg_attr(
13    feature = "python",
14    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
15)]
16pub struct Arithmetic {
17    pub operator: ArithmeticOperator,
18    pub destination: MemoryReference,
19    pub source: ArithmeticOperand,
20}
21
22pickleable_new! {
23    impl Arithmetic {
24        pub fn new(
25            operator: ArithmeticOperator,
26            destination: MemoryReference,
27            source: ArithmeticOperand,
28        );
29    }
30}
31
32impl Quil for Arithmetic {
33    fn write(
34        &self,
35        f: &mut impl std::fmt::Write,
36        fall_back_to_debug: bool,
37    ) -> crate::quil::ToQuilResult<()> {
38        self.operator.write(f, fall_back_to_debug)?;
39        write!(f, " ")?;
40        self.destination.write(f, fall_back_to_debug)?;
41        write!(f, " ")?;
42        self.source.write(f, fall_back_to_debug)
43    }
44}
45
46#[derive(Clone, Debug)]
47#[cfg_attr(feature = "stubs", gen_stub_pyclass_complex_enum)]
48#[cfg_attr(
49    feature = "python",
50    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all)
51)]
52pub enum ArithmeticOperand {
53    LiteralInteger(i64),
54    LiteralReal(f64),
55    MemoryReference(MemoryReference),
56}
57
58impl PartialEq for ArithmeticOperand {
59    fn eq(&self, other: &Self) -> bool {
60        match (self, other) {
61            (Self::LiteralInteger(this), Self::LiteralInteger(that)) => this == that,
62            (Self::LiteralReal(this), Self::LiteralReal(that)) => {
63                floating_point_eq::f64::eq(*this, *that)
64            }
65            (Self::MemoryReference(this), Self::MemoryReference(that)) => this == that,
66            // This explicit or-pattern ensures that we'll get a compilation error if
67            // `ArithmeticOperand` grows another constructor.
68            (Self::LiteralInteger(_) | Self::LiteralReal(_) | Self::MemoryReference(_), _) => false,
69        }
70    }
71}
72
73impl Eq for ArithmeticOperand {}
74
75impl std::hash::Hash for ArithmeticOperand {
76    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
77        match self {
78            Self::LiteralInteger(operand) => operand.hash(state),
79            Self::LiteralReal(operand) => floating_point_eq::f64::hash(*operand, state),
80            Self::MemoryReference(operand) => operand.hash(state),
81        }
82    }
83}
84
85impl Quil for ArithmeticOperand {
86    fn write(
87        &self,
88        f: &mut impl std::fmt::Write,
89        fall_back_to_debug: bool,
90    ) -> crate::quil::ToQuilResult<()> {
91        match &self {
92            ArithmeticOperand::LiteralInteger(value) => write!(f, "{value}").map_err(Into::into),
93            ArithmeticOperand::LiteralReal(value) => write!(f, "{value}").map_err(Into::into),
94            ArithmeticOperand::MemoryReference(value) => value.write(f, fall_back_to_debug),
95        }
96    }
97}
98
99impl From<MemoryReference> for ArithmeticOperand {
100    fn from(memory_reference: MemoryReference) -> Self {
101        ArithmeticOperand::MemoryReference(memory_reference)
102    }
103}
104
105#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
106#[cfg_attr(feature = "stubs", gen_stub_pyclass_enum)]
107#[cfg_attr(
108    feature = "python",
109    pyo3::pyclass(
110        module = "quil.instructions",
111        eq,
112        frozen,
113        hash,
114        rename_all = "SCREAMING_SNAKE_CASE"
115    )
116)]
117pub enum ArithmeticOperator {
118    Add,
119    Subtract,
120    Divide,
121    Multiply,
122}
123
124impl Quil for ArithmeticOperator {
125    fn write(
126        &self,
127        f: &mut impl std::fmt::Write,
128        _fall_back_to_debug: bool,
129    ) -> crate::quil::ToQuilResult<()> {
130        match &self {
131            ArithmeticOperator::Add => write!(f, "ADD"),
132            ArithmeticOperator::Subtract => write!(f, "SUB"),
133            ArithmeticOperator::Divide => write!(f, "DIV"),
134            ArithmeticOperator::Multiply => write!(f, "MUL"),
135        }
136        .map_err(Into::into)
137    }
138}
139
140#[derive(Clone, Debug, Hash, PartialEq, Eq)]
141#[cfg_attr(feature = "stubs", gen_stub_pyclass_complex_enum)]
142#[cfg_attr(
143    feature = "python",
144    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all)
145)]
146pub enum BinaryOperand {
147    LiteralInteger(i64),
148    MemoryReference(MemoryReference),
149}
150
151impl Quil for BinaryOperand {
152    fn write(
153        &self,
154        f: &mut impl std::fmt::Write,
155        fall_back_to_debug: bool,
156    ) -> crate::quil::ToQuilResult<()> {
157        match &self {
158            BinaryOperand::LiteralInteger(value) => write!(f, "{value}").map_err(Into::into),
159            BinaryOperand::MemoryReference(value) => value.write(f, fall_back_to_debug),
160        }
161    }
162}
163
164#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
165#[cfg_attr(feature = "stubs", gen_stub_pyclass_enum)]
166#[cfg_attr(
167    feature = "python",
168    pyo3::pyclass(
169        module = "quil.instructions",
170        eq,
171        frozen,
172        hash,
173        rename_all = "SCREAMING_SNAKE_CASE"
174    )
175)]
176pub enum BinaryOperator {
177    And,
178    Ior,
179    Xor,
180}
181
182impl Quil for BinaryOperator {
183    fn write(
184        &self,
185        f: &mut impl std::fmt::Write,
186        _fall_back_to_debug: bool,
187    ) -> crate::quil::ToQuilResult<()> {
188        match &self {
189            BinaryOperator::And => write!(f, "AND"),
190            BinaryOperator::Ior => write!(f, "IOR"),
191            BinaryOperator::Xor => write!(f, "XOR"),
192        }
193        .map_err(Into::into)
194    }
195}
196
197#[derive(Clone, Debug, Hash, PartialEq, Eq)]
198#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
199#[cfg_attr(
200    feature = "python",
201    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
202)]
203pub struct BinaryLogic {
204    pub operator: BinaryOperator,
205    pub destination: MemoryReference,
206    pub source: BinaryOperand,
207}
208
209impl Quil for BinaryLogic {
210    fn write(
211        &self,
212        f: &mut impl std::fmt::Write,
213        fall_back_to_debug: bool,
214    ) -> crate::quil::ToQuilResult<()> {
215        self.operator.write(f, fall_back_to_debug)?;
216        write!(f, " ")?;
217        self.destination.write(f, fall_back_to_debug)?;
218        write!(f, " ")?;
219        self.source.write(f, fall_back_to_debug)?;
220        Ok(())
221    }
222}
223
224pickleable_new! {
225    impl BinaryLogic {
226        pub fn new(
227            operator: BinaryOperator,
228            destination: MemoryReference,
229            source: BinaryOperand,
230        );
231    }
232}
233
234#[derive(Clone, Debug, Hash, PartialEq, Eq)]
235#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
236#[cfg_attr(
237    feature = "python",
238    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
239)]
240pub struct Convert {
241    pub destination: MemoryReference,
242    pub source: MemoryReference,
243}
244
245pickleable_new! {
246    impl Convert {
247        pub fn new(destination: MemoryReference, source: MemoryReference);
248    }
249}
250
251impl Quil for Convert {
252    fn write(
253        &self,
254        f: &mut impl std::fmt::Write,
255        fall_back_to_debug: bool,
256    ) -> crate::quil::ToQuilResult<()> {
257        write!(f, "CONVERT ")?;
258        self.destination.write(f, fall_back_to_debug)?;
259        write!(f, " ")?;
260        self.source.write(f, fall_back_to_debug)?;
261        Ok(())
262    }
263}
264
265#[derive(Clone, Debug, Hash, PartialEq)]
266#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
267#[cfg_attr(
268    feature = "python",
269    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
270)]
271pub struct Move {
272    pub destination: MemoryReference,
273    pub source: ArithmeticOperand,
274}
275
276pickleable_new! {
277    impl Move {
278        pub fn new(destination: MemoryReference, source: ArithmeticOperand);
279    }
280}
281
282impl Quil for Move {
283    fn write(
284        &self,
285        f: &mut impl std::fmt::Write,
286        fall_back_to_debug: bool,
287    ) -> crate::quil::ToQuilResult<()> {
288        write!(f, "MOVE ")?;
289        self.destination.write(f, fall_back_to_debug)?;
290        write!(f, " ")?;
291        self.source.write(f, fall_back_to_debug)?;
292        Ok(())
293    }
294}
295
296#[derive(Clone, Debug, Hash, PartialEq)]
297#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
298#[cfg_attr(
299    feature = "python",
300    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
301)]
302pub struct Exchange {
303    pub left: MemoryReference,
304    pub right: MemoryReference,
305}
306
307impl Quil for Exchange {
308    fn write(
309        &self,
310        f: &mut impl std::fmt::Write,
311        fall_back_to_debug: bool,
312    ) -> crate::quil::ToQuilResult<()> {
313        write!(f, "EXCHANGE ")?;
314        self.left.write(f, fall_back_to_debug)?;
315        write!(f, " ")?;
316        self.right.write(f, fall_back_to_debug)?;
317        Ok(())
318    }
319}
320
321pickleable_new! {
322    impl Exchange {
323        pub fn new(left: MemoryReference, right: MemoryReference);
324    }
325}
326
327#[derive(Clone, Debug, Hash, PartialEq)]
328#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
329#[cfg_attr(
330    feature = "python",
331    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
332)]
333pub struct Comparison {
334    pub operator: ComparisonOperator,
335    pub destination: MemoryReference,
336    pub lhs: MemoryReference,
337    pub rhs: ComparisonOperand,
338}
339
340pickleable_new! {
341    impl Comparison {
342        pub fn new(
343            operator: ComparisonOperator,
344            destination: MemoryReference,
345            lhs: MemoryReference,
346            rhs: ComparisonOperand,
347        );
348    }
349}
350
351impl Quil for Comparison {
352    fn write(
353        &self,
354        f: &mut impl std::fmt::Write,
355        fall_back_to_debug: bool,
356    ) -> crate::quil::ToQuilResult<()> {
357        self.operator.write(f, fall_back_to_debug)?;
358        write!(f, " ")?;
359        self.destination.write(f, fall_back_to_debug)?;
360        write!(f, " ")?;
361        self.lhs.write(f, fall_back_to_debug)?;
362        write!(f, " ")?;
363        self.rhs.write(f, fall_back_to_debug)?;
364        Ok(())
365    }
366}
367
368#[derive(Clone, Debug)]
369#[cfg_attr(feature = "stubs", gen_stub_pyclass_complex_enum)]
370#[cfg_attr(
371    feature = "python",
372    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all)
373)]
374pub enum ComparisonOperand {
375    LiteralInteger(i64),
376    LiteralReal(f64),
377    MemoryReference(MemoryReference),
378}
379
380impl Quil for ComparisonOperand {
381    fn write(
382        &self,
383        f: &mut impl std::fmt::Write,
384        fall_back_to_debug: bool,
385    ) -> crate::quil::ToQuilResult<()> {
386        match &self {
387            ComparisonOperand::LiteralInteger(value) => write!(f, "{value}").map_err(Into::into),
388            ComparisonOperand::LiteralReal(value) => write!(f, "{value}").map_err(Into::into),
389            ComparisonOperand::MemoryReference(value) => value.write(f, fall_back_to_debug),
390        }
391    }
392}
393
394impl PartialEq for ComparisonOperand {
395    fn eq(&self, other: &Self) -> bool {
396        match (self, other) {
397            (Self::LiteralInteger(this), Self::LiteralInteger(that)) => this == that,
398            (Self::LiteralReal(this), Self::LiteralReal(that)) => {
399                floating_point_eq::f64::eq(*this, *that)
400            }
401            (Self::MemoryReference(this), Self::MemoryReference(that)) => this == that,
402            // This explicit or-pattern ensures that we'll get a compilation error if
403            // `ComparisonOperand` grows another constructor.
404            (Self::LiteralInteger(_) | Self::LiteralReal(_) | Self::MemoryReference(_), _) => false,
405        }
406    }
407}
408
409impl Eq for ComparisonOperand {}
410
411impl std::hash::Hash for ComparisonOperand {
412    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
413        match self {
414            ComparisonOperand::LiteralInteger(operand) => operand.hash(state),
415            ComparisonOperand::LiteralReal(operand) => {
416                floating_point_eq::f64::hash(*operand, state)
417            }
418            ComparisonOperand::MemoryReference(operand) => operand.hash(state),
419        }
420    }
421}
422
423#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
424#[cfg_attr(feature = "stubs", gen_stub_pyclass_enum)]
425#[cfg_attr(
426    feature = "python",
427    pyo3::pyclass(
428        module = "quil.instructions",
429        eq,
430        frozen,
431        hash,
432        rename_all = "SCREAMING_SNAKE_CASE"
433    )
434)]
435pub enum ComparisonOperator {
436    Equal,
437    GreaterThanOrEqual,
438    GreaterThan,
439    LessThanOrEqual,
440    LessThan,
441}
442
443impl Quil for ComparisonOperator {
444    fn write(
445        &self,
446        f: &mut impl std::fmt::Write,
447        _fall_back_to_debug: bool,
448    ) -> crate::quil::ToQuilResult<()> {
449        match &self {
450            ComparisonOperator::Equal => write!(f, "EQ"),
451            ComparisonOperator::GreaterThanOrEqual => write!(f, "GE"),
452            ComparisonOperator::GreaterThan => write!(f, "GT"),
453            ComparisonOperator::LessThanOrEqual => write!(f, "LE"),
454            ComparisonOperator::LessThan => write!(f, "LT"),
455        }
456        .map_err(Into::into)
457    }
458}
459
460#[derive(Clone, Debug, Hash, PartialEq, Eq)]
461#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
462#[cfg_attr(
463    feature = "python",
464    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
465)]
466pub struct UnaryLogic {
467    pub operator: UnaryOperator,
468    pub operand: MemoryReference,
469}
470
471pickleable_new! {
472    impl UnaryLogic {
473        pub fn new(operator: UnaryOperator, operand: MemoryReference);
474    }
475}
476
477impl Quil for UnaryLogic {
478    fn write(
479        &self,
480        f: &mut impl std::fmt::Write,
481        fall_back_to_debug: bool,
482    ) -> crate::quil::ToQuilResult<()> {
483        self.operator.write(f, fall_back_to_debug)?;
484        write!(f, " ")?;
485        self.operand.write(f, fall_back_to_debug)?;
486        Ok(())
487    }
488}
489
490#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
491#[cfg_attr(feature = "stubs", gen_stub_pyclass_enum)]
492#[cfg_attr(
493    feature = "python",
494    pyo3::pyclass(
495        module = "quil.instructions",
496        eq,
497        frozen,
498        hash,
499        rename_all = "SCREAMING_SNAKE_CASE"
500    )
501)]
502pub enum UnaryOperator {
503    Neg,
504    Not,
505}
506
507impl Quil for UnaryOperator {
508    fn write(
509        &self,
510        f: &mut impl std::fmt::Write,
511        _fall_back_to_debug: bool,
512    ) -> crate::quil::ToQuilResult<()> {
513        match &self {
514            UnaryOperator::Neg => write!(f, "NEG"),
515            UnaryOperator::Not => write!(f, "NOT"),
516        }
517        .map_err(Into::into)
518    }
519}