refactor PyNumberBinaryFunc

This commit is contained in:
Kangzhi Shi committed 2023-03-21 21:27:51 +02:00
1 parent ee78527a9e
commit d6acd2ee7d
16 files changed
+198 -407

No files matched your search

+3 -9
View File
@@ -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
+3 -3
View File
@@ -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())
}
+3 -3
View File
@@ -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 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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())
+1 -1
View File
@@ -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
View File
@@ -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())
+6 -6
View File
@@ -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
View File
@@ -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())
}
+3 -4
View File
@@ -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() {
+1 -3
View File
@@ -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
+1 -3
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}