Skip to main content

quil_rs/parser/
instruction.rs

1// Copyright 2021 Rigetti Computing
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use nom::{
16    combinator::all_consuming,
17    multi::{many0, many1},
18    sequence::{delimited, preceded},
19};
20
21use crate::parser::{extract_nom_err, InternalParseError, InternalParserResult};
22use crate::{
23    instruction::{
24        ArithmeticOperator, BinaryOperator, ComparisonOperator, Instruction, UnaryOperator,
25    },
26    token,
27};
28
29use super::{
30    command, common,
31    error::ParserErrorKind,
32    gate,
33    lexer::{Command, Token},
34    ParserInput,
35};
36
37/// Parse the next instructon from the input, skipping past leading newlines, comments, and semicolons.
38pub(crate) fn parse_instruction(input: ParserInput) -> InternalParserResult<Instruction> {
39    let (input, _) = common::skip_newlines_and_comments(input)?;
40    match super::split_first_token(input) {
41        None => Err(nom::Err::Error(InternalParseError::from_kind(
42            input,
43            ParserErrorKind::EndOfInput,
44        ))),
45        Some((Token::Command(command), remainder)) => match command {
46            Command::Add => command::parse_arithmetic(ArithmeticOperator::Add, remainder),
47            Command::And => command::parse_logical_binary(BinaryOperator::And, remainder),
48            Command::Ashr => command::parse_logical_binary(BinaryOperator::Ashr, remainder),
49            Command::Call => command::parse_call(remainder),
50            Command::Capture => command::parse_capture(remainder, true),
51            Command::Convert => command::parse_convert(remainder),
52            Command::Declare => command::parse_declare(remainder),
53            Command::DefCal => command::parse_defcal(remainder),
54            Command::DefCircuit => command::parse_defcircuit(remainder),
55            Command::DefFrame => command::parse_defframe(remainder),
56            Command::DefGate => command::parse_defgate(remainder),
57            Command::DefWaveform => command::parse_defwaveform(remainder),
58            Command::Delay => command::parse_delay(remainder),
59            Command::Div => command::parse_arithmetic(ArithmeticOperator::Divide, remainder),
60            Command::Eq => command::parse_comparison(ComparisonOperator::Equal, remainder),
61            Command::GE => {
62                command::parse_comparison(ComparisonOperator::GreaterThanOrEqual, remainder)
63            }
64            Command::GT => command::parse_comparison(ComparisonOperator::GreaterThan, remainder),
65            Command::LE => {
66                command::parse_comparison(ComparisonOperator::LessThanOrEqual, remainder)
67            }
68            Command::LT => command::parse_comparison(ComparisonOperator::LessThan, remainder),
69            Command::Fence => command::parse_fence(remainder),
70            Command::Halt => Ok((remainder, Instruction::Halt())),
71            Command::Include => command::parse_include(remainder),
72            Command::Ior => command::parse_logical_binary(BinaryOperator::Ior, remainder),
73            Command::Jump => command::parse_jump(remainder),
74            Command::JumpUnless => command::parse_jump_unless(remainder),
75            Command::JumpWhen => command::parse_jump_when(remainder),
76            Command::Label => command::parse_label(remainder),
77            Command::Load => command::parse_load(remainder),
78            Command::Measure => command::parse_measurement(remainder),
79            Command::Move => command::parse_move(remainder),
80            Command::Exchange => command::parse_exchange(remainder),
81            Command::Mul => command::parse_arithmetic(ArithmeticOperator::Multiply, remainder),
82            Command::Neg => command::parse_logical_unary(UnaryOperator::Neg, remainder),
83            Command::Nop => Ok((remainder, Instruction::Nop())),
84            Command::Not => command::parse_logical_unary(UnaryOperator::Not, remainder),
85            Command::Pragma => command::parse_pragma(remainder),
86            Command::Pulse => command::parse_pulse(remainder, true),
87            Command::RawCapture => command::parse_raw_capture(remainder, true),
88            Command::Reset => command::parse_reset(remainder),
89            Command::SetFrequency => command::parse_set_frequency(remainder),
90            Command::SetPhase => command::parse_set_phase(remainder),
91            Command::SetScale => command::parse_set_scale(remainder),
92            Command::ShiftFrequency => command::parse_shift_frequency(remainder),
93            Command::ShiftPhase => command::parse_shift_phase(remainder),
94            Command::Shl => command::parse_logical_binary(BinaryOperator::Shl, remainder),
95            Command::Shr => command::parse_logical_binary(BinaryOperator::Shr, remainder),
96            Command::SwapPhases => command::parse_swap_phases(remainder),
97            Command::Store => command::parse_store(remainder),
98            Command::Sub => command::parse_arithmetic(ArithmeticOperator::Subtract, remainder),
99            Command::Wait => Ok((remainder, Instruction::Wait())),
100            Command::Xor => command::parse_logical_binary(BinaryOperator::Xor, remainder),
101        }
102        .map_err(|err| {
103            nom::Err::Failure(
104                InternalParseError::from_kind(
105                    &input[..1],
106                    ParserErrorKind::InvalidCommand { command: *command },
107                )
108                .with_previous(extract_nom_err(err)),
109            )
110        }),
111        Some((Token::NonBlocking, remainder)) => match super::split_first_token(remainder) {
112            Some((Token::Command(command), remainder)) => match command {
113                Command::Pulse => command::parse_pulse(remainder, false),
114                Command::Capture => command::parse_capture(remainder, false),
115                Command::RawCapture => command::parse_raw_capture(remainder, false),
116                _ => todo!(),
117            },
118            _ => todo!(),
119        },
120        Some((Token::Identifier(_), _)) | Some((Token::Modifier(_), _)) => gate::parse_gate(input),
121        Some((_, _)) => Err(nom::Err::Failure(InternalParseError::from_kind(
122            &input[..1],
123            ParserErrorKind::NotACommandOrGate,
124        ))),
125    }
126}
127
128/// Parse all instructions from the input, trimming leading and trailing newlines and comments.
129/// Returns an error if it does not reach the end of input.
130pub(crate) fn parse_instructions(input: ParserInput) -> InternalParserResult<Vec<Instruction>> {
131    all_consuming(delimited(
132        common::skip_newlines_and_comments,
133        many0(parse_instruction),
134        common::skip_newlines_and_comments,
135    ))(input)
136}
137
138/// Parse a block of indented "block instructions."
139pub(crate) fn parse_block(input: ParserInput) -> InternalParserResult<Vec<Instruction>> {
140    many1(parse_block_instruction)(input)
141}
142
143/// Parse a single indented "block instruction."
144pub(crate) fn parse_block_instruction<'a>(
145    input: ParserInput<'a>,
146) -> InternalParserResult<'a, Instruction> {
147    preceded(
148        token!(NewLine),
149        preceded(token!(Indentation), parse_instruction),
150    )(input)
151}
152
153#[cfg(test)]
154mod tests {
155    use std::str::FromStr;
156
157    use internment::ArcIntern;
158    use nom_locate::LocatedSpan;
159    use num_complex::Complex;
160
161    use crate::expression::{
162        Expression, ExpressionFunction, FunctionCallExpression, InfixExpression, InfixOperator,
163        PrefixExpression, PrefixOperator,
164    };
165    use crate::instruction::{
166        Arithmetic, ArithmeticOperand, ArithmeticOperator, AttributeValue, BinaryLogic,
167        BinaryOperand, BinaryOperator, CalibrationDefinition, CalibrationIdentifier, Capture,
168        Comparison, ComparisonOperand, ComparisonOperator, Convert, FrameDefinition,
169        FrameIdentifier, Gate, GateDefinition, GateSpecification, Include, Instruction, Jump,
170        JumpWhen, Label, MemoryReference, Move, Pulse, Qubit, RawCapture, Reset, SetFrequency,
171        SetPhase, SetScale, ShiftFrequency, ShiftPhase, SwapPhases, Target, UnaryLogic,
172        UnaryOperator, Waveform, WaveformDefinition, WaveformInvocation, WaveformParameters,
173    };
174    use crate::parser::common::tests::KITCHEN_SINK_QUIL;
175    use crate::parser::lexer::lex;
176    use crate::quil::Quil;
177    use crate::{make_test, real, Program};
178
179    use super::parse_instructions;
180
181    make_test!(
182        semicolons_are_newlines,
183        parse_instructions,
184        "X 0; Y 1\nZ 2",
185        vec![
186            Instruction::Gate(Gate {
187                name: "X".to_owned(),
188                parameters: vec![],
189                qubits: vec![Qubit::Fixed(0)],
190                modifiers: vec![],
191            }),
192            Instruction::Gate(Gate {
193                name: "Y".to_owned(),
194                parameters: vec![],
195                qubits: vec![Qubit::Fixed(1)],
196                modifiers: vec![],
197            }),
198            Instruction::Gate(Gate {
199                name: "Z".to_owned(),
200                parameters: vec![],
201                qubits: vec![Qubit::Fixed(2)],
202                modifiers: vec![],
203            }),
204        ]
205    );
206
207    make_test!(
208        arithmetic,
209        parse_instructions,
210        "ADD ro 2\nMUL ro 1.0\nSUB ro[1] -3\nDIV ro[1] -1.0\nADD ro[1] ro[2]",
211        vec![
212            Instruction::Arithmetic(Arithmetic {
213                operator: ArithmeticOperator::Add,
214                destination: MemoryReference {
215                    name: "ro".to_owned(),
216                    index: 0
217                },
218                source: ArithmeticOperand::LiteralInteger(2),
219            }),
220            Instruction::Arithmetic(Arithmetic {
221                operator: ArithmeticOperator::Multiply,
222                destination: MemoryReference {
223                    name: "ro".to_owned(),
224                    index: 0
225                },
226                source: ArithmeticOperand::LiteralReal(1.0),
227            }),
228            Instruction::Arithmetic(Arithmetic {
229                operator: ArithmeticOperator::Subtract,
230                destination: MemoryReference {
231                    name: "ro".to_owned(),
232                    index: 1
233                },
234                source: ArithmeticOperand::LiteralInteger(-3),
235            }),
236            Instruction::Arithmetic(Arithmetic {
237                operator: ArithmeticOperator::Divide,
238                destination: MemoryReference {
239                    name: "ro".to_owned(),
240                    index: 1
241                },
242                source: ArithmeticOperand::LiteralReal(-1f64),
243            }),
244            Instruction::Arithmetic(Arithmetic {
245                operator: ArithmeticOperator::Add,
246                destination: MemoryReference {
247                    name: "ro".to_owned(),
248                    index: 1
249                },
250                source: ArithmeticOperand::MemoryReference(MemoryReference {
251                    name: "ro".to_owned(),
252                    index: 2
253                }),
254            })
255        ]
256    );
257
258    make_test!(
259        comparison_logic,
260        parse_instructions,
261        "EQ dest ro 0\nLT dest ro[1] -1\nLE dest ro 1.2\nGT dest ro[2] 1e-6\nGE dest ro x",
262        vec![
263            Instruction::Comparison(Comparison {
264                operator: ComparisonOperator::Equal,
265                destination: MemoryReference {
266                    name: "dest".to_owned(),
267                    index: 0
268                },
269                lhs: MemoryReference {
270                    name: "ro".to_owned(),
271                    index: 0
272                },
273                rhs: ComparisonOperand::LiteralInteger(0)
274            }),
275            Instruction::Comparison(Comparison {
276                operator: ComparisonOperator::LessThan,
277                destination: MemoryReference {
278                    name: "dest".to_owned(),
279                    index: 0
280                },
281                lhs: MemoryReference {
282                    name: "ro".to_owned(),
283                    index: 1
284                },
285                rhs: ComparisonOperand::LiteralInteger(-1)
286            }),
287            Instruction::Comparison(Comparison {
288                operator: ComparisonOperator::LessThanOrEqual,
289                destination: MemoryReference {
290                    name: "dest".to_owned(),
291                    index: 0
292                },
293                lhs: MemoryReference {
294                    name: "ro".to_owned(),
295                    index: 0
296                },
297                rhs: ComparisonOperand::LiteralReal(1.2)
298            }),
299            Instruction::Comparison(Comparison {
300                operator: ComparisonOperator::GreaterThan,
301                destination: MemoryReference {
302                    name: "dest".to_owned(),
303                    index: 0
304                },
305                lhs: MemoryReference {
306                    name: "ro".to_owned(),
307                    index: 2
308                },
309                rhs: ComparisonOperand::LiteralReal(0.000001)
310            }),
311            Instruction::Comparison(Comparison {
312                operator: ComparisonOperator::GreaterThanOrEqual,
313                destination: MemoryReference {
314                    name: "dest".to_owned(),
315                    index: 0
316                },
317                lhs: MemoryReference {
318                    name: "ro".to_owned(),
319                    index: 0
320                },
321                rhs: ComparisonOperand::MemoryReference(MemoryReference {
322                    name: "x".to_owned(),
323                    index: 0
324                }),
325            })
326        ]
327    );
328
329    #[test]
330    fn test_comparison_logic_error() {
331        [
332            "EQ ro 1 1",
333            "LT 1 1 1",
334            "LE 1 x ro",
335            "GT 1 ro x",
336            "GE dest 0.3 4",
337        ]
338        .iter()
339        .for_each(|input| {
340            let input = LocatedSpan::new(*input);
341            let tokens = lex(input).unwrap();
342            assert!(parse_instructions(&tokens).is_err(), "{}", input);
343        })
344    }
345
346    make_test!(
347        binary_logic,
348        parse_instructions,
349        &[
350            "AND ro[1] ro[11]",
351            "IOR ro[2] ro[12]",
352            "XOR ro[3] ro[13]",
353            "SHL ro[4] ro[14]",
354            "SHR ro[5] ro[15]",
355            "ASHR ro[6] ro[16]",
356            "AND ro 21",
357            "IOR ro 22",
358            "XOR ro 23",
359            "SHL ro 24",
360            "SHR ro 25",
361            "ASHR ro 26",
362        ]
363        .join("\n"),
364        vec![
365            Instruction::BinaryLogic(BinaryLogic {
366                operator: BinaryOperator::And,
367                destination: MemoryReference {
368                    name: "ro".to_owned(),
369                    index: 1,
370                },
371                source: BinaryOperand::MemoryReference(MemoryReference {
372                    name: "ro".to_owned(),
373                    index: 11,
374                }),
375            }),
376            Instruction::BinaryLogic(BinaryLogic {
377                operator: BinaryOperator::Ior,
378                destination: MemoryReference {
379                    name: "ro".to_owned(),
380                    index: 2,
381                },
382                source: BinaryOperand::MemoryReference(MemoryReference {
383                    name: "ro".to_owned(),
384                    index: 12,
385                }),
386            }),
387            Instruction::BinaryLogic(BinaryLogic {
388                operator: BinaryOperator::Xor,
389                destination: MemoryReference {
390                    name: "ro".to_owned(),
391                    index: 3,
392                },
393                source: BinaryOperand::MemoryReference(MemoryReference {
394                    name: "ro".to_owned(),
395                    index: 13,
396                }),
397            }),
398            Instruction::BinaryLogic(BinaryLogic {
399                operator: BinaryOperator::Shl,
400                destination: MemoryReference {
401                    name: "ro".to_owned(),
402                    index: 4,
403                },
404                source: BinaryOperand::MemoryReference(MemoryReference {
405                    name: "ro".to_owned(),
406                    index: 14,
407                }),
408            }),
409            Instruction::BinaryLogic(BinaryLogic {
410                operator: BinaryOperator::Shr,
411                destination: MemoryReference {
412                    name: "ro".to_owned(),
413                    index: 5,
414                },
415                source: BinaryOperand::MemoryReference(MemoryReference {
416                    name: "ro".to_owned(),
417                    index: 15,
418                }),
419            }),
420            Instruction::BinaryLogic(BinaryLogic {
421                operator: BinaryOperator::Ashr,
422                destination: MemoryReference {
423                    name: "ro".to_owned(),
424                    index: 6,
425                },
426                source: BinaryOperand::MemoryReference(MemoryReference {
427                    name: "ro".to_owned(),
428                    index: 16,
429                }),
430            }),
431            Instruction::BinaryLogic(BinaryLogic {
432                operator: BinaryOperator::And,
433                destination: MemoryReference {
434                    name: "ro".to_owned(),
435                    index: 0,
436                },
437                source: BinaryOperand::LiteralInteger(21),
438            }),
439            Instruction::BinaryLogic(BinaryLogic {
440                operator: BinaryOperator::Ior,
441                destination: MemoryReference {
442                    name: "ro".to_owned(),
443                    index: 0,
444                },
445                source: BinaryOperand::LiteralInteger(22),
446            }),
447            Instruction::BinaryLogic(BinaryLogic {
448                operator: BinaryOperator::Xor,
449                destination: MemoryReference {
450                    name: "ro".to_owned(),
451                    index: 0,
452                },
453                source: BinaryOperand::LiteralInteger(23),
454            }),
455            Instruction::BinaryLogic(BinaryLogic {
456                operator: BinaryOperator::Shl,
457                destination: MemoryReference {
458                    name: "ro".to_owned(),
459                    index: 0,
460                },
461                source: BinaryOperand::LiteralInteger(24),
462            }),
463            Instruction::BinaryLogic(BinaryLogic {
464                operator: BinaryOperator::Shr,
465                destination: MemoryReference {
466                    name: "ro".to_owned(),
467                    index: 0,
468                },
469                source: BinaryOperand::LiteralInteger(25),
470            }),
471            Instruction::BinaryLogic(BinaryLogic {
472                operator: BinaryOperator::Ashr,
473                destination: MemoryReference {
474                    name: "ro".to_owned(),
475                    index: 0,
476                },
477                source: BinaryOperand::LiteralInteger(26),
478            }),
479        ]
480    );
481
482    #[test]
483    fn test_binary_logic_error() {
484        ["AND ro", "XOR 1 1", "IOR 1"].iter().for_each(|input| {
485            let input = LocatedSpan::new(*input);
486            let tokens = lex(input).unwrap();
487            assert!(parse_instructions(&tokens).is_err(), "{}", input);
488        })
489    }
490
491    make_test!(
492        unary_logic,
493        parse_instructions,
494        "NOT ro\nNEG ro\nNOT ro[1]\nNEG ro[1]",
495        vec![
496            Instruction::UnaryLogic(UnaryLogic {
497                operator: UnaryOperator::Not,
498                operand: MemoryReference {
499                    name: "ro".to_owned(),
500                    index: 0,
501                }
502            }),
503            Instruction::UnaryLogic(UnaryLogic {
504                operator: UnaryOperator::Neg,
505                operand: MemoryReference {
506                    name: "ro".to_owned(),
507                    index: 0,
508                }
509            }),
510            Instruction::UnaryLogic(UnaryLogic {
511                operator: UnaryOperator::Not,
512                operand: MemoryReference {
513                    name: "ro".to_owned(),
514                    index: 1,
515                }
516            }),
517            Instruction::UnaryLogic(UnaryLogic {
518                operator: UnaryOperator::Neg,
519                operand: MemoryReference {
520                    name: "ro".to_owned(),
521                    index: 1,
522                }
523            }),
524        ]
525    );
526
527    #[test]
528    fn test_unary_logic_error() {
529        ["NEG 1", "NOT 1", "NEG 0", "NOT 0"]
530            .iter()
531            .for_each(|input| {
532                let input = LocatedSpan::new(*input);
533                let tokens = lex(input).unwrap();
534                assert!(parse_instructions(&tokens).is_err(), "{}", input);
535            })
536    }
537
538    make_test!(
539        capture_instructions,
540        parse_instructions,
541        "CAPTURE 0 \"rx\" my_custom_waveform ro\nRAW-CAPTURE 0 1 \"rx\" 2e9 ro\nNONBLOCKING CAPTURE 0 \"rx\" my_custom_waveform(a: 1.0) ro\nNONBLOCKING RAW-CAPTURE 0 1 \"rx\" 2e9 ro",
542        vec![
543            Instruction::Capture(Capture {
544                blocking: true,
545                frame: FrameIdentifier {
546                    name: "rx".to_owned(),
547                    qubits: vec![Qubit::Fixed(0)]
548                },
549                waveform: WaveformInvocation {
550                    name: "my_custom_waveform".to_owned(),
551                    parameters: WaveformParameters::new()
552                },
553                memory_reference: MemoryReference {
554                    name: "ro".to_owned(),
555                    index: 0
556                }
557            }),
558            Instruction::RawCapture(RawCapture {
559                blocking: true,
560                frame: FrameIdentifier {
561                    name: "rx".to_owned(),
562                    qubits: vec![Qubit::Fixed(0), Qubit::Fixed(1)]
563                },
564                duration: Expression::Number(real![2e9]),
565                memory_reference: MemoryReference {
566                    name: "ro".to_owned(),
567                    index: 0
568                }
569            }),
570            Instruction::Capture(Capture {
571                blocking: false,
572                frame: FrameIdentifier {
573                    name: "rx".to_owned(),
574                    qubits: vec![Qubit::Fixed(0)]
575                },
576                waveform: WaveformInvocation {
577                    name: "my_custom_waveform".to_owned(),
578                    parameters: vec![("a".to_owned(), Expression::Number(real!(1f64)))].into_iter().collect()
579                },
580                memory_reference: MemoryReference {
581                    name: "ro".to_owned(),
582                    index: 0
583                }
584            }),
585            Instruction::RawCapture(RawCapture {
586                blocking: false,
587                frame: FrameIdentifier {
588                    name: "rx".to_owned(),
589                    qubits: vec![Qubit::Fixed(0), Qubit::Fixed(1)]
590                },
591                duration: Expression::Number(real![2e9]),
592                memory_reference: MemoryReference {
593                    name: "ro".to_owned(),
594                    index: 0
595                }
596            })
597        ]
598    );
599
600    make_test!(comment, parse_instructions, "# Questions:\n\n\n", vec![]);
601
602    make_test!(
603        comment_and_gate,
604        parse_instructions,
605        "# Questions:\nX 0",
606        vec![Instruction::Gate(Gate {
607            name: "X".to_owned(),
608            parameters: vec![],
609            qubits: vec![Qubit::Fixed(0)],
610            modifiers: vec![],
611        })]
612    );
613
614    make_test!(
615        comment_after_block,
616        parse_instructions,
617        "DEFFRAME 0 \"ro_rx\":\n\tDIRECTION: \"rx\"\n\n# (Pdb) settings.gates[GateID(name=\"x180\", targets=(0,))]\n\n",
618        vec![Instruction::FrameDefinition(FrameDefinition {
619            identifier: FrameIdentifier { name: "ro_rx".to_owned(), qubits: vec![Qubit::Fixed(0)] },
620            attributes: [("DIRECTION".to_owned(), AttributeValue::String("rx".to_owned()))].into_iter().collect()
621        })]);
622
623    make_test!(
624        simple_gate,
625        parse_instructions,
626        "RX 0",
627        vec![Instruction::Gate(Gate {
628            name: "RX".to_owned(),
629            parameters: vec![],
630            qubits: vec![Qubit::Fixed(0)],
631            modifiers: vec![],
632        })]
633    );
634
635    make_test!(
636        parametric_gate,
637        parse_instructions,
638        "RX(pi) 10",
639        vec![Instruction::Gate(Gate {
640            name: "RX".to_owned(),
641            parameters: vec![Expression::PiConstant()],
642            qubits: vec![Qubit::Fixed(10)],
643            modifiers: vec![],
644        })]
645    );
646
647    make_test!(
648        parametric_calibration,
649        parse_instructions,
650        "DEFCAL RX(%theta) %qubit:\n\tPULSE 1 \"xy\" custom_waveform(a: 1)",
651        vec![Instruction::CalibrationDefinition(CalibrationDefinition {
652            identifier: CalibrationIdentifier {
653                name: "RX".to_owned(),
654                parameters: vec![Expression::Variable("theta".to_owned())],
655                qubits: vec![Qubit::Variable("qubit".to_owned())],
656                modifiers: vec![],
657            },
658            instructions: vec![Instruction::Pulse(Pulse {
659                blocking: true,
660                frame: FrameIdentifier {
661                    name: "xy".to_owned(),
662                    qubits: vec![Qubit::Fixed(1)]
663                },
664                waveform: WaveformInvocation {
665                    name: "custom_waveform".to_owned(),
666                    parameters: [("a".to_owned(), Expression::Number(crate::real![1f64]))]
667                        .into_iter()
668                        .collect()
669                }
670            })]
671        })]
672    );
673
674    make_test!(
675        frame_definition,
676        parse_instructions,
677        "DEFFRAME 0 \"rx\":\n\tINITIAL-FREQUENCY: 2e9",
678        vec![Instruction::FrameDefinition(FrameDefinition {
679            identifier: FrameIdentifier {
680                name: "rx".to_owned(),
681                qubits: vec![Qubit::Fixed(0)]
682            },
683            attributes: [(
684                "INITIAL-FREQUENCY".to_owned(),
685                AttributeValue::Expression(Expression::Number(crate::real![2e9]))
686            )]
687            .into_iter()
688            .collect()
689        })]
690    );
691
692    make_test!(
693        control_flow,
694        parse_instructions,
695        "LABEL @hello\nJUMP @hello\nJUMP-WHEN @hello ro",
696        vec![
697            Instruction::Label(Label {
698                target: Target::Fixed("hello".to_owned())
699            }),
700            Instruction::Jump(Jump {
701                target: Target::Fixed("hello".to_owned())
702            }),
703            Instruction::JumpWhen(JumpWhen {
704                target: Target::Fixed("hello".to_owned()),
705                condition: MemoryReference {
706                    name: "ro".to_owned(),
707                    index: 0
708                }
709            })
710        ]
711    );
712
713    make_test!(
714        pulse_instructions,
715        parse_instructions,
716        "PULSE 0 \"xy\" custom\nNONBLOCKING PULSE 0 \"xy\" custom\nPULSE 0 \"xy\" custom(a: 1.0)",
717        vec![
718            Instruction::Pulse(Pulse {
719                blocking: true,
720                frame: FrameIdentifier {
721                    name: "xy".to_owned(),
722                    qubits: vec![Qubit::Fixed(0)]
723                },
724                waveform: WaveformInvocation {
725                    name: "custom".to_owned(),
726                    parameters: WaveformParameters::new()
727                }
728            }),
729            Instruction::Pulse(Pulse {
730                blocking: false,
731                frame: FrameIdentifier {
732                    name: "xy".to_owned(),
733                    qubits: vec![Qubit::Fixed(0)]
734                },
735                waveform: WaveformInvocation {
736                    name: "custom".to_owned(),
737                    parameters: WaveformParameters::new()
738                }
739            }),
740            Instruction::Pulse(Pulse {
741                blocking: true,
742                frame: FrameIdentifier {
743                    name: "xy".to_owned(),
744                    qubits: vec![Qubit::Fixed(0)]
745                },
746                waveform: WaveformInvocation {
747                    name: "custom".to_owned(),
748                    parameters: vec![("a".to_owned(), Expression::Number(real!(1f64)))]
749                        .into_iter()
750                        .collect()
751                }
752            })
753        ]
754    );
755
756    make_test!(
757        moveit,
758        parse_instructions,
759        "MOVE a 1.0",
760        vec![Instruction::Move(Move {
761            destination: MemoryReference {
762                name: "a".to_owned(),
763                index: 0
764            },
765            source: ArithmeticOperand::LiteralReal(1.0)
766        })]
767    );
768
769    make_test!(
770        parse_reset,
771        parse_instructions,
772        "RESET\nRESET 0",
773        vec![
774            Instruction::Reset(Reset { qubit: None }),
775            Instruction::Reset(Reset {
776                qubit: Some(Qubit::Fixed(0))
777            })
778        ]
779    );
780
781    make_test!(
782        waveform_definition,
783        parse_instructions,
784        "DEFWAVEFORM q44_q45_cphase/sqrtCPHASE:\n\t0.0, 0.0, 0.00027685415721916584",
785        vec![Instruction::WaveformDefinition(WaveformDefinition {
786            name: "q44_q45_cphase/sqrtCPHASE".to_owned(),
787            definition: Waveform {
788                matrix: vec![
789                    Expression::Number(real!(0.0)),
790                    Expression::Number(real!(0.0)),
791                    Expression::Number(real!(0.00027685415721916584))
792                ],
793                parameters: vec![],
794            }
795        })]
796    );
797
798    make_test!(
799        gate_definition,
800        parse_instructions,
801        "DEFGATE H:\n\t1/sqrt(2), 1/sqrt(2)\n\t1/sqrt(2), -1/sqrt(2)\n",
802        vec![Instruction::GateDefinition(GateDefinition {
803            name: "H".to_string(),
804            parameters: vec![],
805            specification: GateSpecification::Matrix(vec![
806                vec![
807                    Expression::Infix(InfixExpression {
808                        left: ArcIntern::new(Expression::Number(real!(1.0))),
809                        operator: InfixOperator::Slash,
810                        right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
811                            function: crate::expression::ExpressionFunction::SquareRoot,
812                            expression: ArcIntern::new(Expression::Number(real!(2.0))),
813                        })),
814                    }),
815                    Expression::Infix(InfixExpression {
816                        left: ArcIntern::new(Expression::Number(real!(1.0))),
817                        operator: InfixOperator::Slash,
818                        right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
819                            function: crate::expression::ExpressionFunction::SquareRoot,
820                            expression: ArcIntern::new(Expression::Number(real!(2.0))),
821                        })),
822                    }),
823                ],
824                vec![
825                    Expression::Infix(InfixExpression {
826                        left: ArcIntern::new(Expression::Number(real!(1.0))),
827                        operator: InfixOperator::Slash,
828                        right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
829                            function: crate::expression::ExpressionFunction::SquareRoot,
830                            expression: ArcIntern::new(Expression::Number(real!(2.0))),
831                        })),
832                    }),
833                    Expression::Infix(InfixExpression {
834                        left: ArcIntern::new(Expression::Prefix(PrefixExpression {
835                            operator: PrefixOperator::Minus,
836                            expression: ArcIntern::new(Expression::Number(real!(1.0))),
837                        })),
838                        operator: InfixOperator::Slash,
839                        right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
840                            function: crate::expression::ExpressionFunction::SquareRoot,
841                            expression: ArcIntern::new(Expression::Number(real!(2.0))),
842                        })),
843                    }),
844                ],
845            ]),
846        })]
847    );
848
849    make_test!(
850        gate_definition_with_params,
851        parse_instructions,
852        "DEFGATE RX(%theta):\n\tCOS(%theta/2), -i*SIN(%theta/2)\n\t-i*SIN(%theta/2), COS(%theta/2)\n",
853        vec![Instruction::GateDefinition(GateDefinition {
854            name: "RX".to_string(),
855            parameters: vec!["theta".to_string()],
856            specification: GateSpecification::Matrix(vec![
857                vec![
858                    Expression::FunctionCall(FunctionCallExpression {
859                        function: ExpressionFunction::Cosine,
860                        expression: ArcIntern::new(Expression::Infix(InfixExpression {
861                            left: ArcIntern::new(Expression::Variable("theta".to_string())),
862                            operator: InfixOperator::Slash,
863                            right: ArcIntern::new(Expression::Number(Complex { re: 2.0, im: 0.0 })),
864                        }))
865                    }),
866                    Expression::Infix(InfixExpression {
867                        left: ArcIntern::new(Expression::Prefix(PrefixExpression {
868                            operator: PrefixOperator::Minus,
869                            expression: ArcIntern::new(Expression::Number(Complex { re: 0.0, im: 1.0 })),
870                        })),
871                        operator: InfixOperator::Star,
872                        right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
873                            function: ExpressionFunction::Sine,
874                            expression: ArcIntern::new(Expression::Infix(InfixExpression {
875                                left: ArcIntern::new(Expression::Variable("theta".to_string())),
876                                operator: InfixOperator::Slash,
877                                right: ArcIntern::new(Expression::Number(Complex { re: 2.0, im: 0.0 })),
878                            }))
879                        }))
880                    }),
881                ],
882                vec![
883                    Expression::Infix(InfixExpression {
884                        left: ArcIntern::new(Expression::Prefix(PrefixExpression {
885                            operator: PrefixOperator::Minus,
886                            expression: ArcIntern::new(Expression::Number(Complex { re: 0.0, im: 1.0 }))
887                        })),
888                        operator: InfixOperator::Star,
889                        right: ArcIntern::new(Expression::FunctionCall(FunctionCallExpression {
890                            function: ExpressionFunction::Sine,
891                            expression: ArcIntern::new(Expression::Infix(InfixExpression {
892                                left: ArcIntern::new(Expression::Variable("theta".to_string())),
893                                operator: InfixOperator::Slash,
894                                right: ArcIntern::new(Expression::Number(Complex { re: 2.0, im: 0.0 }))
895                            }))
896                        }))
897                    }),
898                    Expression::FunctionCall(FunctionCallExpression {
899                        function: ExpressionFunction::Cosine,
900                        expression: ArcIntern::new(Expression::Infix(InfixExpression {
901                            left: ArcIntern::new(Expression::Variable("theta".to_string())),
902                            operator: InfixOperator::Slash,
903                            right: ArcIntern::new(Expression::Number(Complex { re: 2.0, im: 0.0 })),
904                        }))
905                    }),
906                ],
907            ]),
908        })]
909    );
910
911    make_test!(
912        convert,
913        parse_instructions,
914        "CONVERT theta unadjusted-theta[1]",
915        vec![Instruction::Convert(Convert {
916            destination: MemoryReference {
917                name: "theta".to_string(),
918                index: 0
919            },
920            source: MemoryReference {
921                name: "unadjusted-theta".to_string(),
922                index: 1
923            },
924        })]
925    );
926
927    make_test!(
928        include,
929        parse_instructions,
930        r#"INCLUDE "another/quil/file.quil""#,
931        vec![Instruction::Include(Include {
932            filename: "another/quil/file.quil".to_string()
933        })]
934    );
935
936    make_test!(nop, parse_instructions, r#"NOP"#, vec![Instruction::Nop()]);
937
938    #[test]
939    fn parse_set_phase() {
940        let input = LocatedSpan::new(r#"SET-PHASE 0 "rf" 1.0; SET-PHASE 0 1 "rf" theta"#);
941        let tokens = lex(input).unwrap();
942        let (remainder, parsed) = parse_instructions(&tokens).unwrap();
943        let expected = vec![
944            Instruction::SetPhase(SetPhase {
945                frame: FrameIdentifier {
946                    name: String::from("rf"),
947                    qubits: vec![Qubit::Fixed(0)],
948                },
949                phase: Expression::Number(real!(1.0)),
950            }),
951            Instruction::SetPhase(SetPhase {
952                frame: FrameIdentifier {
953                    name: String::from("rf"),
954                    qubits: vec![Qubit::Fixed(0), Qubit::Fixed(1)],
955                },
956                phase: Expression::Address(MemoryReference {
957                    name: String::from("theta"),
958                    index: 0,
959                }),
960            }),
961        ];
962        assert_eq!(parsed, expected);
963        assert_eq!(remainder.len(), 0);
964    }
965
966    #[test]
967    fn parse_swap_phases() {
968        let input =
969            LocatedSpan::new(r#"SWAP-PHASES 0 "rf" 1 "rf"; SWAP-PHASES 1 2 3 "rf" 4 5 6 "rf""#);
970        let tokens = lex(input).unwrap();
971        let (remainder, parsed) = parse_instructions(&tokens).unwrap();
972        let expected = vec![
973            Instruction::SwapPhases(SwapPhases {
974                frame_1: FrameIdentifier {
975                    name: String::from("rf"),
976                    qubits: vec![Qubit::Fixed(0)],
977                },
978                frame_2: FrameIdentifier {
979                    name: String::from("rf"),
980                    qubits: vec![Qubit::Fixed(1)],
981                },
982            }),
983            Instruction::SwapPhases(SwapPhases {
984                frame_1: FrameIdentifier {
985                    name: String::from("rf"),
986                    qubits: vec![Qubit::Fixed(1), Qubit::Fixed(2), Qubit::Fixed(3)],
987                },
988                frame_2: FrameIdentifier {
989                    name: String::from("rf"),
990                    qubits: vec![Qubit::Fixed(4), Qubit::Fixed(5), Qubit::Fixed(6)],
991                },
992            }),
993        ];
994        assert_eq!(parsed, expected);
995        assert_eq!(remainder.len(), 0);
996    }
997
998    #[test]
999    fn parse_set_scale() {
1000        let input = LocatedSpan::new(r#"SET-SCALE 0 "rf" 1.0; SET-SCALE 0 1 "rf" theta"#);
1001        let tokens = lex(input).unwrap();
1002        let (remainder, parsed) = parse_instructions(&tokens).unwrap();
1003        let expected = vec![
1004            Instruction::SetScale(SetScale {
1005                frame: FrameIdentifier {
1006                    name: String::from("rf"),
1007                    qubits: vec![Qubit::Fixed(0)],
1008                },
1009                scale: Expression::Number(real!(1.0)),
1010            }),
1011            Instruction::SetScale(SetScale {
1012                frame: FrameIdentifier {
1013                    name: String::from("rf"),
1014                    qubits: vec![Qubit::Fixed(0), Qubit::Fixed(1)],
1015                },
1016                scale: Expression::Address(MemoryReference {
1017                    name: String::from("theta"),
1018                    index: 0,
1019                }),
1020            }),
1021        ];
1022        assert_eq!(parsed, expected);
1023        assert_eq!(remainder.len(), 0);
1024    }
1025
1026    #[test]
1027    fn parse_set_frequency() {
1028        let input = LocatedSpan::new(r#"SET-FREQUENCY 0 "rf" 1.0; SET-FREQUENCY 0 1 "rf" theta"#);
1029        let tokens = lex(input).unwrap();
1030        let (remainder, parsed) = parse_instructions(&tokens).unwrap();
1031        let expected = vec![
1032            Instruction::SetFrequency(SetFrequency {
1033                frame: FrameIdentifier {
1034                    name: String::from("rf"),
1035                    qubits: vec![Qubit::Fixed(0)],
1036                },
1037                frequency: Expression::Number(real!(1.0)),
1038            }),
1039            Instruction::SetFrequency(SetFrequency {
1040                frame: FrameIdentifier {
1041                    name: String::from("rf"),
1042                    qubits: vec![Qubit::Fixed(0), Qubit::Fixed(1)],
1043                },
1044                frequency: Expression::Address(MemoryReference {
1045                    name: String::from("theta"),
1046                    index: 0,
1047                }),
1048            }),
1049        ];
1050        assert_eq!(parsed, expected);
1051        assert_eq!(remainder.len(), 0);
1052    }
1053
1054    #[test]
1055    fn parse_shift_frequency() {
1056        let input =
1057            LocatedSpan::new(r#"SHIFT-FREQUENCY 0 "rf" 1.0; SHIFT-FREQUENCY 0 1 "rf" theta"#);
1058        let tokens = lex(input).unwrap();
1059        let (remainder, parsed) = parse_instructions(&tokens).unwrap();
1060        let expected = vec![
1061            Instruction::ShiftFrequency(ShiftFrequency {
1062                frame: FrameIdentifier {
1063                    name: String::from("rf"),
1064                    qubits: vec![Qubit::Fixed(0)],
1065                },
1066                frequency: Expression::Number(real!(1.0)),
1067            }),
1068            Instruction::ShiftFrequency(ShiftFrequency {
1069                frame: FrameIdentifier {
1070                    name: String::from("rf"),
1071                    qubits: vec![Qubit::Fixed(0), Qubit::Fixed(1)],
1072                },
1073                frequency: Expression::Address(MemoryReference {
1074                    name: String::from("theta"),
1075                    index: 0,
1076                }),
1077            }),
1078        ];
1079        assert_eq!(parsed, expected);
1080        assert_eq!(remainder.len(), 0);
1081    }
1082
1083    #[test]
1084    fn parse_shift_phase() {
1085        let input = LocatedSpan::new(r#"SHIFT-PHASE 0 "rf" 1.0; SHIFT-PHASE 0 1 "rf" theta"#);
1086        let tokens = lex(input).unwrap();
1087        let (remainder, parsed) = parse_instructions(&tokens).unwrap();
1088        let expected = vec![
1089            Instruction::ShiftPhase(ShiftPhase {
1090                frame: FrameIdentifier {
1091                    name: String::from("rf"),
1092                    qubits: vec![Qubit::Fixed(0)],
1093                },
1094                phase: Expression::Number(real!(1.0)),
1095            }),
1096            Instruction::ShiftPhase(ShiftPhase {
1097                frame: FrameIdentifier {
1098                    name: String::from("rf"),
1099                    qubits: vec![Qubit::Fixed(0), Qubit::Fixed(1)],
1100                },
1101                phase: Expression::Address(MemoryReference {
1102                    name: String::from("theta"),
1103                    index: 0,
1104                }),
1105            }),
1106        ];
1107        assert_eq!(parsed, expected);
1108        assert_eq!(remainder.len(), 0);
1109    }
1110
1111    /// Test that an entire sample program can be parsed without failure.
1112    #[test]
1113    fn kitchen_sink() {
1114        Program::from_str(KITCHEN_SINK_QUIL).unwrap();
1115    }
1116
1117    /// Assert that when a program is converted to a string, the conversion of
1118    /// that string into a program produces a program identical to the original
1119    /// program.
1120    #[test]
1121    fn parse_roundtrip() {
1122        let inputs = vec![
1123            r#"DEFCAL MEASURE 0 dest:
1124	DECLARE iq REAL[2]
1125	CAPTURE 0 "out" flat(duration: 1.0, iqs: (2.0+3.0i)) iq[0]"#,
1126            r#"LABEL @target
1127JUMP @target"#,
1128        ];
1129
1130        for input in inputs {
1131            let program = Program::from_str(input).unwrap();
1132            let output = program.to_quil().unwrap();
1133            let roundtrip = Program::from_str(&output).unwrap();
1134            assert_eq!(output, roundtrip.to_quil().unwrap());
1135        }
1136    }
1137}