Skip to content

Commit db8002b

Browse files
committed
Depend on use-stmt transform, skip qubit tracking
1 parent dc7533a commit db8002b

File tree

7 files changed

+77
-124
lines changed

7 files changed

+77
-124
lines changed

compiler/qsc/src/compile.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::error::WithSource;
55
use miette::{Diagnostic, Report};
66
use qsc_frontend::compile::{CompileUnit, PackageStore, SourceMap};
77
use qsc_hir::hir::PackageId;
8-
use qsc_passes::run_default_passes;
8+
use qsc_passes::{run_core_passes, run_default_passes};
99
use thiserror::Error;
1010

1111
#[derive(Clone, Debug, Diagnostic, Error)]
@@ -29,7 +29,7 @@ pub fn compile(
2929
}
3030

3131
if errors.is_empty() {
32-
for error in run_default_passes(&mut unit) {
32+
for error in run_default_passes(&mut unit, store) {
3333
errors.push(error.into());
3434
}
3535
}
@@ -45,17 +45,8 @@ pub fn compile(
4545
#[must_use]
4646
pub fn core() -> CompileUnit {
4747
let mut unit = qsc_frontend::compile::core();
48-
let pass_errors = run_default_passes(&mut unit);
49-
if pass_errors.is_empty() {
50-
unit
51-
} else {
52-
for error in pass_errors {
53-
let report = Report::new(WithSource::from_map(&unit.sources, error, None));
54-
eprintln!("{report:?}");
55-
}
56-
57-
panic!("could not compile core library")
58-
}
48+
run_core_passes(&mut unit);
49+
unit
5950
}
6051

6152
/// Compiles the standard library.
@@ -66,7 +57,7 @@ pub fn core() -> CompileUnit {
6657
#[must_use]
6758
pub fn std(store: &PackageStore) -> CompileUnit {
6859
let mut unit = qsc_frontend::compile::std(store);
69-
let pass_errors = run_default_passes(&mut unit);
60+
let pass_errors = run_default_passes(&mut unit, store);
7061
if pass_errors.is_empty() {
7162
unit
7263
} else {

compiler/qsc_eval/src/intrinsic.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,11 @@ pub(crate) fn invoke_intrinsic(
150150
}
151151

152152
"__quantum__rt__qubit_release" => {
153-
__quantum__rt__qubit_release(args.into_qubit().0);
153+
let qubit = args.into_qubit().0;
154+
if !qubit_is_zero(qubit) {
155+
return Err(Error::ReleasedQubitNotZero(qubit as usize));
156+
}
157+
__quantum__rt__qubit_release(qubit);
154158
Ok(Value::unit())
155159
}
156160

compiler/qsc_eval/src/intrinsic/tests.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use expect_test::{expect, Expect};
77
use indoc::indoc;
88
use num_bigint::BigInt;
99
use qsc_frontend::compile::{self, compile, PackageStore, SourceMap};
10-
use qsc_passes::run_default_passes;
10+
use qsc_passes::{run_core_passes, run_default_passes};
1111

1212
use crate::{
1313
eval_expr,
@@ -18,16 +18,18 @@ use crate::{
1818
};
1919

2020
fn check_intrinsic(file: &str, expr: &str, out: &mut dyn Receiver) -> Result<Value, Error> {
21-
let mut store = PackageStore::new(compile::core());
21+
let mut core = compile::core();
22+
run_core_passes(&mut core);
23+
let mut store = PackageStore::new(core);
2224
let mut std = compile::std(&store);
2325
assert!(std.errors.is_empty());
24-
assert!(run_default_passes(&mut std).is_empty());
26+
assert!(run_default_passes(&mut std, &store).is_empty());
2527

2628
let std_id = store.insert(std);
2729
let sources = SourceMap::new([("test".into(), file.into())], Some(expr.into()));
2830
let mut unit = compile(&store, &[std_id], sources);
2931
assert!(unit.errors.is_empty());
30-
assert!(run_default_passes(&mut unit).is_empty());
32+
assert!(run_default_passes(&mut unit, &store).is_empty());
3133

3234
let id = store.insert(unit);
3335
let entry = store
@@ -874,10 +876,6 @@ fn qubit_release_non_zero_failure() {
874876
&expect![[r#"
875877
ReleasedQubitNotZero(
876878
0,
877-
Span {
878-
lo: 14,
879-
hi: 21,
880-
},
881879
)
882880
"#]],
883881
);

compiler/qsc_eval/src/lib.rs

+13-91
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,12 @@ use intrinsic::invoke_intrinsic;
1717
use miette::Diagnostic;
1818
use num_bigint::BigInt;
1919
use output::Receiver;
20-
use qir_backend::{
21-
__quantum__rt__initialize, __quantum__rt__qubit_allocate, __quantum__rt__qubit_release,
22-
qubit_is_zero,
23-
};
20+
use qir_backend::__quantum__rt__initialize;
2421
use qsc_data_structures::span::Span;
2522
use qsc_hir::hir::{
2623
self, BinOp, Block, CallableBody, CallableDecl, Expr, ExprKind, Functor, Lit, Mutability,
27-
NodeId, PackageId, Pat, PatKind, PrimField, QubitInit, QubitInitKind, Res, Spec, SpecBody,
28-
SpecGen, Stmt, StmtKind, StringComponent, TernOp, UnOp,
24+
NodeId, PackageId, Pat, PatKind, PrimField, Res, Spec, SpecBody, SpecGen, Stmt, StmtKind,
25+
StringComponent, TernOp, UnOp,
2926
};
3027
use std::{
3128
collections::{hash_map::Entry, HashMap},
@@ -35,7 +32,7 @@ use std::{
3532
rc::Rc,
3633
};
3734
use thiserror::Error;
38-
use val::{GlobalId, Qubit};
35+
use val::GlobalId;
3936

4037
#[derive(Clone, Debug, Diagnostic, Error)]
4138
pub enum Error {
@@ -88,7 +85,7 @@ pub enum Error {
8885
RangeStepZero(#[label("invalid range")] Span),
8986

9087
#[error("Qubit{0} released while not in |0⟩ state")]
91-
ReleasedQubitNotZero(usize, #[label] Span),
88+
ReleasedQubitNotZero(usize),
9289

9390
#[error("mismatched types")]
9491
Type(
@@ -247,7 +244,6 @@ impl Env {
247244
#[derive(Default)]
248245
struct Scope {
249246
bindings: HashMap<NodeId, Variable>,
250-
qubits: Vec<(Qubit, Span)>,
251247
}
252248

253249
impl Env {
@@ -261,7 +257,6 @@ enum Event<'a> {
261257
Cont(Cont<'a>),
262258
Expr(&'a Expr),
263259
Frame,
264-
Qubit(&'a QubitInit),
265260
Scope,
266261
Stmt(&'a Stmt),
267262
}
@@ -279,7 +274,6 @@ enum Cont<'a> {
279274
Field(PrimField, Span),
280275
If(&'a Block, &'a Option<Box<Expr>>),
281276
Index(Span),
282-
QubitArray(Span, Span),
283277
Range(bool, bool, bool),
284278
Return,
285279
StringConcat(usize),
@@ -357,38 +351,16 @@ impl<'a, G: GlobalLookup<'a>> State<'a, G> {
357351
self.push_val(last_val);
358352
}
359353

360-
fn push_qubit(&mut self, qubit_init: &'a QubitInit) {
361-
self.stack.push(Event::Qubit(qubit_init));
362-
}
363-
364354
fn push_scope(&mut self) {
365355
self.env.0.push(Scope::default());
366356
self.stack.push(Event::Scope);
367357
}
368358

369-
fn track_qubit(&mut self, qubit: Qubit, span: Span) {
359+
fn leave_scope(&mut self) {
370360
self.env
371-
.0
372-
.last_mut()
373-
.expect("scope should have been entered to track qubits")
374-
.qubits
375-
.push((qubit, span));
376-
}
377-
378-
fn leave_scope(&mut self) -> Result<(), Error> {
379-
for (qubit, span) in self
380-
.env
381361
.0
382362
.pop()
383-
.expect("scope should be entered first before leaving")
384-
.qubits
385-
{
386-
if !qubit_is_zero(qubit.0) {
387-
return Err(Error::ReleasedQubitNotZero(qubit.0 as usize, span));
388-
}
389-
__quantum__rt__qubit_release(qubit.0);
390-
}
391-
Ok(())
363+
.expect("scope should be entered first before leaving");
392364
}
393365

394366
fn push_stmt(&mut self, stmt: &'a Stmt) {
@@ -436,11 +408,10 @@ impl<'a, G: GlobalLookup<'a>> State<'a, G> {
436408
self.leave_frame();
437409
Ok(())
438410
}
439-
Event::Qubit(qubit_init) => {
440-
self.handle_qubit_init(qubit_init);
411+
Event::Scope => {
412+
self.leave_scope();
441413
Ok(())
442414
}
443-
Event::Scope => self.leave_scope(),
444415
Event::Stmt(stmt) => {
445416
self.handle_stmt(stmt);
446417
Ok(())
@@ -698,14 +669,7 @@ impl<'a, G: GlobalLookup<'a>> State<'a, G> {
698669
self.push_expr(expr);
699670
self.push_val(Value::unit());
700671
}
701-
StmtKind::Qubit(_, pat, qubit_init, block) => {
702-
if let Some(block) = block {
703-
self.push_block(block);
704-
}
705-
self.push_cont(Cont::Bind(pat, Mutability::Immutable));
706-
self.push_qubit(qubit_init);
707-
self.push_val(Value::unit());
708-
}
672+
StmtKind::Qubit(..) => panic!("qubit use-stmt should be eliminated by passes"),
709673
StmtKind::Semi(expr) => {
710674
self.push_cont(Cont::Consume);
711675
self.push_expr(expr);
@@ -714,26 +678,6 @@ impl<'a, G: GlobalLookup<'a>> State<'a, G> {
714678
}
715679
}
716680

717-
fn handle_qubit_init(&mut self, qubit_init: &'a QubitInit) {
718-
match &qubit_init.kind {
719-
QubitInitKind::Array(count) => {
720-
self.push_cont(Cont::QubitArray(qubit_init.span, count.span));
721-
self.push_expr(count);
722-
}
723-
QubitInitKind::Single => {
724-
let qubit = Qubit(__quantum__rt__qubit_allocate());
725-
self.track_qubit(qubit, qubit_init.span);
726-
self.push_val(Value::Qubit(qubit));
727-
}
728-
QubitInitKind::Tuple(tup) => {
729-
self.push_cont(Cont::Tuple(tup.len()));
730-
for init in tup.iter().rev() {
731-
self.push_qubit(init);
732-
}
733-
}
734-
}
735-
}
736-
737681
fn cont(&mut self, cont: Cont<'a>) -> Result<(), Error> {
738682
match cont {
739683
Cont::Array(len) => self.cont_array(len),
@@ -754,13 +698,10 @@ impl<'a, G: GlobalLookup<'a>> State<'a, G> {
754698
Cont::Field(field, span) => self.cont_field(field, span)?,
755699
Cont::If(then_block, else_expr) => self.cont_if(then_block, else_expr),
756700
Cont::Index(span) => self.cont_index(span)?,
757-
Cont::QubitArray(qubit_span, count_span) => {
758-
self.cont_qubit_array(qubit_span, count_span)?;
759-
}
760701
Cont::Range(has_start, has_step, has_end) => {
761702
self.cont_range(has_start, has_step, has_end);
762703
}
763-
Cont::Return => self.cont_ret()?,
704+
Cont::Return => self.cont_ret(),
764705
Cont::StringConcat(len) => self.cont_string_concat(len),
765706
Cont::StringLit(str) => self.push_val(Value::String(Rc::clone(str))),
766707
Cont::TernOp(op, mid, rhs) => self.cont_ternop(op, mid, rhs)?,
@@ -947,22 +888,6 @@ impl<'a, G: GlobalLookup<'a>> State<'a, G> {
947888
Ok(())
948889
}
949890

950-
fn cont_qubit_array(&mut self, qubit_span: Span, count_span: Span) -> Result<(), Error> {
951-
let count_val = self.pop_val().into_int();
952-
let count: usize = match count_val.try_into() {
953-
Ok(i) => Ok(i),
954-
Err(_) => Err(Error::Count(count_val, count_span)),
955-
}?;
956-
let mut arr = Vec::new();
957-
for _ in 0..count {
958-
let qubit = Qubit(__quantum__rt__qubit_allocate());
959-
self.track_qubit(qubit, qubit_span);
960-
arr.push(Value::Qubit(qubit));
961-
}
962-
self.push_val(Value::Array(arr.into()));
963-
Ok(())
964-
}
965-
966891
fn cont_range(&mut self, has_start: bool, has_step: bool, has_end: bool) {
967892
let end = if has_end {
968893
Some(self.pop_val().into_int())
@@ -982,7 +907,7 @@ impl<'a, G: GlobalLookup<'a>> State<'a, G> {
982907
self.push_val(Value::Range(start, step, end));
983908
}
984909

985-
fn cont_ret(&mut self) -> Result<(), Error> {
910+
fn cont_ret(&mut self) {
986911
loop {
987912
let Some(event) = self.pop_event() else {
988913
break;
@@ -992,13 +917,10 @@ impl<'a, G: GlobalLookup<'a>> State<'a, G> {
992917
self.leave_frame();
993918
break;
994919
}
995-
Event::Scope => {
996-
self.leave_scope()?;
997-
}
920+
Event::Scope => self.leave_scope(),
998921
_ => {}
999922
}
1000923
}
1001-
Ok(())
1002924
}
1003925

1004926
fn cont_string_concat(&mut self, len: usize) {

compiler/qsc_eval/src/tests.rs

+34-8
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,17 @@ use expect_test::{expect, Expect};
66
use indoc::indoc;
77
use qsc_frontend::compile::{self, compile, PackageStore, SourceMap};
88
use qsc_hir::hir::{CallableDecl, ItemKind};
9-
use qsc_passes::run_default_passes;
9+
use qsc_passes::{run_core_passes, run_default_passes};
1010

1111
fn check_expr(file: &str, expr: &str, expect: &Expect) {
12-
let mut store = PackageStore::new(compile::core());
12+
let mut core = compile::core();
13+
run_core_passes(&mut core);
14+
let mut store = PackageStore::new(core);
1315
let sources = SourceMap::new([("test".into(), file.into())], Some(expr.into()));
1416
let mut unit = compile(&store, &[], sources);
1517
assert!(unit.errors.is_empty(), "{:?}", unit.errors);
1618

17-
let pass_errors = run_default_passes(&mut unit);
19+
let pass_errors = run_default_passes(&mut unit, &store);
1820
assert!(pass_errors.is_empty(), "{pass_errors:?}");
1921

2022
let id = store.insert(unit);
@@ -313,15 +315,39 @@ fn block_qubit_use_array_invalid_count_expr() {
313315
}"},
314316
&expect![[r#"
315317
(
316-
Count(
317-
-3,
318+
UserFail(
319+
"Cannot allocate qubit array with a negative length",
318320
Span {
319-
lo: 20,
320-
hi: 22,
321+
lo: 371,
322+
hi: 428,
321323
},
322324
),
323325
CallStack {
324-
frames: [],
326+
frames: [
327+
Frame {
328+
span: Some(
329+
Span {
330+
lo: 10,
331+
hi: 11,
332+
},
333+
),
334+
id: GlobalId {
335+
package: PackageId(
336+
0,
337+
),
338+
item: LocalItemId(
339+
3,
340+
),
341+
},
342+
caller: PackageId(
343+
1,
344+
),
345+
functor: FunctorApp {
346+
adjoint: false,
347+
controlled: 0,
348+
},
349+
},
350+
],
325351
},
326352
)
327353
"#]],

0 commit comments

Comments
 (0)