microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.29.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

source/compiler/qsc/src/interpret/tests.rs

2391lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4mod given_interpreter {
5 use crate::interpret::{InterpretResult, Interpreter};
6 use expect_test::Expect;
7 use miette::Diagnostic;
8 use qsc_data_structures::source::SourceMap;
9 use qsc_data_structures::{language_features::LanguageFeatures, target::TargetCapabilityFlags};
10 use qsc_eval::{output::CursorReceiver, val::Value};
11 use qsc_passes::PackageType;
12 use std::{fmt::Write, io::Cursor, iter, str::from_utf8};
13
14 fn line(interpreter: &mut Interpreter, line: &str) -> (InterpretResult, String) {
15 let mut cursor = Cursor::new(Vec::<u8>::new());
16 let mut receiver = CursorReceiver::new(&mut cursor);
17 (
18 interpreter.eval_fragments(&mut receiver, line),
19 receiver.dump(),
20 )
21 }
22
23 fn run(interpreter: &mut Interpreter, expr: &str) -> (InterpretResult, String) {
24 let mut cursor = Cursor::new(Vec::<u8>::new());
25 let mut receiver = CursorReceiver::new(&mut cursor);
26 let res = interpreter.run(
27 &mut receiver,
28 Some(expr),
29 None,
30 None,
31 None,
32 None,
33 Default::default(),
34 );
35 (res, receiver.dump())
36 }
37
38 fn entry(interpreter: &mut Interpreter) -> (InterpretResult, String) {
39 let mut cursor = Cursor::new(Vec::<u8>::new());
40 let mut receiver = CursorReceiver::new(&mut cursor);
41 (interpreter.eval_entry(&mut receiver), receiver.dump())
42 }
43
44 fn fragment(
45 interpreter: &mut Interpreter,
46 fragments: &str,
47 package: crate::ast::Package,
48 ) -> (InterpretResult, String) {
49 let mut cursor = Cursor::new(Vec::<u8>::new());
50 let mut receiver = CursorReceiver::new(&mut cursor);
51 let result = interpreter.eval_ast_fragments(&mut receiver, fragments, package);
52 (result, receiver.dump())
53 }
54
55 fn invoke(
56 interpreter: &mut Interpreter,
57 callable: &str,
58 args: Value,
59 ) -> (InterpretResult, String) {
60 let mut cursor = Cursor::new(Vec::<u8>::new());
61 let mut receiver = CursorReceiver::new(&mut cursor);
62 let callable = match interpreter.eval_fragments(&mut receiver, callable) {
63 Ok(val) => val,
64 Err(e) => return (Err(e), receiver.dump()),
65 };
66 let result = interpreter.invoke(&mut receiver, callable, args);
67 (result, receiver.dump())
68 }
69
70 mod without_sources {
71 use std::rc::Rc;
72
73 use expect_test::expect;
74 use indoc::indoc;
75
76 use super::*;
77
78 mod without_stdlib {
79 use qsc_data_structures::source::SourceMap;
80 use qsc_passes::PackageType;
81
82 use super::*;
83
84 #[test]
85 fn stdlib_members_should_be_unavailable() {
86 let store = crate::PackageStore::new(crate::compile::core());
87 let mut interpreter = Interpreter::new(
88 SourceMap::default(),
89 PackageType::Lib,
90 TargetCapabilityFlags::all(),
91 LanguageFeatures::default(),
92 store,
93 &[],
94 )
95 .expect("interpreter should be created");
96
97 let (result, output) = line(&mut interpreter, "Message(\"_\")");
98 is_only_error(
99 &result,
100 &output,
101 &expect![[r#"
102 name error: `Message` not found
103 [line_0] [Message]
104 "#]],
105 );
106 }
107 }
108
109 #[test]
110 fn stdlib_members_should_be_available() {
111 let mut interpreter = get_interpreter();
112 let (result, output) = line(&mut interpreter, "Message(\"_\")");
113 is_unit_with_output(&result, &output, "_");
114 }
115
116 #[test]
117 fn core_members_should_be_available() {
118 let mut interpreter = get_interpreter();
119 let (result, output) = line(&mut interpreter, "Length([1, 2, 3])");
120 is_only_value(&result, &output, &Value::Int(3));
121 }
122
123 #[test]
124 fn let_bindings_update_interpreter() {
125 let mut interpreter = get_interpreter();
126 line(&mut interpreter, "let y = 7;")
127 .0
128 .expect("line should succeed");
129 let (result, output) = line(&mut interpreter, "y");
130 is_only_value(&result, &output, &Value::Int(7));
131 }
132
133 #[test]
134 fn let_bindings_can_be_shadowed() {
135 let mut interpreter = get_interpreter();
136
137 let (result, output) = line(&mut interpreter, "let y = 7;");
138 is_only_value(&result, &output, &Value::unit());
139
140 let (result, output) = line(&mut interpreter, "y");
141 is_only_value(&result, &output, &Value::Int(7));
142
143 let (result, output) = line(&mut interpreter, "let y = \"Hello\";");
144 is_only_value(&result, &output, &Value::unit());
145
146 let (result, output) = line(&mut interpreter, "y");
147 is_only_value(&result, &output, &Value::String("Hello".into()));
148 }
149
150 #[test]
151 fn invalid_statements_return_error() {
152 let mut interpreter = get_interpreter();
153
154 let (result, output) = line(&mut interpreter, "let y = 7");
155 is_only_error(
156 &result,
157 &output,
158 &expect![[r#"
159 syntax error: expected `;`, found EOF
160 [line_0] []
161 "#]],
162 );
163
164 let (result, output) = line(&mut interpreter, "y");
165 is_only_error(
166 &result,
167 &output,
168 &expect![[r#"
169 name error: `y` not found
170 [line_1] [y]
171 "#]],
172 );
173 }
174
175 #[test]
176 fn invalid_statements_and_unbound_vars_return_error_on_immutable_usage() {
177 let mut interpreter = get_interpreter();
178
179 let (result, output) = line(&mut interpreter, "let y = x;");
180 is_only_error(
181 &result,
182 &output,
183 &expect![[r#"
184 name error: `x` not found
185 [line_0] [x]
186 type error: insufficient type information to infer type
187 [line_0] [y]
188 "#]],
189 );
190
191 let (result, output) = line(&mut interpreter, "y");
192 is_only_error(
193 &result,
194 &output,
195 &expect![[r#"
196 runtime error: name is not bound
197 [line_1] [y]
198 "#]],
199 );
200 }
201
202 #[test]
203 fn invalid_statements_and_unbound_vars_return_error_on_mutable_update() {
204 let mut interpreter = get_interpreter();
205
206 let (result, output) = line(&mut interpreter, "mutable y = x;");
207 is_only_error(
208 &result,
209 &output,
210 &expect![[r#"
211 name error: `x` not found
212 [line_0] [x]
213 type error: insufficient type information to infer type
214 [line_0] [y]
215 "#]],
216 );
217
218 let (result, output) = line(&mut interpreter, "y = 3");
219 is_only_error(
220 &result,
221 &output,
222 &expect![[r#"
223 cannot update immutable variable
224 [line_1] [y]
225 "#]],
226 );
227 }
228
229 #[test]
230 fn invalid_statements_and_unbound_vars_return_error_on_immutable_usage_with_rca() {
231 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
232
233 let (result, output) = line(&mut interpreter, "let y = x;");
234 is_only_error(
235 &result,
236 &output,
237 &expect![[r#"
238 name error: `x` not found
239 [line_0] [x]
240 type error: insufficient type information to infer type
241 [line_0] [y]
242 "#]],
243 );
244
245 let (result, output) = line(&mut interpreter, "y");
246 is_only_error(
247 &result,
248 &output,
249 &expect![[r#"
250 runtime error: name is not bound
251 [line_1] [y]
252 "#]],
253 );
254 }
255
256 #[test]
257 fn invalid_statements_and_unbound_vars_return_error_on_mutable_update_with_rca() {
258 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
259
260 let (result, output) = line(&mut interpreter, "mutable y = x;");
261 is_only_error(
262 &result,
263 &output,
264 &expect![[r#"
265 name error: `x` not found
266 [line_0] [x]
267 type error: insufficient type information to infer type
268 [line_0] [y]
269 "#]],
270 );
271
272 let (result, output) = line(&mut interpreter, "y = 3");
273 is_only_error(
274 &result,
275 &output,
276 &expect![[r#"
277 cannot update immutable variable
278 [line_1] [y]
279 "#]],
280 );
281 }
282
283 #[test]
284 fn failing_statements_return_early_error() {
285 let mut interpreter = get_interpreter();
286 let (result, output) = line(&mut interpreter, "let y = 7;y/0;y");
287 is_only_error(
288 &result,
289 &output,
290 &expect![[r#"
291 runtime error: division by zero
292 cannot divide by zero [line_0] [0]
293 "#]],
294 );
295 }
296
297 #[test]
298 fn passes_are_run_on_incremental() {
299 let mut interpreter = get_interpreter();
300 let (result, output) = line(
301 &mut interpreter,
302 "within {Message(\"A\");} apply {Message(\"B\");}",
303 );
304 is_unit_with_output(&result, &output, "A\nB\nA");
305 }
306
307 #[test]
308 fn declare_function() {
309 let mut interpreter = get_interpreter();
310 let (result, output) = line(&mut interpreter, "function Foo() : Int { 2 }");
311 is_only_value(&result, &output, &Value::unit());
312 let (result, output) = line(&mut interpreter, "Foo()");
313 is_only_value(&result, &output, &Value::Int(2));
314 }
315
316 #[test]
317 fn invalid_declare_function_and_unbound_call_return_error() {
318 let mut interpreter = get_interpreter();
319 let (result, output) = line(&mut interpreter, "function Foo() : Int { invalid }");
320 is_only_error(
321 &result,
322 &output,
323 &expect![[r#"
324 name error: `invalid` not found
325 [line_0] [invalid]
326 "#]],
327 );
328 let (result, output) = line(&mut interpreter, "Foo()");
329 is_only_error(
330 &result,
331 &output,
332 &expect![[r#"
333 runtime error: name is not bound
334 [line_1] [Foo]
335 "#]],
336 );
337 }
338
339 #[test]
340 fn declare_function_call_same_line() {
341 let mut interpreter = get_interpreter();
342 let (result, output) = line(&mut interpreter, "function Foo() : Int { 2 }; Foo()");
343 is_only_value(&result, &output, &Value::Int(2));
344 }
345
346 #[test]
347 fn let_binding_function_declaration_call_same_line() {
348 let mut interpreter = get_interpreter();
349 let (result, output) = line(
350 &mut interpreter,
351 "let x = 1; function Foo() : Int { 2 }; Foo() + 1",
352 );
353 is_only_value(&result, &output, &Value::Int(3));
354 }
355
356 #[test]
357 fn nested_function() {
358 let mut interpreter = get_interpreter();
359 let (result, output) = line(
360 &mut interpreter,
361 "function Foo() : Int { function Bar() : Int { 1 }; Bar() + 1 }; Foo() + 1",
362 );
363 is_only_value(&result, &output, &Value::Int(3));
364 }
365
366 #[test]
367 fn open_namespace() {
368 let mut interpreter = get_interpreter();
369 let (result, output) = line(&mut interpreter, "import Std.Diagnostics.*;");
370 is_only_value(&result, &output, &Value::unit());
371 let (result, output) = line(&mut interpreter, "DumpMachine()");
372 is_unit_with_output(&result, &output, "STATE:\nNo qubits allocated");
373 }
374
375 #[test]
376 fn open_namespace_call_same_line() {
377 let mut interpreter = get_interpreter();
378 let (result, output) = line(
379 &mut interpreter,
380 "open Microsoft.Quantum.Diagnostics; DumpMachine()",
381 );
382 is_unit_with_output(&result, &output, "STATE:\nNo qubits allocated");
383 }
384
385 #[test]
386 fn declare_namespace_call() {
387 let mut interpreter = get_interpreter();
388 let (result, output) = line(
389 &mut interpreter,
390 "namespace Foo { function Bar() : Int { 5 } }",
391 );
392 is_only_value(&result, &output, &Value::unit());
393 let (result, output) = line(&mut interpreter, "Foo.Bar()");
394 is_only_value(&result, &output, &Value::Int(5));
395 }
396
397 #[test]
398 fn declare_namespace_open_call() {
399 let mut interpreter = get_interpreter();
400 let (result, output) = line(
401 &mut interpreter,
402 "namespace Foo { function Bar() : Int { 5 } }",
403 );
404 is_only_value(&result, &output, &Value::unit());
405 let (result, output) = line(&mut interpreter, "open Foo;");
406 is_only_value(&result, &output, &Value::unit());
407 let (result, output) = line(&mut interpreter, "Bar()");
408 is_only_value(&result, &output, &Value::Int(5));
409 }
410
411 #[test]
412 fn declare_namespace_open_call_same_line() {
413 let mut interpreter = get_interpreter();
414 let (result, output) = line(
415 &mut interpreter,
416 "namespace Foo { function Bar() : Int { 5 } } open Foo; Bar()",
417 );
418 is_only_value(&result, &output, &Value::Int(5));
419 }
420
421 #[test]
422 fn mix_stmts_and_namespace_same_line() {
423 let mut interpreter = get_interpreter();
424 let (result, output) = line(
425 &mut interpreter,
426 "Message(\"before\"); namespace Foo { function Bar() : Int { 5 } } Message(\"after\")",
427 );
428 is_unit_with_output(&result, &output, "before\nafter");
429 }
430
431 #[test]
432 fn assign_array_index_expr_eval_in_order() {
433 let mut interpreter = get_interpreter();
434 let (result, output) = line(
435 &mut interpreter,
436 "mutable arr = [[[0, 1], [2, 3]], [[4, 5], [6, 7]]];",
437 );
438 is_only_value(&result, &output, &Value::unit());
439 let (result, output) = line(
440 &mut interpreter,
441 "arr[{ Message(\"First Index\"); 0 }][{ Message(\"Second Index\"); 1 }][{ Message(\"Third Index\"); 1 }] = 13;",
442 );
443 is_unit_with_output(&result, &output, "First Index\nSecond Index\nThird Index");
444 let (result, output) = line(&mut interpreter, "arr");
445 is_only_value(
446 &result,
447 &output,
448 &Value::Array(Rc::new(vec![
449 Value::Array(Rc::new(vec![
450 Value::Array(Rc::new(vec![Value::Int(0), Value::Int(1)])),
451 Value::Array(Rc::new(vec![Value::Int(2), Value::Int(13)])),
452 ])),
453 Value::Array(Rc::new(vec![
454 Value::Array(Rc::new(vec![Value::Int(4), Value::Int(5)])),
455 Value::Array(Rc::new(vec![Value::Int(6), Value::Int(7)])),
456 ])),
457 ])),
458 );
459 }
460
461 #[test]
462 fn global_qubits() {
463 let mut interpreter = get_interpreter();
464 let (result, output) = line(&mut interpreter, "import Std.Diagnostics.*;");
465 is_only_value(&result, &output, &Value::unit());
466 let (result, output) = line(&mut interpreter, "DumpMachine()");
467 is_unit_with_output(&result, &output, "STATE:\nNo qubits allocated");
468 let (result, output) = line(&mut interpreter, "use (q0, qs) = (Qubit(), Qubit[3]);");
469 is_only_value(&result, &output, &Value::unit());
470 let (result, output) = line(&mut interpreter, "DumpMachine()");
471 is_unit_with_output(&result, &output, "STATE:\n|0000⟩: 1+0i");
472 let (result, output) = line(&mut interpreter, "X(q0); X(qs[1]);");
473 is_only_value(&result, &output, &Value::unit());
474 let (result, output) = line(&mut interpreter, "DumpMachine()");
475 is_unit_with_output(&result, &output, "STATE:\n|1010⟩: 1+0i");
476 }
477
478 #[test]
479 fn ambiguous_type_error_in_top_level_stmts() {
480 let mut interpreter = get_interpreter();
481 let (result, output) = line(&mut interpreter, "let x = [];");
482 is_only_error(
483 &result,
484 &output,
485 &expect![[r#"
486 type error: insufficient type information to infer type
487 [line_0] [[]]
488 "#]],
489 );
490 let (result, output) = line(&mut interpreter, "let x = []; let y = [0] + x;");
491 is_only_value(&result, &output, &Value::unit());
492 let (result, output) = line(&mut interpreter, "function Foo() : Unit { let x = []; }");
493 is_only_error(
494 &result,
495 &output,
496 &expect![[r#"
497 type error: insufficient type information to infer type
498 [line_2] [[]]
499 "#]],
500 );
501 }
502
503 #[test]
504 fn resolved_type_persists_across_stmts() {
505 let mut interpreter = get_interpreter();
506 let (result, output) = line(&mut interpreter, "let x = []; let y = [0] + x;");
507 is_only_value(&result, &output, &Value::unit());
508 let (result, output) = line(&mut interpreter, "let z = [0.0] + x;");
509 is_only_error(
510 &result,
511 &output,
512 &expect![[r#"
513 type error: expected Double, found Int
514 [line_1] [x]
515 "#]],
516 );
517 }
518
519 #[test]
520 fn incremental_lambas_work() {
521 let mut interpreter = get_interpreter();
522 let (result, output) = line(&mut interpreter, "let x = 1; let f = (y) -> x + y;");
523 is_only_value(&result, &output, &Value::unit());
524 let (result, output) = line(&mut interpreter, "f(1)");
525 is_only_value(&result, &output, &Value::Int(2));
526 }
527
528 #[test]
529 fn mutability_persists_across_stmts() {
530 let mut interpreter = get_interpreter();
531 let (result, output) = line(
532 &mut interpreter,
533 "mutable x : Int[] = []; let y : Int[] = [];",
534 );
535 is_only_value(&result, &output, &Value::unit());
536 let (result, output) = line(&mut interpreter, "set x += [0];");
537 is_only_value(&result, &output, &Value::unit());
538 let (result, output) = line(&mut interpreter, "set y += [0];");
539 is_only_error(
540 &result,
541 &output,
542 &expect![[r#"
543 cannot update immutable variable
544 [line_2] [y]
545 "#]],
546 );
547 let (result, output) = line(&mut interpreter, "let lam = () -> y + [0];");
548 is_only_value(&result, &output, &Value::unit());
549 let (result, output) = line(&mut interpreter, "let lam = () -> x + [0];");
550 is_only_error(
551 &result,
552 &output,
553 &expect![[r#"
554 lambdas cannot close over mutable variables
555 [line_4] [() -> x + [0]]
556 "#]],
557 );
558 }
559
560 #[test]
561 fn runtime_error_across_lines() {
562 let mut interpreter = get_interpreter();
563 let (result, output) = line(
564 &mut interpreter,
565 "operation Main() : Unit { Microsoft.Quantum.Random.DrawRandomInt(2,1); }",
566 );
567 is_only_value(&result, &output, &Value::unit());
568 let (result, output) = line(&mut interpreter, "Main()");
569 is_only_error(
570 &result,
571 &output,
572 &expect![[r#"
573 runtime error: empty range
574 the range cannot be empty [line_0] [(2,1)]
575 "#]],
576 );
577 }
578
579 #[test]
580 fn compiler_error_across_lines() {
581 let mut interpreter = get_interpreter();
582 let (result, output) = line(
583 &mut interpreter,
584 "namespace Other { operation DumpMachine() : Unit { } }",
585 );
586 is_only_value(&result, &output, &Value::unit());
587 let (result, output) = line(&mut interpreter, "open Other;");
588 is_only_value(&result, &output, &Value::unit());
589 let (result, output) = line(&mut interpreter, "import Std.Diagnostics.*;");
590 is_only_value(&result, &output, &Value::unit());
591 let (result, output) = line(&mut interpreter, "DumpMachine();");
592 is_only_error(
593 &result,
594 &output,
595 &expect![[r#"
596 name error: `DumpMachine` could refer to the item in `Other` or `Std.Diagnostics`
597 ambiguous name [line_3] [DumpMachine]
598 found in this namespace [line_1] [Other]
599 and also in this namespace [line_2] [Std.Diagnostics]
600 "#]],
601 );
602 }
603
604 #[test]
605 fn runtime_error_from_stdlib() {
606 let mut interpreter = get_interpreter();
607 let (result, output) = line(&mut interpreter, "use q = Qubit(); CNOT(q,q)");
608 is_only_error(
609 &result,
610 &output,
611 &expect![[r#"
612 runtime error: qubits in invocation are not unique
613 [qsharp-library-source:Std/Intrinsic.qs] [(control, target)]
614 "#]],
615 );
616 }
617
618 #[test]
619 fn items_usable_before_definition() {
620 let mut interpreter = get_interpreter();
621 let (result, output) = line(
622 &mut interpreter,
623 indoc! {r#"
624 function A() : Unit {
625 B();
626 }
627 function B() : Unit {}
628 A()
629 "#},
630 );
631 is_only_value(&result, &output, &Value::unit());
632 }
633
634 #[test]
635 fn items_usable_before_definition_top_level() {
636 let mut interpreter = get_interpreter();
637 let (result, output) = line(
638 &mut interpreter,
639 indoc! {r#"
640 B();
641 function B() : Unit {}
642 "#},
643 );
644 is_only_value(&result, &output, &Value::unit());
645 }
646
647 #[test]
648 fn interpreter_without_sources_has_no_items() {
649 let interpreter = get_interpreter();
650 let items = interpreter.source_globals();
651 assert!(items.is_empty());
652 }
653
654 #[test]
655 fn fragment_without_items_has_no_items() {
656 let mut interpreter = get_interpreter();
657 let (result, output) = line(&mut interpreter, "()");
658 is_only_value(&result, &output, &Value::unit());
659 let items = interpreter.user_globals();
660 assert!(items.is_empty());
661 }
662
663 #[test]
664 fn fragment_defining_items_has_items() {
665 let mut interpreter = get_interpreter();
666 let (result, output) = line(
667 &mut interpreter,
668 indoc! {r#"
669 function Foo() : Int { 2 }
670 function Bar() : Int { 3 }
671 "#},
672 );
673 is_only_value(&result, &output, &Value::unit());
674 let items = interpreter.user_globals();
675 assert_eq!(items.len(), 2);
676 // No namespace for top-level items
677 assert!(items[0].0.is_empty());
678 expect![[r#"
679 "Foo"
680 "#]]
681 .assert_debug_eq(&items[0].1);
682 // No namespace for top-level items
683 assert!(items[1].0.is_empty());
684 expect![[r#"
685 "Bar"
686 "#]]
687 .assert_debug_eq(&items[1].1);
688 }
689
690 #[test]
691 fn fragment_defining_items_with_namespace_has_items() {
692 let mut interpreter = get_interpreter();
693 let (result, output) = line(
694 &mut interpreter,
695 indoc! {r#"
696 namespace Foo {
697 function Bar() : Int { 3 }
698 }
699 "#},
700 );
701 is_only_value(&result, &output, &Value::unit());
702 let items = interpreter.user_globals();
703 assert_eq!(items.len(), 1);
704 expect![[r#"
705 [
706 "Foo",
707 ]
708 "#]]
709 .assert_debug_eq(&items[0].0);
710 expect![[r#"
711 "Bar"
712 "#]]
713 .assert_debug_eq(&items[0].1);
714 }
715
716 #[test]
717 fn fragments_defining_items_add_to_existing_items() {
718 let mut interpreter = get_interpreter();
719 let (result, output) = line(
720 &mut interpreter,
721 indoc! {r#"
722 function Foo() : Int { 2 }
723 function Bar() : Int { 3 }
724 "#},
725 );
726 is_only_value(&result, &output, &Value::unit());
727 let items = interpreter.user_globals();
728 assert_eq!(items.len(), 2);
729 let (result, output) = line(
730 &mut interpreter,
731 indoc! {r#"
732 function Baz() : Int { 4 }
733 function Qux() : Int { 5 }
734 "#},
735 );
736 is_only_value(&result, &output, &Value::unit());
737 let items = interpreter.user_globals();
738 assert_eq!(items.len(), 4);
739 // No namespace for top-level items
740 assert!(items[0].0.is_empty());
741 expect![[r#"
742 "Foo"
743 "#]]
744 .assert_debug_eq(&items[0].1);
745 // No namespace for top-level items
746 assert!(items[1].0.is_empty());
747 expect![[r#"
748 "Bar"
749 "#]]
750 .assert_debug_eq(&items[1].1);
751 // No namespace for top-level items
752 assert!(items[2].0.is_empty());
753 expect![[r#"
754 "Baz"
755 "#]]
756 .assert_debug_eq(&items[2].1);
757 // No namespace for top-level items
758 assert!(items[3].0.is_empty());
759 expect![[r#"
760 "Qux"
761 "#]]
762 .assert_debug_eq(&items[3].1);
763 }
764
765 #[test]
766 fn invoke_callable_without_args_succeeds() {
767 let mut interpreter = get_interpreter();
768 let (result, output) = invoke(
769 &mut interpreter,
770 "Std.Diagnostics.DumpMachine",
771 Value::unit(),
772 );
773 is_unit_with_output(&result, &output, "STATE:\nNo qubits allocated");
774 }
775
776 #[test]
777 fn invoke_callable_with_args_succeeds() {
778 let mut interpreter = get_interpreter();
779 let (result, output) = invoke(
780 &mut interpreter,
781 "Message",
782 Value::String("Hello, World!".into()),
783 );
784 is_unit_with_output(&result, &output, "Hello, World!");
785 }
786
787 #[test]
788 fn invoke_lambda_with_capture_succeeds() {
789 let mut interpreter = get_interpreter();
790 let (result, output) = line(&mut interpreter, "let x = 1; let f = y -> x + y;");
791 is_only_value(&result, &output, &Value::unit());
792 let (result, output) = invoke(&mut interpreter, "f", Value::Int(2));
793 is_only_value(&result, &output, &Value::Int(3));
794 }
795
796 #[test]
797 fn invoke_lambda_with_capture_in_callable_expr_succeeds() {
798 let mut interpreter = get_interpreter();
799 let (result, output) = invoke(
800 &mut interpreter,
801 "{let x = 1; let f = y -> x + y; f}",
802 Value::Int(2),
803 );
804 is_only_value(&result, &output, &Value::Int(3));
805 }
806
807 #[test]
808 fn callables_failing_profile_validation_are_not_registered() {
809 let mut interpreter =
810 get_interpreter_with_capabilities(TargetCapabilityFlags::Adaptive);
811 let (result, output) = line(
812 &mut interpreter,
813 indoc! {r#"
814 operation Foo() : Int { use q = Qubit(); mutable x = 1; if MResetZ(q) == One { set x = 2; } x }
815 "#},
816 );
817 is_only_error(
818 &result,
819 &output,
820 &expect![[r#"
821 cannot use a dynamic integer value
822 [line_0] [set x = 2]
823 cannot use a dynamic integer value
824 [line_0] [x]
825 "#]],
826 );
827 // do something innocuous
828 let (result, output) = line(&mut interpreter, indoc! {r#"Foo()"#});
829 // since the callable wasn't registered, this will return an unbound name error.
830 is_only_error(
831 &result,
832 &output,
833 &expect![[r#"
834 runtime error: name is not bound
835 [line_1] [Foo]
836 "#]],
837 );
838 }
839
840 #[test]
841 fn callables_failing_profile_validation_also_fail_qir_generation() {
842 let mut interpreter =
843 get_interpreter_with_capabilities(TargetCapabilityFlags::Adaptive);
844 let (result, output) = line(
845 &mut interpreter,
846 indoc! {r#"
847 operation Foo() : Int { use q = Qubit(); mutable x = 1; if MResetZ(q) == One { set x = 2; } x }
848 "#},
849 );
850 is_only_error(
851 &result,
852 &output,
853 &expect![[r#"
854 cannot use a dynamic integer value
855 [line_0] [set x = 2]
856 cannot use a dynamic integer value
857 [line_0] [x]
858 "#]],
859 );
860 let res = interpreter.qirgen("{Foo();}");
861 expect![[r#"
862 Err(
863 [
864 PartialEvaluation(
865 WithSource {
866 sources: [
867 Source {
868 name: "<entry>",
869 contents: "{Foo();}",
870 offset: 97,
871 },
872 ],
873 error: EvaluationFailed(
874 "name is not bound",
875 PackageSpan {
876 package: PackageId(
877 3,
878 ),
879 span: Span {
880 lo: 98,
881 hi: 101,
882 },
883 },
884 ),
885 },
886 ),
887 ],
888 )
889 "#]]
890 .assert_debug_eq(&res);
891 }
892
893 #[test]
894 fn once_rca_validation_fails_following_calls_do_not_fail() {
895 let mut interpreter =
896 get_interpreter_with_capabilities(TargetCapabilityFlags::Adaptive);
897 let (result, output) = line(
898 &mut interpreter,
899 indoc! {r#"
900 operation Foo() : Int { use q = Qubit(); mutable x = 1; if MResetZ(q) == One { set x = 2; } x }
901 "#},
902 );
903 is_only_error(
904 &result,
905 &output,
906 &expect![[r#"
907 cannot use a dynamic integer value
908 [line_0] [set x = 2]
909 cannot use a dynamic integer value
910 [line_0] [x]
911 "#]],
912 );
913 // do something innocuous
914 let (result, output) = line(
915 &mut interpreter,
916 indoc! {r#"
917 let y = 7;
918 "#},
919 );
920 is_only_value(&result, &output, &Value::unit());
921 }
922
923 #[test]
924 fn namespace_usable_before_definition() {
925 let mut interpreter = get_interpreter();
926 let (result, output) = line(
927 &mut interpreter,
928 indoc! {r#"
929 A.B();
930 namespace A {
931 function B() : Unit {}
932 }
933 "#},
934 );
935 is_only_value(&result, &output, &Value::unit());
936 }
937
938 #[test]
939 fn mutually_recursive_namespaces_work() {
940 let mut interpreter = get_interpreter();
941 let (result, output) = line(
942 &mut interpreter,
943 indoc! {r#"
944 A.B();
945 namespace A {
946 open C;
947 function B() : Unit {
948 D();
949 }
950 function E() : Unit {}
951 }
952 namespace C {
953 open A;
954 function D() : Unit {
955 E();
956 }
957 }
958 "#},
959 );
960 is_only_value(&result, &output, &Value::unit());
961 }
962
963 #[test]
964 fn local_var_valid_after_item_definition() {
965 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
966 let (result, output) = line(&mut interpreter, "let a = 1;");
967 is_only_value(&result, &output, &Value::unit());
968 let (result, output) = line(&mut interpreter, "a");
969 is_only_value(&result, &output, &Value::Int(1));
970 let (result, output) = line(
971 &mut interpreter,
972 "function B() : Int { let inner_b = 3; inner_b }",
973 );
974 is_only_value(&result, &output, &Value::unit());
975 let (result, output) = line(&mut interpreter, "B()");
976 is_only_value(&result, &output, &Value::Int(3));
977 let (result, output) = line(&mut interpreter, "let b = 2;");
978 is_only_value(&result, &output, &Value::unit());
979 let (result, output) = line(&mut interpreter, "b");
980 is_only_value(&result, &output, &Value::Int(2));
981 let (result, output) = line(&mut interpreter, "a");
982 is_only_value(&result, &output, &Value::Int(1));
983 let (result, output) = line(&mut interpreter, "B()");
984 is_only_value(&result, &output, &Value::Int(3));
985 }
986
987 #[test]
988 fn base_qirgen() {
989 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
990 let (result, output) = line(
991 &mut interpreter,
992 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
993 );
994 is_only_value(&result, &output, &Value::unit());
995 let res = interpreter.qirgen("Foo()").expect("expected success");
996 expect![[r#"
997 %Result = type opaque
998 %Qubit = type opaque
999
1000 @0 = internal constant [4 x i8] c"0_r\00"
1001
1002 define i64 @ENTRYPOINT__main() #0 {
1003 block_0:
1004 call void @__quantum__rt__initialize(i8* null)
1005 call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
1006 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1007 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i64 0, i64 0))
1008 ret i64 0
1009 }
1010
1011 declare void @__quantum__rt__initialize(i8*)
1012
1013 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
1014
1015 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1016
1017 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
1018
1019 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
1020 attributes #1 = { "irreversible" }
1021
1022 ; module flags
1023
1024 !llvm.module.flags = !{!0, !1, !2, !3}
1025
1026 !0 = !{i32 1, !"qir_major_version", i32 1}
1027 !1 = !{i32 7, !"qir_minor_version", i32 0}
1028 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1029 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1030 "#]].assert_eq(&res);
1031 }
1032
1033 #[test]
1034 fn adaptive_qirgen() {
1035 let mut interpreter = get_interpreter_with_capabilities(
1036 TargetCapabilityFlags::Adaptive | TargetCapabilityFlags::IntegerComputations,
1037 );
1038 let (result, output) = line(
1039 &mut interpreter,
1040 indoc! {r#"
1041 namespace Test {
1042 import Std.Math.*;
1043 open QIR.Intrinsic;
1044 @EntryPoint()
1045 operation Main() : Result {
1046 use q = Qubit();
1047 let pi_over_2 = 4.0 / 2.0;
1048 __quantum__qis__rz__body(pi_over_2, q);
1049 mutable some_angle = ArcSin(0.0);
1050 __quantum__qis__rz__body(some_angle, q);
1051 set some_angle = ArcCos(-1.0) / PI();
1052 __quantum__qis__rz__body(some_angle, q);
1053 __quantum__qis__mresetz__body(q)
1054 }
1055 }"#
1056 },
1057 );
1058 is_only_value(&result, &output, &Value::unit());
1059 let res = interpreter.qirgen("Test.Main()").expect("expected success");
1060 expect![[r#"
1061 %Result = type opaque
1062 %Qubit = type opaque
1063
1064 @0 = internal constant [4 x i8] c"0_r\00"
1065
1066 define i64 @ENTRYPOINT__main() #0 {
1067 block_0:
1068 call void @__quantum__rt__initialize(i8* null)
1069 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
1070 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
1071 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
1072 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1073 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i64 0, i64 0))
1074 ret i64 0
1075 }
1076
1077 declare void @__quantum__rt__initialize(i8*)
1078
1079 declare void @__quantum__qis__rz__body(double, %Qubit*)
1080
1081 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1082
1083 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1084
1085 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1086 attributes #1 = { "irreversible" }
1087
1088 ; module flags
1089
1090 !llvm.module.flags = !{!0, !1, !2, !3, !4}
1091
1092 !0 = !{i32 1, !"qir_major_version", i32 1}
1093 !1 = !{i32 7, !"qir_minor_version", i32 0}
1094 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1095 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1096 !4 = !{i32 5, !"int_computations", !{!"i64"}}
1097 "#]]
1098 .assert_eq(&res);
1099 }
1100
1101 #[test]
1102 fn adaptive_qirgen_nested_output_types() {
1103 let mut interpreter =
1104 get_interpreter_with_capabilities(TargetCapabilityFlags::Adaptive);
1105 let (result, output) = line(
1106 &mut interpreter,
1107 indoc! {r#"
1108 namespace Test {
1109 open QIR.Intrinsic;
1110 @EntryPoint()
1111 operation Main() : (Result, (Bool, Bool)) {
1112 use q = Qubit();
1113 let r = __quantum__qis__mresetz__body(q);
1114 (r, (r == One, r == Zero))
1115 }
1116 }"#
1117 },
1118 );
1119 is_only_value(&result, &output, &Value::unit());
1120 let res = interpreter.qirgen("Test.Main()").expect("expected success");
1121 expect![[r#"
1122 %Result = type opaque
1123 %Qubit = type opaque
1124
1125 @0 = internal constant [4 x i8] c"0_t\00"
1126 @1 = internal constant [6 x i8] c"1_t0r\00"
1127 @2 = internal constant [6 x i8] c"2_t1t\00"
1128 @3 = internal constant [8 x i8] c"3_t1t0b\00"
1129 @4 = internal constant [8 x i8] c"4_t1t1b\00"
1130
1131 define i64 @ENTRYPOINT__main() #0 {
1132 block_0:
1133 call void @__quantum__rt__initialize(i8* null)
1134 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1135 %var_0 = call i1 @__quantum__rt__read_result(%Result* inttoptr (i64 0 to %Result*))
1136 %var_2 = call i1 @__quantum__rt__read_result(%Result* inttoptr (i64 0 to %Result*))
1137 %var_3 = icmp eq i1 %var_2, false
1138 call void @__quantum__rt__tuple_record_output(i64 2, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i64 0, i64 0))
1139 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @1, i64 0, i64 0))
1140 call void @__quantum__rt__tuple_record_output(i64 2, i8* getelementptr inbounds ([6 x i8], [6 x i8]* @2, i64 0, i64 0))
1141 call void @__quantum__rt__bool_record_output(i1 %var_0, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @3, i64 0, i64 0))
1142 call void @__quantum__rt__bool_record_output(i1 %var_3, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @4, i64 0, i64 0))
1143 ret i64 0
1144 }
1145
1146 declare void @__quantum__rt__initialize(i8*)
1147
1148 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1149
1150 declare i1 @__quantum__rt__read_result(%Result*)
1151
1152 declare void @__quantum__rt__tuple_record_output(i64, i8*)
1153
1154 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1155
1156 declare void @__quantum__rt__bool_record_output(i1, i8*)
1157
1158 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1159 attributes #1 = { "irreversible" }
1160
1161 ; module flags
1162
1163 !llvm.module.flags = !{!0, !1, !2, !3}
1164
1165 !0 = !{i32 1, !"qir_major_version", i32 1}
1166 !1 = !{i32 7, !"qir_minor_version", i32 0}
1167 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1168 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1169 "#]]
1170 .assert_eq(&res);
1171 }
1172
1173 #[test]
1174 fn adaptive_qirgen_fails_when_entry_expr_does_not_match_profile() {
1175 let mut interpreter =
1176 get_interpreter_with_capabilities(TargetCapabilityFlags::Adaptive);
1177 let (result, output) = line(
1178 &mut interpreter,
1179 indoc! {r#"
1180 use q = Qubit();
1181 mutable x = 1;
1182 "#
1183 },
1184 );
1185 is_only_value(&result, &output, &Value::unit());
1186 let res = interpreter
1187 .qirgen("if M(q) == One { set x = 2; }")
1188 .expect_err("expected error");
1189 is_error(
1190 &res,
1191 &expect![[r#"
1192 cannot use a dynamic integer value
1193 [<entry>] [set x = 2]
1194 "#]],
1195 );
1196 }
1197
1198 #[test]
1199 fn qirgen_entry_expr_in_block() {
1200 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
1201 let (result, output) = line(
1202 &mut interpreter,
1203 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
1204 );
1205 is_only_value(&result, &output, &Value::unit());
1206 let res = interpreter.qirgen("{Foo()}").expect("expected success");
1207 expect![[r#"
1208 %Result = type opaque
1209 %Qubit = type opaque
1210
1211 @0 = internal constant [4 x i8] c"0_r\00"
1212
1213 define i64 @ENTRYPOINT__main() #0 {
1214 block_0:
1215 call void @__quantum__rt__initialize(i8* null)
1216 call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
1217 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1218 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i64 0, i64 0))
1219 ret i64 0
1220 }
1221
1222 declare void @__quantum__rt__initialize(i8*)
1223
1224 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
1225
1226 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1227
1228 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
1229
1230 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
1231 attributes #1 = { "irreversible" }
1232
1233 ; module flags
1234
1235 !llvm.module.flags = !{!0, !1, !2, !3}
1236
1237 !0 = !{i32 1, !"qir_major_version", i32 1}
1238 !1 = !{i32 7, !"qir_minor_version", i32 0}
1239 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1240 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1241 "#]].assert_eq(&res);
1242 }
1243
1244 #[test]
1245 fn qirgen_entry_expr_defines_operation() {
1246 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
1247
1248 let (result, output) = line(
1249 &mut interpreter,
1250 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
1251 );
1252 is_only_value(&result, &output, &Value::unit());
1253 let res = interpreter
1254 .qirgen("{operation Bar() : Unit {}; Foo()}")
1255 .expect("expected success");
1256 expect![[r#"
1257 %Result = type opaque
1258 %Qubit = type opaque
1259
1260 @0 = internal constant [4 x i8] c"0_r\00"
1261
1262 define i64 @ENTRYPOINT__main() #0 {
1263 block_0:
1264 call void @__quantum__rt__initialize(i8* null)
1265 call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
1266 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1267 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i64 0, i64 0))
1268 ret i64 0
1269 }
1270
1271 declare void @__quantum__rt__initialize(i8*)
1272
1273 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
1274
1275 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1276
1277 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
1278
1279 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
1280 attributes #1 = { "irreversible" }
1281
1282 ; module flags
1283
1284 !llvm.module.flags = !{!0, !1, !2, !3}
1285
1286 !0 = !{i32 1, !"qir_major_version", i32 1}
1287 !1 = !{i32 7, !"qir_minor_version", i32 0}
1288 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1289 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1290 "#]].assert_eq(&res);
1291
1292 // Operation should not be visible from global scope
1293 let (result, output) = line(&mut interpreter, indoc! {"Bar()"});
1294 is_only_error(
1295 &result,
1296 &output,
1297 &expect![[r#"
1298 name error: `Bar` not found
1299 [line_1] [Bar]
1300 "#]],
1301 );
1302 }
1303
1304 #[test]
1305 fn qirgen_multiple_exprs_parse_fail() {
1306 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
1307 let (result, output) = line(
1308 &mut interpreter,
1309 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
1310 );
1311 is_only_value(&result, &output, &Value::unit());
1312 let res = interpreter
1313 .qirgen("Foo(); operation Bar() : Unit {}; Foo()")
1314 .expect_err("expected error");
1315 is_error(
1316 &res,
1317 &expect![[r#"
1318 syntax error: expected EOF, found `;`
1319 [<entry>] [;]
1320 "#]],
1321 );
1322 }
1323
1324 #[test]
1325 fn qirgen_entry_expr_defines_operation_then_more_operations() {
1326 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
1327 let (result, output) = line(
1328 &mut interpreter,
1329 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
1330 );
1331 is_only_value(&result, &output, &Value::unit());
1332 let res = interpreter
1333 .qirgen("{operation Bar() : Unit {}; Foo()}")
1334 .expect("expected success");
1335 expect![[r#"
1336 %Result = type opaque
1337 %Qubit = type opaque
1338
1339 @0 = internal constant [4 x i8] c"0_r\00"
1340
1341 define i64 @ENTRYPOINT__main() #0 {
1342 block_0:
1343 call void @__quantum__rt__initialize(i8* null)
1344 call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
1345 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1346 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i64 0, i64 0))
1347 ret i64 0
1348 }
1349
1350 declare void @__quantum__rt__initialize(i8*)
1351
1352 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
1353
1354 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1355
1356 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
1357
1358 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
1359 attributes #1 = { "irreversible" }
1360
1361 ; module flags
1362
1363 !llvm.module.flags = !{!0, !1, !2, !3}
1364
1365 !0 = !{i32 1, !"qir_major_version", i32 1}
1366 !1 = !{i32 7, !"qir_minor_version", i32 0}
1367 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1368 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1369 "#]].assert_eq(&res);
1370
1371 let (result, output) = line(
1372 &mut interpreter,
1373 indoc! {"operation Baz() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
1374 );
1375 is_only_value(&result, &output, &Value::unit());
1376
1377 let (result, output) = line(&mut interpreter, indoc! {"Bar()"});
1378 is_only_error(
1379 &result,
1380 &output,
1381 &expect![[r#"
1382 name error: `Bar` not found
1383 [line_2] [Bar]
1384 "#]],
1385 );
1386 }
1387
1388 #[test]
1389 fn qirgen_define_operation_use_it() {
1390 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
1391 let res = interpreter
1392 .qirgen("{ operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; }; Foo() }")
1393 .expect("expected success");
1394 expect![[r#"
1395 %Result = type opaque
1396 %Qubit = type opaque
1397
1398 @0 = internal constant [4 x i8] c"0_r\00"
1399
1400 define i64 @ENTRYPOINT__main() #0 {
1401 block_0:
1402 call void @__quantum__rt__initialize(i8* null)
1403 call void @__quantum__qis__cx__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Qubit* inttoptr (i64 1 to %Qubit*))
1404 call void @__quantum__qis__m__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1405 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i64 0, i64 0))
1406 ret i64 0
1407 }
1408
1409 declare void @__quantum__rt__initialize(i8*)
1410
1411 declare void @__quantum__qis__m__body(%Qubit*, %Result*) #1
1412
1413 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1414
1415 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
1416
1417 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
1418 attributes #1 = { "irreversible" }
1419
1420 ; module flags
1421
1422 !llvm.module.flags = !{!0, !1, !2, !3}
1423
1424 !0 = !{i32 1, !"qir_major_version", i32 1}
1425 !1 = !{i32 7, !"qir_minor_version", i32 0}
1426 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1427 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1428 "#]].assert_eq(&res);
1429 }
1430
1431 #[test]
1432 fn qirgen_entry_expr_profile_incompatible() {
1433 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
1434 let res = interpreter
1435 .qirgen("1")
1436 .expect_err("expected qirgen to fail");
1437 is_error(
1438 &res,
1439 &expect![[r#"
1440 cannot use an integer value as an output
1441 [<entry>] [1]
1442 "#]],
1443 );
1444 }
1445
1446 #[test]
1447 fn adaptive_qirgen_custom_intrinsic_returning_bool() {
1448 let mut interpreter =
1449 get_interpreter_with_capabilities(TargetCapabilityFlags::Adaptive);
1450 let res = interpreter
1451 .qirgen("{ operation check_result(r : Result) : Bool { body intrinsic; }; operation Foo() : Bool { use q = Qubit(); let r = MResetZ(q); check_result(r) } Foo() }")
1452 .expect("expected success");
1453 expect![[r#"
1454 %Result = type opaque
1455 %Qubit = type opaque
1456
1457 @0 = internal constant [4 x i8] c"0_b\00"
1458
1459 define i64 @ENTRYPOINT__main() #0 {
1460 block_0:
1461 call void @__quantum__rt__initialize(i8* null)
1462 call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
1463 %var_0 = call i1 @check_result(%Result* inttoptr (i64 0 to %Result*))
1464 call void @__quantum__rt__bool_record_output(i1 %var_0, i8* getelementptr inbounds ([4 x i8], [4 x i8]* @0, i64 0, i64 0))
1465 ret i64 0
1466 }
1467
1468 declare void @__quantum__rt__initialize(i8*)
1469
1470 declare void @__quantum__qis__mresetz__body(%Qubit*, %Result*) #1
1471
1472 declare i1 @check_result(%Result*)
1473
1474 declare void @__quantum__rt__bool_record_output(i1, i8*)
1475
1476 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="1" }
1477 attributes #1 = { "irreversible" }
1478
1479 ; module flags
1480
1481 !llvm.module.flags = !{!0, !1, !2, !3}
1482
1483 !0 = !{i32 1, !"qir_major_version", i32 1}
1484 !1 = !{i32 7, !"qir_minor_version", i32 0}
1485 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1486 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1487 "#]].assert_eq(&res);
1488 }
1489
1490 #[test]
1491 fn run_with_shots() {
1492 let mut interpreter = get_interpreter();
1493 let (result, output) = line(
1494 &mut interpreter,
1495 "operation Foo(qs : Qubit[]) : Unit { Microsoft.Quantum.Diagnostics.DumpMachine(); }",
1496 );
1497 is_only_value(&result, &output, &Value::unit());
1498 for _ in 0..4 {
1499 let (results, output) = run(&mut interpreter, "{use qs = Qubit[2]; Foo(qs)}");
1500 is_unit_with_output(&results, &output, "STATE:\n|00⟩: 1+0i");
1501 }
1502 }
1503
1504 #[test]
1505 fn run_parse_error() {
1506 let mut interpreter = get_interpreter();
1507 let (results, _) = run(&mut interpreter, "Foo)");
1508 results.expect_err("run() should fail");
1509 }
1510
1511 #[test]
1512 fn run_compile_error() {
1513 let mut interpreter = get_interpreter();
1514 let (results, _) = run(&mut interpreter, "Foo()");
1515 results.expect_err("run() should fail");
1516 }
1517
1518 #[test]
1519 fn run_multiple_statements_with_return_value() {
1520 let mut interpreter = get_interpreter();
1521 let (result, output) = line(&mut interpreter, "operation Foo() : Int { 1 }");
1522 is_only_value(&result, &output, &Value::unit());
1523 let (result, output) = line(&mut interpreter, "operation Bar() : Int { 2 }");
1524 is_only_value(&result, &output, &Value::unit());
1525 let (result, output) = run(&mut interpreter, "{ Foo(); Bar() }");
1526 is_only_value(&result, &output, &Value::Int(2));
1527 }
1528
1529 #[test]
1530 fn run_runtime_failure() {
1531 let mut interpreter = get_interpreter();
1532 let (result, output) = line(
1533 &mut interpreter,
1534 r#"operation Foo() : Int { fail "failed" }"#,
1535 );
1536 is_only_value(&result, &output, &Value::unit());
1537 for _ in 0..1 {
1538 let (result, output) = run(&mut interpreter, "Foo()");
1539 is_only_error(
1540 &result,
1541 &output,
1542 &expect![[r#"
1543 runtime error: program failed: failed
1544 explicit fail [line_0] [fail "failed"]
1545 "#]],
1546 );
1547 }
1548 }
1549
1550 #[test]
1551 fn run_output_merged() {
1552 let mut interpreter = get_interpreter();
1553 let (result, output) = line(
1554 &mut interpreter,
1555 r#"operation Foo() : Unit { Message("hello!") }"#,
1556 );
1557 is_only_value(&result, &output, &Value::unit());
1558 for _ in 0..4 {
1559 let (result, output) = run(&mut interpreter, "Foo()");
1560 is_unit_with_output(&result, &output, "hello!");
1561 }
1562 }
1563
1564 #[test]
1565 fn base_prof_non_result_return() {
1566 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
1567 let (result, output) = line(&mut interpreter, "123");
1568 is_only_value(&result, &output, &Value::Int(123));
1569 }
1570 }
1571
1572 fn get_interpreter() -> Interpreter {
1573 let (std_id, store) =
1574 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1575 let dependencies = &[(std_id, None)];
1576 Interpreter::new(
1577 SourceMap::default(),
1578 PackageType::Lib,
1579 TargetCapabilityFlags::all(),
1580 LanguageFeatures::default(),
1581 store,
1582 dependencies,
1583 )
1584 .expect("interpreter should be created")
1585 }
1586
1587 fn get_interpreter_with_capabilities(capabilities: TargetCapabilityFlags) -> Interpreter {
1588 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
1589 let dependencies = &[(std_id, None)];
1590 Interpreter::new(
1591 SourceMap::default(),
1592 PackageType::Lib,
1593 capabilities,
1594 LanguageFeatures::default(),
1595 store,
1596 dependencies,
1597 )
1598 .expect("interpreter should be created")
1599 }
1600
1601 fn is_only_value(result: &InterpretResult, output: &str, value: &Value) {
1602 assert_eq!("", output);
1603
1604 match result {
1605 Ok(v) => assert_eq!(value, v),
1606 Err(e) => panic!("Expected {value:?}, got {e:?}"),
1607 }
1608 }
1609
1610 fn is_unit_with_output_eval_entry(
1611 result: &InterpretResult,
1612 output: &str,
1613 expected_output: &str,
1614 ) {
1615 assert_eq!(expected_output, output);
1616
1617 match result {
1618 Ok(value) => assert_eq!(Value::unit(), *value),
1619 Err(e) => panic!("Expected unit value, got {e:?}"),
1620 }
1621 }
1622
1623 fn is_unit_with_output(result: &InterpretResult, output: &str, expected_output: &str) {
1624 match result {
1625 Ok(value) => assert_eq!(Value::unit(), *value),
1626 Err(e) => panic!("Expected unit value, got {e:?}"),
1627 }
1628 assert_eq!(expected_output, output);
1629 }
1630
1631 fn is_only_error<E>(result: &Result<Value, Vec<E>>, output: &str, expected_errors: &Expect)
1632 where
1633 E: Diagnostic,
1634 {
1635 assert_eq!("", output);
1636
1637 match result {
1638 Ok(value) => panic!("Expected error , got {value:?}"),
1639 Err(errors) => is_error(errors, expected_errors),
1640 }
1641 }
1642
1643 fn is_error<E>(errors: &Vec<E>, expected_errors: &Expect)
1644 where
1645 E: Diagnostic,
1646 {
1647 let mut actual = String::new();
1648 for error in errors {
1649 write!(actual, "{error}").expect("writing should succeed");
1650 for s in iter::successors(error.source(), |&s| s.source()) {
1651 write!(actual, ": {s}").expect("writing should succeed");
1652 }
1653 for label in error.labels().into_iter().flatten() {
1654 let span = error
1655 .source_code()
1656 .expect("expected valid source code")
1657 .read_span(label.inner(), 0, 0)
1658 .expect("expected to be able to read span");
1659
1660 write!(
1661 actual,
1662 "\n {} [{}] [{}]",
1663 label.label().unwrap_or(""),
1664 span.name().expect("expected source file name"),
1665 from_utf8(span.data()).expect("expected valid utf-8 string"),
1666 )
1667 .expect("writing should succeed");
1668 }
1669 writeln!(actual).expect("writing should succeed");
1670 }
1671
1672 expected_errors.assert_eq(&actual);
1673 }
1674
1675 #[cfg(test)]
1676 mod with_sources {
1677 use std::{sync::Arc, vec};
1678
1679 use super::*;
1680 use crate::interpret::Debugger;
1681 use crate::line_column::Encoding;
1682 use expect_test::expect;
1683 use indoc::indoc;
1684
1685 use qsc_ast::ast::{
1686 Expr, ExprKind, NodeId, Package, Path, PathKind, Stmt, StmtKind, TopLevelNode,
1687 };
1688 use qsc_data_structures::source::SourceMap;
1689 use qsc_data_structures::span::Span;
1690 use qsc_passes::PackageType;
1691
1692 #[test]
1693 fn entry_expr_is_executed() {
1694 let source = indoc! { r#"
1695 namespace Test {
1696 @EntryPoint()
1697 operation Main() : Unit {
1698 Message("hello there...")
1699 }
1700 }"#};
1701
1702 let sources = SourceMap::new([("test".into(), source.into())], None);
1703 let (std_id, store) =
1704 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1705 let mut interpreter = Interpreter::new(
1706 sources,
1707 PackageType::Exe,
1708 TargetCapabilityFlags::all(),
1709 LanguageFeatures::default(),
1710 store,
1711 &[(std_id, None)],
1712 )
1713 .expect("interpreter should be created");
1714
1715 let (result, output) = entry(&mut interpreter);
1716 is_unit_with_output_eval_entry(&result, &output, "hello there...");
1717 }
1718
1719 #[test]
1720 fn invalid_partial_application_should_fail_not_panic() {
1721 // Found via fuzzing, see #2363
1722 let source = "operation e(oracle:(w=>)){oracle=i(_)";
1723 let sources = SourceMap::new([("test".into(), source.into())], None);
1724 let (std_id, store) =
1725 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1726 assert!(
1727 Interpreter::new(
1728 sources,
1729 PackageType::Exe,
1730 TargetCapabilityFlags::all(),
1731 LanguageFeatures::default(),
1732 store,
1733 &[(std_id, None)],
1734 )
1735 .is_err(),
1736 "interpreter should fail with error"
1737 );
1738 }
1739
1740 #[test]
1741 fn errors_returned_if_sources_do_not_match_profile() {
1742 let source = indoc! { r#"
1743 namespace A { operation Test() : Double { use q = Qubit(); mutable x = 1.0; if MResetZ(q) == One { set x = 2.0; } x } }"#};
1744
1745 let sources = SourceMap::new([("test".into(), source.into())], Some("A.Test()".into()));
1746 let (std_id, store) =
1747 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1748 let result = Interpreter::new(
1749 sources,
1750 PackageType::Exe,
1751 TargetCapabilityFlags::Adaptive | TargetCapabilityFlags::IntegerComputations,
1752 LanguageFeatures::default(),
1753 store,
1754 &[(std_id, None)],
1755 );
1756
1757 match result {
1758 Ok(_) => panic!("Expected error, got interpreter."),
1759 Err(errors) => is_error(
1760 &errors,
1761 &expect![[r#"
1762 cannot use a dynamic double value
1763 [<entry>] [A.Test()]
1764 cannot use a double value as an output
1765 [<entry>] [A.Test()]
1766 cannot use a dynamic double value
1767 [test] [set x = 2.0]
1768 cannot use a dynamic double value
1769 [test] [x]
1770 "#]],
1771 ),
1772 }
1773 }
1774
1775 #[test]
1776 fn stdlib_members_can_be_accessed_from_sources() {
1777 let source = indoc! { r#"
1778 namespace Test {
1779 operation Main() : Unit {
1780 Message("hello there...")
1781 }
1782 }"#};
1783
1784 let sources = SourceMap::new([("test".into(), source.into())], None);
1785 let (std_id, store) =
1786 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1787 let dependencies = &[(std_id, None)];
1788 let mut interpreter = Interpreter::new(
1789 sources,
1790 PackageType::Lib,
1791 TargetCapabilityFlags::all(),
1792 LanguageFeatures::default(),
1793 store,
1794 dependencies,
1795 )
1796 .expect("interpreter should be created");
1797
1798 let (result, output) = line(&mut interpreter, "Test.Main()");
1799 is_unit_with_output(&result, &output, "hello there...");
1800 }
1801
1802 #[test]
1803 fn members_from_namespaced_sources_are_in_context() {
1804 let source = indoc! { r#"
1805 namespace Test {
1806 function Hello() : String {
1807 "hello there..."
1808 }
1809
1810 operation Main() : String {
1811 Hello()
1812 }
1813 }"#};
1814
1815 let sources = SourceMap::new([("test".into(), source.into())], None);
1816 let store = crate::PackageStore::new(crate::compile::core());
1817 let mut interpreter = Interpreter::new(
1818 sources,
1819 PackageType::Lib,
1820 TargetCapabilityFlags::all(),
1821 LanguageFeatures::default(),
1822 store,
1823 &[],
1824 )
1825 .expect("interpreter should be created");
1826
1827 let (result, output) = line(&mut interpreter, "Test.Hello()");
1828 is_only_value(&result, &output, &Value::String("hello there...".into()));
1829 let (result, output) = line(&mut interpreter, "Test.Main()");
1830 is_only_value(&result, &output, &Value::String("hello there...".into()));
1831 }
1832
1833 #[test]
1834 fn multiple_files_are_loaded_from_sources_into_eval_context() {
1835 let sources: [(Arc<str>, Arc<str>); 2] = [
1836 (
1837 "a.qs".into(),
1838 r#"
1839 namespace Test {
1840 function Hello() : String {
1841 "hello there..."
1842 }
1843 }"#
1844 .into(),
1845 ),
1846 (
1847 "b.qs".into(),
1848 r#"
1849 namespace Test2 {
1850 open Test;
1851 @EntryPoint()
1852 operation Main() : String {
1853 Hello();
1854 Hello()
1855 }
1856 }"#
1857 .into(),
1858 ),
1859 ];
1860
1861 let sources = SourceMap::new(sources, None);
1862 let store = crate::PackageStore::new(crate::compile::core());
1863 let debugger = Debugger::new(
1864 sources,
1865 TargetCapabilityFlags::all(),
1866 Encoding::Utf8,
1867 LanguageFeatures::default(),
1868 store,
1869 &[],
1870 )
1871 .expect("debugger should be created");
1872 let bps = debugger.get_breakpoints("a.qs");
1873 assert_eq!(1, bps.len());
1874 let bps = debugger.get_breakpoints("b.qs");
1875 assert_eq!(2, bps.len());
1876 }
1877
1878 #[test]
1879 fn debugger_simple_execution_succeeds() {
1880 let source = indoc! { r#"
1881 namespace Test {
1882 function Hello() : Unit {
1883 Message("hello there...");
1884 }
1885
1886 @EntryPoint()
1887 operation Main() : Unit {
1888 Hello()
1889 }
1890 }"#};
1891
1892 let sources = SourceMap::new([("test".into(), source.into())], None);
1893 let (std_id, store) =
1894 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1895 let mut debugger = Debugger::new(
1896 sources,
1897 TargetCapabilityFlags::all(),
1898 Encoding::Utf8,
1899 LanguageFeatures::default(),
1900 store,
1901 &[(std_id, None)],
1902 )
1903 .expect("debugger should be created");
1904 let (result, output) = entry(&mut debugger.interpreter);
1905 is_unit_with_output_eval_entry(&result, &output, "hello there...");
1906 }
1907
1908 #[test]
1909 fn debugger_execution_with_call_to_library_succeeds() {
1910 let source = indoc! { r#"
1911 namespace Test {
1912 import Std.Math.*;
1913 @EntryPoint()
1914 operation Main() : Int {
1915 Binom(31, 7)
1916 }
1917 }"#};
1918
1919 let sources = SourceMap::new([("test".into(), source.into())], None);
1920 let (std_id, store) =
1921 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1922 let mut debugger = Debugger::new(
1923 sources,
1924 TargetCapabilityFlags::all(),
1925 Encoding::Utf8,
1926 LanguageFeatures::default(),
1927 store,
1928 &[(std_id, None)],
1929 )
1930 .expect("debugger should be created");
1931 let (result, output) = entry(&mut debugger.interpreter);
1932 is_only_value(&result, &output, &Value::Int(2_629_575));
1933 }
1934
1935 #[test]
1936 fn debugger_execution_with_early_return_succeeds() {
1937 let source = indoc! { r#"
1938 namespace Test {
1939 import Std.Arrays.*;
1940
1941 operation Max20(i : Int) : Int {
1942 if (i > 20) {
1943 return 20;
1944 }
1945 return i;
1946 }
1947
1948 @EntryPoint()
1949 operation Main() : Int[] {
1950 ForEach(Max20, [10, 20, 30, 40, 50])
1951 }
1952 }"#};
1953
1954 let sources = SourceMap::new([("test".into(), source.into())], None);
1955 let (std_id, store) =
1956 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1957 let mut debugger = Debugger::new(
1958 sources,
1959 TargetCapabilityFlags::all(),
1960 Encoding::Utf8,
1961 LanguageFeatures::default(),
1962 store,
1963 &[(std_id, None)],
1964 )
1965 .expect("debugger should be created");
1966
1967 let (result, output) = entry(&mut debugger.interpreter);
1968 is_only_value(
1969 &result,
1970 &output,
1971 &Value::Array(
1972 vec![
1973 Value::Int(10),
1974 Value::Int(20),
1975 Value::Int(20),
1976 Value::Int(20),
1977 Value::Int(20),
1978 ]
1979 .into(),
1980 ),
1981 );
1982 }
1983
1984 #[test]
1985 fn multiple_namespaces_are_loaded_from_sources_into_eval_context() {
1986 let source = indoc! { r#"
1987 namespace Test {
1988 function Hello() : String {
1989 "hello there..."
1990 }
1991 }
1992 namespace Test2 {
1993 open Test;
1994 operation Main() : String {
1995 Hello()
1996 }
1997 }"#};
1998
1999 let sources = SourceMap::new([("test".into(), source.into())], None);
2000 let store = crate::PackageStore::new(crate::compile::core());
2001 let mut interpreter = Interpreter::new(
2002 sources,
2003 PackageType::Lib,
2004 TargetCapabilityFlags::all(),
2005 LanguageFeatures::default(),
2006 store,
2007 &[],
2008 )
2009 .expect("interpreter should be created");
2010 let (result, output) = line(&mut interpreter, "Test.Hello()");
2011 is_only_value(&result, &output, &Value::String("hello there...".into()));
2012 let (result, output) = line(&mut interpreter, "Test2.Main()");
2013 is_only_value(&result, &output, &Value::String("hello there...".into()));
2014 }
2015
2016 #[test]
2017 fn runtime_error_from_stdlib() {
2018 let sources = SourceMap::new(
2019 [(
2020 "test".into(),
2021 "namespace Foo {
2022 operation Bar(): Unit {
2023 let x = -1;
2024 use qs = Qubit[x];
2025 }
2026 }
2027 "
2028 .into(),
2029 )],
2030 Some("Foo.Bar()".into()),
2031 );
2032
2033 let store = crate::PackageStore::new(crate::compile::core());
2034 let mut interpreter = Interpreter::new(
2035 sources,
2036 PackageType::Lib,
2037 TargetCapabilityFlags::all(),
2038 LanguageFeatures::default(),
2039 store,
2040 &[],
2041 )
2042 .expect("interpreter should be created");
2043
2044 let (result, output) = entry(&mut interpreter);
2045 is_only_error(
2046 &result,
2047 &output,
2048 &expect![[r#"
2049 runtime error: program failed: Cannot allocate qubit array with a negative length
2050 explicit fail [qsharp-library-source:core/qir.qs] [fail "Cannot allocate qubit array with a negative length"]
2051 "#]],
2052 );
2053 }
2054
2055 #[test]
2056 fn interpreter_returns_items_from_source() {
2057 let sources = SourceMap::new(
2058 [(
2059 "test".into(),
2060 "namespace A {
2061 operation B(): Unit { }
2062 }
2063 "
2064 .into(),
2065 )],
2066 Some("A.B()".into()),
2067 );
2068
2069 let (std_id, store) =
2070 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2071 let interpreter = Interpreter::new(
2072 sources,
2073 PackageType::Lib,
2074 TargetCapabilityFlags::all(),
2075 LanguageFeatures::default(),
2076 store,
2077 &[(std_id, None)],
2078 )
2079 .expect("interpreter should be created");
2080
2081 let items = interpreter.source_globals();
2082 assert_eq!(1, items.len());
2083 expect![[r#"
2084 [
2085 "A",
2086 ]
2087 "#]]
2088 .assert_debug_eq(&items[0].0);
2089 expect![[r#"
2090 "B"
2091 "#]]
2092 .assert_debug_eq(&items[0].1);
2093 }
2094
2095 #[test]
2096 fn interpreter_can_be_created_from_ast() {
2097 let sources = SourceMap::new(
2098 [(
2099 "test".into(),
2100 "namespace A {
2101 operation B(): Result {
2102 use qs = Qubit[2];
2103 X(qs[0]);
2104 CNOT(qs[0], qs[1]);
2105 let res = Measure([PauliZ, PauliZ], qs[...1]);
2106 ResetAll(qs);
2107 res
2108 }
2109 }
2110 "
2111 .into(),
2112 )],
2113 Some("A.B()".into()),
2114 );
2115
2116 let (package_type, capabilities, language_features) = (
2117 PackageType::Lib,
2118 TargetCapabilityFlags::all(),
2119 LanguageFeatures::default(),
2120 );
2121
2122 let mut store = crate::PackageStore::new(crate::compile::core());
2123 let dependencies = vec![(
2124 store.insert(crate::compile::std(&store, capabilities)),
2125 None,
2126 )];
2127
2128 let (mut unit, errors) = crate::compile::compile(
2129 &store,
2130 &dependencies,
2131 sources,
2132 package_type,
2133 capabilities,
2134 language_features,
2135 );
2136 unit.expose();
2137 for e in &errors {
2138 eprintln!("{e:?}");
2139 }
2140 assert!(errors.is_empty(), "compilation failed: {}", errors[0]);
2141 let package_id = store.insert(unit);
2142
2143 let mut interpreter = Interpreter::with_package_store(
2144 false,
2145 store,
2146 package_id,
2147 capabilities,
2148 language_features,
2149 &dependencies,
2150 )
2151 .expect("interpreter should be created");
2152 let (result, output) = entry(&mut interpreter);
2153 is_only_value(
2154 &result,
2155 &output,
2156 &Value::Result(qsc_eval::val::Result::Val(false)),
2157 );
2158 }
2159
2160 #[test]
2161 fn ast_fragments_can_be_evaluated() {
2162 let sources = SourceMap::new(
2163 [(
2164 "test".into(),
2165 "namespace A {
2166 operation B(): Result {
2167 use qs = Qubit[2];
2168 X(qs[0]);
2169 CNOT(qs[0], qs[1]);
2170 let res = Measure([PauliZ, PauliZ], qs[...1]);
2171 ResetAll(qs);
2172 res
2173 }
2174 }
2175 "
2176 .into(),
2177 )],
2178 None,
2179 );
2180 let (std_id, store) =
2181 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2182 let mut interpreter = Interpreter::new(
2183 sources,
2184 PackageType::Lib,
2185 TargetCapabilityFlags::all(),
2186 LanguageFeatures::default(),
2187 store,
2188 &[(std_id, None)],
2189 )
2190 .expect("interpreter should be created");
2191
2192 let package = get_package_for_call("A", "B");
2193 let (result, output) = fragment(&mut interpreter, "A.B()", package);
2194 is_only_value(
2195 &result,
2196 &output,
2197 &Value::Result(qsc_eval::val::Result::Val(false)),
2198 );
2199 }
2200
2201 #[test]
2202 fn ast_fragments_evaluation_returns_runtime_errors() {
2203 let sources = SourceMap::new(
2204 [(
2205 "test".into(),
2206 "namespace A {
2207 operation B(): Int {
2208 42 / 0
2209 }
2210 }
2211 "
2212 .into(),
2213 )],
2214 None,
2215 );
2216 let (std_id, store) =
2217 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2218 let mut interpreter = Interpreter::new(
2219 sources,
2220 PackageType::Lib,
2221 TargetCapabilityFlags::all(),
2222 LanguageFeatures::default(),
2223 store,
2224 &[(std_id, None)],
2225 )
2226 .expect("interpreter should be created");
2227
2228 let package = get_package_for_call("A", "B");
2229 let (result, output) = fragment(&mut interpreter, "A.B()", package);
2230 is_only_error(
2231 &result,
2232 &output,
2233 &expect![[r#"
2234 runtime error: division by zero
2235 cannot divide by zero [test] [0]
2236 "#]],
2237 );
2238 }
2239
2240 fn get_package_for_call(ns: &str, name: &str) -> crate::ast::Package {
2241 let args = Expr {
2242 id: NodeId::default(),
2243 span: Span::default(),
2244 kind: Box::new(ExprKind::Tuple(Box::new([]))),
2245 };
2246 let path = Path {
2247 id: NodeId::default(),
2248 span: Span::default(),
2249 segments: Some(
2250 std::iter::once(qsc_ast::ast::Ident {
2251 id: NodeId::default(),
2252 span: Span::default(),
2253 name: ns.into(),
2254 })
2255 .collect(),
2256 ),
2257 name: Box::new(qsc_ast::ast::Ident {
2258 id: NodeId::default(),
2259 span: Span::default(),
2260 name: name.into(),
2261 }),
2262 };
2263 let path_expr = Expr {
2264 id: NodeId::default(),
2265 span: Span::default(),
2266 kind: Box::new(ExprKind::Path(PathKind::Ok(Box::new(path)))),
2267 };
2268 let expr = Expr {
2269 id: NodeId::default(),
2270 span: Span::default(),
2271 kind: Box::new(ExprKind::Call(Box::new(path_expr), Box::new(args))),
2272 };
2273 let stmt = Stmt {
2274 id: NodeId::default(),
2275 span: Span::default(),
2276 kind: Box::new(StmtKind::Expr(Box::new(expr))),
2277 };
2278 let top_level = TopLevelNode::Stmt(Box::new(stmt));
2279 Package {
2280 id: NodeId::default(),
2281 nodes: vec![top_level].into_boxed_slice(),
2282 entry: None,
2283 }
2284 }
2285
2286 #[test]
2287 fn name_resolution_from_source_named_main_should_succeed() {
2288 let sources = SourceMap::new(
2289 [(
2290 "Main".into(),
2291 r#"function Foo() : Unit { Message("hello there..."); }"#.into(),
2292 )],
2293 None,
2294 );
2295 let (std_id, store) =
2296 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2297 let mut interpreter = Interpreter::new(
2298 sources,
2299 PackageType::Lib,
2300 TargetCapabilityFlags::all(),
2301 LanguageFeatures::default(),
2302 store,
2303 &[(std_id, None)],
2304 )
2305 .expect("interpreter should be created");
2306
2307 // Operations defined in Main.qs should also be visible with Main qualifier.
2308 let (result, output) = line(&mut interpreter, "Main.Foo()");
2309 is_unit_with_output(&result, &output, "hello there...");
2310
2311 // Operations defined in Main.qs should be importable with fully qualified name.
2312 let (result, output) = line(&mut interpreter, "import Main.Foo;");
2313 is_only_value(&result, &output, &Value::unit());
2314
2315 // After import the operation can be invoked without Main qualifier.
2316 let (result, output) = line(&mut interpreter, "Foo()");
2317 is_unit_with_output(&result, &output, "hello there...");
2318 }
2319
2320 #[test]
2321 fn name_resolution_from_source_named_main_without_full_path_or_import_should_fail() {
2322 let sources = SourceMap::new(
2323 [(
2324 "Main".into(),
2325 r#"function Foo() : Unit { Message("hello there..."); }"#.into(),
2326 )],
2327 None,
2328 );
2329 let (std_id, store) =
2330 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2331 let mut interpreter = Interpreter::new(
2332 sources,
2333 PackageType::Lib,
2334 TargetCapabilityFlags::all(),
2335 LanguageFeatures::default(),
2336 store,
2337 &[(std_id, None)],
2338 )
2339 .expect("interpreter should be created");
2340
2341 // Operations defined in Main.qs should also be visible with Main qualifier.
2342 let (errors, _) = line(&mut interpreter, "Foo()");
2343 is_error(
2344 &errors.expect_err("line invocation should fail with error"),
2345 &expect![[r#"
2346 name error: `Foo` not found
2347 [line_0] [Foo]
2348 "#]],
2349 );
2350 }
2351
2352 /// Found via fuzzing, see #2426 <https://github.com/microsoft/qdk/issues/2426>
2353 #[test]
2354 fn recursive_type_constraint_should_fail() {
2355 let sources = SourceMap::new(
2356 [(
2357 "test".into(),
2358 r#"operation a(){(foo,bar)->foo+bar=foo->foo"#.into(),
2359 )],
2360 None,
2361 );
2362 let (std_id, store) =
2363 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2364 match Interpreter::new(
2365 sources,
2366 PackageType::Lib,
2367 TargetCapabilityFlags::all(),
2368 LanguageFeatures::default(),
2369 store,
2370 &[(std_id, None)],
2371 ) {
2372 Ok(_) => panic!("interpreter should fail with error"),
2373 Err(errors) => {
2374 is_error(
2375 &errors,
2376 &expect![[r#"
2377 syntax error: expected `:`, found `{`
2378 [test] [{]
2379 syntax error: expected `}`, found EOF
2380 [test] []
2381 type error: unsupported recursive type constraint
2382 [test] [(foo,bar)->foo+bar]
2383 type error: insufficient type information to infer type
2384 [test] [foo+bar]
2385 "#]],
2386 );
2387 }
2388 }
2389 }
2390 }
2391}
2392