Skip to content

Commit c5fbe86

Browse files
committed
Refactor evaluator for stackless execution
1 parent 0e5381d commit c5fbe86

File tree

9 files changed

+1417
-1313
lines changed

9 files changed

+1417
-1313
lines changed

compiler/qsc_eval/src/intrinsic.rs

+118-84
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,195 +19,229 @@ 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-
"AsString" => Continue(Value::String(args.to_string().into())),
58+
"AsString" => Ok(Value::String(args.to_string().into())),
6059

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

6562
"ArcCos" => {
66-
let val: f64 = args.try_into().with_span(args_span)?;
67-
Continue(Value::Double(val.acos()))
63+
let val = args.into_double();
64+
Ok(Value::Double(val.acos()))
6865
}
6966

7067
"ArcSin" => {
71-
let val: f64 = args.try_into().with_span(args_span)?;
72-
Continue(Value::Double(val.asin()))
68+
let val = args.into_double();
69+
Ok(Value::Double(val.asin()))
7370
}
7471

7572
"ArcTan" => {
76-
let val: f64 = args.try_into().with_span(args_span)?;
77-
Continue(Value::Double(val.atan()))
73+
let val = args.into_double();
74+
Ok(Value::Double(val.atan()))
7875
}
7976

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

8989
"Cos" => {
90-
let val: f64 = args.try_into().with_span(args_span)?;
91-
Continue(Value::Double(val.cos()))
90+
let val = args.into_double();
91+
Ok(Value::Double(val.cos()))
9292
}
9393

9494
"Cosh" => {
95-
let val: f64 = args.try_into().with_span(args_span)?;
96-
Continue(Value::Double(val.cosh()))
95+
let val = args.into_double();
96+
Ok(Value::Double(val.cosh()))
9797
}
9898

9999
"Sin" => {
100-
let val: f64 = args.try_into().with_span(args_span)?;
101-
Continue(Value::Double(val.sin()))
100+
let val = args.into_double();
101+
Ok(Value::Double(val.sin()))
102102
}
103103

104104
"Sinh" => {
105-
let val: f64 = args.try_into().with_span(args_span)?;
106-
Continue(Value::Double(val.sinh()))
105+
let val = args.into_double();
106+
Ok(Value::Double(val.sinh()))
107107
}
108108

109109
"Tan" => {
110-
let val: f64 = args.try_into().with_span(args_span)?;
111-
Continue(Value::Double(val.tan()))
110+
let val = args.into_double();
111+
Ok(Value::Double(val.tan()))
112112
}
113113

114114
"Tanh" => {
115-
let val: f64 = args.try_into().with_span(args_span)?;
116-
Continue(Value::Double(val.tanh()))
115+
let val = args.into_double();
116+
Ok(Value::Double(val.tanh()))
117117
}
118118

119119
"Sqrt" => {
120-
let val: f64 = args.try_into().with_span(args_span)?;
121-
Continue(Value::Double(val.sqrt()))
120+
let val = args.into_double();
121+
Ok(Value::Double(val.sqrt()))
122122
}
123123

124124
"Log" => {
125-
let val: f64 = args.try_into().with_span(args_span)?;
126-
Continue(Value::Double(val.ln()))
125+
let val = args.into_double();
126+
Ok(Value::Double(val.ln()))
127127
}
128128

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

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

140-
_ => Break(Reason::Error(Error::UnknownIntrinsic(name_span))),
143+
_ => Err(Error::UnknownIntrinsic(name_span)),
141144
}
142145
}
143146
}
144147

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

158+
#[allow(clippy::too_many_lines)]
155159
fn invoke_quantum_intrinsic(
156160
name: &str,
157161
name_span: Span,
158162
args: Value,
159163
args_span: Span,
160-
) -> ControlFlow<Reason, Value> {
164+
) -> Result<Value, Error> {
161165
macro_rules! match_intrinsic {
162-
($chosen_op:ident, $chosen_op_span:ident, $(($(1, $op1:ident),* $(2, $op2:ident),* $(3, $op3:ident),*)),* ) => {
166+
($chosen_op:ident, $chosen_op_span:ident, $(($(1, $op1:ident),* $(2, $op2:ident),* $(3, $op3:ident),* $(2.1, $op21:ident),* $(3.1, $op31:ident),*)),* ) => {
163167
match $chosen_op {
164168
$($(stringify!($op1) => {
165-
$op1(args.try_into().with_span(args_span)?);
166-
Continue(Value::unit())
169+
$op1(args.into_qubit().0);
170+
Ok(Value::unit())
167171
})*
168172
$(stringify!($op2) => {
169-
match args.try_into_tuple().with_span(args_span)?.as_ref() {
173+
let tup = args.into_tuple();
174+
match &*tup {
170175
[x, y] => {
171176
$op2(
172-
x.clone().try_into().with_span(args_span)?,
173-
y.clone().try_into().with_span(args_span)?,
177+
x.clone().into_qubit().0,
178+
y.clone().into_qubit().0,
174179
);
175-
Continue(Value::unit())
180+
Ok(Value::unit())
176181
}
177-
args => Break(Reason::Error(Error::TupleArity(2, args.len(), args_span)))
182+
_ => Err(Error::TupleArity(2, tup.len(), args_span))
183+
}
184+
})*
185+
$(stringify!($op21) => {
186+
let tup = args.into_tuple();
187+
match &*tup {
188+
[x, y] => {
189+
$op21(
190+
x.clone().into_double(),
191+
y.clone().into_qubit().0,
192+
);
193+
Ok(Value::unit())
194+
}
195+
_ => Err(Error::TupleArity(2, tup.len(), args_span))
178196
}
179197
})*
180198
$(stringify!($op3) => {
181-
match args.try_into_tuple().with_span(args_span)?.as_ref() {
199+
let tup = args.into_tuple();
200+
match &*tup {
182201
[x, y, z] => {
183202
$op3(
184-
x.clone().try_into().with_span(args_span)?,
185-
y.clone().try_into().with_span(args_span)?,
186-
z.clone().try_into().with_span(args_span)?,
203+
x.clone().into_qubit().0,
204+
y.clone().into_qubit().0,
205+
z.clone().into_qubit().0,
206+
);
207+
Ok(Value::unit())
208+
}
209+
_ => Err(Error::TupleArity(3, tup.len(), args_span))
210+
}
211+
})*
212+
$(stringify!($op31) => {
213+
let tup = args.into_tuple();
214+
match &*tup {
215+
[x, y, z] => {
216+
$op31(
217+
x.clone().into_double(),
218+
y.clone().into_qubit().0,
219+
z.clone().into_qubit().0,
187220
);
188-
Continue(Value::unit())
221+
Ok(Value::unit())
189222
}
190-
args => Break(Reason::Error(Error::TupleArity(3, args.len(), args_span)))
223+
_ => Err(Error::TupleArity(3, tup.len(), args_span))
191224
}
192-
})*)*
225+
})*
226+
)*
193227

194228
"__quantum__qis__m__body" => {
195-
let res = __quantum__qis__m__body(args.try_into().with_span(args_span)?);
196-
Continue(Value::Result(__quantum__rt__result_equal(
229+
let res = __quantum__qis__m__body(args.into_qubit().0);
230+
Ok(Value::Result(__quantum__rt__result_equal(
197231
res,
198232
__quantum__rt__result_get_one(),
199233
)))
200234
}
201235

202236
"__quantum__qis__mresetz__body" => {
203-
let res = __quantum__qis__mresetz__body(args.try_into().with_span(args_span)?);
204-
Continue(Value::Result(__quantum__rt__result_equal(
237+
let res = __quantum__qis__mresetz__body(args.into_qubit().0);
238+
Ok(Value::Result(__quantum__rt__result_equal(
205239
res,
206240
__quantum__rt__result_get_one(),
207241
)))
208242
}
209243

210-
_ => Break(Reason::Error(Error::UnknownIntrinsic($chosen_op_span))),
244+
_ => Err(Error::UnknownIntrinsic($chosen_op_span)),
211245
}
212246
};
213247
}
@@ -219,12 +253,12 @@ fn invoke_quantum_intrinsic(
219253
(2, __quantum__qis__cx__body),
220254
(2, __quantum__qis__cy__body),
221255
(2, __quantum__qis__cz__body),
222-
(2, __quantum__qis__rx__body),
223-
(3, __quantum__qis__rxx__body),
224-
(2, __quantum__qis__ry__body),
225-
(3, __quantum__qis__ryy__body),
226-
(2, __quantum__qis__rz__body),
227-
(3, __quantum__qis__rzz__body),
256+
(2.1, __quantum__qis__rx__body),
257+
(3.1, __quantum__qis__rxx__body),
258+
(2.1, __quantum__qis__ry__body),
259+
(3.1, __quantum__qis__ryy__body),
260+
(2.1, __quantum__qis__rz__body),
261+
(3.1, __quantum__qis__rzz__body),
228262
(1, __quantum__qis__h__body),
229263
(1, __quantum__qis__s__body),
230264
(1, __quantum__qis__s__adj),

0 commit comments

Comments
 (0)