mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Add PyNumberSlots to support right binary ops
This commit is contained in:
1 parent
ba9c354e1b
commit
984db6798c
16 files changed
+611
-434
No files matched your search
@@ -37,7 +37,6 @@ use crate::{
|
||||
VirtualMachine,
|
||||
};
|
||||
use bstr::ByteSlice;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::mem::size_of;
|
||||
|
||||
#[pyclass(module = false, name = "bytearray", unhashable = true)]
|
||||
@@ -859,14 +858,16 @@ impl AsSequence for PyByteArray {
|
||||
|
||||
impl AsNumber for PyByteArray {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
remainder: atomic_func!(|number, other, vm| {
|
||||
PyByteArray::number_downcast(number)
|
||||
.mod_(other.to_owned(), vm)
|
||||
.to_pyresult(vm)
|
||||
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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -629,14 +629,16 @@ impl AsSequence for PyBytes {
|
||||
|
||||
impl AsNumber for PyBytes {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
remainder: atomic_func!(|number, other, vm| {
|
||||
PyBytes::number_downcast(number)
|
||||
.mod_(other.to_owned(), vm)
|
||||
.to_pyresult(vm)
|
||||
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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
+13
-19
@@ -1,6 +1,5 @@
|
||||
use super::{float, PyStr, PyType, PyTypeRef};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
class::PyClassImpl,
|
||||
convert::{ToPyObject, ToPyResult},
|
||||
function::{
|
||||
@@ -15,7 +14,6 @@ use crate::{
|
||||
};
|
||||
use num_complex::Complex64;
|
||||
use num_traits::Zero;
|
||||
use once_cell::sync::Lazy;
|
||||
use rustpython_common::{float_ops, hash};
|
||||
use std::num::Wrapping;
|
||||
|
||||
@@ -454,38 +452,34 @@ impl Hashable for PyComplex {
|
||||
|
||||
impl AsNumber for PyComplex {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
add: atomic_func!(|number, other, vm| {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
add: Some(|number, other, vm| {
|
||||
PyComplex::number_op(number, other, |a, b, _vm| a + b, vm)
|
||||
}),
|
||||
subtract: atomic_func!(|number, other, vm| {
|
||||
subtract: Some(|number, other, vm| {
|
||||
PyComplex::number_op(number, other, |a, b, _vm| a - b, vm)
|
||||
}),
|
||||
multiply: atomic_func!(|number, other, vm| {
|
||||
multiply: Some(|number, other, vm| {
|
||||
PyComplex::number_op(number, other, |a, b, _vm| a * b, vm)
|
||||
}),
|
||||
power: atomic_func!(|number, other, vm| PyComplex::number_op(
|
||||
number, other, inner_pow, vm
|
||||
)),
|
||||
negative: atomic_func!(|number, vm| {
|
||||
power: Some(|number, other, vm| PyComplex::number_op(number, other, inner_pow, vm)),
|
||||
negative: Some(|number, vm| {
|
||||
let value = PyComplex::number_downcast(number).value;
|
||||
(-value).to_pyresult(vm)
|
||||
}),
|
||||
positive: atomic_func!(
|
||||
|number, vm| PyComplex::number_downcast_exact(number, vm).to_pyresult(vm)
|
||||
),
|
||||
absolute: atomic_func!(|number, vm| {
|
||||
positive: Some(|number, vm| {
|
||||
PyComplex::number_downcast_exact(number, vm).to_pyresult(vm)
|
||||
}),
|
||||
absolute: Some(|number, vm| {
|
||||
let value = PyComplex::number_downcast(number).value;
|
||||
value.norm().to_pyresult(vm)
|
||||
}),
|
||||
boolean: atomic_func!(|number, _vm| Ok(PyComplex::number_downcast(number)
|
||||
.value
|
||||
.is_zero())),
|
||||
true_divide: atomic_func!(|number, other, 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)
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
|
||||
|
||||
+14
-11
@@ -479,20 +479,23 @@ impl AsSequence for PyDict {
|
||||
|
||||
impl AsNumber for PyDict {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
or: atomic_func!(|num, args, vm| {
|
||||
PyDict::number_downcast(num).or(args.to_pyobject(vm), vm)
|
||||
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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
inplace_or: atomic_func!(|num, args, vm| {
|
||||
PyDict::ior(
|
||||
PyDict::number_downcast(num).to_owned(),
|
||||
args.to_pyobject(vm),
|
||||
vm,
|
||||
)
|
||||
.map(|d| d.into())
|
||||
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())
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
+16
-39
@@ -2,7 +2,6 @@ use super::{
|
||||
try_bigint_to_f64, PyByteArray, PyBytes, PyInt, PyIntRef, PyStr, PyStrRef, PyType, PyTypeRef,
|
||||
};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
class::PyClassImpl,
|
||||
common::format::FormatSpec,
|
||||
common::{float_ops, hash},
|
||||
@@ -21,7 +20,6 @@ use num_bigint::{BigInt, ToBigInt};
|
||||
use num_complex::Complex64;
|
||||
use num_rational::Ratio;
|
||||
use num_traits::{Signed, ToPrimitive, Zero};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
#[pyclass(module = false, name = "float")]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
@@ -545,53 +543,32 @@ impl Hashable for PyFloat {
|
||||
|
||||
impl AsNumber for PyFloat {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
add: atomic_func!(|num, other, vm| PyFloat::number_op(
|
||||
num,
|
||||
other,
|
||||
|a, b, _vm| a + b,
|
||||
vm
|
||||
)),
|
||||
subtract: atomic_func!(|num, other, vm| PyFloat::number_op(
|
||||
num,
|
||||
other,
|
||||
|a, b, _vm| a - b,
|
||||
vm
|
||||
)),
|
||||
multiply: atomic_func!(|num, other, vm| PyFloat::number_op(
|
||||
num,
|
||||
other,
|
||||
|a, b, _vm| a * b,
|
||||
vm
|
||||
)),
|
||||
remainder: atomic_func!(|num, other, vm| PyFloat::number_op(num, other, inner_mod, vm)),
|
||||
divmod: atomic_func!(|num, other, vm| PyFloat::number_op(num, other, inner_divmod, vm)),
|
||||
power: atomic_func!(|num, other, vm| PyFloat::number_op(num, other, float_pow, vm)),
|
||||
negative: atomic_func!(|num, vm| {
|
||||
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)),
|
||||
negative: Some(|num, vm| {
|
||||
let value = PyFloat::number_downcast(num).value;
|
||||
(-value).to_pyresult(vm)
|
||||
}),
|
||||
positive: atomic_func!(
|
||||
|num, vm| PyFloat::number_downcast_exact(num, vm).to_pyresult(vm)
|
||||
),
|
||||
absolute: atomic_func!(|num, vm| {
|
||||
positive: Some(|num, vm| PyFloat::number_downcast_exact(num, vm).to_pyresult(vm)),
|
||||
absolute: Some(|num, vm| {
|
||||
let value = PyFloat::number_downcast(num).value;
|
||||
value.abs().to_pyresult(vm)
|
||||
}),
|
||||
boolean: atomic_func!(|num, _vm| Ok(PyFloat::number_downcast(num).value.is_zero())),
|
||||
int: atomic_func!(|num, vm| {
|
||||
boolean: Some(|num, _vm| Ok(PyFloat::number_downcast(num).value.is_zero())),
|
||||
int: Some(|num, vm| {
|
||||
let value = PyFloat::number_downcast(num).value;
|
||||
try_to_bigint(value, vm).map(|x| vm.ctx.new_int(x))
|
||||
}),
|
||||
float: atomic_func!(|num, vm| Ok(PyFloat::number_downcast_exact(num, vm))),
|
||||
floor_divide: atomic_func!(|num, other, vm| {
|
||||
PyFloat::number_op(num, other, inner_floordiv, vm)
|
||||
}),
|
||||
true_divide: atomic_func!(|num, other, vm| {
|
||||
PyFloat::number_op(num, other, inner_div, vm)
|
||||
}),
|
||||
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)),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
|
||||
|
||||
+23
-46
@@ -1,6 +1,5 @@
|
||||
use super::{float, PyByteArray, PyBytes, PyStr, PyType, PyTypeRef};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
builtins::PyStrRef,
|
||||
bytesinner::PyBytesInner,
|
||||
class::PyClassImpl,
|
||||
@@ -20,7 +19,6 @@ use num_bigint::{BigInt, BigUint, Sign};
|
||||
use num_integer::Integer;
|
||||
use num_rational::Ratio;
|
||||
use num_traits::{One, Pow, PrimInt, Signed, ToPrimitive, Zero};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::ops::{Div, Neg};
|
||||
use std::{fmt, ops::Not};
|
||||
|
||||
@@ -729,54 +727,33 @@ impl Hashable for PyInt {
|
||||
|
||||
impl AsNumber for PyInt {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
add: atomic_func!(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a + b, vm)),
|
||||
subtract: atomic_func!(|num, other, vm| PyInt::number_op(
|
||||
num,
|
||||
other,
|
||||
|a, b, _vm| a - b,
|
||||
vm
|
||||
)),
|
||||
multiply: atomic_func!(|num, other, vm| PyInt::number_op(
|
||||
num,
|
||||
other,
|
||||
|a, b, _vm| a * b,
|
||||
vm
|
||||
)),
|
||||
remainder: atomic_func!(|num, other, vm| PyInt::number_op(num, other, inner_mod, vm)),
|
||||
divmod: atomic_func!(|num, other, vm| PyInt::number_op(num, other, inner_divmod, vm)),
|
||||
power: atomic_func!(|num, other, vm| PyInt::number_op(num, other, inner_pow, vm)),
|
||||
negative: atomic_func!(|num, vm| (&PyInt::number_downcast(num).value)
|
||||
.neg()
|
||||
.to_pyresult(vm)),
|
||||
positive: atomic_func!(|num, vm| Ok(PyInt::number_downcast_exact(num, vm).into())),
|
||||
absolute: atomic_func!(|num, vm| PyInt::number_downcast(num)
|
||||
.value
|
||||
.abs()
|
||||
.to_pyresult(vm)),
|
||||
boolean: atomic_func!(|num, _vm| Ok(PyInt::number_downcast(num).value.is_zero())),
|
||||
invert: atomic_func!(|num, vm| (&PyInt::number_downcast(num).value)
|
||||
.not()
|
||||
.to_pyresult(vm)),
|
||||
lshift: atomic_func!(|num, other, vm| PyInt::number_op(num, other, inner_lshift, vm)),
|
||||
rshift: atomic_func!(|num, other, vm| PyInt::number_op(num, other, inner_rshift, vm)),
|
||||
and: atomic_func!(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a & b, vm)),
|
||||
xor: atomic_func!(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a ^ b, vm)),
|
||||
or: atomic_func!(|num, other, vm| PyInt::number_op(num, other, |a, b, _vm| a | b, vm)),
|
||||
int: atomic_func!(|num, vm| Ok(PyInt::number_downcast_exact(num, vm))),
|
||||
float: atomic_func!(|num, vm| {
|
||||
static 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)),
|
||||
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)),
|
||||
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: atomic_func!(|num, other, vm| {
|
||||
PyInt::number_op(num, other, inner_floordiv, vm)
|
||||
}),
|
||||
true_divide: atomic_func!(|num, other, vm| {
|
||||
PyInt::number_op(num, other, inner_truediv, vm)
|
||||
}),
|
||||
index: atomic_func!(|num, vm| Ok(PyInt::number_downcast_exact(num, vm))),
|
||||
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)),
|
||||
index: Some(|num, vm| Ok(PyInt::number_downcast_exact(num, vm))),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::{PyDict, PyDictRef, PyGenericAlias, PyList, PyTuple, PyType, PyTypeRef};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
@@ -10,6 +8,7 @@ use crate::{
|
||||
types::{AsMapping, AsNumber, AsSequence, Comparable, Constructor, Iterable, PyComparisonOp},
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
#[pyclass(module = false, name = "mappingproxy")]
|
||||
#[derive(Debug)]
|
||||
@@ -70,7 +69,7 @@ impl Constructor for PyMappingProxy {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(with(AsMapping, Iterable, Constructor, AsSequence, Comparable))]
|
||||
#[pyclass(with(AsMapping, Iterable, Constructor, AsSequence, Comparable, AsNumber))]
|
||||
impl PyMappingProxy {
|
||||
fn get_inner(&self, key: PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
|
||||
let opt = match &self.mapping {
|
||||
@@ -232,15 +231,23 @@ impl AsSequence for PyMappingProxy {
|
||||
|
||||
impl AsNumber for PyMappingProxy {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
or: atomic_func!(|num, args, vm| {
|
||||
PyMappingProxy::number_downcast(num).or(args.to_pyobject(vm), vm)
|
||||
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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
inplace_or: atomic_func!(|num, args, vm| {
|
||||
PyMappingProxy::number_downcast(num).ior(args.to_pyobject(vm), vm)
|
||||
inplace_or: Some(|num, args, vm| {
|
||||
if let Some(num) = num.obj.downcast_ref::<PyMappingProxy>() {
|
||||
num.ior(args.to_pyobject(vm), vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
+96
-64
@@ -805,61 +805,85 @@ impl Iterable for PySet {
|
||||
|
||||
impl AsNumber for PySet {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
subtract: atomic_func!(|number, other, vm| {
|
||||
PySet::number_downcast(number)
|
||||
.sub(other.to_owned(), vm)
|
||||
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)
|
||||
} 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)
|
||||
} 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)
|
||||
} 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)
|
||||
} 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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
and: atomic_func!(|number, other, vm| {
|
||||
PySet::number_downcast(number)
|
||||
.and(other.to_owned(), vm)
|
||||
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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
xor: atomic_func!(|number, other, vm| {
|
||||
PySet::number_downcast(number)
|
||||
.xor(other.to_owned(), vm)
|
||||
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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
or: atomic_func!(|number, other, vm| {
|
||||
PySet::number_downcast(number)
|
||||
.or(other.to_owned(), vm)
|
||||
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_subtract: atomic_func!(|number, other, vm| {
|
||||
PySet::isub(
|
||||
PySet::number_downcast(number).to_owned(),
|
||||
AnySet::try_from_object(vm, other.to_owned())?,
|
||||
vm,
|
||||
)
|
||||
.to_pyresult(vm)
|
||||
}),
|
||||
inplace_and: atomic_func!(|number, other, vm| {
|
||||
PySet::iand(
|
||||
PySet::number_downcast(number).to_owned(),
|
||||
AnySet::try_from_object(vm, other.to_owned())?,
|
||||
vm,
|
||||
)
|
||||
.to_pyresult(vm)
|
||||
}),
|
||||
inplace_xor: atomic_func!(|number, other, vm| {
|
||||
PySet::ixor(
|
||||
PySet::number_downcast(number).to_owned(),
|
||||
AnySet::try_from_object(vm, other.to_owned())?,
|
||||
vm,
|
||||
)
|
||||
.to_pyresult(vm)
|
||||
}),
|
||||
inplace_or: atomic_func!(|number, other, vm| {
|
||||
PySet::ior(
|
||||
PySet::number_downcast(number).to_owned(),
|
||||
AnySet::try_from_object(vm, other.to_owned())?,
|
||||
vm,
|
||||
)
|
||||
.to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
@@ -1105,29 +1129,37 @@ impl Iterable for PyFrozenSet {
|
||||
|
||||
impl AsNumber for PyFrozenSet {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
subtract: atomic_func!(|number, other, vm| {
|
||||
PyFrozenSet::number_downcast(number)
|
||||
.sub(other.to_owned(), vm)
|
||||
.to_pyresult(vm)
|
||||
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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
and: atomic_func!(|number, other, vm| {
|
||||
PyFrozenSet::number_downcast(number)
|
||||
.and(other.to_owned(), vm)
|
||||
.to_pyresult(vm)
|
||||
and: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyFrozenSet>() {
|
||||
number.and(other.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
xor: atomic_func!(|number, other, vm| {
|
||||
PyFrozenSet::number_downcast(number)
|
||||
.xor(other.to_owned(), vm)
|
||||
.to_pyresult(vm)
|
||||
xor: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyFrozenSet>() {
|
||||
number.xor(other.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
or: atomic_func!(|number, other, vm| {
|
||||
PyFrozenSet::number_downcast(number)
|
||||
.or(other.to_owned(), vm)
|
||||
.to_pyresult(vm)
|
||||
or: Some(|number, other, vm| {
|
||||
if let Some(number) = number.obj.downcast_ref::<PyFrozenSet>() {
|
||||
number.or(other.to_owned(), vm).to_pyresult(vm)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::{PyType, PyTypeRef};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
class::PyClassImpl,
|
||||
convert::ToPyObject,
|
||||
protocol::PyNumberMethods,
|
||||
@@ -60,10 +57,10 @@ impl PyNone {
|
||||
|
||||
impl AsNumber for PyNone {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
boolean: atomic_func!(|_number, _vm| Ok(false)),
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
boolean: Some(|_number, _vm| Ok(false)),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1301,14 +1301,16 @@ impl AsMapping for PyStr {
|
||||
|
||||
impl AsNumber for PyStr {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
remainder: atomic_func!(|number, other, vm| {
|
||||
PyStr::number_downcast(number)
|
||||
.modulo(other.to_owned(), vm)
|
||||
.to_pyresult(vm)
|
||||
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)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ use super::{
|
||||
PyStr, PyStrInterned, PyStrRef, PyTuple, PyTupleRef, PyWeak,
|
||||
};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
builtins::{
|
||||
descriptor::{
|
||||
DescrObject, MemberDef, MemberDescrObject, MemberGetter, MemberKind, MemberSetter,
|
||||
@@ -28,7 +27,6 @@ use crate::{
|
||||
};
|
||||
use indexmap::{map::Entry, IndexMap};
|
||||
use itertools::Itertools;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::{borrow::Borrow, collections::HashSet, fmt, ops::Deref, pin::Pin, ptr::NonNull};
|
||||
|
||||
#[pyclass(module = false, name = "type")]
|
||||
@@ -1061,12 +1059,12 @@ impl Callable for PyType {
|
||||
|
||||
impl AsNumber for PyType {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
or: atomic_func!(|num, other, vm| {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
or: Some(|num, other, vm| {
|
||||
or_(num.obj.to_owned(), other.to_owned(), vm).to_pyresult(vm)
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use super::{genericalias, type_};
|
||||
use crate::{
|
||||
atomic_func,
|
||||
@@ -13,6 +11,7 @@ use crate::{
|
||||
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
|
||||
VirtualMachine,
|
||||
};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::fmt;
|
||||
|
||||
const CLS_ATTRS: &[&str] = &["__module__"];
|
||||
@@ -257,12 +256,12 @@ impl AsMapping for PyUnion {
|
||||
|
||||
impl AsNumber for PyUnion {
|
||||
fn as_number() -> &'static PyNumberMethods {
|
||||
static AS_NUMBER: Lazy<PyNumberMethods> = Lazy::new(|| PyNumberMethods {
|
||||
or: atomic_func!(|num, other, vm| {
|
||||
static AS_NUMBER: PyNumberMethods = PyNumberMethods {
|
||||
or: Some(|num, other, vm| {
|
||||
PyUnion::or(num.obj.to_owned(), other.to_owned(), vm).to_pyresult(vm)
|
||||
}),
|
||||
..PyNumberMethods::NOT_IMPLEMENTED
|
||||
});
|
||||
};
|
||||
&AS_NUMBER
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,5 +10,7 @@ pub use buffer::{BufferDescriptor, BufferMethods, BufferResizeGuard, PyBuffer, V
|
||||
pub use callable::PyCallable;
|
||||
pub use iter::{PyIter, PyIterIter, PyIterReturn};
|
||||
pub use mapping::{PyMapping, PyMappingMethods};
|
||||
pub use number::{PyNumber, PyNumberBinaryOpSlot, PyNumberMethods};
|
||||
pub use number::{
|
||||
PyNumber, PyNumberBinaryFunc, PyNumberBinaryOpSlot, PyNumberMethods, PyNumberUnaryFunc,
|
||||
};
|
||||
pub use sequence::{PySequence, PySequenceMethods};
|
||||
+85
-84
@@ -7,11 +7,9 @@ use crate::{
|
||||
AsObject, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromBorrowedObject,
|
||||
VirtualMachine,
|
||||
};
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
type UnaryFunc<R = PyObjectRef> = AtomicCell<Option<fn(PyNumber, &VirtualMachine) -> PyResult<R>>>;
|
||||
type BinaryFunc<R = PyObjectRef> =
|
||||
AtomicCell<Option<fn(PyNumber, &PyObject, &VirtualMachine) -> PyResult<R>>>;
|
||||
pub type PyNumberUnaryFunc<R = PyObjectRef> = fn(PyNumber, &VirtualMachine) -> PyResult<R>;
|
||||
pub type PyNumberBinaryFunc = fn(PyNumber, &PyObject, &VirtualMachine) -> PyResult;
|
||||
|
||||
impl PyObject {
|
||||
#[inline]
|
||||
@@ -113,45 +111,45 @@ pub struct PyNumberMethods {
|
||||
/* Number implementations must check *both*
|
||||
arguments for proper type and implement the necessary conversions
|
||||
in the slot functions themselves. */
|
||||
pub add: BinaryFunc,
|
||||
pub subtract: BinaryFunc,
|
||||
pub multiply: BinaryFunc,
|
||||
pub remainder: BinaryFunc,
|
||||
pub divmod: BinaryFunc,
|
||||
pub power: BinaryFunc,
|
||||
pub negative: UnaryFunc,
|
||||
pub positive: UnaryFunc,
|
||||
pub absolute: UnaryFunc,
|
||||
pub boolean: UnaryFunc<bool>,
|
||||
pub invert: UnaryFunc,
|
||||
pub lshift: BinaryFunc,
|
||||
pub rshift: BinaryFunc,
|
||||
pub and: BinaryFunc,
|
||||
pub xor: BinaryFunc,
|
||||
pub or: BinaryFunc,
|
||||
pub int: UnaryFunc<PyRef<PyInt>>,
|
||||
pub float: UnaryFunc<PyRef<PyFloat>>,
|
||||
pub add: Option<PyNumberBinaryFunc>,
|
||||
pub subtract: Option<PyNumberBinaryFunc>,
|
||||
pub multiply: Option<PyNumberBinaryFunc>,
|
||||
pub remainder: Option<PyNumberBinaryFunc>,
|
||||
pub divmod: Option<PyNumberBinaryFunc>,
|
||||
pub power: Option<PyNumberBinaryFunc>,
|
||||
pub negative: Option<PyNumberUnaryFunc>,
|
||||
pub positive: Option<PyNumberUnaryFunc>,
|
||||
pub absolute: Option<PyNumberUnaryFunc>,
|
||||
pub boolean: Option<PyNumberUnaryFunc<bool>>,
|
||||
pub invert: Option<PyNumberUnaryFunc>,
|
||||
pub lshift: Option<PyNumberBinaryFunc>,
|
||||
pub rshift: Option<PyNumberBinaryFunc>,
|
||||
pub and: Option<PyNumberBinaryFunc>,
|
||||
pub xor: Option<PyNumberBinaryFunc>,
|
||||
pub or: Option<PyNumberBinaryFunc>,
|
||||
pub int: Option<PyNumberUnaryFunc<PyRef<PyInt>>>,
|
||||
pub float: Option<PyNumberUnaryFunc<PyRef<PyFloat>>>,
|
||||
|
||||
pub inplace_add: BinaryFunc,
|
||||
pub inplace_subtract: BinaryFunc,
|
||||
pub inplace_multiply: BinaryFunc,
|
||||
pub inplace_remainder: BinaryFunc,
|
||||
pub inplace_power: BinaryFunc,
|
||||
pub inplace_lshift: BinaryFunc,
|
||||
pub inplace_rshift: BinaryFunc,
|
||||
pub inplace_and: BinaryFunc,
|
||||
pub inplace_xor: BinaryFunc,
|
||||
pub inplace_or: BinaryFunc,
|
||||
pub inplace_add: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_subtract: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_multiply: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_remainder: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_power: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_lshift: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_rshift: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_and: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_xor: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_or: Option<PyNumberBinaryFunc>,
|
||||
|
||||
pub floor_divide: BinaryFunc,
|
||||
pub true_divide: BinaryFunc,
|
||||
pub inplace_floor_divide: BinaryFunc,
|
||||
pub inplace_true_divide: BinaryFunc,
|
||||
pub floor_divide: Option<PyNumberBinaryFunc>,
|
||||
pub true_divide: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_floor_divide: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_true_divide: Option<PyNumberBinaryFunc>,
|
||||
|
||||
pub index: UnaryFunc<PyRef<PyInt>>,
|
||||
pub index: Option<PyNumberUnaryFunc<PyRef<PyInt>>>,
|
||||
|
||||
pub matrix_multiply: BinaryFunc,
|
||||
pub inplace_matrix_multiply: BinaryFunc,
|
||||
pub matrix_multiply: Option<PyNumberBinaryFunc>,
|
||||
pub inplace_matrix_multiply: Option<PyNumberBinaryFunc>,
|
||||
}
|
||||
|
||||
impl PyNumberMethods {
|
||||
@@ -159,44 +157,47 @@ impl PyNumberMethods {
|
||||
// TODO: weak order read for performance
|
||||
#[allow(clippy::declare_interior_mutable_const)]
|
||||
pub const NOT_IMPLEMENTED: PyNumberMethods = PyNumberMethods {
|
||||
add: AtomicCell::new(None),
|
||||
subtract: AtomicCell::new(None),
|
||||
multiply: AtomicCell::new(None),
|
||||
remainder: AtomicCell::new(None),
|
||||
divmod: AtomicCell::new(None),
|
||||
power: AtomicCell::new(None),
|
||||
negative: AtomicCell::new(None),
|
||||
positive: AtomicCell::new(None),
|
||||
absolute: AtomicCell::new(None),
|
||||
boolean: AtomicCell::new(None),
|
||||
invert: AtomicCell::new(None),
|
||||
lshift: AtomicCell::new(None),
|
||||
rshift: AtomicCell::new(None),
|
||||
and: AtomicCell::new(None),
|
||||
xor: AtomicCell::new(None),
|
||||
or: AtomicCell::new(None),
|
||||
int: AtomicCell::new(None),
|
||||
float: AtomicCell::new(None),
|
||||
inplace_add: AtomicCell::new(None),
|
||||
inplace_subtract: AtomicCell::new(None),
|
||||
inplace_multiply: AtomicCell::new(None),
|
||||
inplace_remainder: AtomicCell::new(None),
|
||||
inplace_power: AtomicCell::new(None),
|
||||
inplace_lshift: AtomicCell::new(None),
|
||||
inplace_rshift: AtomicCell::new(None),
|
||||
inplace_and: AtomicCell::new(None),
|
||||
inplace_xor: AtomicCell::new(None),
|
||||
inplace_or: AtomicCell::new(None),
|
||||
floor_divide: AtomicCell::new(None),
|
||||
true_divide: AtomicCell::new(None),
|
||||
inplace_floor_divide: AtomicCell::new(None),
|
||||
inplace_true_divide: AtomicCell::new(None),
|
||||
index: AtomicCell::new(None),
|
||||
matrix_multiply: AtomicCell::new(None),
|
||||
inplace_matrix_multiply: AtomicCell::new(None),
|
||||
add: None,
|
||||
subtract: None,
|
||||
multiply: None,
|
||||
remainder: None,
|
||||
divmod: None,
|
||||
power: None,
|
||||
negative: None,
|
||||
positive: None,
|
||||
absolute: None,
|
||||
boolean: None,
|
||||
invert: None,
|
||||
lshift: None,
|
||||
rshift: None,
|
||||
and: None,
|
||||
xor: None,
|
||||
or: None,
|
||||
int: None,
|
||||
float: None,
|
||||
inplace_add: None,
|
||||
inplace_subtract: None,
|
||||
inplace_multiply: None,
|
||||
inplace_remainder: None,
|
||||
inplace_power: None,
|
||||
inplace_lshift: None,
|
||||
inplace_rshift: None,
|
||||
inplace_and: None,
|
||||
inplace_xor: None,
|
||||
inplace_or: None,
|
||||
floor_divide: None,
|
||||
true_divide: None,
|
||||
inplace_floor_divide: None,
|
||||
inplace_true_divide: None,
|
||||
index: None,
|
||||
matrix_multiply: None,
|
||||
inplace_matrix_multiply: None,
|
||||
};
|
||||
|
||||
pub fn get_binary_op(&self, op_slot: &PyNumberBinaryOpSlot) -> PyResult<&BinaryFunc> {
|
||||
pub fn get_binary_op(
|
||||
&self,
|
||||
op_slot: &PyNumberBinaryOpSlot,
|
||||
) -> PyResult<&Option<PyNumberBinaryFunc>> {
|
||||
use PyNumberBinaryOpSlot::*;
|
||||
let binary_op = match op_slot {
|
||||
Add => &self.add,
|
||||
@@ -287,16 +288,16 @@ impl PyNumber<'_> {
|
||||
self.methods
|
||||
}
|
||||
|
||||
pub fn get_binary_op(&self, op_slot: &PyNumberBinaryOpSlot) -> PyResult<&BinaryFunc> {
|
||||
pub fn get_binary_op(
|
||||
&self,
|
||||
op_slot: &PyNumberBinaryOpSlot,
|
||||
) -> PyResult<&Option<PyNumberBinaryFunc>> {
|
||||
self.methods().get_binary_op(op_slot)
|
||||
}
|
||||
|
||||
// PyNumber_Check
|
||||
pub fn check(obj: &PyObject) -> bool {
|
||||
let Some(methods) = Self::find_methods(obj) else {
|
||||
return false;
|
||||
};
|
||||
let methods = methods.as_ref();
|
||||
let methods = &obj.class().slots.number;
|
||||
methods.int.load().is_some()
|
||||
|| methods.index.load().is_some()
|
||||
|| methods.float.load().is_some()
|
||||
@@ -305,12 +306,12 @@ impl PyNumber<'_> {
|
||||
|
||||
// PyIndex_Check
|
||||
pub fn is_index(&self) -> bool {
|
||||
self.methods().index.load().is_some()
|
||||
self.obj.class().slots.number.index.load().is_some()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn int(self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
|
||||
self.methods().int.load().map(|f| {
|
||||
self.obj.class().slots.number.int.load().map(|f| {
|
||||
let ret = f(self, vm)?;
|
||||
let value = if !ret.class().is(PyInt::class(vm)) {
|
||||
warnings::warn(
|
||||
@@ -334,7 +335,7 @@ impl PyNumber<'_> {
|
||||
|
||||
#[inline]
|
||||
pub fn index(self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
|
||||
self.methods().index.load().map(|f| {
|
||||
self.obj.class().slots.number.index.load().map(|f| {
|
||||
let ret = f(self, vm)?;
|
||||
let value = if !ret.class().is(PyInt::class(vm)) {
|
||||
warnings::warn(
|
||||
@@ -358,7 +359,7 @@ impl PyNumber<'_> {
|
||||
|
||||
#[inline]
|
||||
pub fn float(self, vm: &VirtualMachine) -> Option<PyResult<PyRef<PyFloat>>> {
|
||||
self.methods().float.load().map(|f| {
|
||||
self.obj.class().slots.number.float.load().map(|f| {
|
||||
let ret = f(self, vm)?;
|
||||
let value = if !ret.class().is(PyFloat::class(vm)) {
|
||||
warnings::warn(
|
||||
|
||||
+303
-114
@@ -1,14 +1,13 @@
|
||||
use crate::common::{hash::PyHash, lock::PyRwLock};
|
||||
use crate::convert::ToPyObject;
|
||||
use crate::{
|
||||
builtins::{type_::PointerSlot, PyFloat, PyInt, PyStrInterned, PyStrRef, PyType, PyTypeRef},
|
||||
bytecode::ComparisonOperator,
|
||||
convert::ToPyResult,
|
||||
common::{hash::PyHash, lock::PyRwLock},
|
||||
convert::{ToPyObject, ToPyResult},
|
||||
function::{Either, FromArgs, FuncArgs, OptionalArg, PyComparisonValue, PySetterValue},
|
||||
identifier,
|
||||
protocol::{
|
||||
PyBuffer, PyIterReturn, PyMapping, PyMappingMethods, PyNumber, PyNumberMethods, PySequence,
|
||||
PySequenceMethods,
|
||||
PyBuffer, PyIterReturn, PyMapping, PyMappingMethods, PyNumber, PyNumberBinaryFunc,
|
||||
PyNumberBinaryOpSlot, PyNumberMethods, PyNumberUnaryFunc, PySequence, PySequenceMethods,
|
||||
},
|
||||
vm::Context,
|
||||
AsObject, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, VirtualMachine,
|
||||
@@ -85,6 +84,7 @@ pub struct PyTypeSlots {
|
||||
|
||||
// The count of tp_members.
|
||||
pub member_count: usize,
|
||||
pub number: PyNumberSlots,
|
||||
}
|
||||
|
||||
impl PyTypeSlots {
|
||||
@@ -102,6 +102,128 @@ impl std::fmt::Debug for PyTypeSlots {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PyNumberSlots {
|
||||
pub add: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub subtract: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub multiply: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub remainder: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub divmod: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub power: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub negative: AtomicCell<Option<PyNumberUnaryFunc>>,
|
||||
pub positive: AtomicCell<Option<PyNumberUnaryFunc>>,
|
||||
pub absolute: AtomicCell<Option<PyNumberUnaryFunc>>,
|
||||
pub boolean: AtomicCell<Option<PyNumberUnaryFunc<bool>>>,
|
||||
pub invert: AtomicCell<Option<PyNumberUnaryFunc>>,
|
||||
pub lshift: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub rshift: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub and: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub xor: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub or: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub int: AtomicCell<Option<PyNumberUnaryFunc<PyRef<PyInt>>>>,
|
||||
pub float: AtomicCell<Option<PyNumberUnaryFunc<PyRef<PyFloat>>>>,
|
||||
|
||||
pub right_add: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_subtract: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_multiply: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_remainder: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_divmod: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_power: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_lshift: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_rshift: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_and: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_xor: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_or: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
|
||||
pub inplace_add: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_subtract: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_multiply: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_remainder: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_power: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_lshift: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_rshift: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_and: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_xor: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_or: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
|
||||
pub floor_divide: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub true_divide: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_floor_divide: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_true_divide: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_floor_divide: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_true_divide: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
|
||||
pub index: AtomicCell<Option<PyNumberUnaryFunc<PyRef<PyInt>>>>,
|
||||
|
||||
pub matrix_multiply: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub right_matrix_multiply: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
pub inplace_matrix_multiply: AtomicCell<Option<PyNumberBinaryFunc>>,
|
||||
}
|
||||
|
||||
impl PyNumberSlots {
|
||||
pub fn get_left_binary_op(
|
||||
&self,
|
||||
op_slot: &PyNumberBinaryOpSlot,
|
||||
) -> PyResult<Option<PyNumberBinaryFunc>> {
|
||||
use PyNumberBinaryOpSlot::*;
|
||||
let binary_op = match op_slot {
|
||||
Add => self.add.load(),
|
||||
Subtract => self.subtract.load(),
|
||||
Multiply => self.multiply.load(),
|
||||
Remainder => self.remainder.load(),
|
||||
Divmod => self.divmod.load(),
|
||||
Power => self.power.load(),
|
||||
Lshift => self.lshift.load(),
|
||||
Rshift => self.rshift.load(),
|
||||
And => self.and.load(),
|
||||
Xor => self.xor.load(),
|
||||
Or => self.or.load(),
|
||||
InplaceAdd => self.inplace_add.load(),
|
||||
InplaceSubtract => self.inplace_subtract.load(),
|
||||
InplaceMultiply => self.inplace_multiply.load(),
|
||||
InplaceRemainder => self.inplace_remainder.load(),
|
||||
InplacePower => self.inplace_power.load(),
|
||||
InplaceLshift => self.inplace_lshift.load(),
|
||||
InplaceRshift => self.inplace_rshift.load(),
|
||||
InplaceAnd => self.inplace_and.load(),
|
||||
InplaceXor => self.inplace_xor.load(),
|
||||
InplaceOr => self.inplace_or.load(),
|
||||
FloorDivide => self.floor_divide.load(),
|
||||
TrueDivide => self.true_divide.load(),
|
||||
InplaceFloorDivide => self.inplace_floor_divide.load(),
|
||||
InplaceTrueDivide => self.inplace_true_divide.load(),
|
||||
MatrixMultiply => self.matrix_multiply.load(),
|
||||
InplaceMatrixMultiply => self.inplace_matrix_multiply.load(),
|
||||
};
|
||||
Ok(binary_op)
|
||||
}
|
||||
|
||||
pub fn get_right_binary_op(
|
||||
&self,
|
||||
op_slot: &PyNumberBinaryOpSlot,
|
||||
) -> PyResult<Option<PyNumberBinaryFunc>> {
|
||||
use PyNumberBinaryOpSlot::*;
|
||||
let binary_op = match op_slot {
|
||||
Add => self.right_add.load(),
|
||||
Subtract => self.right_subtract.load(),
|
||||
Multiply => self.right_multiply.load(),
|
||||
Remainder => self.right_remainder.load(),
|
||||
Divmod => self.right_divmod.load(),
|
||||
Power => self.right_power.load(),
|
||||
Lshift => self.right_lshift.load(),
|
||||
Rshift => self.right_rshift.load(),
|
||||
And => self.right_and.load(),
|
||||
Xor => self.right_xor.load(),
|
||||
Or => self.right_or.load(),
|
||||
FloorDivide => self.right_floor_divide.load(),
|
||||
TrueDivide => self.right_true_divide.load(),
|
||||
MatrixMultiply => self.right_matrix_multiply.load(),
|
||||
_ => None,
|
||||
};
|
||||
Ok(binary_op)
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[non_exhaustive]
|
||||
pub struct PyTypeFlags: u64 {
|
||||
@@ -373,6 +495,15 @@ impl PyType {
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! toggle_subslot {
|
||||
($group:ident, $name:ident, $func:expr) => {
|
||||
self.slots
|
||||
.$group
|
||||
.$name
|
||||
.store(if ADD { Some($func) } else { None });
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! update_slot {
|
||||
($name:ident, $func:expr) => {{
|
||||
self.slots.$name.store(Some($func));
|
||||
@@ -485,204 +616,188 @@ impl PyType {
|
||||
toggle_slot!(del, del_wrapper);
|
||||
}
|
||||
_ if name == identifier!(ctx, __int__) => {
|
||||
toggle_ext_func!(number_methods, int, int_wrapper);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, int, int_wrapper);
|
||||
}
|
||||
_ if name == identifier!(ctx, __index__) => {
|
||||
toggle_ext_func!(number_methods, index, index_wrapper);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, index, index_wrapper);
|
||||
}
|
||||
_ if name == identifier!(ctx, __float__) => {
|
||||
toggle_ext_func!(number_methods, float, float_wrapper);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, float, float_wrapper);
|
||||
}
|
||||
_ if name == identifier!(ctx, __add__) => {
|
||||
toggle_ext_func!(number_methods, add, number_binary_op_wrapper!(__add__));
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, add, number_binary_op_wrapper!(__add__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __radd__) => {
|
||||
toggle_subslot!(number, right_add, number_binary_op_wrapper!(__radd__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __iadd__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
inplace_add,
|
||||
number_binary_op_wrapper!(__iadd__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, inplace_add, number_binary_op_wrapper!(__iadd__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __sub__) => {
|
||||
toggle_ext_func!(number_methods, subtract, number_binary_op_wrapper!(__sub__));
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, subtract, number_binary_op_wrapper!(__sub__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rsub__) => {
|
||||
toggle_subslot!(number, right_subtract, number_binary_op_wrapper!(__rsub__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __isub__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
inplace_subtract,
|
||||
number_binary_op_wrapper!(__isub__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __mul__) => {
|
||||
toggle_ext_func!(number_methods, multiply, number_binary_op_wrapper!(__mul__));
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, multiply, number_binary_op_wrapper!(__mul__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rmul__) => {
|
||||
toggle_subslot!(number, right_multiply, number_binary_op_wrapper!(__rmul__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __imul__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
inplace_multiply,
|
||||
number_binary_op_wrapper!(__imul__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __mod__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
remainder,
|
||||
number_binary_op_wrapper!(__mod__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, remainder, number_binary_op_wrapper!(__mod__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rmod__) => {
|
||||
toggle_subslot!(number, right_remainder, number_binary_op_wrapper!(__rmod__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __imod__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
inplace_remainder,
|
||||
number_binary_op_wrapper!(__imod__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __divmod__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
divmod,
|
||||
number_binary_op_wrapper!(__divmod__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, divmod, number_binary_op_wrapper!(__divmod__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rdivmod__) => {
|
||||
toggle_subslot!(number, right_divmod, number_binary_op_wrapper!(__rdivmod__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __pow__) => {
|
||||
toggle_ext_func!(number_methods, power, number_binary_op_wrapper!(__pow__));
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, power, number_binary_op_wrapper!(__pow__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rpow__) => {
|
||||
toggle_subslot!(number, right_power, number_binary_op_wrapper!(__rpow__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __ipow__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
inplace_power,
|
||||
number_binary_op_wrapper!(__ipow__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, inplace_power, number_binary_op_wrapper!(__ipow__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __lshift__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
lshift,
|
||||
number_binary_op_wrapper!(__lshift__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, lshift, number_binary_op_wrapper!(__lshift__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rlshift__) => {
|
||||
toggle_subslot!(number, right_lshift, number_binary_op_wrapper!(__rlshift__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __ilshift__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
inplace_lshift,
|
||||
number_binary_op_wrapper!(__ilshift__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __rshift__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
rshift,
|
||||
number_binary_op_wrapper!(__rshift__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, rshift, number_binary_op_wrapper!(__rshift__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rrshift__) => {
|
||||
toggle_subslot!(number, right_rshift, number_binary_op_wrapper!(__rrshift__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __irshift__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
inplace_rshift,
|
||||
number_binary_op_wrapper!(__irshift__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __and__) => {
|
||||
toggle_ext_func!(number_methods, and, number_binary_op_wrapper!(__and__));
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, and, number_binary_op_wrapper!(__and__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rand__) => {
|
||||
toggle_subslot!(number, right_and, number_binary_op_wrapper!(__rand__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __iand__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
inplace_and,
|
||||
number_binary_op_wrapper!(__iand__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, inplace_and, number_binary_op_wrapper!(__iand__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __xor__) => {
|
||||
toggle_ext_func!(number_methods, xor, number_binary_op_wrapper!(__xor__));
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, xor, number_binary_op_wrapper!(__xor__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rxor__) => {
|
||||
toggle_subslot!(number, right_xor, number_binary_op_wrapper!(__rxor__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __ixor__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
inplace_xor,
|
||||
number_binary_op_wrapper!(__ixor__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, inplace_xor, number_binary_op_wrapper!(__ixor__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __or__) => {
|
||||
toggle_ext_func!(number_methods, or, number_binary_op_wrapper!(__or__));
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, or, number_binary_op_wrapper!(__or__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __ror__) => {
|
||||
toggle_subslot!(number, right_or, number_binary_op_wrapper!(__ror__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __ior__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
inplace_or,
|
||||
number_binary_op_wrapper!(__ior__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
toggle_subslot!(number, inplace_or, number_binary_op_wrapper!(__ior__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __floordiv__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
floor_divide,
|
||||
number_binary_op_wrapper!(__floordiv__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __rfloordiv__) => {
|
||||
toggle_subslot!(
|
||||
number,
|
||||
right_floor_divide,
|
||||
number_binary_op_wrapper!(__rfloordiv__)
|
||||
);
|
||||
}
|
||||
_ if name == identifier!(ctx, __ifloordiv__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
inplace_floor_divide,
|
||||
number_binary_op_wrapper!(__ifloordiv__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __truediv__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
true_divide,
|
||||
number_binary_op_wrapper!(__truediv__)
|
||||
toggle_subslot!(number, true_divide, number_binary_op_wrapper!(__truediv__));
|
||||
}
|
||||
_ if name == identifier!(ctx, __rtruediv__) => {
|
||||
toggle_subslot!(
|
||||
number,
|
||||
right_true_divide,
|
||||
number_binary_op_wrapper!(__rtruediv__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __itruediv__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
inplace_true_divide,
|
||||
number_binary_op_wrapper!(__itruediv__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __matmul__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
matrix_multiply,
|
||||
number_binary_op_wrapper!(__matmul__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ if name == identifier!(ctx, __rmatmul__) => {
|
||||
toggle_subslot!(
|
||||
number,
|
||||
right_matrix_multiply,
|
||||
number_binary_op_wrapper!(__rmatmul__)
|
||||
);
|
||||
}
|
||||
_ if name == identifier!(ctx, __imatmul__) => {
|
||||
toggle_ext_func!(
|
||||
number_methods,
|
||||
toggle_subslot!(
|
||||
number,
|
||||
inplace_matrix_multiply,
|
||||
number_binary_op_wrapper!(__imatmul__)
|
||||
);
|
||||
update_pointer_slot!(as_number, number_methods);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
@@ -1161,6 +1276,26 @@ 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.get_binary_op(&PyNumberBinaryOpSlot::$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]
|
||||
@@ -1184,6 +1319,60 @@ pub trait AsNumber: PyPayload {
|
||||
Self::clone_exact(Self::number_downcast(number), 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]
|
||||
|
||||
+8
-12
@@ -128,18 +128,15 @@ impl VirtualMachine {
|
||||
/// Calling scheme used for binary operations:
|
||||
///
|
||||
/// Order operations are tried until either a valid result or error:
|
||||
/// b.op(a,b)[*], a.op(a,b), b.op(a,b)
|
||||
/// b.rop(b,a)[*], a.op(a,b), b.rop(b,a)
|
||||
///
|
||||
/// [*] only when Py_TYPE(a) != Py_TYPE(b) && Py_TYPE(b) is a subclass of Py_TYPE(a)
|
||||
fn binary_op1(&self, a: &PyObject, b: &PyObject, op_slot: &PyNumberBinaryOpSlot) -> PyResult {
|
||||
let num_a = a.to_number();
|
||||
let num_b = b.to_number();
|
||||
|
||||
let slot_a = num_a.get_binary_op(op_slot)?.load();
|
||||
let slot_a = a.class().slots.number.get_left_binary_op(op_slot)?;
|
||||
let mut slot_b = if b.class().is(a.class()) {
|
||||
None
|
||||
} else {
|
||||
match num_b.get_binary_op(op_slot)?.load() {
|
||||
match b.class().slots.number.get_right_binary_op(op_slot)? {
|
||||
Some(slot_b)
|
||||
if slot_b as usize == slot_a.map(|s| s as usize).unwrap_or_default() =>
|
||||
{
|
||||
@@ -152,21 +149,21 @@ impl VirtualMachine {
|
||||
if let Some(slot_a) = slot_a {
|
||||
if let Some(slot_bb) = slot_b {
|
||||
if b.fast_isinstance(a.class()) {
|
||||
let x = slot_bb(num_a, b, self)?;
|
||||
let x = slot_bb(b.to_number(), a, self)?;
|
||||
if !x.is(&self.ctx.not_implemented) {
|
||||
return Ok(x);
|
||||
}
|
||||
slot_b = None;
|
||||
}
|
||||
}
|
||||
let x = slot_a(num_a, b, self)?;
|
||||
let x = slot_a(a.to_number(), b, self)?;
|
||||
if !x.is(&self.ctx.not_implemented) {
|
||||
return Ok(x);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(slot_b) = slot_b {
|
||||
let x = slot_b(num_a, b, self)?;
|
||||
let x = slot_b(b.to_number(), a, self)?;
|
||||
if !x.is(&self.ctx.not_implemented) {
|
||||
return Ok(x);
|
||||
}
|
||||
@@ -209,9 +206,8 @@ impl VirtualMachine {
|
||||
iop_slot: &PyNumberBinaryOpSlot,
|
||||
op_slot: &PyNumberBinaryOpSlot,
|
||||
) -> PyResult {
|
||||
let num_a = a.to_number();
|
||||
if let Some(slot) = num_a.get_binary_op(iop_slot)?.load() {
|
||||
let x = slot(num_a, b, self)?;
|
||||
if let Some(slot) = a.class().slots.number.get_left_binary_op(iop_slot)? {
|
||||
let x = slot(a.to_number(), b, self)?;
|
||||
if !x.is(&self.ctx.not_implemented) {
|
||||
return Ok(x);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user