microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e874bfb8e1dbfc3eec7aebe87f45fc0cb4c547b6

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc/src/interpret/tests.rs

1544lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4#![allow(clippy::needless_raw_string_hashes)]
5
6mod given_interpreter {
7 use crate::interpret::{Error, InterpretResult, Interpreter};
8 use expect_test::Expect;
9 use miette::Diagnostic;
10 use qsc_data_structures::language_features::LanguageFeatures;
11 use qsc_eval::{output::CursorReceiver, val::Value};
12 use qsc_frontend::compile::{SourceMap, TargetCapabilityFlags};
13 use qsc_passes::PackageType;
14 use std::{fmt::Write, io::Cursor, iter, str::from_utf8};
15
16 fn line(interpreter: &mut Interpreter, line: &str) -> (InterpretResult, String) {
17 let mut cursor = Cursor::new(Vec::<u8>::new());
18 let mut receiver = CursorReceiver::new(&mut cursor);
19 (
20 interpreter.eval_fragments(&mut receiver, line),
21 receiver.dump(),
22 )
23 }
24
25 fn run(
26 interpreter: &mut Interpreter,
27 expr: &str,
28 ) -> (Result<InterpretResult, Vec<Error>>, String) {
29 let mut cursor = Cursor::new(Vec::<u8>::new());
30 let mut receiver = CursorReceiver::new(&mut cursor);
31 (interpreter.run(&mut receiver, expr), receiver.dump())
32 }
33
34 fn entry(
35 interpreter: &mut Interpreter,
36 ) -> (Result<Value, Vec<crate::interpret::Error>>, String) {
37 let mut cursor = Cursor::new(Vec::<u8>::new());
38 let mut receiver = CursorReceiver::new(&mut cursor);
39 (interpreter.eval_entry(&mut receiver), receiver.dump())
40 }
41
42 mod without_sources {
43 use expect_test::expect;
44 use indoc::indoc;
45 use qsc_frontend::compile::TargetCapabilityFlags;
46
47 use super::*;
48
49 mod without_stdlib {
50 use qsc_frontend::compile::SourceMap;
51 use qsc_passes::PackageType;
52
53 use super::*;
54
55 #[test]
56 fn stdlib_members_should_be_unavailable() {
57 let mut interpreter = Interpreter::new(
58 false,
59 SourceMap::default(),
60 PackageType::Lib,
61 TargetCapabilityFlags::all(),
62 LanguageFeatures::default(),
63 )
64 .expect("interpreter should be created");
65
66 let (result, output) = line(&mut interpreter, "Message(\"_\")");
67 is_only_error(
68 &result,
69 &output,
70 &expect![[r#"
71 name error: `Message` not found
72 [line_0] [Message]
73 type error: insufficient type information to infer type
74 [line_0] [Message("_")]
75 "#]],
76 );
77 }
78 }
79
80 #[test]
81 fn stdlib_members_should_be_available() {
82 let mut interpreter = get_interpreter();
83 let (result, output) = line(&mut interpreter, "Message(\"_\")");
84 is_unit_with_output(&result, &output, "_");
85 }
86
87 #[test]
88 fn core_members_should_be_available() {
89 let mut interpreter = get_interpreter();
90 let (result, output) = line(&mut interpreter, "Length([1, 2, 3])");
91 is_only_value(&result, &output, &Value::Int(3));
92 }
93
94 #[test]
95 fn let_bindings_update_interpreter() {
96 let mut interpreter = get_interpreter();
97 line(&mut interpreter, "let y = 7;")
98 .0
99 .expect("line should succeed");
100 let (result, output) = line(&mut interpreter, "y");
101 is_only_value(&result, &output, &Value::Int(7));
102 }
103
104 #[test]
105 fn let_bindings_can_be_shadowed() {
106 let mut interpreter = get_interpreter();
107
108 let (result, output) = line(&mut interpreter, "let y = 7;");
109 is_only_value(&result, &output, &Value::unit());
110
111 let (result, output) = line(&mut interpreter, "y");
112 is_only_value(&result, &output, &Value::Int(7));
113
114 let (result, output) = line(&mut interpreter, "let y = \"Hello\";");
115 is_only_value(&result, &output, &Value::unit());
116
117 let (result, output) = line(&mut interpreter, "y");
118 is_only_value(&result, &output, &Value::String("Hello".into()));
119 }
120
121 #[test]
122 fn invalid_statements_return_error() {
123 let mut interpreter = get_interpreter();
124
125 let (result, output) = line(&mut interpreter, "let y = 7");
126 is_only_error(
127 &result,
128 &output,
129 &expect![[r#"
130 syntax error: expected `;`, found EOF
131 [line_0] []
132 "#]],
133 );
134
135 let (result, output) = line(&mut interpreter, "y");
136 is_only_error(
137 &result,
138 &output,
139 &expect![[r#"
140 name error: `y` not found
141 [line_1] [y]
142 "#]],
143 );
144 }
145
146 #[test]
147 fn invalid_statements_and_unbound_vars_return_error() {
148 let mut interpreter = get_interpreter();
149
150 let (result, output) = line(&mut interpreter, "let y = x;");
151 is_only_error(
152 &result,
153 &output,
154 &expect![[r#"
155 name error: `x` not found
156 [line_0] [x]
157 type error: insufficient type information to infer type
158 [line_0] [y]
159 "#]],
160 );
161
162 let (result, output) = line(&mut interpreter, "y");
163 is_only_error(
164 &result,
165 &output,
166 &expect![[r#"
167 runtime error: name is not bound
168 [line_1] [y]
169 "#]],
170 );
171 }
172
173 #[test]
174 fn failing_statements_return_early_error() {
175 let mut interpreter = get_interpreter();
176 let (result, output) = line(&mut interpreter, "let y = 7;y/0;y");
177 is_only_error(
178 &result,
179 &output,
180 &expect![[r#"
181 runtime error: division by zero
182 cannot divide by zero [line_0] [0]
183 "#]],
184 );
185 }
186
187 #[test]
188 fn passes_are_run_on_incremental() {
189 let mut interpreter = get_interpreter();
190 let (result, output) = line(
191 &mut interpreter,
192 "within {Message(\"A\");} apply {Message(\"B\");}",
193 );
194 is_unit_with_output(&result, &output, "A\nB\nA");
195 }
196
197 #[test]
198 fn declare_function() {
199 let mut interpreter = get_interpreter();
200 let (result, output) = line(&mut interpreter, "function Foo() : Int { 2 }");
201 is_only_value(&result, &output, &Value::unit());
202 let (result, output) = line(&mut interpreter, "Foo()");
203 is_only_value(&result, &output, &Value::Int(2));
204 }
205
206 #[test]
207 fn invalid_declare_function_and_unbound_call_return_error() {
208 let mut interpreter = get_interpreter();
209 let (result, output) = line(&mut interpreter, "function Foo() : Int { invalid }");
210 is_only_error(
211 &result,
212 &output,
213 &expect![[r#"
214 name error: `invalid` not found
215 [line_0] [invalid]
216 "#]],
217 );
218 let (result, output) = line(&mut interpreter, "Foo()");
219 is_only_error(
220 &result,
221 &output,
222 &expect![[r#"
223 runtime error: name is not bound
224 [line_1] [Foo]
225 "#]],
226 );
227 }
228
229 #[test]
230 fn declare_function_call_same_line() {
231 let mut interpreter = get_interpreter();
232 let (result, output) = line(&mut interpreter, "function Foo() : Int { 2 }; Foo()");
233 is_only_value(&result, &output, &Value::Int(2));
234 }
235
236 #[test]
237 fn let_binding_function_declaration_call_same_line() {
238 let mut interpreter = get_interpreter();
239 let (result, output) = line(
240 &mut interpreter,
241 "let x = 1; function Foo() : Int { 2 }; Foo() + 1",
242 );
243 is_only_value(&result, &output, &Value::Int(3));
244 }
245
246 #[test]
247 fn nested_function() {
248 let mut interpreter = get_interpreter();
249 let (result, output) = line(
250 &mut interpreter,
251 "function Foo() : Int { function Bar() : Int { 1 }; Bar() + 1 }; Foo() + 1",
252 );
253 is_only_value(&result, &output, &Value::Int(3));
254 }
255
256 #[test]
257 fn open_namespace() {
258 let mut interpreter = get_interpreter();
259 let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
260 is_only_value(&result, &output, &Value::unit());
261 let (result, output) = line(&mut interpreter, "DumpMachine()");
262 is_unit_with_output(&result, &output, "STATE:\n|0⟩: 1+0i");
263 }
264
265 #[test]
266 fn open_namespace_call_same_line() {
267 let mut interpreter = get_interpreter();
268 let (result, output) = line(
269 &mut interpreter,
270 "open Microsoft.Quantum.Diagnostics; DumpMachine()",
271 );
272 is_unit_with_output(&result, &output, "STATE:\n|0⟩: 1+0i");
273 }
274
275 #[test]
276 fn declare_namespace_call() {
277 let mut interpreter = get_interpreter();
278 let (result, output) = line(
279 &mut interpreter,
280 "namespace Foo { function Bar() : Int { 5 } }",
281 );
282 is_only_value(&result, &output, &Value::unit());
283 let (result, output) = line(&mut interpreter, "Foo.Bar()");
284 is_only_value(&result, &output, &Value::Int(5));
285 }
286
287 #[test]
288 fn declare_namespace_open_call() {
289 let mut interpreter = get_interpreter();
290 let (result, output) = line(
291 &mut interpreter,
292 "namespace Foo { function Bar() : Int { 5 } }",
293 );
294 is_only_value(&result, &output, &Value::unit());
295 let (result, output) = line(&mut interpreter, "open Foo;");
296 is_only_value(&result, &output, &Value::unit());
297 let (result, output) = line(&mut interpreter, "Bar()");
298 is_only_value(&result, &output, &Value::Int(5));
299 }
300
301 #[test]
302 fn declare_namespace_open_call_same_line() {
303 let mut interpreter = get_interpreter();
304 let (result, output) = line(
305 &mut interpreter,
306 "namespace Foo { function Bar() : Int { 5 } } open Foo; Bar()",
307 );
308 is_only_value(&result, &output, &Value::Int(5));
309 }
310
311 #[test]
312 fn mix_stmts_and_namespace_same_line() {
313 let mut interpreter = get_interpreter();
314 let (result, output) = line(
315 &mut interpreter,
316 "Message(\"before\"); namespace Foo { function Bar() : Int { 5 } } Message(\"after\")",
317 );
318 is_unit_with_output(&result, &output, "before\nafter");
319 }
320
321 #[test]
322 fn global_qubits() {
323 let mut interpreter = get_interpreter();
324 let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
325 is_only_value(&result, &output, &Value::unit());
326 let (result, output) = line(&mut interpreter, "DumpMachine()");
327 is_unit_with_output(&result, &output, "STATE:\n|0⟩: 1+0i");
328 let (result, output) = line(&mut interpreter, "use (q0, qs) = (Qubit(), Qubit[3]);");
329 is_only_value(&result, &output, &Value::unit());
330 let (result, output) = line(&mut interpreter, "DumpMachine()");
331 is_unit_with_output(&result, &output, "STATE:\n|0000⟩: 1+0i");
332 let (result, output) = line(&mut interpreter, "X(q0); X(qs[1]);");
333 is_only_value(&result, &output, &Value::unit());
334 let (result, output) = line(&mut interpreter, "DumpMachine()");
335 is_unit_with_output(&result, &output, "STATE:\n|1010⟩: 1+0i");
336 }
337
338 #[test]
339 fn ambiguous_type_error_in_top_level_stmts() {
340 let mut interpreter = get_interpreter();
341 let (result, output) = line(&mut interpreter, "let x = [];");
342 is_only_error(
343 &result,
344 &output,
345 &expect![[r#"
346 type error: insufficient type information to infer type
347 [line_0] [[]]
348 "#]],
349 );
350 let (result, output) = line(&mut interpreter, "let x = []; let y = [0] + x;");
351 is_only_value(&result, &output, &Value::unit());
352 let (result, output) = line(&mut interpreter, "function Foo() : Unit { let x = []; }");
353 is_only_error(
354 &result,
355 &output,
356 &expect![[r#"
357 type error: insufficient type information to infer type
358 [line_2] [[]]
359 "#]],
360 );
361 }
362
363 #[test]
364 fn resolved_type_persists_across_stmts() {
365 let mut interpreter = get_interpreter();
366 let (result, output) = line(&mut interpreter, "let x = []; let y = [0] + x;");
367 is_only_value(&result, &output, &Value::unit());
368 let (result, output) = line(&mut interpreter, "let z = [0.0] + x;");
369 is_only_error(
370 &result,
371 &output,
372 &expect![[r#"
373 type error: expected Double, found Int
374 [line_1] [x]
375 "#]],
376 );
377 }
378
379 #[test]
380 fn incremental_lambas_work() {
381 let mut interpreter = get_interpreter();
382 let (result, output) = line(&mut interpreter, "let x = 1; let f = (y) -> x + y;");
383 is_only_value(&result, &output, &Value::unit());
384 let (result, output) = line(&mut interpreter, "f(1)");
385 is_only_value(&result, &output, &Value::Int(2));
386 }
387
388 #[test]
389 fn mutability_persists_across_stmts() {
390 let mut interpreter = get_interpreter();
391 let (result, output) = line(
392 &mut interpreter,
393 "mutable x : Int[] = []; let y : Int[] = [];",
394 );
395 is_only_value(&result, &output, &Value::unit());
396 let (result, output) = line(&mut interpreter, "set x += [0];");
397 is_only_value(&result, &output, &Value::unit());
398 let (result, output) = line(&mut interpreter, "set y += [0];");
399 is_only_error(
400 &result,
401 &output,
402 &expect![[r#"
403 cannot update immutable variable
404 [line_2] [y]
405 "#]],
406 );
407 let (result, output) = line(&mut interpreter, "let lam = () -> y + [0];");
408 is_only_value(&result, &output, &Value::unit());
409 let (result, output) = line(&mut interpreter, "let lam = () -> x + [0];");
410 is_only_error(
411 &result,
412 &output,
413 &expect![[r#"
414 lambdas cannot close over mutable variables
415 [line_4] [() -> x + [0]]
416 "#]],
417 );
418 }
419
420 #[test]
421 fn runtime_error_across_lines() {
422 let mut interpreter = get_interpreter();
423 let (result, output) = line(
424 &mut interpreter,
425 "operation Main() : Unit { Microsoft.Quantum.Random.DrawRandomInt(2,1); }",
426 );
427 is_only_value(&result, &output, &Value::unit());
428 let (result, output) = line(&mut interpreter, "Main()");
429 is_only_error(
430 &result,
431 &output,
432 &expect![[r#"
433 runtime error: empty range
434 the range cannot be empty [line_0] [(2,1)]
435 "#]],
436 );
437 }
438
439 #[test]
440 fn compiler_error_across_lines() {
441 let mut interpreter = get_interpreter();
442 let (result, output) = line(
443 &mut interpreter,
444 "namespace Other { operation DumpMachine() : Unit { } }",
445 );
446 is_only_value(&result, &output, &Value::unit());
447 let (result, output) = line(&mut interpreter, "open Other;");
448 is_only_value(&result, &output, &Value::unit());
449 let (result, output) = line(&mut interpreter, "open Microsoft.Quantum.Diagnostics;");
450 is_only_value(&result, &output, &Value::unit());
451 let (result, output) = line(&mut interpreter, "DumpMachine();");
452 is_only_error(
453 &result,
454 &output,
455 &expect![[r#"
456 name error: `DumpMachine` could refer to the item in `Other` or `Microsoft.Quantum.Diagnostics`
457 ambiguous name [line_3] [DumpMachine]
458 found in this namespace [line_1] [Other]
459 and also in this namespace [line_2] [Microsoft.Quantum.Diagnostics]
460 type error: insufficient type information to infer type
461 [line_3] [DumpMachine()]
462 "#]],
463 );
464 }
465
466 #[test]
467 fn runtime_error_from_stdlib() {
468 let mut interpreter = get_interpreter();
469 let (result, output) = line(&mut interpreter, "use q = Qubit(); CNOT(q,q)");
470 is_only_error(
471 &result,
472 &output,
473 &expect![[r#"
474 runtime error: qubits in invocation are not unique
475 [intrinsic.qs] [(control, target)]
476 "#]],
477 );
478 }
479
480 #[test]
481 fn items_usable_before_definition() {
482 let mut interpreter = get_interpreter();
483 let (result, output) = line(
484 &mut interpreter,
485 indoc! {r#"
486 function A() : Unit {
487 B();
488 }
489 function B() : Unit {}
490 A()
491 "#},
492 );
493 is_only_value(&result, &output, &Value::unit());
494 }
495
496 #[test]
497 fn items_usable_before_definition_top_level() {
498 let mut interpreter = get_interpreter();
499 let (result, output) = line(
500 &mut interpreter,
501 indoc! {r#"
502 B();
503 function B() : Unit {}
504 "#},
505 );
506 is_only_value(&result, &output, &Value::unit());
507 }
508
509 #[test]
510 fn callables_failing_profile_validation_are_still_registered() {
511 fn verify_same_error<E>(result: &Result<Value, Vec<E>>, output: &str)
512 where
513 E: Diagnostic,
514 {
515 is_only_error(
516 result,
517 output,
518 &expect![[r#"
519 cannot use a dynamic integer value
520 [line_0] [set x = 2]
521 cannot use a dynamic integer value
522 [line_0] [x]
523 "#]],
524 );
525 }
526 let mut interpreter = get_interpreter_with_capbilities(TargetCapabilityFlags::Adaptive);
527 let (result, output) = line(
528 &mut interpreter,
529 indoc! {r#"
530 operation Foo() : Int { use q = Qubit(); mutable x = 1; if MResetZ(q) == One { set x = 2; } x }
531 "#},
532 );
533 verify_same_error(&result, &output);
534 // do something innocuous
535 let (result, output) = line(&mut interpreter, indoc! {r#"Foo()"#});
536 // if the callable wasn't registered, this would panic instead of returning an error.
537 verify_same_error(&result, &output);
538 }
539
540 #[test]
541 fn once_rca_validation_fails_following_calls_also_fail_by_design() {
542 fn verify_same_error<E>(result: &Result<Value, Vec<E>>, output: &str)
543 where
544 E: Diagnostic,
545 {
546 is_only_error(
547 result,
548 output,
549 &expect![[r#"
550 cannot use a dynamic integer value
551 [line_0] [set x = 2]
552 cannot use a dynamic integer value
553 [line_0] [x]
554 "#]],
555 );
556 }
557 let mut interpreter = get_interpreter_with_capbilities(TargetCapabilityFlags::Adaptive);
558 let (result, output) = line(
559 &mut interpreter,
560 indoc! {r#"
561 operation Foo() : Int { use q = Qubit(); mutable x = 1; if MResetZ(q) == One { set x = 2; } x }
562 "#},
563 );
564 verify_same_error(&result, &output);
565 // do something innocuous
566 let (result, output) = line(
567 &mut interpreter,
568 indoc! {r#"
569 let y = 7;
570 "#},
571 );
572 verify_same_error(&result, &output);
573 }
574
575 #[test]
576 fn namespace_usable_before_definition() {
577 let mut interpreter = get_interpreter();
578 let (result, output) = line(
579 &mut interpreter,
580 indoc! {r#"
581 A.B();
582 namespace A {
583 function B() : Unit {}
584 }
585 "#},
586 );
587 is_only_value(&result, &output, &Value::unit());
588 }
589
590 #[test]
591 fn mutually_recursive_namespaces_work() {
592 let mut interpreter = get_interpreter();
593 let (result, output) = line(
594 &mut interpreter,
595 indoc! {r#"
596 A.B();
597 namespace A {
598 open C;
599 function B() : Unit {
600 D();
601 }
602 function E() : Unit {}
603 }
604 namespace C {
605 open A;
606 function D() : Unit {
607 E();
608 }
609 }
610 "#},
611 );
612 is_only_value(&result, &output, &Value::unit());
613 }
614
615 #[test]
616 fn local_var_valid_after_item_definition() {
617 let mut interpreter = Interpreter::new(
618 true,
619 SourceMap::default(),
620 PackageType::Lib,
621 TargetCapabilityFlags::empty(),
622 LanguageFeatures::default(),
623 )
624 .expect("interpreter should be created");
625 let (result, output) = line(&mut interpreter, "let a = 1;");
626 is_only_value(&result, &output, &Value::unit());
627 let (result, output) = line(&mut interpreter, "a");
628 is_only_value(&result, &output, &Value::Int(1));
629 let (result, output) = line(
630 &mut interpreter,
631 "function B() : Int { let inner_b = 3; inner_b }",
632 );
633 is_only_value(&result, &output, &Value::unit());
634 let (result, output) = line(&mut interpreter, "B()");
635 is_only_value(&result, &output, &Value::Int(3));
636 let (result, output) = line(&mut interpreter, "let b = 2;");
637 is_only_value(&result, &output, &Value::unit());
638 let (result, output) = line(&mut interpreter, "b");
639 is_only_value(&result, &output, &Value::Int(2));
640 let (result, output) = line(&mut interpreter, "a");
641 is_only_value(&result, &output, &Value::Int(1));
642 let (result, output) = line(&mut interpreter, "B()");
643 is_only_value(&result, &output, &Value::Int(3));
644 }
645
646 #[test]
647 fn normal_qirgen() {
648 let mut interpreter = Interpreter::new(
649 true,
650 SourceMap::default(),
651 PackageType::Lib,
652 TargetCapabilityFlags::empty(),
653 LanguageFeatures::default(),
654 )
655 .expect("interpreter should be created");
656 let (result, output) = line(
657 &mut interpreter,
658 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
659 );
660 is_only_value(&result, &output, &Value::unit());
661 let res = interpreter.qirgen("Foo()").expect("expected success");
662 expect![[r#"
663 %Result = type opaque
664 %Qubit = type opaque
665
666 define void @ENTRYPOINT__main() #0 {
667 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
668 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
669 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
670 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
671 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
672 ret void
673 }
674
675 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
676 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
677 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
678 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
679 declare void @__quantum__qis__rx__body(double, %Qubit*)
680 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
681 declare void @__quantum__qis__ry__body(double, %Qubit*)
682 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
683 declare void @__quantum__qis__rz__body(double, %Qubit*)
684 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
685 declare void @__quantum__qis__h__body(%Qubit*)
686 declare void @__quantum__qis__s__body(%Qubit*)
687 declare void @__quantum__qis__s__adj(%Qubit*)
688 declare void @__quantum__qis__t__body(%Qubit*)
689 declare void @__quantum__qis__t__adj(%Qubit*)
690 declare void @__quantum__qis__x__body(%Qubit*)
691 declare void @__quantum__qis__y__body(%Qubit*)
692 declare void @__quantum__qis__z__body(%Qubit*)
693 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
694 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
695 declare void @__quantum__rt__result_record_output(%Result*, i8*)
696 declare void @__quantum__rt__array_record_output(i64, i8*)
697 declare void @__quantum__rt__tuple_record_output(i64, i8*)
698
699 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
700 attributes #1 = { "irreversible" }
701
702 ; module flags
703
704 !llvm.module.flags = !{!0, !1, !2, !3}
705
706 !0 = !{i32 1, !"qir_major_version", i32 1}
707 !1 = !{i32 7, !"qir_minor_version", i32 0}
708 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
709 !3 = !{i32 1, !"dynamic_result_management", i1 false}
710 "#]].assert_eq(&res);
711 }
712
713 #[test]
714 fn adaptive_qirgen() {
715 let mut interpreter = Interpreter::new(
716 true,
717 SourceMap::default(),
718 PackageType::Lib,
719 TargetCapabilityFlags::Adaptive,
720 LanguageFeatures::default(),
721 )
722 .expect("interpreter should be created");
723 let (result, output) = line(
724 &mut interpreter,
725 indoc! {r#"
726 namespace Test {
727 open Microsoft.Quantum.Math;
728 open QIR.Intrinsic;
729 @EntryPoint()
730 operation Main() : Unit {
731 use q = Qubit();
732 let pi_over_2 = 4.0 / 2.0;
733 __quantum__qis__rz__body(pi_over_2, q);
734 mutable some_angle = ArcSin(0.0);
735 __quantum__qis__rz__body(some_angle, q);
736 set some_angle = ArcCos(-1.0) / PI();
737 __quantum__qis__rz__body(some_angle, q);
738 }
739 }"#
740 },
741 );
742 is_only_value(&result, &output, &Value::unit());
743 let res = interpreter.qirgen("Test.Main()").expect("expected success");
744 expect![[r#"
745 %Result = type opaque
746 %Qubit = type opaque
747
748 define void @ENTRYPOINT__main() #0 {
749 block_0:
750 call void @__quantum__qis__rz__body(double 2.0, %Qubit* inttoptr (i64 0 to %Qubit*))
751 call void @__quantum__qis__rz__body(double 0.0, %Qubit* inttoptr (i64 0 to %Qubit*))
752 call void @__quantum__qis__rz__body(double 1.0, %Qubit* inttoptr (i64 0 to %Qubit*))
753 ret void
754 }
755
756 declare void @__quantum__qis__rz__body(double, %Qubit*)
757
758 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="adaptive_profile" "required_num_qubits"="1" "required_num_results"="0" }
759 attributes #1 = { "irreversible" }
760
761 ; module flags
762
763 !llvm.module.flags = !{!0, !1, !2, !3}
764
765 !0 = !{i32 1, !"qir_major_version", i32 1}
766 !1 = !{i32 7, !"qir_minor_version", i32 0}
767 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
768 !3 = !{i32 1, !"dynamic_result_management", i1 false}
769 "#]]
770 .assert_eq(&res);
771 }
772
773 #[test]
774 fn adaptive_qirgen_fails_when_entry_expr_does_not_match_profile() {
775 let mut interpreter = Interpreter::new(
776 true,
777 SourceMap::default(),
778 PackageType::Lib,
779 TargetCapabilityFlags::Adaptive,
780 LanguageFeatures::default(),
781 )
782 .expect("interpreter should be created");
783 let (result, output) = line(
784 &mut interpreter,
785 indoc! {r#"
786 use q = Qubit();
787 mutable x = 1;
788 "#
789 },
790 );
791 is_only_value(&result, &output, &Value::unit());
792 let res = interpreter
793 .qirgen("if M(q) == One { set x = 2; }")
794 .expect_err("expected error");
795 is_error(
796 &res,
797 &expect![[r#"
798 cannot use a dynamic integer value
799 [<entry>] [set x = 2]
800 "#]],
801 );
802 }
803
804 #[test]
805 fn qirgen_entry_expr_in_block() {
806 let mut interpreter = Interpreter::new(
807 true,
808 SourceMap::default(),
809 PackageType::Lib,
810 TargetCapabilityFlags::empty(),
811 LanguageFeatures::default(),
812 )
813 .expect("interpreter should be created");
814 let (result, output) = line(
815 &mut interpreter,
816 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
817 );
818 is_only_value(&result, &output, &Value::unit());
819 let res = interpreter.qirgen("{Foo()}").expect("expected success");
820 expect![[r#"
821 %Result = type opaque
822 %Qubit = type opaque
823
824 define void @ENTRYPOINT__main() #0 {
825 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
826 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
827 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
828 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
829 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
830 ret void
831 }
832
833 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
834 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
835 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
836 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
837 declare void @__quantum__qis__rx__body(double, %Qubit*)
838 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
839 declare void @__quantum__qis__ry__body(double, %Qubit*)
840 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
841 declare void @__quantum__qis__rz__body(double, %Qubit*)
842 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
843 declare void @__quantum__qis__h__body(%Qubit*)
844 declare void @__quantum__qis__s__body(%Qubit*)
845 declare void @__quantum__qis__s__adj(%Qubit*)
846 declare void @__quantum__qis__t__body(%Qubit*)
847 declare void @__quantum__qis__t__adj(%Qubit*)
848 declare void @__quantum__qis__x__body(%Qubit*)
849 declare void @__quantum__qis__y__body(%Qubit*)
850 declare void @__quantum__qis__z__body(%Qubit*)
851 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
852 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
853 declare void @__quantum__rt__result_record_output(%Result*, i8*)
854 declare void @__quantum__rt__array_record_output(i64, i8*)
855 declare void @__quantum__rt__tuple_record_output(i64, i8*)
856
857 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
858 attributes #1 = { "irreversible" }
859
860 ; module flags
861
862 !llvm.module.flags = !{!0, !1, !2, !3}
863
864 !0 = !{i32 1, !"qir_major_version", i32 1}
865 !1 = !{i32 7, !"qir_minor_version", i32 0}
866 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
867 !3 = !{i32 1, !"dynamic_result_management", i1 false}
868 "#]].assert_eq(&res);
869 }
870
871 #[test]
872 fn qirgen_entry_expr_defines_operation() {
873 let mut interpreter = Interpreter::new(
874 true,
875 SourceMap::default(),
876 PackageType::Lib,
877 TargetCapabilityFlags::empty(),
878 LanguageFeatures::default(),
879 )
880 .expect("interpreter should be created");
881 let (result, output) = line(
882 &mut interpreter,
883 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
884 );
885 is_only_value(&result, &output, &Value::unit());
886 let res = interpreter
887 .qirgen("{operation Bar() : Unit {}; Foo()}")
888 .expect("expected success");
889 expect![[r#"
890 %Result = type opaque
891 %Qubit = type opaque
892
893 define void @ENTRYPOINT__main() #0 {
894 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
895 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
896 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
897 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
898 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
899 ret void
900 }
901
902 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
903 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
904 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
905 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
906 declare void @__quantum__qis__rx__body(double, %Qubit*)
907 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
908 declare void @__quantum__qis__ry__body(double, %Qubit*)
909 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
910 declare void @__quantum__qis__rz__body(double, %Qubit*)
911 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
912 declare void @__quantum__qis__h__body(%Qubit*)
913 declare void @__quantum__qis__s__body(%Qubit*)
914 declare void @__quantum__qis__s__adj(%Qubit*)
915 declare void @__quantum__qis__t__body(%Qubit*)
916 declare void @__quantum__qis__t__adj(%Qubit*)
917 declare void @__quantum__qis__x__body(%Qubit*)
918 declare void @__quantum__qis__y__body(%Qubit*)
919 declare void @__quantum__qis__z__body(%Qubit*)
920 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
921 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
922 declare void @__quantum__rt__result_record_output(%Result*, i8*)
923 declare void @__quantum__rt__array_record_output(i64, i8*)
924 declare void @__quantum__rt__tuple_record_output(i64, i8*)
925
926 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
927 attributes #1 = { "irreversible" }
928
929 ; module flags
930
931 !llvm.module.flags = !{!0, !1, !2, !3}
932
933 !0 = !{i32 1, !"qir_major_version", i32 1}
934 !1 = !{i32 7, !"qir_minor_version", i32 0}
935 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
936 !3 = !{i32 1, !"dynamic_result_management", i1 false}
937 "#]].assert_eq(&res);
938
939 // Operation should not be visible from global scope
940 let (result, output) = line(&mut interpreter, indoc! {"Bar()"});
941 is_only_error(
942 &result,
943 &output,
944 &expect![[r#"
945 name error: `Bar` not found
946 [line_1] [Bar]
947 type error: insufficient type information to infer type
948 [line_1] [Bar()]
949 "#]],
950 );
951 }
952
953 #[test]
954 fn qirgen_multiple_exprs_parse_fail() {
955 let mut interpreter = Interpreter::new(
956 true,
957 SourceMap::default(),
958 PackageType::Lib,
959 TargetCapabilityFlags::empty(),
960 LanguageFeatures::default(),
961 )
962 .expect("interpreter should be created");
963 let (result, output) = line(
964 &mut interpreter,
965 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
966 );
967 is_only_value(&result, &output, &Value::unit());
968 let res = interpreter
969 .qirgen("Foo(); operation Bar() : Unit {}; Foo()")
970 .expect_err("expected error");
971 is_error(
972 &res,
973 &expect![[r#"
974 syntax error: expected EOF, found `;`
975 [<entry>] [;]
976 "#]],
977 );
978 }
979
980 #[test]
981 fn qirgen_entry_expr_defines_operation_then_more_operations() {
982 let mut interpreter = Interpreter::new(
983 true,
984 SourceMap::default(),
985 PackageType::Lib,
986 TargetCapabilityFlags::empty(),
987 LanguageFeatures::default(),
988 )
989 .expect("interpreter should be created");
990 let (result, output) = line(
991 &mut interpreter,
992 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
993 );
994 is_only_value(&result, &output, &Value::unit());
995 let res = interpreter
996 .qirgen("{operation Bar() : Unit {}; Foo()}")
997 .expect("expected success");
998 expect![[r#"
999 %Result = type opaque
1000 %Qubit = type opaque
1001
1002 define void @ENTRYPOINT__main() #0 {
1003 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
1004 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
1005 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
1006 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
1007 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1008 ret void
1009 }
1010
1011 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
1012 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
1013 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
1014 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
1015 declare void @__quantum__qis__rx__body(double, %Qubit*)
1016 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
1017 declare void @__quantum__qis__ry__body(double, %Qubit*)
1018 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
1019 declare void @__quantum__qis__rz__body(double, %Qubit*)
1020 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
1021 declare void @__quantum__qis__h__body(%Qubit*)
1022 declare void @__quantum__qis__s__body(%Qubit*)
1023 declare void @__quantum__qis__s__adj(%Qubit*)
1024 declare void @__quantum__qis__t__body(%Qubit*)
1025 declare void @__quantum__qis__t__adj(%Qubit*)
1026 declare void @__quantum__qis__x__body(%Qubit*)
1027 declare void @__quantum__qis__y__body(%Qubit*)
1028 declare void @__quantum__qis__z__body(%Qubit*)
1029 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
1030 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
1031 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1032 declare void @__quantum__rt__array_record_output(i64, i8*)
1033 declare void @__quantum__rt__tuple_record_output(i64, i8*)
1034
1035 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
1036 attributes #1 = { "irreversible" }
1037
1038 ; module flags
1039
1040 !llvm.module.flags = !{!0, !1, !2, !3}
1041
1042 !0 = !{i32 1, !"qir_major_version", i32 1}
1043 !1 = !{i32 7, !"qir_minor_version", i32 0}
1044 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1045 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1046 "#]].assert_eq(&res);
1047
1048 let (result, output) = line(
1049 &mut interpreter,
1050 indoc! {"operation Baz() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
1051 );
1052 is_only_value(&result, &output, &Value::unit());
1053
1054 let (result, output) = line(&mut interpreter, indoc! {"Bar()"});
1055 is_only_error(
1056 &result,
1057 &output,
1058 &expect![[r#"
1059 name error: `Bar` not found
1060 [line_2] [Bar]
1061 type error: insufficient type information to infer type
1062 [line_2] [Bar()]
1063 "#]],
1064 );
1065 }
1066
1067 #[test]
1068 fn qirgen_define_operation_use_it() {
1069 let mut interpreter = Interpreter::new(
1070 true,
1071 SourceMap::default(),
1072 PackageType::Lib,
1073 TargetCapabilityFlags::empty(),
1074 LanguageFeatures::default(),
1075 )
1076 .expect("interpreter should be created");
1077 let res = interpreter
1078 .qirgen("{ operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; }; Foo() }")
1079 .expect("expected success");
1080 expect![[r#"
1081 %Result = type opaque
1082 %Qubit = type opaque
1083
1084 define void @ENTRYPOINT__main() #0 {
1085 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
1086 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
1087 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
1088 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
1089 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
1090 ret void
1091 }
1092
1093 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
1094 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
1095 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
1096 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
1097 declare void @__quantum__qis__rx__body(double, %Qubit*)
1098 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
1099 declare void @__quantum__qis__ry__body(double, %Qubit*)
1100 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
1101 declare void @__quantum__qis__rz__body(double, %Qubit*)
1102 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
1103 declare void @__quantum__qis__h__body(%Qubit*)
1104 declare void @__quantum__qis__s__body(%Qubit*)
1105 declare void @__quantum__qis__s__adj(%Qubit*)
1106 declare void @__quantum__qis__t__body(%Qubit*)
1107 declare void @__quantum__qis__t__adj(%Qubit*)
1108 declare void @__quantum__qis__x__body(%Qubit*)
1109 declare void @__quantum__qis__y__body(%Qubit*)
1110 declare void @__quantum__qis__z__body(%Qubit*)
1111 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
1112 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
1113 declare void @__quantum__rt__result_record_output(%Result*, i8*)
1114 declare void @__quantum__rt__array_record_output(i64, i8*)
1115 declare void @__quantum__rt__tuple_record_output(i64, i8*)
1116
1117 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
1118 attributes #1 = { "irreversible" }
1119
1120 ; module flags
1121
1122 !llvm.module.flags = !{!0, !1, !2, !3}
1123
1124 !0 = !{i32 1, !"qir_major_version", i32 1}
1125 !1 = !{i32 7, !"qir_minor_version", i32 0}
1126 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
1127 !3 = !{i32 1, !"dynamic_result_management", i1 false}
1128 "#]].assert_eq(&res);
1129 }
1130
1131 #[test]
1132 fn qirgen_entry_expr_profile_incompatible() {
1133 let mut interpreter = Interpreter::new(
1134 true,
1135 SourceMap::default(),
1136 PackageType::Lib,
1137 TargetCapabilityFlags::empty(),
1138 LanguageFeatures::default(),
1139 )
1140 .expect("interpreter should be created");
1141 let res = interpreter
1142 .qirgen("1")
1143 .expect_err("expected qirgen to fail");
1144 is_error(
1145 &res,
1146 &expect![[r#"
1147 non-Result return type in entry expression
1148 [<entry>] [1]
1149 "#]],
1150 );
1151 }
1152
1153 #[test]
1154 fn run_with_shots() {
1155 let mut interpreter = get_interpreter();
1156 let (result, output) = line(&mut interpreter, "operation Foo(qs : Qubit[]) : Unit { Microsoft.Quantum.Diagnostics.DumpMachine(); }");
1157 is_only_value(&result, &output, &Value::unit());
1158 for _ in 0..4 {
1159 let (results, output) = run(&mut interpreter, "{use qs = Qubit[2]; Foo(qs)}");
1160 is_unit_with_output(
1161 &results.expect("compilation should succeed"),
1162 &output,
1163 "STATE:\n|00⟩: 1+0i",
1164 );
1165 }
1166 }
1167
1168 #[test]
1169 fn run_parse_error() {
1170 let mut interpreter = get_interpreter();
1171 let (results, _) = run(&mut interpreter, "Foo)");
1172 results.expect_err("run() should fail");
1173 }
1174
1175 #[test]
1176 fn run_compile_error() {
1177 let mut interpreter = get_interpreter();
1178 let (results, _) = run(&mut interpreter, "Foo()");
1179 results.expect_err("run() should fail");
1180 }
1181
1182 #[test]
1183 fn run_multiple_statements_with_return_value() {
1184 let mut interpreter = get_interpreter();
1185 let (result, output) = line(&mut interpreter, "operation Foo() : Int { 1 }");
1186 is_only_value(&result, &output, &Value::unit());
1187 let (result, output) = line(&mut interpreter, "operation Bar() : Int { 2 }");
1188 is_only_value(&result, &output, &Value::unit());
1189 let (result, output) = run(&mut interpreter, "{ Foo(); Bar() }");
1190 is_only_value(
1191 &result.expect("compilation should succeed"),
1192 &output,
1193 &Value::Int(2),
1194 );
1195 }
1196
1197 #[test]
1198 fn run_runtime_failure() {
1199 let mut interpreter = get_interpreter();
1200 let (result, output) = line(
1201 &mut interpreter,
1202 r#"operation Foo() : Int { fail "failed" }"#,
1203 );
1204 is_only_value(&result, &output, &Value::unit());
1205 for _ in 0..1 {
1206 let (result, output) = run(&mut interpreter, "Foo()");
1207 is_only_error(
1208 &result.expect("compilation should succeed"),
1209 &output,
1210 &expect![[r#"
1211 runtime error: program failed: failed
1212 explicit fail [line_0] [fail "failed"]
1213 "#]],
1214 );
1215 }
1216 }
1217
1218 #[test]
1219 fn run_output_merged() {
1220 let mut interpreter = get_interpreter();
1221 let (result, output) = line(
1222 &mut interpreter,
1223 r#"operation Foo() : Unit { Message("hello!") }"#,
1224 );
1225 is_only_value(&result, &output, &Value::unit());
1226 for _ in 0..4 {
1227 let (result, output) = run(&mut interpreter, "Foo()");
1228 is_unit_with_output(
1229 &result.expect("compilation should succeed"),
1230 &output,
1231 "hello!",
1232 );
1233 }
1234 }
1235
1236 #[test]
1237 fn base_prof_non_result_return() {
1238 let mut interpreter = Interpreter::new(
1239 true,
1240 SourceMap::default(),
1241 PackageType::Lib,
1242 TargetCapabilityFlags::empty(),
1243 LanguageFeatures::default(),
1244 )
1245 .expect("interpreter should be created");
1246 let (result, output) = line(&mut interpreter, "123");
1247 is_only_value(&result, &output, &Value::Int(123));
1248 }
1249 }
1250
1251 fn get_interpreter() -> Interpreter {
1252 Interpreter::new(
1253 true,
1254 SourceMap::default(),
1255 PackageType::Lib,
1256 TargetCapabilityFlags::all(),
1257 LanguageFeatures::default(),
1258 )
1259 .expect("interpreter should be created")
1260 }
1261
1262 fn get_interpreter_with_capbilities(capabilities: TargetCapabilityFlags) -> Interpreter {
1263 Interpreter::new(
1264 true,
1265 SourceMap::default(),
1266 PackageType::Lib,
1267 capabilities,
1268 LanguageFeatures::default(),
1269 )
1270 .expect("interpreter should be created")
1271 }
1272
1273 fn is_only_value(result: &InterpretResult, output: &str, value: &Value) {
1274 assert_eq!("", output);
1275
1276 match result {
1277 Ok(v) => assert_eq!(value, v),
1278 Err(e) => panic!("Expected {value:?}, got {e:?}"),
1279 }
1280 }
1281
1282 fn is_unit_with_output_eval_entry(
1283 result: &Result<Value, Vec<crate::interpret::Error>>,
1284 output: &str,
1285 expected_output: &str,
1286 ) {
1287 assert_eq!(expected_output, output);
1288
1289 match result {
1290 Ok(value) => assert_eq!(Value::unit(), *value),
1291 Err(e) => panic!("Expected unit value, got {e:?}"),
1292 }
1293 }
1294
1295 fn is_unit_with_output(result: &InterpretResult, output: &str, expected_output: &str) {
1296 assert_eq!(expected_output, output);
1297
1298 match result {
1299 Ok(value) => assert_eq!(Value::unit(), *value),
1300 Err(e) => panic!("Expected unit value, got {e:?}"),
1301 }
1302 }
1303
1304 fn is_only_error<E>(result: &Result<Value, Vec<E>>, output: &str, expected_errors: &Expect)
1305 where
1306 E: Diagnostic,
1307 {
1308 assert_eq!("", output);
1309
1310 match result {
1311 Ok(value) => panic!("Expected error , got {value:?}"),
1312 Err(errors) => is_error(errors, expected_errors),
1313 }
1314 }
1315
1316 fn is_error<E>(errors: &Vec<E>, expected_errors: &Expect)
1317 where
1318 E: Diagnostic,
1319 {
1320 let mut actual = String::new();
1321 for error in errors {
1322 write!(actual, "{error}").expect("writing should succeed");
1323 for s in iter::successors(error.source(), |&s| s.source()) {
1324 write!(actual, ": {s}").expect("writing should succeed");
1325 }
1326 for label in error.labels().into_iter().flatten() {
1327 let span = error
1328 .source_code()
1329 .expect("expected valid source code")
1330 .read_span(label.inner(), 0, 0)
1331 .expect("expected to be able to read span");
1332
1333 write!(
1334 actual,
1335 "\n {} [{}] [{}]",
1336 label.label().unwrap_or(""),
1337 span.name().expect("expected source file name"),
1338 from_utf8(span.data()).expect("expected valid utf-8 string"),
1339 )
1340 .expect("writing should succeed");
1341 }
1342 writeln!(actual).expect("writing should succeed");
1343 }
1344
1345 expected_errors.assert_eq(&actual);
1346 }
1347
1348 #[cfg(test)]
1349 mod with_sources {
1350 use std::sync::Arc;
1351
1352 use super::*;
1353 use crate::interpret::Debugger;
1354 use crate::line_column::Encoding;
1355 use expect_test::expect;
1356 use indoc::indoc;
1357 use qsc_frontend::compile::{SourceMap, TargetCapabilityFlags};
1358 use qsc_passes::PackageType;
1359
1360 #[test]
1361 fn entry_expr_is_executed() {
1362 let source = indoc! { r#"
1363 namespace Test {
1364 @EntryPoint()
1365 operation Main() : Unit {
1366 Message("hello there...")
1367 }
1368 }"#};
1369
1370 let sources = SourceMap::new([("test".into(), source.into())], None);
1371 let mut interpreter = Interpreter::new(
1372 true,
1373 sources,
1374 PackageType::Exe,
1375 TargetCapabilityFlags::all(),
1376 LanguageFeatures::default(),
1377 )
1378 .expect("interpreter should be created");
1379
1380 let (result, output) = entry(&mut interpreter);
1381 is_unit_with_output_eval_entry(&result, &output, "hello there...");
1382 }
1383
1384 #[test]
1385 fn stdlib_members_can_be_accessed_from_sources() {
1386 let source = indoc! { r#"
1387 namespace Test {
1388 operation Main() : Unit {
1389 Message("hello there...")
1390 }
1391 }"#};
1392
1393 let sources = SourceMap::new([("test".into(), source.into())], None);
1394 let mut interpreter = Interpreter::new(
1395 true,
1396 sources,
1397 PackageType::Lib,
1398 TargetCapabilityFlags::all(),
1399 LanguageFeatures::default(),
1400 )
1401 .expect("interpreter should be created");
1402
1403 let (result, output) = line(&mut interpreter, "Test.Main()");
1404 is_unit_with_output(&result, &output, "hello there...");
1405 }
1406
1407 #[test]
1408 fn members_from_namespaced_sources_are_in_context() {
1409 let source = indoc! { r#"
1410 namespace Test {
1411 function Hello() : String {
1412 "hello there..."
1413 }
1414
1415 operation Main() : String {
1416 Hello()
1417 }
1418 }"#};
1419
1420 let sources = SourceMap::new([("test".into(), source.into())], None);
1421 let mut interpreter = Interpreter::new(
1422 true,
1423 sources,
1424 PackageType::Lib,
1425 TargetCapabilityFlags::all(),
1426 LanguageFeatures::default(),
1427 )
1428 .expect("interpreter should be created");
1429
1430 let (result, output) = line(&mut interpreter, "Test.Hello()");
1431 is_only_value(&result, &output, &Value::String("hello there...".into()));
1432 let (result, output) = line(&mut interpreter, "Test.Main()");
1433 is_only_value(&result, &output, &Value::String("hello there...".into()));
1434 }
1435
1436 #[test]
1437 fn multiple_files_are_loaded_from_sources_into_eval_context() {
1438 let sources: [(Arc<str>, Arc<str>); 2] = [
1439 (
1440 "a.qs".into(),
1441 r#"
1442 namespace Test {
1443 function Hello() : String {
1444 "hello there..."
1445 }
1446 }"#
1447 .into(),
1448 ),
1449 (
1450 "b.qs".into(),
1451 r#"
1452 namespace Test2 {
1453 open Test;
1454 @EntryPoint()
1455 operation Main() : String {
1456 Hello();
1457 Hello()
1458 }
1459 }"#
1460 .into(),
1461 ),
1462 ];
1463
1464 let sources = SourceMap::new(sources, None);
1465 let debugger = Debugger::new(
1466 sources,
1467 TargetCapabilityFlags::all(),
1468 Encoding::Utf8,
1469 LanguageFeatures::default(),
1470 )
1471 .expect("debugger should be created");
1472 let bps = debugger.get_breakpoints("a.qs");
1473 assert_eq!(1, bps.len());
1474 let bps = debugger.get_breakpoints("b.qs");
1475 assert_eq!(2, bps.len());
1476 }
1477
1478 #[test]
1479 fn multiple_namespaces_are_loaded_from_sources_into_eval_context() {
1480 let source = indoc! { r#"
1481 namespace Test {
1482 function Hello() : String {
1483 "hello there..."
1484 }
1485 }
1486 namespace Test2 {
1487 open Test;
1488 operation Main() : String {
1489 Hello()
1490 }
1491 }"#};
1492
1493 let sources = SourceMap::new([("test".into(), source.into())], None);
1494 let mut interpreter = Interpreter::new(
1495 true,
1496 sources,
1497 PackageType::Lib,
1498 TargetCapabilityFlags::all(),
1499 LanguageFeatures::default(),
1500 )
1501 .expect("interpreter should be created");
1502 let (result, output) = line(&mut interpreter, "Test.Hello()");
1503 is_only_value(&result, &output, &Value::String("hello there...".into()));
1504 let (result, output) = line(&mut interpreter, "Test2.Main()");
1505 is_only_value(&result, &output, &Value::String("hello there...".into()));
1506 }
1507
1508 #[test]
1509 fn runtime_error_from_stdlib() {
1510 let sources = SourceMap::new(
1511 [(
1512 "test".into(),
1513 "namespace Foo {
1514 operation Bar(): Unit {
1515 let x = -1;
1516 use qs = Qubit[x];
1517 }
1518 }
1519 "
1520 .into(),
1521 )],
1522 Some("Foo.Bar()".into()),
1523 );
1524
1525 let mut interpreter = Interpreter::new(
1526 true,
1527 sources,
1528 PackageType::Lib,
1529 TargetCapabilityFlags::all(),
1530 LanguageFeatures::default(),
1531 )
1532 .expect("interpreter should be created");
1533 let (result, output) = entry(&mut interpreter);
1534 is_only_error(
1535 &result,
1536 &output,
1537 &expect![[r#"
1538 runtime error: program failed: Cannot allocate qubit array with a negative length
1539 explicit fail [core/qir.qs] [fail "Cannot allocate qubit array with a negative length"]
1540 "#]],
1541 );
1542 }
1543 }
1544}
1545