microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.19.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

2276lines · 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, 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(
1375 &mut interpreter,
1376 "operation Foo(qs : Qubit[]) : Unit { Microsoft.Quantum.Diagnostics.DumpMachine(); }",
1377 );
1378 is_only_value(&result, &output, &Value::unit());
1379 for _ in 0..4 {
1380 let (results, output) = run(&mut interpreter, "{use qs = Qubit[2]; Foo(qs)}");
1381 is_unit_with_output(&results, &output, "STATE:\n|00⟩: 1+0i");
1382 }
1383 }
1384
1385 #[test]
1386 fn run_parse_error() {
1387 let mut interpreter = get_interpreter();
1388 let (results, _) = run(&mut interpreter, "Foo)");
1389 results.expect_err("run() should fail");
1390 }
1391
1392 #[test]
1393 fn run_compile_error() {
1394 let mut interpreter = get_interpreter();
1395 let (results, _) = run(&mut interpreter, "Foo()");
1396 results.expect_err("run() should fail");
1397 }
1398
1399 #[test]
1400 fn run_multiple_statements_with_return_value() {
1401 let mut interpreter = get_interpreter();
1402 let (result, output) = line(&mut interpreter, "operation Foo() : Int { 1 }");
1403 is_only_value(&result, &output, &Value::unit());
1404 let (result, output) = line(&mut interpreter, "operation Bar() : Int { 2 }");
1405 is_only_value(&result, &output, &Value::unit());
1406 let (result, output) = run(&mut interpreter, "{ Foo(); Bar() }");
1407 is_only_value(&result, &output, &Value::Int(2));
1408 }
1409
1410 #[test]
1411 fn run_runtime_failure() {
1412 let mut interpreter = get_interpreter();
1413 let (result, output) = line(
1414 &mut interpreter,
1415 r#"operation Foo() : Int { fail "failed" }"#,
1416 );
1417 is_only_value(&result, &output, &Value::unit());
1418 for _ in 0..1 {
1419 let (result, output) = run(&mut interpreter, "Foo()");
1420 is_only_error(
1421 &result,
1422 &output,
1423 &expect![[r#"
1424 runtime error: program failed: failed
1425 explicit fail [line_0] [fail "failed"]
1426 "#]],
1427 );
1428 }
1429 }
1430
1431 #[test]
1432 fn run_output_merged() {
1433 let mut interpreter = get_interpreter();
1434 let (result, output) = line(
1435 &mut interpreter,
1436 r#"operation Foo() : Unit { Message("hello!") }"#,
1437 );
1438 is_only_value(&result, &output, &Value::unit());
1439 for _ in 0..4 {
1440 let (result, output) = run(&mut interpreter, "Foo()");
1441 is_unit_with_output(&result, &output, "hello!");
1442 }
1443 }
1444
1445 #[test]
1446 fn base_prof_non_result_return() {
1447 let mut interpreter = get_interpreter_with_capabilities(TargetCapabilityFlags::empty());
1448 let (result, output) = line(&mut interpreter, "123");
1449 is_only_value(&result, &output, &Value::Int(123));
1450 }
1451 }
1452
1453 fn get_interpreter() -> Interpreter {
1454 let (std_id, store) =
1455 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1456 let dependencies = &[(std_id, None)];
1457 Interpreter::new(
1458 SourceMap::default(),
1459 PackageType::Lib,
1460 TargetCapabilityFlags::all(),
1461 LanguageFeatures::default(),
1462 store,
1463 dependencies,
1464 )
1465 .expect("interpreter should be created")
1466 }
1467
1468 fn get_interpreter_with_capabilities(capabilities: TargetCapabilityFlags) -> Interpreter {
1469 let (std_id, store) = crate::compile::package_store_with_stdlib(capabilities);
1470 let dependencies = &[(std_id, None)];
1471 Interpreter::new(
1472 SourceMap::default(),
1473 PackageType::Lib,
1474 capabilities,
1475 LanguageFeatures::default(),
1476 store,
1477 dependencies,
1478 )
1479 .expect("interpreter should be created")
1480 }
1481
1482 fn is_only_value(result: &InterpretResult, output: &str, value: &Value) {
1483 assert_eq!("", output);
1484
1485 match result {
1486 Ok(v) => assert_eq!(value, v),
1487 Err(e) => panic!("Expected {value:?}, got {e:?}"),
1488 }
1489 }
1490
1491 fn is_unit_with_output_eval_entry(
1492 result: &InterpretResult,
1493 output: &str,
1494 expected_output: &str,
1495 ) {
1496 assert_eq!(expected_output, output);
1497
1498 match result {
1499 Ok(value) => assert_eq!(Value::unit(), *value),
1500 Err(e) => panic!("Expected unit value, got {e:?}"),
1501 }
1502 }
1503
1504 fn is_unit_with_output(result: &InterpretResult, output: &str, expected_output: &str) {
1505 match result {
1506 Ok(value) => assert_eq!(Value::unit(), *value),
1507 Err(e) => panic!("Expected unit value, got {e:?}"),
1508 }
1509 assert_eq!(expected_output, output);
1510 }
1511
1512 fn is_only_error<E>(result: &Result<Value, Vec<E>>, output: &str, expected_errors: &Expect)
1513 where
1514 E: Diagnostic,
1515 {
1516 assert_eq!("", output);
1517
1518 match result {
1519 Ok(value) => panic!("Expected error , got {value:?}"),
1520 Err(errors) => is_error(errors, expected_errors),
1521 }
1522 }
1523
1524 fn is_error<E>(errors: &Vec<E>, expected_errors: &Expect)
1525 where
1526 E: Diagnostic,
1527 {
1528 let mut actual = String::new();
1529 for error in errors {
1530 write!(actual, "{error}").expect("writing should succeed");
1531 for s in iter::successors(error.source(), |&s| s.source()) {
1532 write!(actual, ": {s}").expect("writing should succeed");
1533 }
1534 for label in error.labels().into_iter().flatten() {
1535 let span = error
1536 .source_code()
1537 .expect("expected valid source code")
1538 .read_span(label.inner(), 0, 0)
1539 .expect("expected to be able to read span");
1540
1541 write!(
1542 actual,
1543 "\n {} [{}] [{}]",
1544 label.label().unwrap_or(""),
1545 span.name().expect("expected source file name"),
1546 from_utf8(span.data()).expect("expected valid utf-8 string"),
1547 )
1548 .expect("writing should succeed");
1549 }
1550 writeln!(actual).expect("writing should succeed");
1551 }
1552
1553 expected_errors.assert_eq(&actual);
1554 }
1555
1556 #[cfg(test)]
1557 mod with_sources {
1558 use std::{sync::Arc, vec};
1559
1560 use super::*;
1561 use crate::interpret::Debugger;
1562 use crate::line_column::Encoding;
1563 use expect_test::expect;
1564 use indoc::indoc;
1565
1566 use qsc_ast::ast::{
1567 Expr, ExprKind, NodeId, Package, Path, PathKind, Stmt, StmtKind, TopLevelNode,
1568 };
1569 use qsc_data_structures::span::Span;
1570 use qsc_frontend::compile::SourceMap;
1571 use qsc_passes::PackageType;
1572
1573 #[test]
1574 fn entry_expr_is_executed() {
1575 let source = indoc! { r#"
1576 namespace Test {
1577 @EntryPoint()
1578 operation Main() : Unit {
1579 Message("hello there...")
1580 }
1581 }"#};
1582
1583 let sources = SourceMap::new([("test".into(), source.into())], None);
1584 let (std_id, store) =
1585 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1586 let mut interpreter = Interpreter::new(
1587 sources,
1588 PackageType::Exe,
1589 TargetCapabilityFlags::all(),
1590 LanguageFeatures::default(),
1591 store,
1592 &[(std_id, None)],
1593 )
1594 .expect("interpreter should be created");
1595
1596 let (result, output) = entry(&mut interpreter);
1597 is_unit_with_output_eval_entry(&result, &output, "hello there...");
1598 }
1599
1600 #[test]
1601 fn invalid_partial_application_should_fail_not_panic() {
1602 // Found via fuzzing, see #2363
1603 let source = "operation e(oracle:(w=>)){oracle=i(_)";
1604 let sources = SourceMap::new([("test".into(), source.into())], None);
1605 let (std_id, store) =
1606 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1607 assert!(
1608 Interpreter::new(
1609 sources,
1610 PackageType::Exe,
1611 TargetCapabilityFlags::all(),
1612 LanguageFeatures::default(),
1613 store,
1614 &[(std_id, None)],
1615 )
1616 .is_err(),
1617 "interpreter should fail with error"
1618 );
1619 }
1620
1621 #[test]
1622 fn errors_returned_if_sources_do_not_match_profile() {
1623 let source = indoc! { r#"
1624 namespace A { operation Test() : Double { use q = Qubit(); mutable x = 1.0; if MResetZ(q) == One { set x = 2.0; } x } }"#};
1625
1626 let sources = SourceMap::new([("test".into(), source.into())], Some("A.Test()".into()));
1627 let (std_id, store) =
1628 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1629 let result = Interpreter::new(
1630 sources,
1631 PackageType::Exe,
1632 TargetCapabilityFlags::Adaptive
1633 | TargetCapabilityFlags::IntegerComputations
1634 | TargetCapabilityFlags::QubitReset,
1635 LanguageFeatures::default(),
1636 store,
1637 &[(std_id, None)],
1638 );
1639
1640 match result {
1641 Ok(_) => panic!("Expected error, got interpreter."),
1642 Err(errors) => is_error(
1643 &errors,
1644 &expect![[r#"
1645 cannot use a dynamic double value
1646 [<entry>] [A.Test()]
1647 cannot use a double value as an output
1648 [<entry>] [A.Test()]
1649 cannot use a dynamic double value
1650 [test] [set x = 2.0]
1651 cannot use a dynamic double value
1652 [test] [x]
1653 "#]],
1654 ),
1655 }
1656 }
1657
1658 #[test]
1659 fn stdlib_members_can_be_accessed_from_sources() {
1660 let source = indoc! { r#"
1661 namespace Test {
1662 operation Main() : Unit {
1663 Message("hello there...")
1664 }
1665 }"#};
1666
1667 let sources = SourceMap::new([("test".into(), source.into())], None);
1668 let (std_id, store) =
1669 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1670 let dependencies = &[(std_id, None)];
1671 let mut interpreter = Interpreter::new(
1672 sources,
1673 PackageType::Lib,
1674 TargetCapabilityFlags::all(),
1675 LanguageFeatures::default(),
1676 store,
1677 dependencies,
1678 )
1679 .expect("interpreter should be created");
1680
1681 let (result, output) = line(&mut interpreter, "Test.Main()");
1682 is_unit_with_output(&result, &output, "hello there...");
1683 }
1684
1685 #[test]
1686 fn members_from_namespaced_sources_are_in_context() {
1687 let source = indoc! { r#"
1688 namespace Test {
1689 function Hello() : String {
1690 "hello there..."
1691 }
1692
1693 operation Main() : String {
1694 Hello()
1695 }
1696 }"#};
1697
1698 let sources = SourceMap::new([("test".into(), source.into())], None);
1699 let store = crate::PackageStore::new(crate::compile::core());
1700 let mut interpreter = Interpreter::new(
1701 sources,
1702 PackageType::Lib,
1703 TargetCapabilityFlags::all(),
1704 LanguageFeatures::default(),
1705 store,
1706 &[],
1707 )
1708 .expect("interpreter should be created");
1709
1710 let (result, output) = line(&mut interpreter, "Test.Hello()");
1711 is_only_value(&result, &output, &Value::String("hello there...".into()));
1712 let (result, output) = line(&mut interpreter, "Test.Main()");
1713 is_only_value(&result, &output, &Value::String("hello there...".into()));
1714 }
1715
1716 #[test]
1717 fn multiple_files_are_loaded_from_sources_into_eval_context() {
1718 let sources: [(Arc<str>, Arc<str>); 2] = [
1719 (
1720 "a.qs".into(),
1721 r#"
1722 namespace Test {
1723 function Hello() : String {
1724 "hello there..."
1725 }
1726 }"#
1727 .into(),
1728 ),
1729 (
1730 "b.qs".into(),
1731 r#"
1732 namespace Test2 {
1733 open Test;
1734 @EntryPoint()
1735 operation Main() : String {
1736 Hello();
1737 Hello()
1738 }
1739 }"#
1740 .into(),
1741 ),
1742 ];
1743
1744 let sources = SourceMap::new(sources, None);
1745 let store = crate::PackageStore::new(crate::compile::core());
1746 let debugger = Debugger::new(
1747 sources,
1748 TargetCapabilityFlags::all(),
1749 Encoding::Utf8,
1750 LanguageFeatures::default(),
1751 store,
1752 &[],
1753 )
1754 .expect("debugger should be created");
1755 let bps = debugger.get_breakpoints("a.qs");
1756 assert_eq!(1, bps.len());
1757 let bps = debugger.get_breakpoints("b.qs");
1758 assert_eq!(2, bps.len());
1759 }
1760
1761 #[test]
1762 fn debugger_simple_execution_succeeds() {
1763 let source = indoc! { r#"
1764 namespace Test {
1765 function Hello() : Unit {
1766 Message("hello there...");
1767 }
1768
1769 @EntryPoint()
1770 operation Main() : Unit {
1771 Hello()
1772 }
1773 }"#};
1774
1775 let sources = SourceMap::new([("test".into(), source.into())], None);
1776 let (std_id, store) =
1777 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1778 let mut debugger = Debugger::new(
1779 sources,
1780 TargetCapabilityFlags::all(),
1781 Encoding::Utf8,
1782 LanguageFeatures::default(),
1783 store,
1784 &[(std_id, None)],
1785 )
1786 .expect("debugger should be created");
1787 let (result, output) = entry(&mut debugger.interpreter);
1788 is_unit_with_output_eval_entry(&result, &output, "hello there...");
1789 }
1790
1791 #[test]
1792 fn debugger_execution_with_call_to_library_succeeds() {
1793 let source = indoc! { r#"
1794 namespace Test {
1795 import Std.Math.*;
1796 @EntryPoint()
1797 operation Main() : Int {
1798 Binom(31, 7)
1799 }
1800 }"#};
1801
1802 let sources = SourceMap::new([("test".into(), source.into())], None);
1803 let (std_id, store) =
1804 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1805 let mut debugger = Debugger::new(
1806 sources,
1807 TargetCapabilityFlags::all(),
1808 Encoding::Utf8,
1809 LanguageFeatures::default(),
1810 store,
1811 &[(std_id, None)],
1812 )
1813 .expect("debugger should be created");
1814 let (result, output) = entry(&mut debugger.interpreter);
1815 is_only_value(&result, &output, &Value::Int(2_629_575));
1816 }
1817
1818 #[test]
1819 fn debugger_execution_with_early_return_succeeds() {
1820 let source = indoc! { r#"
1821 namespace Test {
1822 import Std.Arrays.*;
1823
1824 operation Max20(i : Int) : Int {
1825 if (i > 20) {
1826 return 20;
1827 }
1828 return i;
1829 }
1830
1831 @EntryPoint()
1832 operation Main() : Int[] {
1833 ForEach(Max20, [10, 20, 30, 40, 50])
1834 }
1835 }"#};
1836
1837 let sources = SourceMap::new([("test".into(), source.into())], None);
1838 let (std_id, store) =
1839 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1840 let mut debugger = Debugger::new(
1841 sources,
1842 TargetCapabilityFlags::all(),
1843 Encoding::Utf8,
1844 LanguageFeatures::default(),
1845 store,
1846 &[(std_id, None)],
1847 )
1848 .expect("debugger should be created");
1849
1850 let (result, output) = entry(&mut debugger.interpreter);
1851 is_only_value(
1852 &result,
1853 &output,
1854 &Value::Array(
1855 vec![
1856 Value::Int(10),
1857 Value::Int(20),
1858 Value::Int(20),
1859 Value::Int(20),
1860 Value::Int(20),
1861 ]
1862 .into(),
1863 ),
1864 );
1865 }
1866
1867 #[test]
1868 fn multiple_namespaces_are_loaded_from_sources_into_eval_context() {
1869 let source = indoc! { r#"
1870 namespace Test {
1871 function Hello() : String {
1872 "hello there..."
1873 }
1874 }
1875 namespace Test2 {
1876 open Test;
1877 operation Main() : String {
1878 Hello()
1879 }
1880 }"#};
1881
1882 let sources = SourceMap::new([("test".into(), source.into())], None);
1883 let store = crate::PackageStore::new(crate::compile::core());
1884 let mut interpreter = Interpreter::new(
1885 sources,
1886 PackageType::Lib,
1887 TargetCapabilityFlags::all(),
1888 LanguageFeatures::default(),
1889 store,
1890 &[],
1891 )
1892 .expect("interpreter should be created");
1893 let (result, output) = line(&mut interpreter, "Test.Hello()");
1894 is_only_value(&result, &output, &Value::String("hello there...".into()));
1895 let (result, output) = line(&mut interpreter, "Test2.Main()");
1896 is_only_value(&result, &output, &Value::String("hello there...".into()));
1897 }
1898
1899 #[test]
1900 fn runtime_error_from_stdlib() {
1901 let sources = SourceMap::new(
1902 [(
1903 "test".into(),
1904 "namespace Foo {
1905 operation Bar(): Unit {
1906 let x = -1;
1907 use qs = Qubit[x];
1908 }
1909 }
1910 "
1911 .into(),
1912 )],
1913 Some("Foo.Bar()".into()),
1914 );
1915
1916 let store = crate::PackageStore::new(crate::compile::core());
1917 let mut interpreter = Interpreter::new(
1918 sources,
1919 PackageType::Lib,
1920 TargetCapabilityFlags::all(),
1921 LanguageFeatures::default(),
1922 store,
1923 &[],
1924 )
1925 .expect("interpreter should be created");
1926
1927 let (result, output) = entry(&mut interpreter);
1928 is_only_error(
1929 &result,
1930 &output,
1931 &expect![[r#"
1932 runtime error: program failed: Cannot allocate qubit array with a negative length
1933 explicit fail [qsharp-library-source:core/qir.qs] [fail "Cannot allocate qubit array with a negative length"]
1934 "#]],
1935 );
1936 }
1937
1938 #[test]
1939 fn interpreter_returns_items_from_source() {
1940 let sources = SourceMap::new(
1941 [(
1942 "test".into(),
1943 "namespace A {
1944 operation B(): Unit { }
1945 }
1946 "
1947 .into(),
1948 )],
1949 Some("A.B()".into()),
1950 );
1951
1952 let (std_id, store) =
1953 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
1954 let interpreter = Interpreter::new(
1955 sources,
1956 PackageType::Lib,
1957 TargetCapabilityFlags::all(),
1958 LanguageFeatures::default(),
1959 store,
1960 &[(std_id, None)],
1961 )
1962 .expect("interpreter should be created");
1963
1964 let items = interpreter.user_globals();
1965 assert_eq!(1, items.len());
1966 expect![[r#"
1967 [
1968 "A",
1969 ]
1970 "#]]
1971 .assert_debug_eq(&items[0].0);
1972 expect![[r#"
1973 "B"
1974 "#]]
1975 .assert_debug_eq(&items[0].1);
1976 }
1977
1978 #[test]
1979 fn interpreter_can_be_created_from_ast() {
1980 let sources = SourceMap::new(
1981 [(
1982 "test".into(),
1983 "namespace A {
1984 operation B(): Result {
1985 use qs = Qubit[2];
1986 X(qs[0]);
1987 CNOT(qs[0], qs[1]);
1988 let res = Measure([PauliZ, PauliZ], qs[...1]);
1989 ResetAll(qs);
1990 res
1991 }
1992 }
1993 "
1994 .into(),
1995 )],
1996 Some("A.B()".into()),
1997 );
1998
1999 let (package_type, capabilities, language_features) = (
2000 PackageType::Lib,
2001 TargetCapabilityFlags::all(),
2002 LanguageFeatures::default(),
2003 );
2004
2005 let mut store = crate::PackageStore::new(crate::compile::core());
2006 let dependencies = vec![(
2007 store.insert(crate::compile::std(&store, capabilities)),
2008 None,
2009 )];
2010
2011 let (mut unit, errors) = crate::compile::compile(
2012 &store,
2013 &dependencies,
2014 sources,
2015 package_type,
2016 capabilities,
2017 language_features,
2018 );
2019 unit.expose();
2020 for e in &errors {
2021 eprintln!("{e:?}");
2022 }
2023 assert!(errors.is_empty(), "compilation failed: {}", errors[0]);
2024 let package_id = store.insert(unit);
2025
2026 let mut interpreter = Interpreter::from(
2027 false,
2028 store,
2029 package_id,
2030 capabilities,
2031 language_features,
2032 &dependencies,
2033 )
2034 .expect("interpreter should be created");
2035 let (result, output) = entry(&mut interpreter);
2036 is_only_value(
2037 &result,
2038 &output,
2039 &Value::Result(qsc_eval::val::Result::Val(false)),
2040 );
2041 }
2042
2043 #[test]
2044 fn ast_fragments_can_be_evaluated() {
2045 let sources = SourceMap::new(
2046 [(
2047 "test".into(),
2048 "namespace A {
2049 operation B(): Result {
2050 use qs = Qubit[2];
2051 X(qs[0]);
2052 CNOT(qs[0], qs[1]);
2053 let res = Measure([PauliZ, PauliZ], qs[...1]);
2054 ResetAll(qs);
2055 res
2056 }
2057 }
2058 "
2059 .into(),
2060 )],
2061 None,
2062 );
2063 let (std_id, store) =
2064 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2065 let mut interpreter = Interpreter::new(
2066 sources,
2067 PackageType::Lib,
2068 TargetCapabilityFlags::all(),
2069 LanguageFeatures::default(),
2070 store,
2071 &[(std_id, None)],
2072 )
2073 .expect("interpreter should be created");
2074
2075 let package = get_package_for_call("A", "B");
2076 let (result, output) = fragment(&mut interpreter, "A.B()", package);
2077 is_only_value(
2078 &result,
2079 &output,
2080 &Value::Result(qsc_eval::val::Result::Val(false)),
2081 );
2082 }
2083
2084 #[test]
2085 fn ast_fragments_evaluation_returns_runtime_errors() {
2086 let sources = SourceMap::new(
2087 [(
2088 "test".into(),
2089 "namespace A {
2090 operation B(): Int {
2091 42 / 0
2092 }
2093 }
2094 "
2095 .into(),
2096 )],
2097 None,
2098 );
2099 let (std_id, store) =
2100 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2101 let mut interpreter = Interpreter::new(
2102 sources,
2103 PackageType::Lib,
2104 TargetCapabilityFlags::all(),
2105 LanguageFeatures::default(),
2106 store,
2107 &[(std_id, None)],
2108 )
2109 .expect("interpreter should be created");
2110
2111 let package = get_package_for_call("A", "B");
2112 let (result, output) = fragment(&mut interpreter, "A.B()", package);
2113 is_only_error(
2114 &result,
2115 &output,
2116 &expect![[r#"
2117 runtime error: division by zero
2118 cannot divide by zero [test] [0]
2119 "#]],
2120 );
2121 }
2122
2123 fn get_package_for_call(ns: &str, name: &str) -> crate::ast::Package {
2124 let args = Expr {
2125 id: NodeId::default(),
2126 span: Span::default(),
2127 kind: Box::new(ExprKind::Tuple(Box::new([]))),
2128 };
2129 let path = Path {
2130 id: NodeId::default(),
2131 span: Span::default(),
2132 segments: Some(
2133 std::iter::once(qsc_ast::ast::Ident {
2134 id: NodeId::default(),
2135 span: Span::default(),
2136 name: ns.into(),
2137 })
2138 .collect(),
2139 ),
2140 name: Box::new(qsc_ast::ast::Ident {
2141 id: NodeId::default(),
2142 span: Span::default(),
2143 name: name.into(),
2144 }),
2145 };
2146 let path_expr = Expr {
2147 id: NodeId::default(),
2148 span: Span::default(),
2149 kind: Box::new(ExprKind::Path(PathKind::Ok(Box::new(path)))),
2150 };
2151 let expr = Expr {
2152 id: NodeId::default(),
2153 span: Span::default(),
2154 kind: Box::new(ExprKind::Call(Box::new(path_expr), Box::new(args))),
2155 };
2156 let stmt = Stmt {
2157 id: NodeId::default(),
2158 span: Span::default(),
2159 kind: Box::new(StmtKind::Expr(Box::new(expr))),
2160 };
2161 let top_level = TopLevelNode::Stmt(Box::new(stmt));
2162 Package {
2163 id: NodeId::default(),
2164 nodes: vec![top_level].into_boxed_slice(),
2165 entry: None,
2166 }
2167 }
2168
2169 #[test]
2170 fn name_resolution_from_source_named_main_should_succeed() {
2171 let sources = SourceMap::new(
2172 [(
2173 "Main".into(),
2174 r#"function Foo() : Unit { Message("hello there..."); }"#.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 // Operations defined in Main.qs should also be visible with Main qualifier.
2191 let (result, output) = line(&mut interpreter, "Main.Foo()");
2192 is_unit_with_output(&result, &output, "hello there...");
2193
2194 // Operations defined in Main.qs should be importable with fully qualified name.
2195 let (result, output) = line(&mut interpreter, "import Main.Foo;");
2196 is_only_value(&result, &output, &Value::unit());
2197
2198 // After import the operation can be invoked without Main qualifier.
2199 let (result, output) = line(&mut interpreter, "Foo()");
2200 is_unit_with_output(&result, &output, "hello there...");
2201 }
2202
2203 #[test]
2204 fn name_resolution_from_source_named_main_without_full_path_or_import_should_fail() {
2205 let sources = SourceMap::new(
2206 [(
2207 "Main".into(),
2208 r#"function Foo() : Unit { Message("hello there..."); }"#.into(),
2209 )],
2210 None,
2211 );
2212 let (std_id, store) =
2213 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2214 let mut interpreter = Interpreter::new(
2215 sources,
2216 PackageType::Lib,
2217 TargetCapabilityFlags::all(),
2218 LanguageFeatures::default(),
2219 store,
2220 &[(std_id, None)],
2221 )
2222 .expect("interpreter should be created");
2223
2224 // Operations defined in Main.qs should also be visible with Main qualifier.
2225 let (errors, _) = line(&mut interpreter, "Foo()");
2226 is_error(
2227 &errors.expect_err("line invocation should fail with error"),
2228 &expect![[r#"
2229 name error: `Foo` not found
2230 [line_0] [Foo]
2231 type error: insufficient type information to infer type
2232 [line_0] [Foo()]
2233 "#]],
2234 );
2235 }
2236
2237 /// Found via fuzzing, see #2426 <https://github.com/microsoft/qsharp/issues/2426>
2238 #[test]
2239 fn recursive_type_constraint_should_fail() {
2240 let sources = SourceMap::new(
2241 [(
2242 "test".into(),
2243 r#"operation a(){(foo,bar)->foo+bar=foo->foo"#.into(),
2244 )],
2245 None,
2246 );
2247 let (std_id, store) =
2248 crate::compile::package_store_with_stdlib(TargetCapabilityFlags::all());
2249 match Interpreter::new(
2250 sources,
2251 PackageType::Lib,
2252 TargetCapabilityFlags::all(),
2253 LanguageFeatures::default(),
2254 store,
2255 &[(std_id, None)],
2256 ) {
2257 Ok(_) => panic!("interpreter should fail with error"),
2258 Err(errors) => {
2259 is_error(
2260 &errors,
2261 &expect![[r#"
2262 syntax error: expected `:`, found `{`
2263 [test] [{]
2264 syntax error: expected `}`, found EOF
2265 [test] []
2266 type error: unsupported recursive type constraint
2267 [test] [(foo,bar)->foo+bar]
2268 type error: insufficient type information to infer type
2269 [test] [foo+bar]
2270 "#]],
2271 );
2272 }
2273 }
2274 }
2275 }
2276}
2277