mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 10:44:36 +08:00
refactor PyNumberBinaryFunc
This commit is contained in:
1 parent
ee78527a9e
commit
d6acd2ee7d
16 files changed
+198
-407
No files matched your search
@@ -164,15 +164,9 @@ impl PyBool {
|
||||
impl AsNumber for PyBool {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
and: Some(|number, other, vm| {
|
||||
PyBool::and(number.obj.to_owned(), other.to_owned(), vm).to_pyresult(vm)
|
||||
}),
|
||||
xor: Some(|number, other, vm| {
|
||||
PyBool::xor(number.obj.to_owned(), other.to_owned(), vm).to_pyresult(vm)
|
||||
}),
|
||||
or: Some(|number, other, vm| {
|
||||
PyBool::or(number.obj.to_owned(), other.to_owned(), vm).to_pyresult(vm)
|
||||
}),
|
||||
and: Some(|a, b, vm| PyBool::and(a.to_owned(), b.to_owned(), vm).to_pyresult(vm)),
|
||||
xor: Some(|a, b, vm| PyBool::xor(a.to_owned(), b.to_owned(), vm).to_pyresult(vm)),
|
||||
or: Some(|a, b, vm| PyBool::or(a.to_owned(), b.to_owned(), vm).to_pyresult(vm)),
|
||||
..PyInt::AS_NUMBER
|
||||
};
|
||||
&AS_NUMBER
|
||||
|
||||
@@ -843,9 +843,9 @@ impl AsSequence for PyByteArray {
|
||||
impl AsNumber for PyByteArray {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
remainder: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyByteArray>() {
|
||||
number.mod_(other.to_owned(), vm).to_pyresult(vm)
|
||||
remainder: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyByteArray>() {
|
||||
a.mod_(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
@@ -615,9 +615,9 @@ impl AsSequence for PyBytes {
|
||||
impl AsNumber for PyBytes {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
remainder: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyBytes>() {
|
||||
number.mod_(other.to_owned(), vm).to_pyresult(vm)
|
||||
remainder: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyBytes>() {
|
||||
a.mod_(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::{
|
||||
PyComparisonValue,
|
||||
},
|
||||
identifier,
|
||||
protocol::{PyNumber, PyNumberMethods},
|
||||
protocol::PyNumberMethods,
|
||||
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
};
|
||||
@@ -418,16 +418,10 @@ impl Hashable for PyComplex {
|
||||
impl AsNumber for PyComplex {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
add: Some(|number, other, vm| {
|
||||
PyComplex::number_op(number, other, |a, b, _vm| a + b, vm)
|
||||
}),
|
||||
subtract: Some(|number, other, vm| {
|
||||
PyComplex::number_op(number, other, |a, b, _vm| a - b, vm)
|
||||
}),
|
||||
multiply: Some(|number, other, vm| {
|
||||
PyComplex::number_op(number, other, |a, b, _vm| a * b, vm)
|
||||
}),
|
||||
power: Some(|number, other, vm| PyComplex::number_op(number, other, inner_pow, vm)),
|
||||
add: Some(|a, b, vm| PyComplex::number_op(a, b, |a, b, _vm| a + b, vm)),
|
||||
subtract: Some(|a, b, vm| PyComplex::number_op(a, b, |a, b, _vm| a - b, vm)),
|
||||
multiply: Some(|a, b, vm| PyComplex::number_op(a, b, |a, b, _vm| a * b, vm)),
|
||||
power: Some(|a, b, vm| PyComplex::number_op(a, b, inner_pow, vm)),
|
||||
negative: Some(|number, vm| {
|
||||
let value = PyComplex::number_downcast(number).value;
|
||||
(-value).to_pyresult(vm)
|
||||
@@ -440,9 +434,7 @@ impl AsNumber for PyComplex {
|
||||
value.norm().to_pyresult(vm)
|
||||
}),
|
||||
boolean: Some(|number, _vm| Ok(PyComplex::number_downcast(number).value.is_zero())),
|
||||
true_divide: Some(|number, other, vm| {
|
||||
PyComplex::number_op(number, other, inner_div, vm)
|
||||
}),
|
||||
true_divide: Some(|a, b, vm| PyComplex::number_op(a, b, inner_div, vm)),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
};
|
||||
&AS_NUMBER
|
||||
@@ -494,12 +486,12 @@ impl Representable for PyComplex {
|
||||
}
|
||||
|
||||
impl PyComplex {
|
||||
fn number_op<F, R>(number: PyNumber, other: &PyObject, op: F, vm: &VirtualMachine) -> PyResult
|
||||
fn number_op<F, R>(a: &PyObject, b: &PyObject, op: F, vm: &VirtualMachine) -> PyResult
|
||||
where
|
||||
F: FnOnce(Complex64, Complex64, &VirtualMachine) -> R,
|
||||
R: ToPyResult,
|
||||
{
|
||||
if let (Some(a), Some(b)) = (to_op_complex(number.obj, vm)?, to_op_complex(other, vm)?) {
|
||||
if let (Some(a), Some(b)) = (to_op_complex(a, vm)?, to_op_complex(b, vm)?) {
|
||||
op(a, b, vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
|
||||
+42
-96
@@ -472,16 +472,16 @@ impl AsSequence for PyDict {
|
||||
impl AsNumber for PyDict {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
or: Some(|num, args, vm| {
|
||||
if let Some(num) = num.obj.downcast_ref::<PyDict>() {
|
||||
PyDict::or(num, args.to_pyobject(vm), vm)
|
||||
or: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyDict>() {
|
||||
PyDict::or(a, b.to_pyobject(vm), vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
inplace_or: Some(|num, args, vm| {
|
||||
if let Some(num) = num.obj.downcast_ref::<PyDict>() {
|
||||
PyDict::ior(num.to_owned(), args.to_pyobject(vm), vm).map(|d| d.into())
|
||||
inplace_or: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyDict>() {
|
||||
PyDict::ior(a.to_owned(), b.to_pyobject(vm), vm).map(|d| d.into())
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
@@ -1169,51 +1169,10 @@ impl AsSequence for PyDictKeys {
|
||||
impl AsNumber for PyDictKeys {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
subtract: Some(|num, args, vm| {
|
||||
let num = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
Ok(PySet {
|
||||
inner: num
|
||||
.difference(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}),
|
||||
and: Some(|num, args, vm| {
|
||||
let num = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
Ok(PySet {
|
||||
inner: num
|
||||
.intersection(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}),
|
||||
xor: Some(|num, args, vm| {
|
||||
let num = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
Ok(PySet {
|
||||
inner: num.symmetric_difference(
|
||||
ArgIterable::try_from_object(vm, args.to_owned())?,
|
||||
vm,
|
||||
)?,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}),
|
||||
or: Some(|num, args, vm| {
|
||||
let num = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
Ok(PySet {
|
||||
inner: num.union(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}),
|
||||
subtract: Some(set_inner_number_subtract),
|
||||
and: Some(set_inner_number_and),
|
||||
xor: Some(set_inner_number_xor),
|
||||
or: Some(set_inner_number_or),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
};
|
||||
&AS_NUMBER
|
||||
@@ -1288,51 +1247,10 @@ impl AsSequence for PyDictItems {
|
||||
impl AsNumber for PyDictItems {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
subtract: Some(|num, args, vm| {
|
||||
let num = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
Ok(PySet {
|
||||
inner: num
|
||||
.difference(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}),
|
||||
and: Some(|num, args, vm| {
|
||||
let num = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
Ok(PySet {
|
||||
inner: num
|
||||
.intersection(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}),
|
||||
xor: Some(|num, args, vm| {
|
||||
let num = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
Ok(PySet {
|
||||
inner: num.symmetric_difference(
|
||||
ArgIterable::try_from_object(vm, args.to_owned())?,
|
||||
vm,
|
||||
)?,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}),
|
||||
or: Some(|num, args, vm| {
|
||||
let num = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, num.obj.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
Ok(PySet {
|
||||
inner: num.union(ArgIterable::try_from_object(vm, args.to_owned())?, vm)?,
|
||||
}
|
||||
.into_pyobject(vm))
|
||||
}),
|
||||
subtract: Some(set_inner_number_subtract),
|
||||
and: Some(set_inner_number_and),
|
||||
xor: Some(set_inner_number_xor),
|
||||
or: Some(set_inner_number_or),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
};
|
||||
&AS_NUMBER
|
||||
@@ -1358,6 +1276,34 @@ impl AsSequence for PyDictValues {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_inner_number_op<F>(a: &PyObject, b: &PyObject, f: F, vm: &VirtualMachine) -> PyResult
|
||||
where
|
||||
F: FnOnce(PySetInner, ArgIterable) -> PyResult<PySetInner>,
|
||||
{
|
||||
let a = PySetInner::from_iter(
|
||||
ArgIterable::try_from_object(vm, a.to_owned())?.iter(vm)?,
|
||||
vm,
|
||||
)?;
|
||||
let b = ArgIterable::try_from_object(vm, b.to_owned())?;
|
||||
Ok(PySet { inner: f(a, b)? }.into_pyobject(vm))
|
||||
}
|
||||
|
||||
fn set_inner_number_subtract(a: &PyObject, b: &PyObject, vm: &VirtualMachine) -> PyResult {
|
||||
set_inner_number_op(a, b, |a, b| a.difference(b, vm), vm)
|
||||
}
|
||||
|
||||
fn set_inner_number_and(a: &PyObject, b: &PyObject, vm: &VirtualMachine) -> PyResult {
|
||||
set_inner_number_op(a, b, |a, b| a.intersection(b, vm), vm)
|
||||
}
|
||||
|
||||
fn set_inner_number_xor(a: &PyObject, b: &PyObject, vm: &VirtualMachine) -> PyResult {
|
||||
set_inner_number_op(a, b, |a, b| a.symmetric_difference(b, vm), vm)
|
||||
}
|
||||
|
||||
fn set_inner_number_or(a: &PyObject, b: &PyObject, vm: &VirtualMachine) -> PyResult {
|
||||
set_inner_number_op(a, b, |a, b| a.union(b, vm), vm)
|
||||
}
|
||||
|
||||
pub(crate) fn init(context: &Context) {
|
||||
PyDict::extend_class(context, context.types.dict_type);
|
||||
PyDictKeys::extend_class(context, context.types.dict_keys_type);
|
||||
|
||||
+11
-11
@@ -13,7 +13,7 @@ use crate::{
|
||||
PyArithmeticValue::{self, *},
|
||||
PyComparisonValue,
|
||||
},
|
||||
protocol::{PyNumber, PyNumberMethods},
|
||||
protocol::PyNumberMethods,
|
||||
types::{AsNumber, Callable, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
|
||||
TryFromBorrowedObject, TryFromObject, VirtualMachine,
|
||||
@@ -544,12 +544,12 @@ impl Hashable for PyFloat {
|
||||
impl AsNumber for PyFloat {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
add: Some(|num, other, vm| PyFloat::number_op(num, other, |a, b, _vm| a + b, vm)),
|
||||
subtract: Some(|num, other, vm| PyFloat::number_op(num, other, |a, b, _vm| a - b, vm)),
|
||||
multiply: Some(|num, other, vm| PyFloat::number_op(num, other, |a, b, _vm| a * b, vm)),
|
||||
remainder: Some(|num, other, vm| PyFloat::number_op(num, other, inner_mod, vm)),
|
||||
divmod: Some(|num, other, vm| PyFloat::number_op(num, other, inner_divmod, vm)),
|
||||
power: Some(|num, other, vm| PyFloat::number_op(num, other, float_pow, vm)),
|
||||
add: Some(|a, b, vm| PyFloat::number_op(a, b, |a, b, _vm| a + b, vm)),
|
||||
subtract: Some(|a, b, vm| PyFloat::number_op(a, b, |a, b, _vm| a - b, vm)),
|
||||
multiply: Some(|a, b, vm| PyFloat::number_op(a, b, |a, b, _vm| a * b, vm)),
|
||||
remainder: Some(|a, b, vm| PyFloat::number_op(a, b, inner_mod, vm)),
|
||||
divmod: Some(|a, b, vm| PyFloat::number_op(a, b, inner_divmod, vm)),
|
||||
power: Some(|a, b, vm| PyFloat::number_op(a, b, float_pow, vm)),
|
||||
negative: Some(|num, vm| {
|
||||
let value = PyFloat::number_downcast(num).value;
|
||||
(-value).to_pyresult(vm)
|
||||
@@ -565,8 +565,8 @@ impl AsNumber for PyFloat {
|
||||
try_to_bigint(value, vm).map(|x| vm.ctx.new_int(x))
|
||||
}),
|
||||
float: Some(|num, vm| Ok(PyFloat::number_downcast_exact(num, vm))),
|
||||
floor_divide: Some(|num, other, vm| PyFloat::number_op(num, other, inner_floordiv, vm)),
|
||||
true_divide: Some(|num, other, vm| PyFloat::number_op(num, other, inner_div, vm)),
|
||||
floor_divide: Some(|a, b, vm| PyFloat::number_op(a, b, inner_floordiv, vm)),
|
||||
true_divide: Some(|a, b, vm| PyFloat::number_op(a, b, inner_div, vm)),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
};
|
||||
&AS_NUMBER
|
||||
@@ -586,12 +586,12 @@ impl Representable for PyFloat {
|
||||
}
|
||||
|
||||
impl PyFloat {
|
||||
fn number_op<F, R>(number: PyNumber, other: &PyObject, op: F, vm: &VirtualMachine) -> PyResult
|
||||
fn number_op<F, R>(a: &PyObject, b: &PyObject, op: F, vm: &VirtualMachine) -> PyResult
|
||||
where
|
||||
F: FnOnce(f64, f64, &VirtualMachine) -> R,
|
||||
R: ToPyResult,
|
||||
{
|
||||
if let (Some(a), Some(b)) = (to_op_float(number.obj, vm)?, to_op_float(other, vm)?) {
|
||||
if let (Some(a), Some(b)) = (to_op_float(a, vm)?, to_op_float(b, vm)?) {
|
||||
op(a, b, vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
|
||||
@@ -345,7 +345,7 @@ impl AsMapping for PyGenericAlias {
|
||||
impl AsNumber for PyGenericAlias {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
or: Some(|a, b, vm| Ok(PyGenericAlias::or(a.obj.to_owned(), b.to_owned(), vm))),
|
||||
or: Some(|a, b, vm| Ok(PyGenericAlias::or(a.to_owned(), b.to_owned(), vm))),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
};
|
||||
&AS_NUMBER
|
||||
|
||||
+16
-16
@@ -13,7 +13,7 @@ use crate::{
|
||||
ArgByteOrder, ArgIntoBool, OptionalArg, OptionalOption, PyArithmeticValue,
|
||||
PyComparisonValue,
|
||||
},
|
||||
protocol::{PyNumber, PyNumberMethods},
|
||||
protocol::PyNumberMethods,
|
||||
types::{AsNumber, Comparable, Constructor, Hashable, PyComparisonOp, Representable},
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult,
|
||||
TryFromBorrowedObject, VirtualMachine,
|
||||
@@ -743,39 +743,39 @@ impl AsNumber for PyInt {
|
||||
|
||||
impl PyInt {
|
||||
pub(super) const AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
add: Some(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a + b, vm)),
|
||||
subtract: Some(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a - b, vm)),
|
||||
multiply: Some(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a * b, vm)),
|
||||
remainder: Some(|num, other, vm| PyInt::number_op(num, other, inner_mod, vm)),
|
||||
divmod: Some(|num, other, vm| PyInt::number_op(num, other, inner_divmod, vm)),
|
||||
power: Some(|num, other, vm| PyInt::number_op(num, other, inner_pow, vm)),
|
||||
add: Some(|a, b, vm| PyInt::number_op(a, b, |a, b, _vm| a + b, vm)),
|
||||
subtract: Some(|a, b, vm| PyInt::number_op(a, b, |a, b, _vm| a - b, vm)),
|
||||
multiply: Some(|a, b, vm| PyInt::number_op(a, b, |a, b, _vm| a * b, vm)),
|
||||
remainder: Some(|a, b, vm| PyInt::number_op(a, b, inner_mod, vm)),
|
||||
divmod: Some(|a, b, vm| PyInt::number_op(a, b, inner_divmod, vm)),
|
||||
power: Some(|a, b, vm| PyInt::number_op(a, b, inner_pow, vm)),
|
||||
negative: Some(|num, vm| (&PyInt::number_downcast(num).value).neg().to_pyresult(vm)),
|
||||
positive: Some(|num, vm| Ok(PyInt::number_downcast_exact(num, vm).into())),
|
||||
absolute: Some(|num, vm| PyInt::number_downcast(num).value.abs().to_pyresult(vm)),
|
||||
boolean: Some(|num, _vm| Ok(PyInt::number_downcast(num).value.is_zero())),
|
||||
invert: Some(|num, vm| (&PyInt::number_downcast(num).value).not().to_pyresult(vm)),
|
||||
lshift: Some(|num, other, vm| PyInt::number_op(num, other, inner_lshift, vm)),
|
||||
rshift: Some(|num, other, vm| PyInt::number_op(num, other, inner_rshift, vm)),
|
||||
and: Some(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a & b, vm)),
|
||||
xor: Some(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a ^ b, vm)),
|
||||
or: Some(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a | b, vm)),
|
||||
lshift: Some(|a, b, vm| PyInt::number_op(a, b, inner_lshift, vm)),
|
||||
rshift: Some(|a, b, vm| PyInt::number_op(a, b, inner_rshift, vm)),
|
||||
and: Some(|a, b, vm| PyInt::number_op(a, b, |a, b, _vm| a & b, vm)),
|
||||
xor: Some(|a, b, vm| PyInt::number_op(a, b, |a, b, _vm| a ^ b, vm)),
|
||||
or: Some(|a, b, vm| PyInt::number_op(a, b, |a, b, _vm| a | b, vm)),
|
||||
int: Some(|num, vm| Ok(PyInt::number_downcast_exact(num, vm))),
|
||||
float: Some(|num, vm| {
|
||||
let zelf = PyInt::number_downcast(num);
|
||||
try_to_float(&zelf.value, vm).map(|x| vm.ctx.new_float(x))
|
||||
}),
|
||||
floor_divide: Some(|num, other, vm| PyInt::number_op(num, other, inner_floordiv, vm)),
|
||||
true_divide: Some(|num, other, vm| PyInt::number_op(num, other, inner_truediv, vm)),
|
||||
floor_divide: Some(|a, b, vm| PyInt::number_op(a, b, inner_floordiv, vm)),
|
||||
true_divide: Some(|a, b, vm| PyInt::number_op(a, b, inner_truediv, vm)),
|
||||
index: Some(|num, vm| Ok(PyInt::number_downcast_exact(num, vm))),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
};
|
||||
|
||||
fn number_op<F, R>(number: PyNumber, other: &PyObject, op: F, vm: &VirtualMachine) -> PyResult
|
||||
fn number_op<F, R>(a: &PyObject, b: &PyObject, op: F, vm: &VirtualMachine) -> PyResult
|
||||
where
|
||||
F: FnOnce(&BigInt, &BigInt, &VirtualMachine) -> R,
|
||||
R: ToPyResult,
|
||||
{
|
||||
if let (Some(a), Some(b)) = (number.obj.payload::<Self>(), other.payload::<Self>()) {
|
||||
if let (Some(a), Some(b)) = (a.payload::<Self>(), b.payload::<Self>()) {
|
||||
op(&a.value, &b.value, vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
|
||||
@@ -238,16 +238,16 @@ impl AsSequence for PyMappingProxy {
|
||||
impl AsNumber for PyMappingProxy {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
or: Some(|num, args, vm| {
|
||||
if let Some(num) = num.obj.downcast_ref::<PyMappingProxy>() {
|
||||
num.or(args.to_pyobject(vm), vm)
|
||||
or: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyMappingProxy>() {
|
||||
a.or(b.to_pyobject(vm), vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
inplace_or: Some(|num, args, vm| {
|
||||
if let Some(num) = num.obj.downcast_ref::<PyMappingProxy>() {
|
||||
num.ior(args.to_pyobject(vm), vm)
|
||||
inplace_or: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyMappingProxy>() {
|
||||
a.ior(b.to_pyobject(vm), vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
+40
-56
@@ -794,78 +794,62 @@ impl Iterable for PySet {
|
||||
impl AsNumber for PySet {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
subtract: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PySet>() {
|
||||
number.sub(other.to_owned(), vm).to_pyresult(vm)
|
||||
subtract: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PySet>() {
|
||||
a.sub(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
and: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PySet>() {
|
||||
number.and(other.to_owned(), vm).to_pyresult(vm)
|
||||
and: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PySet>() {
|
||||
a.and(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
xor: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PySet>() {
|
||||
number.xor(other.to_owned(), vm).to_pyresult(vm)
|
||||
xor: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PySet>() {
|
||||
a.xor(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
or: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PySet>() {
|
||||
number.or(other.to_owned(), vm).to_pyresult(vm)
|
||||
or: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PySet>() {
|
||||
a.or(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
inplace_subtract: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PySet>() {
|
||||
PySet::isub(
|
||||
number.to_owned(),
|
||||
AnySet::try_from_object(vm, other.to_owned())?,
|
||||
vm,
|
||||
)
|
||||
.to_pyresult(vm)
|
||||
inplace_subtract: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PySet>() {
|
||||
PySet::isub(a.to_owned(), AnySet::try_from_object(vm, b.to_owned())?, vm)
|
||||
.to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
inplace_and: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PySet>() {
|
||||
PySet::iand(
|
||||
number.to_owned(),
|
||||
AnySet::try_from_object(vm, other.to_owned())?,
|
||||
vm,
|
||||
)
|
||||
.to_pyresult(vm)
|
||||
inplace_and: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PySet>() {
|
||||
PySet::iand(a.to_owned(), AnySet::try_from_object(vm, b.to_owned())?, vm)
|
||||
.to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
inplace_xor: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PySet>() {
|
||||
PySet::ixor(
|
||||
number.to_owned(),
|
||||
AnySet::try_from_object(vm, other.to_owned())?,
|
||||
vm,
|
||||
)
|
||||
.to_pyresult(vm)
|
||||
inplace_xor: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PySet>() {
|
||||
PySet::ixor(a.to_owned(), AnySet::try_from_object(vm, b.to_owned())?, vm)
|
||||
.to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
inplace_or: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PySet>() {
|
||||
PySet::ior(
|
||||
number.to_owned(),
|
||||
AnySet::try_from_object(vm, other.to_owned())?,
|
||||
vm,
|
||||
)
|
||||
.to_pyresult(vm)
|
||||
inplace_or: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PySet>() {
|
||||
PySet::ior(a.to_owned(), AnySet::try_from_object(vm, b.to_owned())?, vm)
|
||||
.to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
@@ -1133,30 +1117,30 @@ impl Iterable for PyFrozenSet {
|
||||
impl AsNumber for PyFrozenSet {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
subtract: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyFrozenSet>() {
|
||||
number.sub(other.to_owned(), vm).to_pyresult(vm)
|
||||
subtract: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyFrozenSet>() {
|
||||
a.sub(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
and: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyFrozenSet>() {
|
||||
number.and(other.to_owned(), vm).to_pyresult(vm)
|
||||
and: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyFrozenSet>() {
|
||||
a.and(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
xor: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyFrozenSet>() {
|
||||
number.xor(other.to_owned(), vm).to_pyresult(vm)
|
||||
xor: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyFrozenSet>() {
|
||||
a.xor(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
or: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyFrozenSet>() {
|
||||
number.or(other.to_owned(), vm).to_pyresult(vm)
|
||||
or: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyFrozenSet>() {
|
||||
a.or(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
@@ -1337,9 +1337,9 @@ impl AsMapping for PyStr {
|
||||
impl AsNumber for PyStr {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
remainder: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyStr>() {
|
||||
number.modulo(other.to_owned(), vm).to_pyresult(vm)
|
||||
remainder: Some(|a, b, vm| {
|
||||
if let Some(a) = a.downcast_ref::<PyStr>() {
|
||||
a.modulo(b.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
@@ -1577,7 +1577,6 @@ impl AsRef<str> for PyExact<PyStr> {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::Interpreter;
|
||||
use std::ops::Deref;
|
||||
|
||||
#[test]
|
||||
fn str_title() {
|
||||
|
||||
@@ -1089,9 +1089,7 @@ impl Callable for PyType {
|
||||
impl AsNumber for PyType {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
or: Some(|num, other, vm| {
|
||||
or_(num.obj.to_owned(), other.to_owned(), vm).to_pyresult(vm)
|
||||
}),
|
||||
or: Some(|a, b, vm| or_(a.to_owned(), b.to_owned(), vm).to_pyresult(vm)),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
};
|
||||
&AS_NUMBER
|
||||
|
||||
@@ -252,9 +252,7 @@ impl AsMapping for PyUnion {
|
||||
impl AsNumber for PyUnion {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
or: Some(|num, other, vm| {
|
||||
PyUnion::or(num.obj.to_owned(), other.to_owned(), vm).to_pyresult(vm)
|
||||
}),
|
||||
or: Some(|a, b, vm| PyUnion::or(a.to_owned(), b.to_owned(), vm).to_pyresult(vm)),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
};
|
||||
&AS_NUMBER
|
||||
|
||||
+22
-59
@@ -1,7 +1,7 @@
|
||||
use std::ops::Deref;
|
||||
|
||||
use crate::{
|
||||
builtins::{
|
||||
int, type_::PointerSlot, PyByteArray, PyBytes, PyComplex, PyFloat, PyInt, PyIntRef, PyStr,
|
||||
},
|
||||
builtins::{int, PyByteArray, PyBytes, PyComplex, PyFloat, PyInt, PyIntRef, PyStr},
|
||||
common::int::bytes_to_int,
|
||||
function::ArgBytesLike,
|
||||
stdlib::warnings,
|
||||
@@ -10,12 +10,12 @@ use crate::{
|
||||
};
|
||||
|
||||
pub type PyNumberUnaryFunc<R = PyObjectRef> = fn(PyNumber, &VirtualMachine) -> PyResult<R>;
|
||||
pub type PyNumberBinaryFunc = fn(PyNumber, &PyObject, &VirtualMachine) -> PyResult;
|
||||
pub type PyNumberBinaryFunc = fn(&PyObject, &PyObject, &VirtualMachine) -> PyResult;
|
||||
|
||||
impl PyObject {
|
||||
#[inline]
|
||||
pub fn to_number(&self) -> PyNumber<'_> {
|
||||
PyNumber::from(self)
|
||||
pub fn to_number(&self) -> PyNumber {
|
||||
PyNumber(self)
|
||||
}
|
||||
|
||||
pub fn try_index_opt(&self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
|
||||
@@ -197,39 +197,6 @@ impl PyNumberMethods {
|
||||
matrix_multiply: None,
|
||||
inplace_matrix_multiply: None,
|
||||
};
|
||||
|
||||
pub fn binary_op(&self, op_slot: PyNumberBinaryOp) -> Option<PyNumberBinaryFunc> {
|
||||
use PyNumberBinaryOp::*;
|
||||
match op_slot {
|
||||
Add => self.add,
|
||||
Subtract => self.subtract,
|
||||
Multiply => self.multiply,
|
||||
Remainder => self.remainder,
|
||||
Divmod => self.divmod,
|
||||
Power => self.power,
|
||||
Lshift => self.lshift,
|
||||
Rshift => self.rshift,
|
||||
And => self.and,
|
||||
Xor => self.xor,
|
||||
Or => self.or,
|
||||
InplaceAdd => self.inplace_add,
|
||||
InplaceSubtract => self.inplace_subtract,
|
||||
InplaceMultiply => self.inplace_multiply,
|
||||
InplaceRemainder => self.inplace_remainder,
|
||||
InplacePower => self.inplace_power,
|
||||
InplaceLshift => self.inplace_lshift,
|
||||
InplaceRshift => self.inplace_rshift,
|
||||
InplaceAnd => self.inplace_and,
|
||||
InplaceXor => self.inplace_xor,
|
||||
InplaceOr => self.inplace_or,
|
||||
FloorDivide => self.floor_divide,
|
||||
TrueDivide => self.true_divide,
|
||||
InplaceFloorDivide => self.inplace_floor_divide,
|
||||
InplaceTrueDivide => self.inplace_true_divide,
|
||||
MatrixMultiply => self.matrix_multiply,
|
||||
InplaceMatrixMultiply => self.inplace_matrix_multiply,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
@@ -264,25 +231,19 @@ pub enum PyNumberBinaryOp {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct PyNumber<'a> {
|
||||
pub obj: &'a PyObject,
|
||||
pub(crate) methods: &'a PyNumberMethods,
|
||||
}
|
||||
pub struct PyNumber<'a>(&'a PyObject);
|
||||
|
||||
impl<'a> From<&'a PyObject> for PyNumber<'a> {
|
||||
fn from(obj: &'a PyObject) -> Self {
|
||||
static GLOBAL_NOT_IMPLEMENTED: PyNumberMethods = PyNumberMethods::NOT_IMPLEMENTED;
|
||||
Self {
|
||||
obj,
|
||||
methods: Self::find_methods(obj)
|
||||
.map_or(&GLOBAL_NOT_IMPLEMENTED, |m| unsafe { m.borrow_static() }),
|
||||
}
|
||||
impl<'a> Deref for PyNumber<'a> {
|
||||
type Target = PyObject;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PyNumber<'_> {
|
||||
fn find_methods(obj: &PyObject) -> Option<PointerSlot<PyNumberMethods>> {
|
||||
obj.class().mro_find_map(|x| x.slots.as_number.load())
|
||||
impl<'a> PyNumber<'a> {
|
||||
pub(crate) fn obj(self) -> &'a PyObject {
|
||||
self.0
|
||||
}
|
||||
|
||||
// PyNumber_Check
|
||||
@@ -293,15 +254,17 @@ impl PyNumber<'_> {
|
||||
|| methods.float.load().is_some()
|
||||
|| obj.payload_is::<PyComplex>()
|
||||
}
|
||||
}
|
||||
|
||||
impl PyNumber<'_> {
|
||||
// PyIndex_Check
|
||||
pub fn is_index(&self) -> bool {
|
||||
self.obj.class().slots.number.index.load().is_some()
|
||||
pub fn is_index(self) -> bool {
|
||||
self.class().slots.number.index.load().is_some()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn int(self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
|
||||
self.obj.class().slots.number.int.load().map(|f| {
|
||||
self.class().slots.number.int.load().map(|f| {
|
||||
let ret = f(self, vm)?;
|
||||
let value = if !ret.class().is(PyInt::class(&vm.ctx)) {
|
||||
warnings::warn(
|
||||
@@ -325,7 +288,7 @@ impl PyNumber<'_> {
|
||||
|
||||
#[inline]
|
||||
pub fn index(self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
|
||||
self.obj.class().slots.number.index.load().map(|f| {
|
||||
self.class().slots.number.index.load().map(|f| {
|
||||
let ret = f(self, vm)?;
|
||||
let value = if !ret.class().is(PyInt::class(&vm.ctx)) {
|
||||
warnings::warn(
|
||||
@@ -349,7 +312,7 @@ impl PyNumber<'_> {
|
||||
|
||||
#[inline]
|
||||
pub fn float(self, vm: &VirtualMachine) -> Option<PyResult<PyRef<PyFloat>>> {
|
||||
self.obj.class().slots.number.float.load().map(|f| {
|
||||
self.class().slots.number.float.load().map(|f| {
|
||||
let ret = f(self, vm)?;
|
||||
let value = if !ret.class().is(PyFloat::class(&vm.ctx)) {
|
||||
warnings::warn(
|
||||
|
||||
+15
-97
@@ -16,7 +16,7 @@ use crate::{
|
||||
};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
use num_traits::{Signed, ToPrimitive};
|
||||
use std::{borrow::Borrow, cmp::Ordering};
|
||||
use std::{borrow::Borrow, cmp::Ordering, ops::Deref};
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! atomic_func {
|
||||
@@ -168,12 +168,9 @@ pub struct PyNumberSlots {
|
||||
}
|
||||
|
||||
impl PyNumberSlots {
|
||||
pub fn left_binary_op(
|
||||
&self,
|
||||
op_slot: PyNumberBinaryOp,
|
||||
) -> PyResult<Option<PyNumberBinaryFunc>> {
|
||||
pub fn left_binary_op(&self, op_slot: PyNumberBinaryOp) -> Option<PyNumberBinaryFunc> {
|
||||
use PyNumberBinaryOp::*;
|
||||
let binary_op = match op_slot {
|
||||
match op_slot {
|
||||
Add => self.add.load(),
|
||||
Subtract => self.subtract.load(),
|
||||
Multiply => self.multiply.load(),
|
||||
@@ -201,16 +198,12 @@ impl PyNumberSlots {
|
||||
InplaceTrueDivide => self.inplace_true_divide.load(),
|
||||
MatrixMultiply => self.matrix_multiply.load(),
|
||||
InplaceMatrixMultiply => self.inplace_matrix_multiply.load(),
|
||||
};
|
||||
Ok(binary_op)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn right_binary_op(
|
||||
&self,
|
||||
op_slot: PyNumberBinaryOp,
|
||||
) -> PyResult<Option<PyNumberBinaryFunc>> {
|
||||
pub fn right_binary_op(&self, op_slot: PyNumberBinaryOp) -> Option<PyNumberBinaryFunc> {
|
||||
use PyNumberBinaryOp::*;
|
||||
let binary_op = match op_slot {
|
||||
match op_slot {
|
||||
Add => self.right_add.load(),
|
||||
Subtract => self.right_subtract.load(),
|
||||
Multiply => self.right_multiply.load(),
|
||||
@@ -226,8 +219,7 @@ impl PyNumberSlots {
|
||||
TrueDivide => self.right_true_divide.load(),
|
||||
MatrixMultiply => self.right_matrix_multiply.load(),
|
||||
_ => None,
|
||||
};
|
||||
Ok(binary_op)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,21 +313,21 @@ pub(crate) fn len_wrapper(obj: &PyObject, vm: &VirtualMachine) -> PyResult<usize
|
||||
}
|
||||
|
||||
fn int_wrapper(num: PyNumber, vm: &VirtualMachine) -> PyResult<PyRef<PyInt>> {
|
||||
let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __int__), ())?;
|
||||
let ret = vm.call_special_method(num.deref().to_owned(), identifier!(vm, __int__), ())?;
|
||||
ret.downcast::<PyInt>().map_err(|obj| {
|
||||
vm.new_type_error(format!("__int__ returned non-int (type {})", obj.class()))
|
||||
})
|
||||
}
|
||||
|
||||
fn index_wrapper(num: PyNumber, vm: &VirtualMachine) -> PyResult<PyRef<PyInt>> {
|
||||
let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __index__), ())?;
|
||||
let ret = vm.call_special_method(num.deref().to_owned(), identifier!(vm, __index__), ())?;
|
||||
ret.downcast::<PyInt>().map_err(|obj| {
|
||||
vm.new_type_error(format!("__index__ returned non-int (type {})", obj.class()))
|
||||
})
|
||||
}
|
||||
|
||||
fn float_wrapper(num: PyNumber, vm: &VirtualMachine) -> PyResult<PyRef<PyFloat>> {
|
||||
let ret = vm.call_special_method(num.obj.to_owned(), identifier!(vm, __float__), ())?;
|
||||
let ret = vm.call_special_method(num.deref().to_owned(), identifier!(vm, __float__), ())?;
|
||||
ret.downcast::<PyFloat>().map_err(|obj| {
|
||||
vm.new_type_error(format!(
|
||||
"__float__ returned non-float (type {})",
|
||||
@@ -348,7 +340,7 @@ macro_rules! number_binary_op_wrapper {
|
||||
($name:ident) => {
|
||||
|num, other, vm| {
|
||||
vm.call_special_method(
|
||||
num.obj.to_owned(),
|
||||
num.deref().to_owned(),
|
||||
identifier!(vm, $name),
|
||||
(other.to_owned(),),
|
||||
)
|
||||
@@ -1314,26 +1306,6 @@ pub trait AsSequence: PyPayload {
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! extend_number_slot {
|
||||
($slots:ident, $methods:ident, $method:ident, $right_method:ident, $op_slot:ident) => {
|
||||
if $methods.$method.is_some() {
|
||||
$slots.number.$method.store($methods.$method);
|
||||
$slots.number.$right_method.store(Some(|num, other, vm| {
|
||||
num.methods.binary_op(PyNumberBinaryOp::$op_slot).unwrap()(
|
||||
other.to_number(),
|
||||
num.obj,
|
||||
vm,
|
||||
)
|
||||
}));
|
||||
}
|
||||
};
|
||||
($slots:ident, $methods:ident, $method:ident) => {
|
||||
if $methods.$method.is_some() {
|
||||
$slots.number.$method.store($methods.$method);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
pub trait AsNumber: PyPayload {
|
||||
#[pyslot]
|
||||
@@ -1346,71 +1318,17 @@ pub trait AsNumber: PyPayload {
|
||||
|
||||
#[inline]
|
||||
fn number_downcast(num: PyNumber) -> &Py<Self> {
|
||||
unsafe { num.obj.downcast_unchecked_ref() }
|
||||
unsafe { num.obj().downcast_unchecked_ref() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn number_downcast_exact(number: PyNumber, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
if let Some(zelf) = number.obj.downcast_ref_if_exact::<Self>(vm) {
|
||||
fn number_downcast_exact(num: PyNumber, vm: &VirtualMachine) -> PyRef<Self> {
|
||||
if let Some(zelf) = num.downcast_ref_if_exact::<Self>(vm) {
|
||||
zelf.to_owned()
|
||||
} else {
|
||||
Self::clone_exact(Self::number_downcast(number), vm)
|
||||
Self::clone_exact(Self::number_downcast(num), vm)
|
||||
}
|
||||
}
|
||||
|
||||
fn extend_slots(slots: &mut PyTypeSlots) {
|
||||
let methods = Self::as_number();
|
||||
|
||||
extend_number_slot!(slots, methods, add, right_add, Add);
|
||||
extend_number_slot!(slots, methods, subtract, right_subtract, Subtract);
|
||||
extend_number_slot!(slots, methods, multiply, right_multiply, Multiply);
|
||||
extend_number_slot!(slots, methods, remainder, right_remainder, Remainder);
|
||||
extend_number_slot!(slots, methods, divmod, right_divmod, Divmod);
|
||||
extend_number_slot!(slots, methods, power, right_power, Power);
|
||||
extend_number_slot!(slots, methods, lshift, right_lshift, Lshift);
|
||||
extend_number_slot!(slots, methods, rshift, right_rshift, Rshift);
|
||||
extend_number_slot!(slots, methods, and, right_and, And);
|
||||
extend_number_slot!(slots, methods, xor, right_xor, Xor);
|
||||
extend_number_slot!(slots, methods, or, right_or, Or);
|
||||
extend_number_slot!(
|
||||
slots,
|
||||
methods,
|
||||
floor_divide,
|
||||
right_floor_divide,
|
||||
FloorDivide
|
||||
);
|
||||
extend_number_slot!(slots, methods, true_divide, right_true_divide, TrueDivide);
|
||||
extend_number_slot!(
|
||||
slots,
|
||||
methods,
|
||||
matrix_multiply,
|
||||
right_matrix_multiply,
|
||||
MatrixMultiply
|
||||
);
|
||||
|
||||
extend_number_slot!(slots, methods, negative);
|
||||
extend_number_slot!(slots, methods, positive);
|
||||
extend_number_slot!(slots, methods, absolute);
|
||||
extend_number_slot!(slots, methods, boolean);
|
||||
extend_number_slot!(slots, methods, invert);
|
||||
extend_number_slot!(slots, methods, int);
|
||||
extend_number_slot!(slots, methods, float);
|
||||
extend_number_slot!(slots, methods, index);
|
||||
|
||||
extend_number_slot!(slots, methods, inplace_add);
|
||||
extend_number_slot!(slots, methods, inplace_subtract);
|
||||
extend_number_slot!(slots, methods, inplace_multiply);
|
||||
extend_number_slot!(slots, methods, inplace_remainder);
|
||||
extend_number_slot!(slots, methods, inplace_power);
|
||||
extend_number_slot!(slots, methods, inplace_lshift);
|
||||
extend_number_slot!(slots, methods, inplace_rshift);
|
||||
extend_number_slot!(slots, methods, inplace_and);
|
||||
extend_number_slot!(slots, methods, inplace_xor);
|
||||
extend_number_slot!(slots, methods, inplace_or);
|
||||
extend_number_slot!(slots, methods, inplace_floor_divide);
|
||||
extend_number_slot!(slots, methods, inplace_true_divide);
|
||||
extend_number_slot!(slots, methods, inplace_matrix_multiply);
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
|
||||
+23
-24
@@ -132,40 +132,39 @@ impl VirtualMachine {
|
||||
///
|
||||
/// [*] only when Py_TYPE(a) != Py_TYPE(b) && Py_TYPE(b) is a subclass of Py_TYPE(a)
|
||||
pub fn binary_op1(&self, a: &PyObject, b: &PyObject, op_slot: PyNumberBinaryOp) -> PyResult {
|
||||
let slot_a = a.class().slots.number.left_binary_op(op_slot)?;
|
||||
let mut slot_b = if b.class().is(a.class()) {
|
||||
None
|
||||
} else {
|
||||
match b.class().slots.number.right_binary_op(op_slot)? {
|
||||
Some(slot_b)
|
||||
if slot_b as usize == slot_a.map(|s| s as usize).unwrap_or_default() =>
|
||||
{
|
||||
None
|
||||
}
|
||||
slot_b => slot_b,
|
||||
let class_a = a.class();
|
||||
let class_b = b.class();
|
||||
|
||||
let slot_a = class_a.slots.number.left_binary_op(op_slot);
|
||||
let mut slot_b = None;
|
||||
|
||||
if !class_a.is(class_b) {
|
||||
let slot_bb = class_b.slots.number.right_binary_op(op_slot);
|
||||
if slot_bb.map(|x| x as usize) != slot_a.map(|x| x as usize) {
|
||||
slot_b = slot_bb;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if let Some(slot_a) = slot_a {
|
||||
if let Some(slot_bb) = slot_b {
|
||||
if b.fast_isinstance(a.class()) {
|
||||
let x = slot_bb(b.to_number(), a, self)?;
|
||||
if !x.is(&self.ctx.not_implemented) {
|
||||
return Ok(x);
|
||||
if class_b.fast_issubclass(class_a) {
|
||||
let ret = slot_bb(a, b, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
slot_b = None;
|
||||
}
|
||||
}
|
||||
let x = slot_a(a.to_number(), b, self)?;
|
||||
if !x.is(&self.ctx.not_implemented) {
|
||||
return Ok(x);
|
||||
let ret = slot_a(a, b, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(slot_b) = slot_b {
|
||||
let x = slot_b(b.to_number(), a, self)?;
|
||||
if !x.is(&self.ctx.not_implemented) {
|
||||
return Ok(x);
|
||||
let ret = slot_b(a, b, self)?;
|
||||
if !ret.is(&self.ctx.not_implemented) {
|
||||
return Ok(ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,8 +205,8 @@ impl VirtualMachine {
|
||||
iop_slot: PyNumberBinaryOp,
|
||||
op_slot: PyNumberBinaryOp,
|
||||
) -> PyResult {
|
||||
if let Some(slot) = a.class().slots.number.left_binary_op(iop_slot)? {
|
||||
let x = slot(a.to_number(), b, self)?;
|
||||
if let Some(slot) = a.class().slots.number.left_binary_op(iop_slot) {
|
||||
let x = slot(a, b, self)?;
|
||||
if !x.is(&self.ctx.not_implemented) {
|
||||
return Ok(x);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user