quil_rs/instruction/
frame.rs

1use std::str::FromStr;
2
3use indexmap::IndexMap;
4use nom_locate::LocatedSpan;
5
6#[cfg(feature = "stubs")]
7use pyo3_stub_gen::derive::{gen_stub_pyclass, gen_stub_pyclass_complex_enum};
8
9use super::{MemoryReference, Qubit, QuotedString, WaveformInvocation};
10use crate::{
11    expression::Expression,
12    parser::{common::parse_frame_identifier, lex, ParseError},
13    pickleable_new,
14    program::{disallow_leftover, SyntaxError},
15    quil::{Quil, INDENT},
16};
17
18#[derive(Clone, Debug, PartialEq, Eq, Hash, strum::EnumTryAs)]
19#[cfg_attr(feature = "stubs", gen_stub_pyclass_complex_enum)]
20#[cfg_attr(
21    feature = "python",
22    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all)
23)]
24pub enum AttributeValue {
25    String(String),
26    Expression(Expression),
27}
28
29impl Quil for AttributeValue {
30    fn write(
31        &self,
32        f: &mut impl std::fmt::Write,
33        fall_back_to_debug: bool,
34    ) -> crate::quil::ToQuilResult<()> {
35        use AttributeValue::*;
36        match self {
37            String(value) => write!(f, "{}", QuotedString(value)).map_err(Into::into),
38            Expression(value) => value.write(f, fall_back_to_debug),
39        }
40    }
41}
42
43pub type FrameAttributes = IndexMap<String, AttributeValue>;
44
45#[derive(Clone, Debug, PartialEq, Eq)]
46#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
47#[cfg_attr(
48    feature = "python",
49    pyo3::pyclass(module = "quil.instructions", eq, get_all, set_all, subclass)
50)]
51pub struct FrameDefinition {
52    pub identifier: FrameIdentifier,
53    pub attributes: FrameAttributes,
54}
55
56pickleable_new! {
57    impl FrameDefinition {
58        pub fn new(identifier: FrameIdentifier, attributes: FrameAttributes);
59    }
60}
61
62impl Quil for FrameDefinition {
63    fn write(
64        &self,
65        writer: &mut impl std::fmt::Write,
66        fall_back_to_debug: bool,
67    ) -> crate::quil::ToQuilResult<()> {
68        write!(writer, "DEFFRAME ")?;
69        self.identifier.write(writer, fall_back_to_debug)?;
70        write!(writer, ":")?;
71        for (key, value) in &self.attributes {
72            write!(writer, "\n{INDENT}{key}: ")?;
73            value.write(writer, fall_back_to_debug)?;
74        }
75
76        Ok(())
77    }
78}
79
80#[derive(Clone, Debug, Eq, Hash, PartialEq)]
81#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
82#[cfg_attr(
83    feature = "python",
84    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
85)]
86pub struct FrameIdentifier {
87    pub name: String,
88    pub qubits: Vec<Qubit>,
89}
90
91pickleable_new! {
92    impl FrameIdentifier {
93        pub fn new(name: String, qubits: Vec<Qubit>);
94    }
95}
96
97impl Quil for FrameIdentifier {
98    fn write(
99        &self,
100        writer: &mut impl std::fmt::Write,
101        fall_back_to_debug: bool,
102    ) -> std::result::Result<(), crate::quil::ToQuilError> {
103        for qubit in &self.qubits {
104            qubit.write(writer, fall_back_to_debug)?;
105            write!(writer, " ")?;
106        }
107        write!(writer, "{}", QuotedString(&self.name)).map_err(Into::into)
108    }
109}
110
111impl FromStr for FrameIdentifier {
112    type Err = SyntaxError<Self>;
113
114    fn from_str(s: &str) -> Result<Self, Self::Err> {
115        let input = LocatedSpan::new(s);
116        let tokens = lex(input)?;
117        disallow_leftover(
118            parse_frame_identifier(&tokens).map_err(ParseError::from_nom_internal_err),
119        )
120    }
121}
122
123#[derive(Clone, Debug, PartialEq, Eq)]
124#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
125#[cfg_attr(
126    feature = "python",
127    pyo3::pyclass(module = "quil.instructions", eq, get_all, set_all, subclass)
128)]
129pub struct Capture {
130    pub blocking: bool,
131    pub frame: FrameIdentifier,
132    pub memory_reference: MemoryReference,
133    pub waveform: WaveformInvocation,
134}
135
136pickleable_new! {
137    impl Capture {
138        pub fn new(
139            blocking: bool,
140            frame: FrameIdentifier,
141            memory_reference: MemoryReference,
142            waveform: WaveformInvocation,
143        );
144    }
145}
146
147impl Quil for Capture {
148    fn write(
149        &self,
150        writer: &mut impl std::fmt::Write,
151        fall_back_to_debug: bool,
152    ) -> Result<(), crate::quil::ToQuilError> {
153        {
154            if self.blocking {
155                write!(writer, "CAPTURE ")?;
156            } else {
157                write!(writer, "NONBLOCKING CAPTURE ")?;
158            }
159
160            self.frame.write(writer, fall_back_to_debug)?;
161            write!(writer, " ")?;
162            self.waveform.write(writer, fall_back_to_debug)?;
163            write!(writer, " ")?;
164            self.memory_reference.write(writer, fall_back_to_debug)?;
165            Ok(())
166        }
167    }
168}
169
170#[derive(Clone, Debug, PartialEq, Eq)]
171#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
172#[cfg_attr(
173    feature = "python",
174    pyo3::pyclass(module = "quil.instructions", eq, get_all, set_all, subclass)
175)]
176pub struct Pulse {
177    pub blocking: bool,
178    pub frame: FrameIdentifier,
179    pub waveform: WaveformInvocation,
180}
181
182pickleable_new! {
183    impl Pulse {
184        pub fn new(blocking: bool, frame: FrameIdentifier, waveform: WaveformInvocation);
185    }
186}
187
188impl Quil for Pulse {
189    fn write(
190        &self,
191        writer: &mut impl std::fmt::Write,
192        fall_back_to_debug: bool,
193    ) -> crate::quil::ToQuilResult<()> {
194        {
195            if self.blocking {
196                write!(writer, "PULSE ")?;
197            } else {
198                write!(writer, "NONBLOCKING PULSE ")?;
199            }
200            self.frame.write(writer, fall_back_to_debug)?;
201            write!(writer, " ")?;
202            self.waveform.write(writer, fall_back_to_debug)?;
203            Ok(())
204        }
205    }
206}
207
208#[derive(Clone, Debug, PartialEq, Eq, Hash)]
209#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
210#[cfg_attr(
211    feature = "python",
212    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
213)]
214pub struct RawCapture {
215    pub blocking: bool,
216    pub frame: FrameIdentifier,
217    pub duration: Expression,
218    pub memory_reference: MemoryReference,
219}
220
221pickleable_new! {
222    impl RawCapture {
223        pub fn new(
224            blocking: bool,
225            frame: FrameIdentifier,
226            duration: Expression,
227            memory_reference: MemoryReference,
228        );
229    }
230}
231
232impl Quil for RawCapture {
233    fn write(
234        &self,
235        writer: &mut impl std::fmt::Write,
236        fall_back_to_debug: bool,
237    ) -> crate::quil::ToQuilResult<()> {
238        {
239            if self.blocking {
240                write!(writer, "RAW-CAPTURE ")?;
241            } else {
242                write!(writer, "NONBLOCKING RAW-CAPTURE ")?;
243            }
244            self.frame.write(writer, fall_back_to_debug)?;
245            write!(writer, " ")?;
246            self.duration.write(writer, fall_back_to_debug)?;
247            write!(writer, " ")?;
248            self.memory_reference.write(writer, fall_back_to_debug)?;
249            Ok(())
250        }
251    }
252}
253
254#[derive(Clone, Debug, PartialEq, Eq, Hash)]
255#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
256#[cfg_attr(
257    feature = "python",
258    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
259)]
260pub struct SetFrequency {
261    pub frame: FrameIdentifier,
262    pub frequency: Expression,
263}
264
265pickleable_new! {
266    impl SetFrequency {
267        pub fn new(frame: FrameIdentifier, frequency: Expression);
268    }
269}
270
271impl Quil for SetFrequency {
272    fn write(
273        &self,
274        writer: &mut impl std::fmt::Write,
275        fall_back_to_debug: bool,
276    ) -> crate::quil::ToQuilResult<()> {
277        write!(writer, "SET-FREQUENCY ")?;
278        self.frame.write(writer, fall_back_to_debug)?;
279        write!(writer, " ")?;
280        self.frequency.write(writer, fall_back_to_debug)?;
281        Ok(())
282    }
283}
284
285#[derive(Clone, Debug, PartialEq, Eq, Hash)]
286#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
287#[cfg_attr(
288    feature = "python",
289    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
290)]
291pub struct SetPhase {
292    pub frame: FrameIdentifier,
293    pub phase: Expression,
294}
295
296pickleable_new! {
297    impl SetPhase {
298        pub fn new(frame: FrameIdentifier, phase: Expression);
299    }
300}
301
302impl Quil for SetPhase {
303    fn write(
304        &self,
305        writer: &mut impl std::fmt::Write,
306        fall_back_to_debug: bool,
307    ) -> crate::quil::ToQuilResult<()> {
308        write!(writer, "SET-PHASE ")?;
309        self.frame.write(writer, fall_back_to_debug)?;
310        write!(writer, " ")?;
311        self.phase.write(writer, fall_back_to_debug)?;
312        Ok(())
313    }
314}
315
316#[derive(Clone, Debug, PartialEq, Eq, Hash)]
317#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
318#[cfg_attr(
319    feature = "python",
320    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
321)]
322pub struct SetScale {
323    pub frame: FrameIdentifier,
324    pub scale: Expression,
325}
326
327pickleable_new! {
328    impl SetScale {
329        pub fn new(frame: FrameIdentifier, scale: Expression);
330    }
331}
332
333impl Quil for SetScale {
334    fn write(
335        &self,
336        writer: &mut impl std::fmt::Write,
337        fall_back_to_debug: bool,
338    ) -> crate::quil::ToQuilResult<()> {
339        write!(writer, "SET-SCALE ")?;
340        self.frame.write(writer, fall_back_to_debug)?;
341        write!(writer, " ")?;
342        self.scale.write(writer, fall_back_to_debug)?;
343        Ok(())
344    }
345}
346
347#[derive(Clone, Debug, PartialEq, Eq, Hash)]
348#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
349#[cfg_attr(
350    feature = "python",
351    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
352)]
353pub struct ShiftFrequency {
354    pub frame: FrameIdentifier,
355    pub frequency: Expression,
356}
357
358pickleable_new! {
359    impl ShiftFrequency {
360        pub fn new(frame: FrameIdentifier, frequency: Expression);
361    }
362}
363
364impl Quil for ShiftFrequency {
365    fn write(
366        &self,
367        writer: &mut impl std::fmt::Write,
368        fall_back_to_debug: bool,
369    ) -> crate::quil::ToQuilResult<()> {
370        write!(writer, "SHIFT-FREQUENCY ")?;
371        self.frame.write(writer, fall_back_to_debug)?;
372        write!(writer, " ")?;
373        self.frequency.write(writer, fall_back_to_debug)?;
374        Ok(())
375    }
376}
377
378#[derive(Clone, Debug, PartialEq, Eq, Hash)]
379#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
380#[cfg_attr(
381    feature = "python",
382    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
383)]
384pub struct ShiftPhase {
385    pub frame: FrameIdentifier,
386    pub phase: Expression,
387}
388
389pickleable_new! {
390    impl ShiftPhase {
391        pub fn new(frame: FrameIdentifier, phase: Expression);
392    }
393}
394
395impl Quil for ShiftPhase {
396    fn write(
397        &self,
398        writer: &mut impl std::fmt::Write,
399        fall_back_to_debug: bool,
400    ) -> crate::quil::ToQuilResult<()> {
401        write!(writer, "SHIFT-PHASE ")?;
402        self.frame.write(writer, fall_back_to_debug)?;
403        write!(writer, " ")?;
404        self.phase.write(writer, fall_back_to_debug)?;
405        Ok(())
406    }
407}
408
409#[derive(Clone, Debug, PartialEq, Eq, Hash)]
410#[cfg_attr(feature = "stubs", gen_stub_pyclass)]
411#[cfg_attr(
412    feature = "python",
413    pyo3::pyclass(module = "quil.instructions", eq, frozen, hash, get_all, subclass)
414)]
415pub struct SwapPhases {
416    pub frame_1: FrameIdentifier,
417    pub frame_2: FrameIdentifier,
418}
419
420pickleable_new! {
421    impl SwapPhases {
422        pub fn new(frame_1: FrameIdentifier, frame_2: FrameIdentifier);
423    }
424}
425
426impl Quil for SwapPhases {
427    fn write(
428        &self,
429        writer: &mut impl std::fmt::Write,
430        fall_back_to_debug: bool,
431    ) -> crate::quil::ToQuilResult<()> {
432        write!(writer, "SWAP-PHASES ")?;
433        self.frame_1.write(writer, fall_back_to_debug)?;
434        write!(writer, " ")?;
435        self.frame_2.write(writer, fall_back_to_debug)?;
436        Ok(())
437    }
438}