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