microsoft/qdk

Public

mirrored fromhttps://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
iadavis/pipeline-issue-debugging

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

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