microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.27.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

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

2383lines · modecode

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