Skip to content

Commit 53356de

Browse files
committed
Refactor evaluator for stackless execution
1 parent aa33471 commit 53356de

File tree

9 files changed

+1416
-1312
lines changed

9 files changed

+1416
-1312
lines changed

compiler/qsc_eval/src/intrinsic.rs

Lines changed: 117 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#[cfg(test)]
55
mod tests;
66

7-
use crate::{output::Receiver, val::Value, Error, Reason, WithSpan};
7+
use crate::{output::Receiver, val::Value, Error};
88
use num_bigint::BigInt;
99
use qir_backend::{
1010
__quantum__qis__ccx__body, __quantum__qis__cx__body, __quantum__qis__cy__body,
@@ -19,193 +19,227 @@ use qir_backend::{
1919
};
2020
use qsc_data_structures::span::Span;
2121
use rand::Rng;
22-
use std::ops::ControlFlow::{self, Break, Continue};
2322

2423
pub(crate) fn invoke_intrinsic(
2524
name: &str,
2625
name_span: Span,
2726
args: Value,
2827
args_span: Span,
2928
out: &mut dyn Receiver,
30-
) -> ControlFlow<Reason, Value> {
29+
) -> Result<Value, Error> {
3130
if name.starts_with("__quantum__qis__") {
3231
invoke_quantum_intrinsic(name, name_span, args, args_span)
3332
} else {
3433
match name {
3534
#[allow(clippy::cast_precision_loss)]
3635
"IntAsDouble" => {
37-
let val: i64 = args.try_into().with_span(args_span)?;
38-
Continue(Value::Double(val as f64))
36+
let val = args.into_int();
37+
Ok(Value::Double(val as f64))
3938
}
4039

4140
"IntAsBigInt" => {
42-
let val: i64 = args.try_into().with_span(args_span)?;
43-
Continue(Value::BigInt(BigInt::from(val)))
41+
let val = args.into_int();
42+
Ok(Value::BigInt(BigInt::from(val)))
4443
}
4544

4645
"DumpMachine" => {
4746
let (state, qubit_count) = capture_quantum_state();
4847
match out.state(state, qubit_count) {
49-
Ok(_) => Continue(Value::unit()),
50-
Err(_) => Break(Reason::Error(Error::Output(name_span))),
48+
Ok(_) => Ok(Value::unit()),
49+
Err(_) => Err(Error::Output(name_span)),
5150
}
5251
}
5352

54-
"Message" => match out.message(&args.try_into_string().with_span(args_span)?) {
55-
Ok(_) => Continue(Value::unit()),
56-
Err(_) => Break(Reason::Error(Error::Output(name_span))),
53+
"Message" => match out.message(&args.into_string()) {
54+
Ok(_) => Ok(Value::unit()),
55+
Err(_) => Err(Error::Output(name_span)),
5756
},
5857

59-
"CheckZero" => Continue(Value::Bool(qubit_is_zero(
60-
args.try_into().with_span(args_span)?,
61-
))),
58+
"CheckZero" => Ok(Value::Bool(qubit_is_zero(args.into_qubit().0))),
6259

6360
"ArcCos" => {
64-
let val: f64 = args.try_into().with_span(args_span)?;
65-
Continue(Value::Double(val.acos()))
61+
let val = args.into_double();
62+
Ok(Value::Double(val.acos()))
6663
}
6764

6865
"ArcSin" => {
69-
let val: f64 = args.try_into().with_span(args_span)?;
70-
Continue(Value::Double(val.asin()))
66+
let val = args.into_double();
67+
Ok(Value::Double(val.asin()))
7168
}
7269

7370
"ArcTan" => {
74-
let val: f64 = args.try_into().with_span(args_span)?;
75-
Continue(Value::Double(val.atan()))
71+
let val = args.into_double();
72+
Ok(Value::Double(val.atan()))
7673
}
7774

78-
"ArcTan2" => match args.try_into_tuple().with_span(args_span)?.as_ref() {
79-
[x, y] => {
80-
let x: f64 = x.clone().try_into().with_span(args_span)?;
81-
let y = y.clone().try_into().with_span(args_span)?;
82-
Continue(Value::Double(x.atan2(y)))
75+
"ArcTan2" => {
76+
let tup = args.into_tuple();
77+
match &*tup {
78+
[x, y] => {
79+
let x = x.clone().into_double();
80+
let y = y.clone().into_double();
81+
Ok(Value::Double(x.atan2(y)))
82+
}
83+
_ => Err(Error::TupleArity(2, tup.len(), args_span)),
8384
}
84-
args => Break(Reason::Error(Error::TupleArity(2, args.len(), args_span))),
85-
},
85+
}
8686

8787
"Cos" => {
88-
let val: f64 = args.try_into().with_span(args_span)?;
89-
Continue(Value::Double(val.cos()))
88+
let val = args.into_double();
89+
Ok(Value::Double(val.cos()))
9090
}
9191

9292
"Cosh" => {
93-
let val: f64 = args.try_into().with_span(args_span)?;
94-
Continue(Value::Double(val.cosh()))
93+
let val = args.into_double();
94+
Ok(Value::Double(val.cosh()))
9595
}
9696

9797
"Sin" => {
98-
let val: f64 = args.try_into().with_span(args_span)?;
99-
Continue(Value::Double(val.sin()))
98+
let val = args.into_double();
99+
Ok(Value::Double(val.sin()))
100100
}
101101

102102
"Sinh" => {
103-
let val: f64 = args.try_into().with_span(args_span)?;
104-
Continue(Value::Double(val.sinh()))
103+
let val = args.into_double();
104+
Ok(Value::Double(val.sinh()))
105105
}
106106

107107
"Tan" => {
108-
let val: f64 = args.try_into().with_span(args_span)?;
109-
Continue(Value::Double(val.tan()))
108+
let val = args.into_double();
109+
Ok(Value::Double(val.tan()))
110110
}
111111

112112
"Tanh" => {
113-
let val: f64 = args.try_into().with_span(args_span)?;
114-
Continue(Value::Double(val.tanh()))
113+
let val = args.into_double();
114+
Ok(Value::Double(val.tanh()))
115115
}
116116

117117
"Sqrt" => {
118-
let val: f64 = args.try_into().with_span(args_span)?;
119-
Continue(Value::Double(val.sqrt()))
118+
let val = args.into_double();
119+
Ok(Value::Double(val.sqrt()))
120120
}
121121

122122
"Log" => {
123-
let val: f64 = args.try_into().with_span(args_span)?;
124-
Continue(Value::Double(val.ln()))
123+
let val = args.into_double();
124+
Ok(Value::Double(val.ln()))
125125
}
126126

127-
"DrawRandomInt" => match args.try_into_tuple().with_span(args_span)?.as_ref() {
128-
[lo, hi] => invoke_draw_random_int(lo.clone(), hi.clone(), args_span),
129-
args => Break(Reason::Error(Error::TupleArity(2, args.len(), args_span))),
130-
},
127+
"DrawRandomInt" => {
128+
let tup = args.into_tuple();
129+
match &*tup {
130+
[lo, hi] => invoke_draw_random_int(lo.clone(), hi.clone(), args_span),
131+
_ => Err(Error::TupleArity(2, tup.len(), args_span)),
132+
}
133+
}
131134

132135
"Truncate" => {
133-
let val: f64 = args.try_into().with_span(args_span)?;
136+
let val = args.into_double();
134137
#[allow(clippy::cast_possible_truncation)]
135-
Continue(Value::Int(val as i64))
138+
Ok(Value::Int(val as i64))
136139
}
137140

138-
_ => Break(Reason::Error(Error::UnknownIntrinsic(name_span))),
141+
_ => Err(Error::UnknownIntrinsic(name_span)),
139142
}
140143
}
141144
}
142145

143-
fn invoke_draw_random_int(lo: Value, hi: Value, args_span: Span) -> ControlFlow<Reason, Value> {
144-
let lo: i64 = lo.try_into().with_span(args_span)?;
145-
let hi: i64 = hi.try_into().with_span(args_span)?;
146+
fn invoke_draw_random_int(lo: Value, hi: Value, args_span: Span) -> Result<Value, Error> {
147+
let lo = lo.into_int();
148+
let hi = hi.into_int();
146149
if lo > hi {
147-
Break(Reason::Error(Error::EmptyRange(args_span)))
150+
Err(Error::EmptyRange(args_span))
148151
} else {
149-
Continue(Value::Int(rand::thread_rng().gen_range(lo..=hi)))
152+
Ok(Value::Int(rand::thread_rng().gen_range(lo..=hi)))
150153
}
151154
}
152155

156+
#[allow(clippy::too_many_lines)]
153157
fn invoke_quantum_intrinsic(
154158
name: &str,
155159
name_span: Span,
156160
args: Value,
157161
args_span: Span,
158-
) -> ControlFlow<Reason, Value> {
162+
) -> Result<Value, Error> {
159163
macro_rules! match_intrinsic {
160-
($chosen_op:ident, $chosen_op_span:ident, $(($(1, $op1:ident),* $(2, $op2:ident),* $(3, $op3:ident),*)),* ) => {
164+
($chosen_op:ident, $chosen_op_span:ident, $(($(1, $op1:ident),* $(2, $op2:ident),* $(3, $op3:ident),* $(2.1, $op21:ident),* $(3.1, $op31:ident),*)),* ) => {
161165
match $chosen_op {
162166
$($(stringify!($op1) => {
163-
$op1(args.try_into().with_span(args_span)?);
164-
Continue(Value::unit())
167+
$op1(args.into_qubit().0);
168+
Ok(Value::unit())
165169
})*
166170
$(stringify!($op2) => {
167-
match args.try_into_tuple().with_span(args_span)?.as_ref() {
171+
let tup = args.into_tuple();
172+
match &*tup {
168173
[x, y] => {
169174
$op2(
170-
x.clone().try_into().with_span(args_span)?,
171-
y.clone().try_into().with_span(args_span)?,
175+
x.clone().into_qubit().0,
176+
y.clone().into_qubit().0,
172177
);
173-
Continue(Value::unit())
178+
Ok(Value::unit())
174179
}
175-
args => Break(Reason::Error(Error::TupleArity(2, args.len(), args_span)))
180+
_ => Err(Error::TupleArity(2, tup.len(), args_span))
181+
}
182+
})*
183+
$(stringify!($op21) => {
184+
let tup = args.into_tuple();
185+
match &*tup {
186+
[x, y] => {
187+
$op21(
188+
x.clone().into_double(),
189+
y.clone().into_qubit().0,
190+
);
191+
Ok(Value::unit())
192+
}
193+
_ => Err(Error::TupleArity(2, tup.len(), args_span))
176194
}
177195
})*
178196
$(stringify!($op3) => {
179-
match args.try_into_tuple().with_span(args_span)?.as_ref() {
197+
let tup = args.into_tuple();
198+
match &*tup {
180199
[x, y, z] => {
181200
$op3(
182-
x.clone().try_into().with_span(args_span)?,
183-
y.clone().try_into().with_span(args_span)?,
184-
z.clone().try_into().with_span(args_span)?,
201+
x.clone().into_qubit().0,
202+
y.clone().into_qubit().0,
203+
z.clone().into_qubit().0,
204+
);
205+
Ok(Value::unit())
206+
}
207+
_ => Err(Error::TupleArity(3, tup.len(), args_span))
208+
}
209+
})*
210+
$(stringify!($op31) => {
211+
let tup = args.into_tuple();
212+
match &*tup {
213+
[x, y, z] => {
214+
$op31(
215+
x.clone().into_double(),
216+
y.clone().into_qubit().0,
217+
z.clone().into_qubit().0,
185218
);
186-
Continue(Value::unit())
219+
Ok(Value::unit())
187220
}
188-
args => Break(Reason::Error(Error::TupleArity(3, args.len(), args_span)))
221+
_ => Err(Error::TupleArity(3, tup.len(), args_span))
189222
}
190-
})*)*
223+
})*
224+
)*
191225

192226
"__quantum__qis__m__body" => {
193-
let res = __quantum__qis__m__body(args.try_into().with_span(args_span)?);
194-
Continue(Value::Result(__quantum__rt__result_equal(
227+
let res = __quantum__qis__m__body(args.into_qubit().0);
228+
Ok(Value::Result(__quantum__rt__result_equal(
195229
res,
196230
__quantum__rt__result_get_one(),
197231
)))
198232
}
199233

200234
"__quantum__qis__mresetz__body" => {
201-
let res = __quantum__qis__mresetz__body(args.try_into().with_span(args_span)?);
202-
Continue(Value::Result(__quantum__rt__result_equal(
235+
let res = __quantum__qis__mresetz__body(args.into_qubit().0);
236+
Ok(Value::Result(__quantum__rt__result_equal(
203237
res,
204238
__quantum__rt__result_get_one(),
205239
)))
206240
}
207241

208-
_ => Break(Reason::Error(Error::UnknownIntrinsic($chosen_op_span))),
242+
_ => Err(Error::UnknownIntrinsic($chosen_op_span)),
209243
}
210244
};
211245
}
@@ -217,12 +251,12 @@ fn invoke_quantum_intrinsic(
217251
(2, __quantum__qis__cx__body),
218252
(2, __quantum__qis__cy__body),
219253
(2, __quantum__qis__cz__body),
220-
(2, __quantum__qis__rx__body),
221-
(3, __quantum__qis__rxx__body),
222-
(2, __quantum__qis__ry__body),
223-
(3, __quantum__qis__ryy__body),
224-
(2, __quantum__qis__rz__body),
225-
(3, __quantum__qis__rzz__body),
254+
(2.1, __quantum__qis__rx__body),
255+
(3.1, __quantum__qis__rxx__body),
256+
(2.1, __quantum__qis__ry__body),
257+
(3.1, __quantum__qis__ryy__body),
258+
(2.1, __quantum__qis__rz__body),
259+
(3.1, __quantum__qis__rzz__body),
226260
(1, __quantum__qis__h__body),
227261
(1, __quantum__qis__s__body),
228262
(1, __quantum__qis__s__adj),

0 commit comments

Comments
 (0)