@@ -41,14 +41,48 @@ impl From<f64> for PyFloat {
41
41
}
42
42
}
43
43
44
- fn mod_ ( v1 : f64 , v2 : f64 , vm : & VirtualMachine ) -> PyResult {
44
+ fn try_float ( value : & PyObjectRef , vm : & VirtualMachine ) -> PyResult < Option < f64 > > {
45
+ Ok ( if objtype:: isinstance ( & value, & vm. ctx . float_type ( ) ) {
46
+ Some ( get_value ( & value) )
47
+ } else if objtype:: isinstance ( & value, & vm. ctx . int_type ( ) ) {
48
+ Some ( objint:: get_float_value ( & value, vm) ?)
49
+ } else {
50
+ None
51
+ } )
52
+ }
53
+
54
+ fn inner_div ( v1 : f64 , v2 : f64 , vm : & VirtualMachine ) -> PyResult < f64 > {
45
55
if v2 != 0.0 {
46
- Ok ( vm. ctx . new_float ( v1 % v2) )
56
+ Ok ( v1 / v2)
57
+ } else {
58
+ Err ( vm. new_zero_division_error ( "float division by zero" . to_string ( ) ) )
59
+ }
60
+ }
61
+
62
+ fn inner_mod ( v1 : f64 , v2 : f64 , vm : & VirtualMachine ) -> PyResult < f64 > {
63
+ if v2 != 0.0 {
64
+ Ok ( v1 % v2)
47
65
} else {
48
66
Err ( vm. new_zero_division_error ( "float mod by zero" . to_string ( ) ) )
49
67
}
50
68
}
51
69
70
+ fn inner_floordiv ( v1 : f64 , v2 : f64 , vm : & VirtualMachine ) -> PyResult < f64 > {
71
+ if v2 != 0.0 {
72
+ Ok ( ( v1 / v2) . floor ( ) )
73
+ } else {
74
+ Err ( vm. new_zero_division_error ( "float floordiv by zero" . to_string ( ) ) )
75
+ }
76
+ }
77
+
78
+ fn inner_divmod ( v1 : f64 , v2 : f64 , vm : & VirtualMachine ) -> PyResult < ( f64 , f64 ) > {
79
+ if v2 != 0.0 {
80
+ Ok ( ( ( v1 / v2) . floor ( ) , v1 % v2) )
81
+ } else {
82
+ Err ( vm. new_zero_division_error ( "float divmod()" . to_string ( ) ) )
83
+ }
84
+ }
85
+
52
86
#[ pyimpl]
53
87
impl PyFloat {
54
88
#[ pymethod( name = "__eq__" ) ]
@@ -129,20 +163,15 @@ impl PyFloat {
129
163
}
130
164
131
165
#[ pymethod( name = "__add__" ) ]
132
- fn add ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyObjectRef {
133
- let v1 = self . value ;
134
- if objtype:: isinstance ( & other, & vm. ctx . float_type ( ) ) {
135
- vm. ctx . new_float ( v1 + get_value ( & other) )
136
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ( ) ) {
137
- vm. ctx
138
- . new_float ( v1 + objint:: get_value ( & other) . to_f64 ( ) . unwrap ( ) )
139
- } else {
140
- vm. ctx . not_implemented ( )
141
- }
166
+ fn add ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
167
+ try_float ( & other, vm) ?. map_or_else (
168
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
169
+ |other| ( self . value + other) . into_pyobject ( vm) ,
170
+ )
142
171
}
143
172
144
173
#[ pymethod( name = "__radd__" ) ]
145
- fn radd ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyObjectRef {
174
+ fn radd ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
146
175
self . add ( other, vm)
147
176
}
148
177
@@ -153,45 +182,51 @@ impl PyFloat {
153
182
154
183
#[ pymethod( name = "__divmod__" ) ]
155
184
fn divmod ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
156
- if objtype:: isinstance ( & other, & vm. ctx . float_type ( ) )
157
- || objtype:: isinstance ( & other, & vm. ctx . int_type ( ) )
158
- {
159
- let r1 = self . floordiv ( other. clone ( ) , vm) ?;
160
- let r2 = self . mod_ ( other, vm) ?;
161
- Ok ( vm. ctx . new_tuple ( vec ! [ r1, r2] ) )
162
- } else {
163
- Ok ( vm. ctx . not_implemented ( ) )
164
- }
185
+ try_float ( & other, vm) ?. map_or_else (
186
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
187
+ |other| {
188
+ let ( r1, r2) = inner_divmod ( self . value , other, vm) ?;
189
+ Ok ( vm
190
+ . ctx
191
+ . new_tuple ( vec ! [ vm. ctx. new_float( r1) , vm. ctx. new_float( r2) ] ) )
192
+ } ,
193
+ )
194
+ }
195
+
196
+ #[ pymethod( name = "__rdivmod__" ) ]
197
+ fn rdivmod ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
198
+ try_float ( & other, vm) ?. map_or_else (
199
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
200
+ |other| {
201
+ let ( r1, r2) = inner_divmod ( other, self . value , vm) ?;
202
+ Ok ( vm
203
+ . ctx
204
+ . new_tuple ( vec ! [ vm. ctx. new_float( r1) , vm. ctx. new_float( r2) ] ) )
205
+ } ,
206
+ )
165
207
}
166
208
167
209
#[ pymethod( name = "__floordiv__" ) ]
168
210
fn floordiv ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
169
- let v1 = self . value ;
170
- let v2 = if objtype:: isinstance ( & other, & vm. ctx . float_type ) {
171
- get_value ( & other)
172
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ) {
173
- objint:: get_float_value ( & other, vm) ?
174
- } else {
175
- return Ok ( vm. ctx . not_implemented ( ) ) ;
176
- } ;
211
+ try_float ( & other, vm) ?. map_or_else (
212
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
213
+ |other| inner_floordiv ( self . value , other, vm) ?. into_pyobject ( vm) ,
214
+ )
215
+ }
177
216
178
- if v2 != 0.0 {
179
- Ok ( vm. ctx . new_float ( ( v1 / v2) . floor ( ) ) )
180
- } else {
181
- Err ( vm. new_zero_division_error ( "float floordiv by zero" . to_string ( ) ) )
182
- }
217
+ #[ pymethod( name = "__rfloordiv__" ) ]
218
+ fn rfloordiv ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
219
+ try_float ( & other, vm) ?. map_or_else (
220
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
221
+ |other| inner_floordiv ( other, self . value , vm) ?. into_pyobject ( vm) ,
222
+ )
183
223
}
184
224
185
225
fn new_float ( cls : PyClassRef , arg : PyObjectRef , vm : & VirtualMachine ) -> PyResult < PyFloatRef > {
186
226
let value = if objtype:: isinstance ( & arg, & vm. ctx . float_type ( ) ) {
187
227
get_value ( & arg)
188
228
} else if objtype:: isinstance ( & arg, & vm. ctx . int_type ( ) ) {
189
- match objint:: get_float_value ( & arg, vm) {
190
- Ok ( f) => f,
191
- Err ( e) => {
192
- return Err ( e) ;
193
- }
194
- }
229
+ objint:: get_float_value ( & arg, vm) ?
195
230
} else if objtype:: isinstance ( & arg, & vm. ctx . str_type ( ) ) {
196
231
match lexical:: try_parse ( objstr:: get_value ( & arg) ) {
197
232
Ok ( f) => f,
@@ -222,28 +257,18 @@ impl PyFloat {
222
257
223
258
#[ pymethod( name = "__mod__" ) ]
224
259
fn mod_ ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
225
- let v1 = self . value ;
226
- let v2 = if objtype:: isinstance ( & other, & vm. ctx . float_type ) {
227
- get_value ( & other)
228
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ) {
229
- objint:: get_float_value ( & other, vm) ?
230
- } else {
231
- return Ok ( vm. ctx . not_implemented ( ) ) ;
232
- } ;
233
-
234
- mod_ ( v1, v2, vm)
260
+ try_float ( & other, vm) ?. map_or_else (
261
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
262
+ |other| inner_mod ( self . value , other, vm) ?. into_pyobject ( vm) ,
263
+ )
235
264
}
236
265
237
266
#[ pymethod( name = "__rmod__" ) ]
238
267
fn rmod ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
239
- let v2 = self . value ;
240
- let v1 = if objtype:: isinstance ( & other, & vm. ctx . int_type ) {
241
- objint:: get_float_value ( & other, vm) ?
242
- } else {
243
- return Ok ( vm. ctx . not_implemented ( ) ) ;
244
- } ;
245
-
246
- mod_ ( v1, v2, vm)
268
+ try_float ( & other, vm) ?. map_or_else (
269
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
270
+ |other| inner_mod ( other, self . value , vm) ?. into_pyobject ( vm) ,
271
+ )
247
272
}
248
273
249
274
#[ pymethod( name = "__neg__" ) ]
@@ -252,44 +277,35 @@ impl PyFloat {
252
277
}
253
278
254
279
#[ pymethod( name = "__pow__" ) ]
255
- fn pow ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyObjectRef {
256
- let v1 = self . value ;
257
- if objtype:: isinstance ( & other, & vm. ctx . float_type ( ) ) {
258
- vm. ctx . new_float ( v1. powf ( get_value ( & other) ) )
259
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ( ) ) {
260
- let result = v1. powf ( objint:: get_value ( & other) . to_f64 ( ) . unwrap ( ) ) ;
261
- vm. ctx . new_float ( result)
262
- } else {
263
- vm. ctx . not_implemented ( )
264
- }
280
+ fn pow ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
281
+ try_float ( & other, vm) ?. map_or_else (
282
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
283
+ |other| self . value . powf ( other) . into_pyobject ( vm) ,
284
+ )
285
+ }
286
+
287
+ #[ pymethod( name = "__rpow__" ) ]
288
+ fn rpow ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
289
+ try_float ( & other, vm) ?. map_or_else (
290
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
291
+ |other| other. powf ( self . value ) . into_pyobject ( vm) ,
292
+ )
265
293
}
266
294
267
295
#[ pymethod( name = "__sub__" ) ]
268
296
fn sub ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
269
- let v1 = self . value ;
270
- if objtype:: isinstance ( & other, & vm. ctx . float_type ( ) ) {
271
- Ok ( vm. ctx . new_float ( v1 - get_value ( & other) ) )
272
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ( ) ) {
273
- Ok ( vm
274
- . ctx
275
- . new_float ( v1 - objint:: get_value ( & other) . to_f64 ( ) . unwrap ( ) ) )
276
- } else {
277
- Ok ( vm. ctx . not_implemented ( ) )
278
- }
297
+ try_float ( & other, vm) ?. map_or_else (
298
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
299
+ |other| ( self . value - other) . into_pyobject ( vm) ,
300
+ )
279
301
}
280
302
281
303
#[ pymethod( name = "__rsub__" ) ]
282
304
fn rsub ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
283
- let v1 = self . value ;
284
- if objtype:: isinstance ( & other, & vm. ctx . float_type ( ) ) {
285
- Ok ( vm. ctx . new_float ( get_value ( & other) - v1) )
286
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ( ) ) {
287
- Ok ( vm
288
- . ctx
289
- . new_float ( objint:: get_value ( & other) . to_f64 ( ) . unwrap ( ) - v1) )
290
- } else {
291
- Ok ( vm. ctx . not_implemented ( ) )
292
- }
305
+ try_float ( & other, vm) ?. map_or_else (
306
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
307
+ |other| ( other - self . value ) . into_pyobject ( vm) ,
308
+ )
293
309
}
294
310
295
311
#[ pymethod( name = "__repr__" ) ]
@@ -299,52 +315,26 @@ impl PyFloat {
299
315
300
316
#[ pymethod( name = "__truediv__" ) ]
301
317
fn truediv ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
302
- let v1 = self . value ;
303
- let v2 = if objtype:: isinstance ( & other, & vm. ctx . float_type ) {
304
- get_value ( & other)
305
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ) {
306
- objint:: get_float_value ( & other, vm) ?
307
- } else {
308
- return Ok ( vm. ctx . not_implemented ( ) ) ;
309
- } ;
310
-
311
- if v2 != 0.0 {
312
- Ok ( vm. ctx . new_float ( v1 / v2) )
313
- } else {
314
- Err ( vm. new_zero_division_error ( "float division by zero" . to_string ( ) ) )
315
- }
318
+ try_float ( & other, vm) ?. map_or_else (
319
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
320
+ |other| inner_div ( self . value , other, vm) ?. into_pyobject ( vm) ,
321
+ )
316
322
}
317
323
318
324
#[ pymethod( name = "__rtruediv__" ) ]
319
325
fn rtruediv ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
320
- let v1 = self . value ;
321
- let v2 = if objtype:: isinstance ( & other, & vm. ctx . float_type ) {
322
- get_value ( & other)
323
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ) {
324
- objint:: get_float_value ( & other, vm) ?
325
- } else {
326
- return Ok ( vm. ctx . not_implemented ( ) ) ;
327
- } ;
328
-
329
- if v1 != 0.0 {
330
- Ok ( vm. ctx . new_float ( v2 / v1) )
331
- } else {
332
- Err ( vm. new_zero_division_error ( "float division by zero" . to_string ( ) ) )
333
- }
326
+ try_float ( & other, vm) ?. map_or_else (
327
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
328
+ |other| inner_div ( other, self . value , vm) ?. into_pyobject ( vm) ,
329
+ )
334
330
}
335
331
336
332
#[ pymethod( name = "__mul__" ) ]
337
333
fn mul ( & self , other : PyObjectRef , vm : & VirtualMachine ) -> PyResult {
338
- let v1 = self . value ;
339
- if objtype:: isinstance ( & other, & vm. ctx . float_type ) {
340
- Ok ( vm. ctx . new_float ( v1 * get_value ( & other) ) )
341
- } else if objtype:: isinstance ( & other, & vm. ctx . int_type ) {
342
- Ok ( vm
343
- . ctx
344
- . new_float ( v1 * objint:: get_value ( & other) . to_f64 ( ) . unwrap ( ) ) )
345
- } else {
346
- Ok ( vm. ctx . not_implemented ( ) )
347
- }
334
+ try_float ( & other, vm) ?. map_or_else (
335
+ || Ok ( vm. ctx . not_implemented ( ) ) ,
336
+ |other| ( self . value * other) . into_pyobject ( vm) ,
337
+ )
348
338
}
349
339
350
340
#[ pymethod( name = "__rmul__" ) ]
0 commit comments