1use 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
37pub(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
128pub(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
138pub(crate) fn parse_block(input: ParserInput) -> InternalParserResult<Vec<Instruction>> {
140 many1(parse_block_instruction)(input)
141}
142
143pub(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]
1113 fn kitchen_sink() {
1114 Program::from_str(KITCHEN_SINK_QUIL).unwrap();
1115 }
1116
1117 #[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}