microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.3.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc/src/interpret/tests.rs

1376lines · 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::{RuntimeCapabilityFlags, SourceMap};
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::RuntimeCapabilityFlags;
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 RuntimeCapabilityFlags::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 namespace_usable_before_definition() {
511 let mut interpreter = get_interpreter();
512 let (result, output) = line(
513 &mut interpreter,
514 indoc! {r#"
515 A.B();
516 namespace A {
517 function B() : Unit {}
518 }
519 "#},
520 );
521 is_only_value(&result, &output, &Value::unit());
522 }
523
524 #[test]
525 fn mutually_recursive_namespaces_work() {
526 let mut interpreter = get_interpreter();
527 let (result, output) = line(
528 &mut interpreter,
529 indoc! {r#"
530 A.B();
531 namespace A {
532 open C;
533 function B() : Unit {
534 D();
535 }
536 function E() : Unit {}
537 }
538 namespace C {
539 open A;
540 function D() : Unit {
541 E();
542 }
543 }
544 "#},
545 );
546 is_only_value(&result, &output, &Value::unit());
547 }
548
549 #[test]
550 fn local_var_valid_after_item_definition() {
551 let mut interpreter = Interpreter::new(
552 true,
553 SourceMap::default(),
554 PackageType::Lib,
555 RuntimeCapabilityFlags::empty(),
556 LanguageFeatures::default(),
557 )
558 .expect("interpreter should be created");
559 let (result, output) = line(&mut interpreter, "let a = 1;");
560 is_only_value(&result, &output, &Value::unit());
561 let (result, output) = line(&mut interpreter, "a");
562 is_only_value(&result, &output, &Value::Int(1));
563 let (result, output) = line(
564 &mut interpreter,
565 "function B() : Int { let inner_b = 3; inner_b }",
566 );
567 is_only_value(&result, &output, &Value::unit());
568 let (result, output) = line(&mut interpreter, "B()");
569 is_only_value(&result, &output, &Value::Int(3));
570 let (result, output) = line(&mut interpreter, "let b = 2;");
571 is_only_value(&result, &output, &Value::unit());
572 let (result, output) = line(&mut interpreter, "b");
573 is_only_value(&result, &output, &Value::Int(2));
574 let (result, output) = line(&mut interpreter, "a");
575 is_only_value(&result, &output, &Value::Int(1));
576 let (result, output) = line(&mut interpreter, "B()");
577 is_only_value(&result, &output, &Value::Int(3));
578 }
579
580 #[test]
581 fn normal_qirgen() {
582 let mut interpreter = Interpreter::new(
583 true,
584 SourceMap::default(),
585 PackageType::Lib,
586 RuntimeCapabilityFlags::empty(),
587 LanguageFeatures::default(),
588 )
589 .expect("interpreter should be created");
590 let (result, output) = line(
591 &mut interpreter,
592 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
593 );
594 is_only_value(&result, &output, &Value::unit());
595 let res = interpreter.qirgen("Foo()").expect("expected success");
596 expect![[r#"
597 %Result = type opaque
598 %Qubit = type opaque
599
600 define void @ENTRYPOINT__main() #0 {
601 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
602 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
603 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
604 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
605 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
606 ret void
607 }
608
609 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
610 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
611 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
612 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
613 declare void @__quantum__qis__rx__body(double, %Qubit*)
614 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
615 declare void @__quantum__qis__ry__body(double, %Qubit*)
616 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
617 declare void @__quantum__qis__rz__body(double, %Qubit*)
618 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
619 declare void @__quantum__qis__h__body(%Qubit*)
620 declare void @__quantum__qis__s__body(%Qubit*)
621 declare void @__quantum__qis__s__adj(%Qubit*)
622 declare void @__quantum__qis__t__body(%Qubit*)
623 declare void @__quantum__qis__t__adj(%Qubit*)
624 declare void @__quantum__qis__x__body(%Qubit*)
625 declare void @__quantum__qis__y__body(%Qubit*)
626 declare void @__quantum__qis__z__body(%Qubit*)
627 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
628 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
629 declare void @__quantum__rt__result_record_output(%Result*, i8*)
630 declare void @__quantum__rt__array_record_output(i64, i8*)
631 declare void @__quantum__rt__tuple_record_output(i64, i8*)
632
633 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
634 attributes #1 = { "irreversible" }
635
636 ; module flags
637
638 !llvm.module.flags = !{!0, !1, !2, !3}
639
640 !0 = !{i32 1, !"qir_major_version", i32 1}
641 !1 = !{i32 7, !"qir_minor_version", i32 0}
642 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
643 !3 = !{i32 1, !"dynamic_result_management", i1 false}
644 "#]].assert_eq(&res);
645 }
646
647 #[test]
648 fn qirgen_entry_expr_in_block() {
649 let mut interpreter = Interpreter::new(
650 true,
651 SourceMap::default(),
652 PackageType::Lib,
653 RuntimeCapabilityFlags::empty(),
654 LanguageFeatures::default(),
655 )
656 .expect("interpreter should be created");
657 let (result, output) = line(
658 &mut interpreter,
659 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
660 );
661 is_only_value(&result, &output, &Value::unit());
662 let res = interpreter.qirgen("{Foo()}").expect("expected success");
663 expect![[r#"
664 %Result = type opaque
665 %Qubit = type opaque
666
667 define void @ENTRYPOINT__main() #0 {
668 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
669 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
670 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
671 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
672 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
673 ret void
674 }
675
676 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
677 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
678 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
679 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
680 declare void @__quantum__qis__rx__body(double, %Qubit*)
681 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
682 declare void @__quantum__qis__ry__body(double, %Qubit*)
683 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
684 declare void @__quantum__qis__rz__body(double, %Qubit*)
685 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
686 declare void @__quantum__qis__h__body(%Qubit*)
687 declare void @__quantum__qis__s__body(%Qubit*)
688 declare void @__quantum__qis__s__adj(%Qubit*)
689 declare void @__quantum__qis__t__body(%Qubit*)
690 declare void @__quantum__qis__t__adj(%Qubit*)
691 declare void @__quantum__qis__x__body(%Qubit*)
692 declare void @__quantum__qis__y__body(%Qubit*)
693 declare void @__quantum__qis__z__body(%Qubit*)
694 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
695 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
696 declare void @__quantum__rt__result_record_output(%Result*, i8*)
697 declare void @__quantum__rt__array_record_output(i64, i8*)
698 declare void @__quantum__rt__tuple_record_output(i64, i8*)
699
700 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
701 attributes #1 = { "irreversible" }
702
703 ; module flags
704
705 !llvm.module.flags = !{!0, !1, !2, !3}
706
707 !0 = !{i32 1, !"qir_major_version", i32 1}
708 !1 = !{i32 7, !"qir_minor_version", i32 0}
709 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
710 !3 = !{i32 1, !"dynamic_result_management", i1 false}
711 "#]].assert_eq(&res);
712 }
713
714 #[test]
715 fn qirgen_entry_expr_defines_operation() {
716 let mut interpreter = Interpreter::new(
717 true,
718 SourceMap::default(),
719 PackageType::Lib,
720 RuntimeCapabilityFlags::empty(),
721 LanguageFeatures::default(),
722 )
723 .expect("interpreter should be created");
724 let (result, output) = line(
725 &mut interpreter,
726 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
727 );
728 is_only_value(&result, &output, &Value::unit());
729 let res = interpreter
730 .qirgen("{operation Bar() : Unit {}; Foo()}")
731 .expect("expected success");
732 expect![[r#"
733 %Result = type opaque
734 %Qubit = type opaque
735
736 define void @ENTRYPOINT__main() #0 {
737 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
738 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
739 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
740 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
741 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
742 ret void
743 }
744
745 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
746 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
747 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
748 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
749 declare void @__quantum__qis__rx__body(double, %Qubit*)
750 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
751 declare void @__quantum__qis__ry__body(double, %Qubit*)
752 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
753 declare void @__quantum__qis__rz__body(double, %Qubit*)
754 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
755 declare void @__quantum__qis__h__body(%Qubit*)
756 declare void @__quantum__qis__s__body(%Qubit*)
757 declare void @__quantum__qis__s__adj(%Qubit*)
758 declare void @__quantum__qis__t__body(%Qubit*)
759 declare void @__quantum__qis__t__adj(%Qubit*)
760 declare void @__quantum__qis__x__body(%Qubit*)
761 declare void @__quantum__qis__y__body(%Qubit*)
762 declare void @__quantum__qis__z__body(%Qubit*)
763 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
764 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
765 declare void @__quantum__rt__result_record_output(%Result*, i8*)
766 declare void @__quantum__rt__array_record_output(i64, i8*)
767 declare void @__quantum__rt__tuple_record_output(i64, i8*)
768
769 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
770 attributes #1 = { "irreversible" }
771
772 ; module flags
773
774 !llvm.module.flags = !{!0, !1, !2, !3}
775
776 !0 = !{i32 1, !"qir_major_version", i32 1}
777 !1 = !{i32 7, !"qir_minor_version", i32 0}
778 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
779 !3 = !{i32 1, !"dynamic_result_management", i1 false}
780 "#]].assert_eq(&res);
781
782 // Operation should not be visible from global scope
783 let (result, output) = line(&mut interpreter, indoc! {"Bar()"});
784 is_only_error(
785 &result,
786 &output,
787 &expect![[r#"
788 name error: `Bar` not found
789 [line_1] [Bar]
790 type error: insufficient type information to infer type
791 [line_1] [Bar()]
792 "#]],
793 );
794 }
795
796 #[test]
797 fn qirgen_multiple_exprs_parse_fail() {
798 let mut interpreter = Interpreter::new(
799 true,
800 SourceMap::default(),
801 PackageType::Lib,
802 RuntimeCapabilityFlags::empty(),
803 LanguageFeatures::default(),
804 )
805 .expect("interpreter should be created");
806 let (result, output) = line(
807 &mut interpreter,
808 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
809 );
810 is_only_value(&result, &output, &Value::unit());
811 let res = interpreter
812 .qirgen("Foo(); operation Bar() : Unit {}; Foo()")
813 .expect_err("expected error");
814 is_error(
815 &res,
816 &expect![[r#"
817 syntax error: expected EOF, found `;`
818 [<entry>] [;]
819 "#]],
820 );
821 }
822
823 #[test]
824 fn qirgen_entry_expr_defines_operation_then_more_operations() {
825 let mut interpreter = Interpreter::new(
826 true,
827 SourceMap::default(),
828 PackageType::Lib,
829 RuntimeCapabilityFlags::empty(),
830 LanguageFeatures::default(),
831 )
832 .expect("interpreter should be created");
833 let (result, output) = line(
834 &mut interpreter,
835 indoc! {"operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
836 );
837 is_only_value(&result, &output, &Value::unit());
838 let res = interpreter
839 .qirgen("{operation Bar() : Unit {}; Foo()}")
840 .expect("expected success");
841 expect![[r#"
842 %Result = type opaque
843 %Qubit = type opaque
844
845 define void @ENTRYPOINT__main() #0 {
846 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
847 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
848 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
849 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
850 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
851 ret void
852 }
853
854 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
855 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
856 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
857 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
858 declare void @__quantum__qis__rx__body(double, %Qubit*)
859 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
860 declare void @__quantum__qis__ry__body(double, %Qubit*)
861 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
862 declare void @__quantum__qis__rz__body(double, %Qubit*)
863 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
864 declare void @__quantum__qis__h__body(%Qubit*)
865 declare void @__quantum__qis__s__body(%Qubit*)
866 declare void @__quantum__qis__s__adj(%Qubit*)
867 declare void @__quantum__qis__t__body(%Qubit*)
868 declare void @__quantum__qis__t__adj(%Qubit*)
869 declare void @__quantum__qis__x__body(%Qubit*)
870 declare void @__quantum__qis__y__body(%Qubit*)
871 declare void @__quantum__qis__z__body(%Qubit*)
872 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
873 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
874 declare void @__quantum__rt__result_record_output(%Result*, i8*)
875 declare void @__quantum__rt__array_record_output(i64, i8*)
876 declare void @__quantum__rt__tuple_record_output(i64, i8*)
877
878 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
879 attributes #1 = { "irreversible" }
880
881 ; module flags
882
883 !llvm.module.flags = !{!0, !1, !2, !3}
884
885 !0 = !{i32 1, !"qir_major_version", i32 1}
886 !1 = !{i32 7, !"qir_minor_version", i32 0}
887 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
888 !3 = !{i32 1, !"dynamic_result_management", i1 false}
889 "#]].assert_eq(&res);
890
891 let (result, output) = line(
892 &mut interpreter,
893 indoc! {"operation Baz() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; } "},
894 );
895 is_only_value(&result, &output, &Value::unit());
896
897 let (result, output) = line(&mut interpreter, indoc! {"Bar()"});
898 is_only_error(
899 &result,
900 &output,
901 &expect![[r#"
902 name error: `Bar` not found
903 [line_2] [Bar]
904 type error: insufficient type information to infer type
905 [line_2] [Bar()]
906 "#]],
907 );
908 }
909
910 #[test]
911 fn qirgen_define_operation_use_it() {
912 let mut interpreter = Interpreter::new(
913 true,
914 SourceMap::default(),
915 PackageType::Lib,
916 RuntimeCapabilityFlags::empty(),
917 LanguageFeatures::default(),
918 )
919 .expect("interpreter should be created");
920 let res = interpreter
921 .qirgen("{ operation Foo() : Result { use q = Qubit(); let r = M(q); Reset(q); return r; }; Foo() }")
922 .expect("expected success");
923 expect![[r#"
924 %Result = type opaque
925 %Qubit = type opaque
926
927 define void @ENTRYPOINT__main() #0 {
928 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
929 call void @__quantum__qis__cz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Qubit* inttoptr (i64 0 to %Qubit*))
930 call void @__quantum__qis__h__body(%Qubit* inttoptr (i64 1 to %Qubit*))
931 call void @__quantum__qis__mz__body(%Qubit* inttoptr (i64 1 to %Qubit*), %Result* inttoptr (i64 0 to %Result*)) #1
932 call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
933 ret void
934 }
935
936 declare void @__quantum__qis__ccx__body(%Qubit*, %Qubit*, %Qubit*)
937 declare void @__quantum__qis__cx__body(%Qubit*, %Qubit*)
938 declare void @__quantum__qis__cy__body(%Qubit*, %Qubit*)
939 declare void @__quantum__qis__cz__body(%Qubit*, %Qubit*)
940 declare void @__quantum__qis__rx__body(double, %Qubit*)
941 declare void @__quantum__qis__rxx__body(double, %Qubit*, %Qubit*)
942 declare void @__quantum__qis__ry__body(double, %Qubit*)
943 declare void @__quantum__qis__ryy__body(double, %Qubit*, %Qubit*)
944 declare void @__quantum__qis__rz__body(double, %Qubit*)
945 declare void @__quantum__qis__rzz__body(double, %Qubit*, %Qubit*)
946 declare void @__quantum__qis__h__body(%Qubit*)
947 declare void @__quantum__qis__s__body(%Qubit*)
948 declare void @__quantum__qis__s__adj(%Qubit*)
949 declare void @__quantum__qis__t__body(%Qubit*)
950 declare void @__quantum__qis__t__adj(%Qubit*)
951 declare void @__quantum__qis__x__body(%Qubit*)
952 declare void @__quantum__qis__y__body(%Qubit*)
953 declare void @__quantum__qis__z__body(%Qubit*)
954 declare void @__quantum__qis__swap__body(%Qubit*, %Qubit*)
955 declare void @__quantum__qis__mz__body(%Qubit*, %Result* writeonly) #1
956 declare void @__quantum__rt__result_record_output(%Result*, i8*)
957 declare void @__quantum__rt__array_record_output(i64, i8*)
958 declare void @__quantum__rt__tuple_record_output(i64, i8*)
959
960 attributes #0 = { "entry_point" "output_labeling_schema" "qir_profiles"="base_profile" "required_num_qubits"="2" "required_num_results"="1" }
961 attributes #1 = { "irreversible" }
962
963 ; module flags
964
965 !llvm.module.flags = !{!0, !1, !2, !3}
966
967 !0 = !{i32 1, !"qir_major_version", i32 1}
968 !1 = !{i32 7, !"qir_minor_version", i32 0}
969 !2 = !{i32 1, !"dynamic_qubit_management", i1 false}
970 !3 = !{i32 1, !"dynamic_result_management", i1 false}
971 "#]].assert_eq(&res);
972 }
973
974 #[test]
975 fn qirgen_entry_expr_profile_incompatible() {
976 let mut interpreter = Interpreter::new(
977 true,
978 SourceMap::default(),
979 PackageType::Lib,
980 RuntimeCapabilityFlags::empty(),
981 LanguageFeatures::default(),
982 )
983 .expect("interpreter should be created");
984 let res = interpreter
985 .qirgen("1")
986 .expect_err("expected qirgen to fail");
987 is_error(
988 &res,
989 &expect![[r#"
990 non-Result return type in entry expression
991 [<entry>] [1]
992 "#]],
993 );
994 }
995
996 #[test]
997 fn run_with_shots() {
998 let mut interpreter = get_interpreter();
999 let (result, output) = line(&mut interpreter, "operation Foo(qs : Qubit[]) : Unit { Microsoft.Quantum.Diagnostics.DumpMachine(); }");
1000 is_only_value(&result, &output, &Value::unit());
1001 for _ in 0..4 {
1002 let (results, output) = run(&mut interpreter, "{use qs = Qubit[2]; Foo(qs)}");
1003 is_unit_with_output(
1004 &results.expect("compilation should succeed"),
1005 &output,
1006 "STATE:\n|00⟩: 1+0i",
1007 );
1008 }
1009 }
1010
1011 #[test]
1012 fn run_parse_error() {
1013 let mut interpreter = get_interpreter();
1014 let (results, _) = run(&mut interpreter, "Foo)");
1015 results.expect_err("run() should fail");
1016 }
1017
1018 #[test]
1019 fn run_compile_error() {
1020 let mut interpreter = get_interpreter();
1021 let (results, _) = run(&mut interpreter, "Foo()");
1022 results.expect_err("run() should fail");
1023 }
1024
1025 #[test]
1026 fn run_multiple_statements_with_return_value() {
1027 let mut interpreter = get_interpreter();
1028 let (result, output) = line(&mut interpreter, "operation Foo() : Int { 1 }");
1029 is_only_value(&result, &output, &Value::unit());
1030 let (result, output) = line(&mut interpreter, "operation Bar() : Int { 2 }");
1031 is_only_value(&result, &output, &Value::unit());
1032 let (result, output) = run(&mut interpreter, "{ Foo(); Bar() }");
1033 is_only_value(
1034 &result.expect("compilation should succeed"),
1035 &output,
1036 &Value::Int(2),
1037 );
1038 }
1039
1040 #[test]
1041 fn run_runtime_failure() {
1042 let mut interpreter = get_interpreter();
1043 let (result, output) = line(
1044 &mut interpreter,
1045 r#"operation Foo() : Int { fail "failed" }"#,
1046 );
1047 is_only_value(&result, &output, &Value::unit());
1048 for _ in 0..1 {
1049 let (result, output) = run(&mut interpreter, "Foo()");
1050 is_only_error(
1051 &result.expect("compilation should succeed"),
1052 &output,
1053 &expect![[r#"
1054 runtime error: program failed: failed
1055 explicit fail [line_0] [fail "failed"]
1056 "#]],
1057 );
1058 }
1059 }
1060
1061 #[test]
1062 fn run_output_merged() {
1063 let mut interpreter = get_interpreter();
1064 let (result, output) = line(
1065 &mut interpreter,
1066 r#"operation Foo() : Unit { Message("hello!") }"#,
1067 );
1068 is_only_value(&result, &output, &Value::unit());
1069 for _ in 0..4 {
1070 let (result, output) = run(&mut interpreter, "Foo()");
1071 is_unit_with_output(
1072 &result.expect("compilation should succeed"),
1073 &output,
1074 "hello!",
1075 );
1076 }
1077 }
1078
1079 #[test]
1080 fn base_prof_non_result_return() {
1081 let mut interpreter = Interpreter::new(
1082 true,
1083 SourceMap::default(),
1084 PackageType::Lib,
1085 RuntimeCapabilityFlags::empty(),
1086 LanguageFeatures::default(),
1087 )
1088 .expect("interpreter should be created");
1089 let (result, output) = line(&mut interpreter, "123");
1090 is_only_value(&result, &output, &Value::Int(123));
1091 }
1092 }
1093
1094 fn get_interpreter() -> Interpreter {
1095 Interpreter::new(
1096 true,
1097 SourceMap::default(),
1098 PackageType::Lib,
1099 RuntimeCapabilityFlags::all(),
1100 LanguageFeatures::default(),
1101 )
1102 .expect("interpreter should be created")
1103 }
1104
1105 fn is_only_value(result: &InterpretResult, output: &str, value: &Value) {
1106 assert_eq!("", output);
1107
1108 match result {
1109 Ok(v) => assert_eq!(value, v),
1110 Err(e) => panic!("Expected {value:?}, got {e:?}"),
1111 }
1112 }
1113
1114 fn is_unit_with_output_eval_entry(
1115 result: &Result<Value, Vec<crate::interpret::Error>>,
1116 output: &str,
1117 expected_output: &str,
1118 ) {
1119 assert_eq!(expected_output, output);
1120
1121 match result {
1122 Ok(value) => assert_eq!(Value::unit(), *value),
1123 Err(e) => panic!("Expected unit value, got {e:?}"),
1124 }
1125 }
1126
1127 fn is_unit_with_output(result: &InterpretResult, output: &str, expected_output: &str) {
1128 assert_eq!(expected_output, output);
1129
1130 match result {
1131 Ok(value) => assert_eq!(Value::unit(), *value),
1132 Err(e) => panic!("Expected unit value, got {e:?}"),
1133 }
1134 }
1135
1136 fn is_only_error<E>(result: &Result<Value, Vec<E>>, output: &str, expected_errors: &Expect)
1137 where
1138 E: Diagnostic,
1139 {
1140 assert_eq!("", output);
1141
1142 match result {
1143 Ok(value) => panic!("Expected error , got {value:?}"),
1144 Err(errors) => is_error(errors, expected_errors),
1145 }
1146 }
1147
1148 fn is_error<E>(errors: &Vec<E>, expected_errors: &Expect)
1149 where
1150 E: Diagnostic,
1151 {
1152 let mut actual = String::new();
1153 for error in errors {
1154 write!(actual, "{error}").expect("writing should succeed");
1155 for s in iter::successors(error.source(), |&s| s.source()) {
1156 write!(actual, ": {s}").expect("writing should succeed");
1157 }
1158 for label in error.labels().into_iter().flatten() {
1159 let span = error
1160 .source_code()
1161 .expect("expected valid source code")
1162 .read_span(label.inner(), 0, 0)
1163 .expect("expected to be able to read span");
1164
1165 write!(
1166 actual,
1167 "\n {} [{}] [{}]",
1168 label.label().unwrap_or(""),
1169 span.name().expect("expected source file name"),
1170 from_utf8(span.data()).expect("expected valid utf-8 string"),
1171 )
1172 .expect("writing should succeed");
1173 }
1174 writeln!(actual).expect("writing should succeed");
1175 }
1176
1177 expected_errors.assert_eq(&actual);
1178 }
1179
1180 #[cfg(test)]
1181 mod with_sources {
1182 use std::sync::Arc;
1183
1184 use super::*;
1185 use crate::interpret::Debugger;
1186 use crate::line_column::Encoding;
1187 use expect_test::expect;
1188 use indoc::indoc;
1189 use qsc_frontend::compile::{RuntimeCapabilityFlags, SourceMap};
1190 use qsc_passes::PackageType;
1191
1192 #[test]
1193 fn entry_expr_is_executed() {
1194 let source = indoc! { r#"
1195 namespace Test {
1196 @EntryPoint()
1197 operation Main() : Unit {
1198 Message("hello there...")
1199 }
1200 }"#};
1201
1202 let sources = SourceMap::new([("test".into(), source.into())], None);
1203 let mut interpreter = Interpreter::new(
1204 true,
1205 sources,
1206 PackageType::Exe,
1207 RuntimeCapabilityFlags::all(),
1208 LanguageFeatures::default(),
1209 )
1210 .expect("interpreter should be created");
1211
1212 let (result, output) = entry(&mut interpreter);
1213 is_unit_with_output_eval_entry(&result, &output, "hello there...");
1214 }
1215
1216 #[test]
1217 fn stdlib_members_can_be_accessed_from_sources() {
1218 let source = indoc! { r#"
1219 namespace Test {
1220 operation Main() : Unit {
1221 Message("hello there...")
1222 }
1223 }"#};
1224
1225 let sources = SourceMap::new([("test".into(), source.into())], None);
1226 let mut interpreter = Interpreter::new(
1227 true,
1228 sources,
1229 PackageType::Lib,
1230 RuntimeCapabilityFlags::all(),
1231 LanguageFeatures::default(),
1232 )
1233 .expect("interpreter should be created");
1234
1235 let (result, output) = line(&mut interpreter, "Test.Main()");
1236 is_unit_with_output(&result, &output, "hello there...");
1237 }
1238
1239 #[test]
1240 fn members_from_namespaced_sources_are_in_context() {
1241 let source = indoc! { r#"
1242 namespace Test {
1243 function Hello() : String {
1244 "hello there..."
1245 }
1246
1247 operation Main() : String {
1248 Hello()
1249 }
1250 }"#};
1251
1252 let sources = SourceMap::new([("test".into(), source.into())], None);
1253 let mut interpreter = Interpreter::new(
1254 true,
1255 sources,
1256 PackageType::Lib,
1257 RuntimeCapabilityFlags::all(),
1258 LanguageFeatures::default(),
1259 )
1260 .expect("interpreter should be created");
1261
1262 let (result, output) = line(&mut interpreter, "Test.Hello()");
1263 is_only_value(&result, &output, &Value::String("hello there...".into()));
1264 let (result, output) = line(&mut interpreter, "Test.Main()");
1265 is_only_value(&result, &output, &Value::String("hello there...".into()));
1266 }
1267
1268 #[test]
1269 fn multiple_files_are_loaded_from_sources_into_eval_context() {
1270 let sources: [(Arc<str>, Arc<str>); 2] = [
1271 (
1272 "a.qs".into(),
1273 r#"
1274 namespace Test {
1275 function Hello() : String {
1276 "hello there..."
1277 }
1278 }"#
1279 .into(),
1280 ),
1281 (
1282 "b.qs".into(),
1283 r#"
1284 namespace Test2 {
1285 open Test;
1286 @EntryPoint()
1287 operation Main() : String {
1288 Hello();
1289 Hello()
1290 }
1291 }"#
1292 .into(),
1293 ),
1294 ];
1295
1296 let sources = SourceMap::new(sources, None);
1297 let debugger = Debugger::new(
1298 sources,
1299 RuntimeCapabilityFlags::all(),
1300 Encoding::Utf8,
1301 LanguageFeatures::default(),
1302 )
1303 .expect("debugger should be created");
1304 let bps = debugger.get_breakpoints("a.qs");
1305 assert_eq!(1, bps.len());
1306 let bps = debugger.get_breakpoints("b.qs");
1307 assert_eq!(2, bps.len());
1308 }
1309
1310 #[test]
1311 fn multiple_namespaces_are_loaded_from_sources_into_eval_context() {
1312 let source = indoc! { r#"
1313 namespace Test {
1314 function Hello() : String {
1315 "hello there..."
1316 }
1317 }
1318 namespace Test2 {
1319 open Test;
1320 operation Main() : String {
1321 Hello()
1322 }
1323 }"#};
1324
1325 let sources = SourceMap::new([("test".into(), source.into())], None);
1326 let mut interpreter = Interpreter::new(
1327 true,
1328 sources,
1329 PackageType::Lib,
1330 RuntimeCapabilityFlags::all(),
1331 LanguageFeatures::default(),
1332 )
1333 .expect("interpreter should be created");
1334 let (result, output) = line(&mut interpreter, "Test.Hello()");
1335 is_only_value(&result, &output, &Value::String("hello there...".into()));
1336 let (result, output) = line(&mut interpreter, "Test2.Main()");
1337 is_only_value(&result, &output, &Value::String("hello there...".into()));
1338 }
1339
1340 #[test]
1341 fn runtime_error_from_stdlib() {
1342 let sources = SourceMap::new(
1343 [(
1344 "test".into(),
1345 "namespace Foo {
1346 operation Bar(): Unit {
1347 let x = -1;
1348 use qs = Qubit[x];
1349 }
1350 }
1351 "
1352 .into(),
1353 )],
1354 Some("Foo.Bar()".into()),
1355 );
1356
1357 let mut interpreter = Interpreter::new(
1358 true,
1359 sources,
1360 PackageType::Lib,
1361 RuntimeCapabilityFlags::all(),
1362 LanguageFeatures::default(),
1363 )
1364 .expect("interpreter should be created");
1365 let (result, output) = entry(&mut interpreter);
1366 is_only_error(
1367 &result,
1368 &output,
1369 &expect![[r#"
1370 runtime error: program failed: Cannot allocate qubit array with a negative length
1371 explicit fail [core/qir.qs] [fail "Cannot allocate qubit array with a negative length"]
1372 "#]],
1373 );
1374 }
1375 }
1376}
1377