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,195 +19,229 @@ 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
- "AsString" => Continue ( Value :: String ( args. to_string ( ) . into ( ) ) ) ,
58
+ "AsString" => Ok ( Value :: String ( args. to_string ( ) . into ( ) ) ) ,
60
59
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 ) ) ) ,
64
61
65
62
"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 ( ) ) )
68
65
}
69
66
70
67
"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 ( ) ) )
73
70
}
74
71
75
72
"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 ( ) ) )
78
75
}
79
76
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) ) ,
85
86
}
86
- args => Break ( Reason :: Error ( Error :: TupleArity ( 2 , args. len ( ) , args_span) ) ) ,
87
- } ,
87
+ }
88
88
89
89
"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 ( ) ) )
92
92
}
93
93
94
94
"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 ( ) ) )
97
97
}
98
98
99
99
"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 ( ) ) )
102
102
}
103
103
104
104
"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 ( ) ) )
107
107
}
108
108
109
109
"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 ( ) ) )
112
112
}
113
113
114
114
"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 ( ) ) )
117
117
}
118
118
119
119
"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 ( ) ) )
122
122
}
123
123
124
124
"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 ( ) ) )
127
127
}
128
128
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
+ }
133
136
134
137
"Truncate" => {
135
- let val: f64 = args. try_into ( ) . with_span ( args_span ) ? ;
138
+ let val = args. into_double ( ) ;
136
139
#[ allow( clippy:: cast_possible_truncation) ]
137
- Continue ( Value :: Int ( val as i64 ) )
140
+ Ok ( Value :: Int ( val as i64 ) )
138
141
}
139
142
140
- _ => Break ( Reason :: Error ( Error :: UnknownIntrinsic ( name_span) ) ) ,
143
+ _ => Err ( Error :: UnknownIntrinsic ( name_span) ) ,
141
144
}
142
145
}
143
146
}
144
147
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 ( ) ;
148
151
if lo > hi {
149
- Break ( Reason :: Error ( Error :: EmptyRange ( args_span) ) )
152
+ Err ( Error :: EmptyRange ( args_span) )
150
153
} else {
151
- Continue ( Value :: Int ( rand:: thread_rng ( ) . gen_range ( lo..=hi) ) )
154
+ Ok ( Value :: Int ( rand:: thread_rng ( ) . gen_range ( lo..=hi) ) )
152
155
}
153
156
}
154
157
158
+ #[ allow( clippy:: too_many_lines) ]
155
159
fn invoke_quantum_intrinsic (
156
160
name : & str ,
157
161
name_span : Span ,
158
162
args : Value ,
159
163
args_span : Span ,
160
- ) -> ControlFlow < Reason , Value > {
164
+ ) -> Result < Value , Error > {
161
165
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 ) , * ) ) ,* ) => {
163
167
match $chosen_op {
164
168
$( $( 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( ) )
167
171
} ) *
168
172
$( stringify!( $op2) => {
169
- match args. try_into_tuple( ) . with_span( args_span) ?. as_ref( ) {
173
+ let tup = args. into_tuple( ) ;
174
+ match & * tup {
170
175
[ x, y] => {
171
176
$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 ,
174
179
) ;
175
- Continue ( Value :: unit( ) )
180
+ Ok ( Value :: unit( ) )
176
181
}
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) )
178
196
}
179
197
} ) *
180
198
$( stringify!( $op3) => {
181
- match args. try_into_tuple( ) . with_span( args_span) ?. as_ref( ) {
199
+ let tup = args. into_tuple( ) ;
200
+ match & * tup {
182
201
[ x, y, z] => {
183
202
$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 ,
187
220
) ;
188
- Continue ( Value :: unit( ) )
221
+ Ok ( Value :: unit( ) )
189
222
}
190
- args => Break ( Reason :: Error ( Error :: TupleArity ( 3 , args . len( ) , args_span) ) )
223
+ _ => Err ( Error :: TupleArity ( 3 , tup . len( ) , args_span) )
191
224
}
192
- } ) * ) *
225
+ } ) *
226
+ ) *
193
227
194
228
"__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(
197
231
res,
198
232
__quantum__rt__result_get_one( ) ,
199
233
) ) )
200
234
}
201
235
202
236
"__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(
205
239
res,
206
240
__quantum__rt__result_get_one( ) ,
207
241
) ) )
208
242
}
209
243
210
- _ => Break ( Reason :: Error ( Error :: UnknownIntrinsic ( $chosen_op_span) ) ) ,
244
+ _ => Err ( Error :: UnknownIntrinsic ( $chosen_op_span) ) ,
211
245
}
212
246
} ;
213
247
}
@@ -219,12 +253,12 @@ fn invoke_quantum_intrinsic(
219
253
( 2 , __quantum__qis__cx__body) ,
220
254
( 2 , __quantum__qis__cy__body) ,
221
255
( 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) ,
228
262
( 1 , __quantum__qis__h__body) ,
229
263
( 1 , __quantum__qis__s__body) ,
230
264
( 1 , __quantum__qis__s__adj) ,
0 commit comments