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}