4
4
#[ cfg( test) ]
5
5
mod tests;
6
6
7
- use crate :: { output:: Receiver , val:: Value , Error , Reason , WithSpan } ;
7
+ use crate :: { output:: Receiver , val:: Value , Error } ;
8
8
use num_bigint:: BigInt ;
9
9
use qir_backend:: {
10
10
__quantum__qis__ccx__body, __quantum__qis__cx__body, __quantum__qis__cy__body,
@@ -19,193 +19,227 @@ use qir_backend::{
19
19
} ;
20
20
use qsc_data_structures:: span:: Span ;
21
21
use rand:: Rng ;
22
- use std:: ops:: ControlFlow :: { self , Break , Continue } ;
23
22
24
23
pub ( crate ) fn invoke_intrinsic (
25
24
name : & str ,
26
25
name_span : Span ,
27
26
args : Value ,
28
27
args_span : Span ,
29
28
out : & mut dyn Receiver ,
30
- ) -> ControlFlow < Reason , Value > {
29
+ ) -> Result < Value , Error > {
31
30
if name. starts_with ( "__quantum__qis__" ) {
32
31
invoke_quantum_intrinsic ( name, name_span, args, args_span)
33
32
} else {
34
33
match name {
35
34
#[ allow( clippy:: cast_precision_loss) ]
36
35
"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 ) )
39
38
}
40
39
41
40
"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) ) )
44
43
}
45
44
46
45
"DumpMachine" => {
47
46
let ( state, qubit_count) = capture_quantum_state ( ) ;
48
47
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) ) ,
51
50
}
52
51
}
53
52
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) ) ,
57
56
} ,
58
57
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 ) ) ) ,
62
59
63
60
"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 ( ) ) )
66
63
}
67
64
68
65
"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 ( ) ) )
71
68
}
72
69
73
70
"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 ( ) ) )
76
73
}
77
74
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) ) ,
83
84
}
84
- args => Break ( Reason :: Error ( Error :: TupleArity ( 2 , args. len ( ) , args_span) ) ) ,
85
- } ,
85
+ }
86
86
87
87
"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 ( ) ) )
90
90
}
91
91
92
92
"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 ( ) ) )
95
95
}
96
96
97
97
"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 ( ) ) )
100
100
}
101
101
102
102
"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 ( ) ) )
105
105
}
106
106
107
107
"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 ( ) ) )
110
110
}
111
111
112
112
"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 ( ) ) )
115
115
}
116
116
117
117
"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 ( ) ) )
120
120
}
121
121
122
122
"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 ( ) ) )
125
125
}
126
126
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
+ }
131
134
132
135
"Truncate" => {
133
- let val: f64 = args. try_into ( ) . with_span ( args_span ) ? ;
136
+ let val = args. into_double ( ) ;
134
137
#[ allow( clippy:: cast_possible_truncation) ]
135
- Continue ( Value :: Int ( val as i64 ) )
138
+ Ok ( Value :: Int ( val as i64 ) )
136
139
}
137
140
138
- _ => Break ( Reason :: Error ( Error :: UnknownIntrinsic ( name_span) ) ) ,
141
+ _ => Err ( Error :: UnknownIntrinsic ( name_span) ) ,
139
142
}
140
143
}
141
144
}
142
145
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 ( ) ;
146
149
if lo > hi {
147
- Break ( Reason :: Error ( Error :: EmptyRange ( args_span) ) )
150
+ Err ( Error :: EmptyRange ( args_span) )
148
151
} else {
149
- Continue ( Value :: Int ( rand:: thread_rng ( ) . gen_range ( lo..=hi) ) )
152
+ Ok ( Value :: Int ( rand:: thread_rng ( ) . gen_range ( lo..=hi) ) )
150
153
}
151
154
}
152
155
156
+ #[ allow( clippy:: too_many_lines) ]
153
157
fn invoke_quantum_intrinsic (
154
158
name : & str ,
155
159
name_span : Span ,
156
160
args : Value ,
157
161
args_span : Span ,
158
- ) -> ControlFlow < Reason , Value > {
162
+ ) -> Result < Value , Error > {
159
163
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 ) , * ) ) ,* ) => {
161
165
match $chosen_op {
162
166
$( $( 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( ) )
165
169
} ) *
166
170
$( stringify!( $op2) => {
167
- match args. try_into_tuple( ) . with_span( args_span) ?. as_ref( ) {
171
+ let tup = args. into_tuple( ) ;
172
+ match & * tup {
168
173
[ x, y] => {
169
174
$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 ,
172
177
) ;
173
- Continue ( Value :: unit( ) )
178
+ Ok ( Value :: unit( ) )
174
179
}
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) )
176
194
}
177
195
} ) *
178
196
$( stringify!( $op3) => {
179
- match args. try_into_tuple( ) . with_span( args_span) ?. as_ref( ) {
197
+ let tup = args. into_tuple( ) ;
198
+ match & * tup {
180
199
[ x, y, z] => {
181
200
$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 ,
185
218
) ;
186
- Continue ( Value :: unit( ) )
219
+ Ok ( Value :: unit( ) )
187
220
}
188
- args => Break ( Reason :: Error ( Error :: TupleArity ( 3 , args . len( ) , args_span) ) )
221
+ _ => Err ( Error :: TupleArity ( 3 , tup . len( ) , args_span) )
189
222
}
190
- } ) * ) *
223
+ } ) *
224
+ ) *
191
225
192
226
"__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(
195
229
res,
196
230
__quantum__rt__result_get_one( ) ,
197
231
) ) )
198
232
}
199
233
200
234
"__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(
203
237
res,
204
238
__quantum__rt__result_get_one( ) ,
205
239
) ) )
206
240
}
207
241
208
- _ => Break ( Reason :: Error ( Error :: UnknownIntrinsic ( $chosen_op_span) ) ) ,
242
+ _ => Err ( Error :: UnknownIntrinsic ( $chosen_op_span) ) ,
209
243
}
210
244
} ;
211
245
}
@@ -217,12 +251,12 @@ fn invoke_quantum_intrinsic(
217
251
( 2 , __quantum__qis__cx__body) ,
218
252
( 2 , __quantum__qis__cy__body) ,
219
253
( 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) ,
226
260
( 1 , __quantum__qis__h__body) ,
227
261
( 1 , __quantum__qis__s__body) ,
228
262
( 1 , __quantum__qis__s__adj) ,
0 commit comments