Skip to content

Commit 81d51f4

Browse files
xiaozhiyanyouknowone
authored andcommitted
Improve: binaryops with Number Protocol
1 parent bf70c53 commit 81d51f4

File tree

4 files changed

+223
-490
lines changed

4 files changed

+223
-490
lines changed

vm/src/protocol/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ mod sequence;
88
pub use buffer::{BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, VecBuffer};
99
pub use iter::{PyIter, PyIterIter, PyIterReturn};
1010
pub use mapping::{PyMapping, PyMappingMethods};
11-
pub use number::{PyNumber, PyNumberMethods, PyNumberMethodsOffset};
11+
pub use number::{PyNumber, PyNumberBinaryOpSlot, PyNumberMethods};
1212
pub use sequence::{PySequence, PySequenceMethods};

vm/src/protocol/number.rs

Lines changed: 45 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use crate::{
88
VirtualMachine,
99
};
1010
use crossbeam_utils::atomic::AtomicCell;
11-
use std::ptr;
1211

1312
type UnaryFunc<R = PyObjectRef> = AtomicCell<Option<fn(PyNumber, &VirtualMachine) -> PyResult<R>>>;
1413
type BinaryFunc<R = PyObjectRef> =
@@ -110,7 +109,6 @@ impl PyObject {
110109
}
111110

112111
#[derive(Default)]
113-
// #[repr(C)]
114112
pub struct PyNumberMethods {
115113
/* Number implementations must check *both*
116114
arguments for proper type and implement the necessary conversions
@@ -138,7 +136,6 @@ pub struct PyNumberMethods {
138136
pub inplace_subtract: BinaryFunc,
139137
pub inplace_multiply: BinaryFunc,
140138
pub inplace_remainder: BinaryFunc,
141-
pub inplace_divmod: BinaryFunc,
142139
pub inplace_power: BinaryFunc,
143140
pub inplace_lshift: BinaryFunc,
144141
pub inplace_rshift: BinaryFunc,
@@ -184,7 +181,6 @@ impl PyNumberMethods {
184181
inplace_subtract: AtomicCell::new(None),
185182
inplace_multiply: AtomicCell::new(None),
186183
inplace_remainder: AtomicCell::new(None),
187-
inplace_divmod: AtomicCell::new(None),
188184
inplace_power: AtomicCell::new(None),
189185
inplace_lshift: AtomicCell::new(None),
190186
inplace_rshift: AtomicCell::new(None),
@@ -199,32 +195,58 @@ impl PyNumberMethods {
199195
matrix_multiply: AtomicCell::new(None),
200196
inplace_matrix_multiply: AtomicCell::new(None),
201197
};
198+
199+
pub fn get_binary_op(&self, op_slot: &PyNumberBinaryOpSlot) -> PyResult<&BinaryFunc> {
200+
use PyNumberBinaryOpSlot::*;
201+
let binary_op = match op_slot {
202+
Add => &self.add,
203+
Subtract => &self.subtract,
204+
Multiply => &self.multiply,
205+
Remainder => &self.remainder,
206+
Divmod => &self.divmod,
207+
Power => &self.power,
208+
Lshift => &self.lshift,
209+
Rshift => &self.rshift,
210+
And => &self.and,
211+
Xor => &self.xor,
212+
Or => &self.or,
213+
InplaceAdd => &self.inplace_add,
214+
InplaceSubtract => &self.inplace_subtract,
215+
InplaceMultiply => &self.inplace_multiply,
216+
InplaceRemainder => &self.inplace_remainder,
217+
InplacePower => &self.inplace_power,
218+
InplaceLshift => &self.inplace_lshift,
219+
InplaceRshift => &self.inplace_rshift,
220+
InplaceAnd => &self.inplace_and,
221+
InplaceXor => &self.inplace_xor,
222+
InplaceOr => &self.inplace_or,
223+
FloorDivide => &self.floor_divide,
224+
TrueDivide => &self.true_divide,
225+
InplaceFloorDivide => &self.inplace_floor_divide,
226+
InplaceTrueDivide => &self.inplace_true_divide,
227+
MatrixMultiply => &self.matrix_multiply,
228+
InplaceMatrixMultiply => &self.inplace_matrix_multiply,
229+
};
230+
Ok(binary_op)
231+
}
202232
}
203233

204-
pub enum PyNumberMethodsOffset {
234+
pub enum PyNumberBinaryOpSlot {
205235
Add,
206236
Subtract,
207237
Multiply,
208238
Remainder,
209239
Divmod,
210240
Power,
211-
Negative,
212-
Positive,
213-
Absolute,
214-
Boolean,
215-
Invert,
216241
Lshift,
217242
Rshift,
218243
And,
219244
Xor,
220245
Or,
221-
Int,
222-
Float,
223246
InplaceAdd,
224247
InplaceSubtract,
225248
InplaceMultiply,
226249
InplaceRemainder,
227-
InplaceDivmod,
228250
InplacePower,
229251
InplaceLshift,
230252
InplaceRshift,
@@ -235,63 +257,10 @@ pub enum PyNumberMethodsOffset {
235257
TrueDivide,
236258
InplaceFloorDivide,
237259
InplaceTrueDivide,
238-
Index,
239260
MatrixMultiply,
240261
InplaceMatrixMultiply,
241262
}
242263

243-
impl PyNumberMethodsOffset {
244-
pub fn method(&self, methods: &PyNumberMethods, vm: &VirtualMachine) -> PyResult<&BinaryFunc> {
245-
use PyNumberMethodsOffset::*;
246-
unsafe {
247-
match self {
248-
// BinaryFunc
249-
Add => ptr::addr_of!(methods.add),
250-
Subtract => ptr::addr_of!(methods.subtract),
251-
Multiply => ptr::addr_of!(methods.multiply),
252-
Remainder => ptr::addr_of!(methods.remainder),
253-
Divmod => ptr::addr_of!(methods.divmod),
254-
Power => ptr::addr_of!(methods.power),
255-
Lshift => ptr::addr_of!(methods.lshift),
256-
Rshift => ptr::addr_of!(methods.rshift),
257-
And => ptr::addr_of!(methods.and),
258-
Xor => ptr::addr_of!(methods.xor),
259-
Or => ptr::addr_of!(methods.or),
260-
InplaceAdd => ptr::addr_of!(methods.inplace_add),
261-
InplaceSubtract => ptr::addr_of!(methods.inplace_subtract),
262-
InplaceMultiply => ptr::addr_of!(methods.inplace_multiply),
263-
InplaceRemainder => ptr::addr_of!(methods.inplace_remainder),
264-
InplaceDivmod => ptr::addr_of!(methods.inplace_divmod),
265-
InplacePower => ptr::addr_of!(methods.inplace_power),
266-
InplaceLshift => ptr::addr_of!(methods.inplace_lshift),
267-
InplaceRshift => ptr::addr_of!(methods.inplace_rshift),
268-
InplaceAnd => ptr::addr_of!(methods.inplace_and),
269-
InplaceXor => ptr::addr_of!(methods.inplace_xor),
270-
InplaceOr => ptr::addr_of!(methods.inplace_or),
271-
FloorDivide => ptr::addr_of!(methods.floor_divide),
272-
TrueDivide => ptr::addr_of!(methods.true_divide),
273-
InplaceFloorDivide => ptr::addr_of!(methods.inplace_floor_divide),
274-
InplaceTrueDivide => ptr::addr_of!(methods.inplace_true_divide),
275-
MatrixMultiply => ptr::addr_of!(methods.matrix_multiply),
276-
InplaceMatrixMultiply => ptr::addr_of!(methods.inplace_matrix_multiply),
277-
// UnaryFunc
278-
Negative => ptr::null(),
279-
Positive => ptr::null(),
280-
Absolute => ptr::null(),
281-
Boolean => ptr::null(),
282-
Invert => ptr::null(),
283-
Int => ptr::null(),
284-
Float => ptr::null(),
285-
Index => ptr::null(),
286-
}
287-
.as_ref()
288-
.ok_or_else(|| {
289-
vm.new_value_error("No unaryop supported for PyNumberMethodsOffset".to_owned())
290-
})
291-
}
292-
}
293-
}
294-
295264
#[derive(Copy, Clone)]
296265
pub struct PyNumber<'a> {
297266
pub obj: &'a PyObject,
@@ -314,12 +283,12 @@ impl PyNumber<'_> {
314283
obj.class().mro_find_map(|x| x.slots.as_number.load())
315284
}
316285

317-
pub fn methods<'a>(
318-
&'a self,
319-
op_slot: &'a PyNumberMethodsOffset,
320-
vm: &VirtualMachine,
321-
) -> PyResult<&BinaryFunc> {
322-
op_slot.method(self.methods, vm)
286+
pub fn methods(&self) -> &PyNumberMethods {
287+
self.methods
288+
}
289+
290+
pub fn get_binary_op(&self, op_slot: &PyNumberBinaryOpSlot) -> PyResult<&BinaryFunc> {
291+
self.methods().get_binary_op(op_slot)
323292
}
324293

325294
// PyNumber_Check
@@ -336,12 +305,12 @@ impl PyNumber<'_> {
336305

337306
// PyIndex_Check
338307
pub fn is_index(&self) -> bool {
339-
self.methods.index.load().is_some()
308+
self.methods().index.load().is_some()
340309
}
341310

342311
#[inline]
343312
pub fn int(self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
344-
self.methods.int.load().map(|f| {
313+
self.methods().int.load().map(|f| {
345314
let ret = f(self, vm)?;
346315
let value = if !ret.class().is(PyInt::class(vm)) {
347316
warnings::warn(
@@ -365,7 +334,7 @@ impl PyNumber<'_> {
365334

366335
#[inline]
367336
pub fn index(self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
368-
self.methods.index.load().map(|f| {
337+
self.methods().index.load().map(|f| {
369338
let ret = f(self, vm)?;
370339
let value = if !ret.class().is(PyInt::class(vm)) {
371340
warnings::warn(
@@ -389,7 +358,7 @@ impl PyNumber<'_> {
389358

390359
#[inline]
391360
pub fn float(self, vm: &VirtualMachine) -> Option<PyResult<PyRef<PyFloat>>> {
392-
self.methods.float.load().map(|f| {
361+
self.methods().float.load().map(|f| {
393362
let ret = f(self, vm)?;
394363
let value = if !ret.class().is(PyFloat::class(vm)) {
395364
warnings::warn(

vm/src/stdlib/builtins.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ mod builtins {
2222
ArgBytesLike, ArgCallable, ArgIntoBool, ArgIterable, ArgMapping, ArgStrOrBytesLike,
2323
Either, FuncArgs, KwArgs, OptionalArg, OptionalOption, PosArgs, PyArithmeticValue,
2424
},
25-
protocol::{PyIter, PyIterReturn, PyNumberMethodsOffset},
25+
protocol::{PyIter, PyIterReturn, PyNumberBinaryOpSlot},
2626
py_io,
2727
readline::{Readline, ReadlineResult},
2828
stdlib::sys,
@@ -610,9 +610,7 @@ mod builtins {
610610
modulus,
611611
} = args;
612612
match modulus {
613-
None => vm.binary_op(&x, &y, PyNumberMethodsOffset::Power, "pow", |vm, _, _| {
614-
Ok(vm.ctx.not_implemented())
615-
}),
613+
None => vm.binary_op(&x, &y, &PyNumberBinaryOpSlot::Power, "pow"),
616614
Some(z) => {
617615
let try_pow_value = |obj: &PyObject,
618616
args: (PyObjectRef, PyObjectRef, PyObjectRef)|

0 commit comments

Comments
 (0)