microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
copilot/fix-2145

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc/src/interpret/tests.rs

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