microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.2.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

compiler/qsc/src/interpret/tests.rs

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