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 (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)]
167#[cfg_attr(feature = "stubs", gen_stub_pyclass_enum)]
168#[cfg_attr(
169 feature = "python",
170 pyo3::pyclass(
171 module = "quil.instructions",
172 eq,
173 frozen,
174 hash,
175 rename_all = "SCREAMING_SNAKE_CASE"
176 )
177)]
178pub enum BinaryOperator {
179 And,
181
182 Ior,
184
185 Xor,
187
188 Shl,
193
194 Shr,
200
201 Ashr,
209}
210
211impl Quil for BinaryOperator {
212 fn write(
213 &self,
214 f: &mut impl std::fmt::Write,
215 _fall_back_to_debug: bool,
216 ) -> crate::quil::ToQuilResult<()> {
217 match self {
218 BinaryOperator::And => write!(f, "AND"),
219 BinaryOperator::Ior => write!(f, "IOR"),
220 BinaryOperator::Xor => write!(f, "XOR"),
221 BinaryOperator::Shl => write!(f, "SHL"),
222 BinaryOperator::Shr => write!(f, "SHR"),
223 BinaryOperator::Ashr => write!(f, "ASHR"),
224 }
225 .map_err(Into::into)
226 }
227}
228
229#[derive(Clone, Debug, Hash, PartialEq, Eq)]
230#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
231#[cfg_attr(
232 feature = "python",
233 pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
234)]
235pub struct BinaryLogic {
236 pub operator: BinaryOperator,
237 pub destination: MemoryReference,
238 pub source: BinaryOperand,
239}
240
241impl Quil for BinaryLogic {
242 fn write(
243 &self,
244 f: &mut impl std::fmt::Write,
245 fall_back_to_debug: bool,
246 ) -> crate::quil::ToQuilResult<()> {
247 self.operator.write(f, fall_back_to_debug)?;
248 write!(f, " ")?;
249 self.destination.write(f, fall_back_to_debug)?;
250 write!(f, " ")?;
251 self.source.write(f, fall_back_to_debug)?;
252 Ok(())
253 }
254}
255
256pickleable_new! {
257 impl BinaryLogic {
258 pub fn new(
259 operator: BinaryOperator,
260 destination: MemoryReference,
261 source: BinaryOperand,
262 );
263 }
264}
265
266#[derive(Clone, Debug, Hash, PartialEq, Eq)]
267#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
268#[cfg_attr(
269 feature = "python",
270 pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
271)]
272pub struct Convert {
273 pub destination: MemoryReference,
274 pub source: MemoryReference,
275}
276
277pickleable_new! {
278 impl Convert {
279 pub fn new(destination: MemoryReference, source: MemoryReference);
280 }
281}
282
283impl Quil for Convert {
284 fn write(
285 &self,
286 f: &mut impl std::fmt::Write,
287 fall_back_to_debug: bool,
288 ) -> crate::quil::ToQuilResult<()> {
289 write!(f, "CONVERT ")?;
290 self.destination.write(f, fall_back_to_debug)?;
291 write!(f, " ")?;
292 self.source.write(f, fall_back_to_debug)?;
293 Ok(())
294 }
295}
296
297#[derive(Clone, Debug, Hash, PartialEq)]
298#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
299#[cfg_attr(
300 feature = "python",
301 pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
302)]
303pub struct Move {
304 pub destination: MemoryReference,
305 pub source: ArithmeticOperand,
306}
307
308pickleable_new! {
309 impl Move {
310 pub fn new(destination: MemoryReference, source: ArithmeticOperand);
311 }
312}
313
314impl Quil for Move {
315 fn write(
316 &self,
317 f: &mut impl std::fmt::Write,
318 fall_back_to_debug: bool,
319 ) -> crate::quil::ToQuilResult<()> {
320 write!(f, "MOVE ")?;
321 self.destination.write(f, fall_back_to_debug)?;
322 write!(f, " ")?;
323 self.source.write(f, fall_back_to_debug)?;
324 Ok(())
325 }
326}
327
328#[derive(Clone, Debug, Hash, PartialEq)]
329#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
330#[cfg_attr(
331 feature = "python",
332 pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
333)]
334pub struct Exchange {
335 pub left: MemoryReference,
336 pub right: MemoryReference,
337}
338
339impl Quil for Exchange {
340 fn write(
341 &self,
342 f: &mut impl std::fmt::Write,
343 fall_back_to_debug: bool,
344 ) -> crate::quil::ToQuilResult<()> {
345 write!(f, "EXCHANGE ")?;
346 self.left.write(f, fall_back_to_debug)?;
347 write!(f, " ")?;
348 self.right.write(f, fall_back_to_debug)?;
349 Ok(())
350 }
351}
352
353pickleable_new! {
354 impl Exchange {
355 pub fn new(left: MemoryReference, right: MemoryReference);
356 }
357}
358
359#[derive(Clone, Debug, Hash, PartialEq)]
360#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
361#[cfg_attr(
362 feature = "python",
363 pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
364)]
365pub struct Comparison {
366 pub operator: ComparisonOperator,
367 pub destination: MemoryReference,
368 pub lhs: MemoryReference,
369 pub rhs: ComparisonOperand,
370}
371
372pickleable_new! {
373 impl Comparison {
374 pub fn new(
375 operator: ComparisonOperator,
376 destination: MemoryReference,
377 lhs: MemoryReference,
378 rhs: ComparisonOperand,
379 );
380 }
381}
382
383impl Quil for Comparison {
384 fn write(
385 &self,
386 f: &mut impl std::fmt::Write,
387 fall_back_to_debug: bool,
388 ) -> crate::quil::ToQuilResult<()> {
389 self.operator.write(f, fall_back_to_debug)?;
390 write!(f, " ")?;
391 self.destination.write(f, fall_back_to_debug)?;
392 write!(f, " ")?;
393 self.lhs.write(f, fall_back_to_debug)?;
394 write!(f, " ")?;
395 self.rhs.write(f, fall_back_to_debug)?;
396 Ok(())
397 }
398}
399
400#[derive(Clone, Debug)]
401#[cfg_attr(feature = "stubs", gen_stub_pyclass_complex_enum)]
402#[cfg_attr(
403 feature = "python",
404 pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all)
405)]
406pub enum ComparisonOperand {
407 LiteralInteger(i64),
408 LiteralReal(f64),
409 MemoryReference(MemoryReference),
410}
411
412impl Quil for ComparisonOperand {
413 fn write(
414 &self,
415 f: &mut impl std::fmt::Write,
416 fall_back_to_debug: bool,
417 ) -> crate::quil::ToQuilResult<()> {
418 match &self {
419 ComparisonOperand::LiteralInteger(value) => write!(f, "{value}").map_err(Into::into),
420 ComparisonOperand::LiteralReal(value) => write!(f, "{value}").map_err(Into::into),
421 ComparisonOperand::MemoryReference(value) => value.write(f, fall_back_to_debug),
422 }
423 }
424}
425
426impl PartialEq for ComparisonOperand {
427 fn eq(&self, other: &Self) -> bool {
428 match (self, other) {
429 (Self::LiteralInteger(this), Self::LiteralInteger(that)) => this == that,
430 (Self::LiteralReal(this), Self::LiteralReal(that)) => {
431 floating_point_eq::f64::eq(*this, *that)
432 }
433 (Self::MemoryReference(this), Self::MemoryReference(that)) => this == that,
434 (Self::LiteralInteger(_) | Self::LiteralReal(_) | Self::MemoryReference(_), _) => false,
437 }
438 }
439}
440
441impl Eq for ComparisonOperand {}
442
443impl std::hash::Hash for ComparisonOperand {
444 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
445 match self {
446 ComparisonOperand::LiteralInteger(operand) => operand.hash(state),
447 ComparisonOperand::LiteralReal(operand) => {
448 floating_point_eq::f64::hash(*operand, state)
449 }
450 ComparisonOperand::MemoryReference(operand) => operand.hash(state),
451 }
452 }
453}
454
455pub trait ClassicalOperand: Clone + std::fmt::Debug {
456 fn memory_reference(&self) -> Option<&MemoryReference>;
457}
458
459macro_rules! classical_operands {
460 ($($operand:ident),* $(,)?) => {
461 $(
462 impl ClassicalOperand for $operand {
463 fn memory_reference(&self) -> Option<&MemoryReference> {
464 if let Self::MemoryReference(memory_reference) = self {
465 Some(memory_reference)
466 } else {
467 None
468 }
469 }
470 }
471 )*
472 }
473}
474
475classical_operands! { ArithmeticOperand, BinaryOperand, ComparisonOperand }
476
477#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
478#[cfg_attr(feature = "stubs", gen_stub_pyclass_enum)]
479#[cfg_attr(
480 feature = "python",
481 pyo3::pyclass(
482 module = "quil.instructions",
483 eq,
484 frozen,
485 hash,
486 rename_all = "SCREAMING_SNAKE_CASE"
487 )
488)]
489pub enum ComparisonOperator {
490 Equal,
491 GreaterThanOrEqual,
492 GreaterThan,
493 LessThanOrEqual,
494 LessThan,
495}
496
497impl Quil for ComparisonOperator {
498 fn write(
499 &self,
500 f: &mut impl std::fmt::Write,
501 _fall_back_to_debug: bool,
502 ) -> crate::quil::ToQuilResult<()> {
503 match &self {
504 ComparisonOperator::Equal => write!(f, "EQ"),
505 ComparisonOperator::GreaterThanOrEqual => write!(f, "GE"),
506 ComparisonOperator::GreaterThan => write!(f, "GT"),
507 ComparisonOperator::LessThanOrEqual => write!(f, "LE"),
508 ComparisonOperator::LessThan => write!(f, "LT"),
509 }
510 .map_err(Into::into)
511 }
512}
513
514#[derive(Clone, Debug, Hash, PartialEq, Eq)]
515#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
516#[cfg_attr(
517 feature = "python",
518 pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
519)]
520pub struct UnaryLogic {
521 pub operator: UnaryOperator,
522 pub operand: MemoryReference,
523}
524
525pickleable_new! {
526 impl UnaryLogic {
527 pub fn new(operator: UnaryOperator, operand: MemoryReference);
528 }
529}
530
531impl Quil for UnaryLogic {
532 fn write(
533 &self,
534 f: &mut impl std::fmt::Write,
535 fall_back_to_debug: bool,
536 ) -> crate::quil::ToQuilResult<()> {
537 self.operator.write(f, fall_back_to_debug)?;
538 write!(f, " ")?;
539 self.operand.write(f, fall_back_to_debug)?;
540 Ok(())
541 }
542}
543
544#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
545#[cfg_attr(feature = "stubs", gen_stub_pyclass_enum)]
546#[cfg_attr(
547 feature = "python",
548 pyo3::pyclass(
549 module = "quil.instructions",
550 eq,
551 frozen,
552 hash,
553 rename_all = "SCREAMING_SNAKE_CASE"
554 )
555)]
556pub enum UnaryOperator {
557 Neg,
558 Not,
559}
560
561impl Quil for UnaryOperator {
562 fn write(
563 &self,
564 f: &mut impl std::fmt::Write,
565 _fall_back_to_debug: bool,
566 ) -> crate::quil::ToQuilResult<()> {
567 match &self {
568 UnaryOperator::Neg => write!(f, "NEG"),
569 UnaryOperator::Not => write!(f, "NOT"),
570 }
571 .map_err(Into::into)
572 }
573}