mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-09 22:49:57 +09:00
Merge pull request #1641 from youknowone/refactor-float
Refactor float, complex cmp/op , str, None
This commit is contained in:
@@ -3,7 +3,7 @@ use num_traits::Zero;
|
||||
use std::num::Wrapping;
|
||||
|
||||
use super::objfloat::{self, IntoPyFloat};
|
||||
use super::objtype::{self, PyClassRef};
|
||||
use super::objtype::PyClassRef;
|
||||
use crate::function::OptionalArg;
|
||||
use crate::pyhash;
|
||||
use crate::pyobject::{
|
||||
@@ -43,18 +43,15 @@ pub fn init(context: &PyContext) {
|
||||
PyComplex::extend_class(context, &context.types.complex_type);
|
||||
}
|
||||
|
||||
pub fn get_value(obj: &PyObjectRef) -> Complex64 {
|
||||
obj.payload::<PyComplex>().unwrap().value
|
||||
}
|
||||
|
||||
fn try_complex(value: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<Complex64>> {
|
||||
Ok(if objtype::isinstance(&value, &vm.ctx.complex_type()) {
|
||||
Some(get_value(&value))
|
||||
let r = if let Some(complex) = value.payload_if_subclass::<PyComplex>(vm) {
|
||||
Some(complex.value)
|
||||
} else if let Some(float) = objfloat::try_float(value, vm)? {
|
||||
Some(Complex64::new(float, 0.0))
|
||||
} else {
|
||||
None
|
||||
})
|
||||
};
|
||||
Ok(r)
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
@@ -75,14 +72,22 @@ impl PyComplex {
|
||||
re.hypot(im)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__add__")]
|
||||
fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
#[inline]
|
||||
fn op<F>(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult
|
||||
where
|
||||
F: Fn(Complex64, Complex64) -> Complex64,
|
||||
{
|
||||
try_complex(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (self.value + other).into_pyobject(vm),
|
||||
|other| op(self.value, other).into_pyobject(vm),
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__add__")]
|
||||
fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
self.op(other, |a, b| a + b, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__radd__")]
|
||||
fn radd(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
self.add(other, vm)
|
||||
@@ -90,18 +95,12 @@ impl PyComplex {
|
||||
|
||||
#[pymethod(name = "__sub__")]
|
||||
fn sub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_complex(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (self.value - other).into_pyobject(vm),
|
||||
)
|
||||
self.op(other, |a, b| a - b, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rsub__")]
|
||||
fn rsub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_complex(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (other - self.value).into_pyobject(vm),
|
||||
)
|
||||
self.op(other, |a, b| b - a, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "conjugate")]
|
||||
@@ -111,8 +110,8 @@ impl PyComplex {
|
||||
|
||||
#[pymethod(name = "__eq__")]
|
||||
fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let result = if objtype::isinstance(&other, &vm.ctx.complex_type()) {
|
||||
self.value == get_value(&other)
|
||||
let result = if let Some(other) = other.payload_if_subclass::<PyComplex>(vm) {
|
||||
self.value == other.value
|
||||
} else {
|
||||
match objfloat::try_float(&other, vm) {
|
||||
Ok(Some(other)) => self.value.im == 0.0f64 && self.value.re == other,
|
||||
@@ -136,10 +135,7 @@ impl PyComplex {
|
||||
|
||||
#[pymethod(name = "__mul__")]
|
||||
fn mul(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_complex(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (self.value * other).into_pyobject(vm),
|
||||
)
|
||||
self.op(other, |a, b| a * b, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmul__")]
|
||||
@@ -149,18 +145,12 @@ impl PyComplex {
|
||||
|
||||
#[pymethod(name = "__truediv__")]
|
||||
fn truediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_complex(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (self.value / other).into_pyobject(vm),
|
||||
)
|
||||
self.op(other, |a, b| a / b, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rtruediv__")]
|
||||
fn rtruediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_complex(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (other / self.value).into_pyobject(vm),
|
||||
)
|
||||
self.op(other, |a, b| b / a, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mod__")]
|
||||
@@ -210,18 +200,12 @@ impl PyComplex {
|
||||
|
||||
#[pymethod(name = "__pow__")]
|
||||
fn pow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_complex(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (self.value.powc(other)).into_pyobject(vm),
|
||||
)
|
||||
self.op(other, |a, b| a.powc(b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rpow__")]
|
||||
fn rpow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_complex(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (other.powc(self.value)).into_pyobject(vm),
|
||||
)
|
||||
self.op(other, |a, b| b.powc(a), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
|
||||
@@ -90,7 +90,7 @@ fn inner_mod(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_to_bigint(value: f64, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
pub fn try_bigint(value: f64, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
match value.to_bigint() {
|
||||
Some(int) => Ok(int),
|
||||
None => {
|
||||
@@ -154,12 +154,20 @@ fn inner_gt_int(value: f64, other_int: &BigInt) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn float_pow(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult {
|
||||
pub fn float_pow(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
if v1.is_zero() {
|
||||
let msg = format!("{} cannot be raised to a negative power", v1);
|
||||
Err(vm.new_zero_division_error(msg))
|
||||
} else {
|
||||
v1.powf(v2).into_pyobject(vm)
|
||||
Ok(v1.powf(v2))
|
||||
}
|
||||
}
|
||||
|
||||
fn int_eq(value: f64, other: &BigInt) -> bool {
|
||||
if let (Some(self_int), Some(other_float)) = (value.to_bigint(), other.to_f64()) {
|
||||
value == other_float && self_int == *other
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,117 +187,78 @@ impl PyFloat {
|
||||
PyFloat::from(float_val?).into_ref_with_type(vm, cls)
|
||||
}
|
||||
|
||||
fn float_eq(&self, other: PyObjectRef) -> bool {
|
||||
let other = get_value(&other);
|
||||
self.value == other
|
||||
}
|
||||
|
||||
fn int_eq(&self, other: PyObjectRef) -> bool {
|
||||
let other_int = objint::get_value(&other);
|
||||
let value = self.value;
|
||||
if let (Some(self_int), Some(other_float)) = (value.to_bigint(), other_int.to_f64()) {
|
||||
value == other_float && self_int == *other_int
|
||||
#[inline]
|
||||
fn cmp<F, G>(
|
||||
&self,
|
||||
other: PyObjectRef,
|
||||
float_op: F,
|
||||
int_op: G,
|
||||
vm: &VirtualMachine,
|
||||
) -> PyObjectRef
|
||||
where
|
||||
F: Fn(f64, f64) -> bool,
|
||||
G: Fn(f64, &BigInt) -> bool,
|
||||
{
|
||||
let result = if let Some(other) = other.payload_if_subclass::<PyFloat>(vm) {
|
||||
float_op(self.value, other.value)
|
||||
} else if let Some(other) = other.payload_if_subclass::<PyInt>(vm) {
|
||||
int_op(self.value, other.as_bigint())
|
||||
} else {
|
||||
false
|
||||
}
|
||||
return vm.ctx.not_implemented();
|
||||
};
|
||||
vm.ctx.new_bool(result)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__eq__")]
|
||||
fn eq(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let result = if objtype::isinstance(&other, &vm.ctx.float_type()) {
|
||||
self.float_eq(other)
|
||||
} else if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
self.int_eq(other)
|
||||
} else {
|
||||
return vm.ctx.not_implemented();
|
||||
};
|
||||
vm.ctx.new_bool(result)
|
||||
self.cmp(other, |a, b| a == b, |a, b| int_eq(a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ne__")]
|
||||
fn ne(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let result = if objtype::isinstance(&other, &vm.ctx.float_type()) {
|
||||
!self.float_eq(other)
|
||||
} else if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
!self.int_eq(other)
|
||||
} else {
|
||||
return vm.ctx.not_implemented();
|
||||
};
|
||||
vm.ctx.new_bool(result)
|
||||
self.cmp(other, |a, b| a != b, |a, b| !int_eq(a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__lt__")]
|
||||
fn lt(&self, i2: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let v1 = self.value;
|
||||
if objtype::isinstance(&i2, &vm.ctx.float_type()) {
|
||||
vm.ctx.new_bool(v1 < get_value(&i2))
|
||||
} else if objtype::isinstance(&i2, &vm.ctx.int_type()) {
|
||||
let other_int = objint::get_value(&i2);
|
||||
|
||||
vm.ctx.new_bool(inner_lt_int(self.value, other_int))
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
fn lt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.cmp(other, |a, b| a < b, |a, b| inner_lt_int(a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__le__")]
|
||||
fn le(&self, i2: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let v1 = self.value;
|
||||
if objtype::isinstance(&i2, &vm.ctx.float_type()) {
|
||||
vm.ctx.new_bool(v1 <= get_value(&i2))
|
||||
} else if objtype::isinstance(&i2, &vm.ctx.int_type()) {
|
||||
let other_int = objint::get_value(&i2);
|
||||
|
||||
let result = if let (Some(self_int), Some(other_float)) =
|
||||
(self.value.to_bigint(), other_int.to_f64())
|
||||
{
|
||||
self.value <= other_float && self_int <= *other_int
|
||||
} else {
|
||||
// certainly not equal, forward to inner_lt_int
|
||||
inner_lt_int(self.value, other_int)
|
||||
};
|
||||
|
||||
vm.ctx.new_bool(result)
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
fn le(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.cmp(
|
||||
other,
|
||||
|a, b| a <= b,
|
||||
|a, b| {
|
||||
if let (Some(a_int), Some(b_float)) = (a.to_bigint(), b.to_f64()) {
|
||||
a <= b_float && a_int <= *b
|
||||
} else {
|
||||
inner_lt_int(a, b)
|
||||
}
|
||||
},
|
||||
vm,
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__gt__")]
|
||||
fn gt(&self, i2: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let v1 = self.value;
|
||||
if objtype::isinstance(&i2, &vm.ctx.float_type()) {
|
||||
vm.ctx.new_bool(v1 > get_value(&i2))
|
||||
} else if objtype::isinstance(&i2, &vm.ctx.int_type()) {
|
||||
let other_int = objint::get_value(&i2);
|
||||
|
||||
vm.ctx.new_bool(inner_gt_int(self.value, other_int))
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
fn gt(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.cmp(other, |a, b| a > b, |a, b| inner_gt_int(a, b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ge__")]
|
||||
fn ge(&self, i2: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
let v1 = self.value;
|
||||
if objtype::isinstance(&i2, &vm.ctx.float_type()) {
|
||||
vm.ctx.new_bool(v1 >= get_value(&i2))
|
||||
} else if objtype::isinstance(&i2, &vm.ctx.int_type()) {
|
||||
let other_int = objint::get_value(&i2);
|
||||
|
||||
let result = if let (Some(self_int), Some(other_float)) =
|
||||
(self.value.to_bigint(), other_int.to_f64())
|
||||
{
|
||||
self.value >= other_float && self_int >= *other_int
|
||||
} else {
|
||||
// certainly not equal, forward to inner_gt_int
|
||||
inner_gt_int(self.value, other_int)
|
||||
};
|
||||
|
||||
vm.ctx.new_bool(result)
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
fn ge(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
self.cmp(
|
||||
other,
|
||||
|a, b| a >= b,
|
||||
|a, b| {
|
||||
if let (Some(a_int), Some(b_float)) = (a.to_bigint(), b.to_f64()) {
|
||||
a >= b_float && a_int >= *b
|
||||
} else {
|
||||
inner_gt_int(a, b)
|
||||
}
|
||||
},
|
||||
vm,
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__abs__")]
|
||||
@@ -297,14 +266,38 @@ impl PyFloat {
|
||||
self.value.abs()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__add__")]
|
||||
fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
#[inline]
|
||||
fn simple_op<F>(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult
|
||||
where
|
||||
F: Fn(f64, f64) -> PyResult<f64>,
|
||||
{
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (self.value + other).into_pyobject(vm),
|
||||
|other| op(self.value, other).into_pyobject(vm),
|
||||
)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn tuple_op<F>(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult
|
||||
where
|
||||
F: Fn(f64, f64) -> PyResult<(f64, f64)>,
|
||||
{
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| {
|
||||
let (r1, r2) = op(self.value, other)?;
|
||||
Ok(vm
|
||||
.ctx
|
||||
.new_tuple(vec![vm.ctx.new_float(r1), vm.ctx.new_float(r2)]))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__add__")]
|
||||
fn add(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
self.simple_op(other, |a, b| Ok(a + b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__radd__")]
|
||||
fn radd(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
self.add(other, vm)
|
||||
@@ -317,60 +310,32 @@ impl PyFloat {
|
||||
|
||||
#[pymethod(name = "__divmod__")]
|
||||
fn divmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| {
|
||||
let (r1, r2) = inner_divmod(self.value, other, vm)?;
|
||||
Ok(vm
|
||||
.ctx
|
||||
.new_tuple(vec![vm.ctx.new_float(r1), vm.ctx.new_float(r2)]))
|
||||
},
|
||||
)
|
||||
self.tuple_op(other, |a, b| inner_divmod(a, b, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rdivmod__")]
|
||||
fn rdivmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| {
|
||||
let (r1, r2) = inner_divmod(other, self.value, vm)?;
|
||||
Ok(vm
|
||||
.ctx
|
||||
.new_tuple(vec![vm.ctx.new_float(r1), vm.ctx.new_float(r2)]))
|
||||
},
|
||||
)
|
||||
self.tuple_op(other, |a, b| inner_divmod(b, a, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__floordiv__")]
|
||||
fn floordiv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| inner_floordiv(self.value, other, vm)?.into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| inner_floordiv(a, b, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rfloordiv__")]
|
||||
fn rfloordiv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| inner_floordiv(other, self.value, vm)?.into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| inner_floordiv(b, a, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mod__")]
|
||||
fn mod_(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| inner_mod(self.value, other, vm)?.into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| inner_mod(a, b, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmod__")]
|
||||
fn rmod(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| inner_mod(other, self.value, vm)?.into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| inner_mod(b, a, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__pos__")]
|
||||
@@ -385,34 +350,22 @@ impl PyFloat {
|
||||
|
||||
#[pymethod(name = "__pow__")]
|
||||
fn pow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| float_pow(self.value, other, vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| float_pow(a, b, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rpow__")]
|
||||
fn rpow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| float_pow(other, self.value, vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| float_pow(b, a, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__sub__")]
|
||||
fn sub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (self.value - other).into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| Ok(a - b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rsub__")]
|
||||
fn rsub(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (other - self.value).into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| Ok(b - a), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
@@ -438,26 +391,17 @@ impl PyFloat {
|
||||
|
||||
#[pymethod(name = "__truediv__")]
|
||||
fn truediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| inner_div(self.value, other, vm)?.into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| inner_div(a, b, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rtruediv__")]
|
||||
fn rtruediv(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| inner_div(other, self.value, vm)?.into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| inner_div(b, a, vm), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__mul__")]
|
||||
fn mul(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
try_float(&other, vm)?.map_or_else(
|
||||
|| Ok(vm.ctx.not_implemented()),
|
||||
|other| (self.value * other).into_pyobject(vm),
|
||||
)
|
||||
self.simple_op(other, |a, b| Ok(a * b), vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__rmul__")]
|
||||
@@ -467,7 +411,7 @@ impl PyFloat {
|
||||
|
||||
#[pymethod(name = "__trunc__")]
|
||||
fn trunc(&self, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
try_to_bigint(self.value, vm)
|
||||
try_bigint(self.value, vm)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__round__")]
|
||||
@@ -523,7 +467,7 @@ impl PyFloat {
|
||||
} else {
|
||||
self.value.round()
|
||||
};
|
||||
let int = try_to_bigint(value, vm)?;
|
||||
let int = try_bigint(value, vm)?;
|
||||
Ok(vm.ctx.new_int(int))
|
||||
}
|
||||
}
|
||||
@@ -757,8 +701,8 @@ pub fn get_value(obj: &PyObjectRef) -> f64 {
|
||||
}
|
||||
|
||||
fn make_float(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<f64> {
|
||||
if objtype::isinstance(obj, &vm.ctx.float_type()) {
|
||||
Ok(get_value(obj))
|
||||
if let Some(float) = obj.payload_if_subclass::<PyFloat>(vm) {
|
||||
Ok(float.value)
|
||||
} else {
|
||||
let method = vm.get_method_or_type_error(obj.clone(), "__float__", || {
|
||||
format!(
|
||||
|
||||
@@ -120,7 +120,7 @@ fn inner_pow(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
if int2.is_negative() {
|
||||
let v1 = try_float(int1, vm)?;
|
||||
let v2 = try_float(int2, vm)?;
|
||||
objfloat::float_pow(v1, v2, vm)
|
||||
objfloat::float_pow(v1, v2, vm).into_pyobject(vm)
|
||||
} else {
|
||||
Ok(if let Some(v2) = int2.to_u64() {
|
||||
vm.ctx.new_int(int1.pow(v2))
|
||||
@@ -223,8 +223,8 @@ impl PyInt {
|
||||
where
|
||||
F: Fn(&BigInt, &BigInt) -> bool,
|
||||
{
|
||||
if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
vm.ctx.new_bool(op(&self.value, get_value(&other)))
|
||||
if let Some(other) = other.payload_if_subclass::<PyInt>(vm) {
|
||||
vm.ctx.new_bool(op(&self.value, &other.value))
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
@@ -265,8 +265,8 @@ impl PyInt {
|
||||
where
|
||||
F: Fn(&BigInt, &BigInt) -> BigInt,
|
||||
{
|
||||
if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
vm.ctx.new_int(op(&self.value, get_value(&other)))
|
||||
if let Some(other) = other.payload_if_subclass::<PyInt>(vm) {
|
||||
vm.ctx.new_int(op(&self.value, &other.value))
|
||||
} else {
|
||||
vm.ctx.not_implemented()
|
||||
}
|
||||
@@ -277,8 +277,8 @@ impl PyInt {
|
||||
where
|
||||
F: Fn(&BigInt, &BigInt) -> PyResult,
|
||||
{
|
||||
if objtype::isinstance(&other, &vm.ctx.int_type()) {
|
||||
op(&self.value, get_value(&other))
|
||||
if let Some(other) = other.payload_if_subclass::<PyInt>(vm) {
|
||||
op(&self.value, &other.value)
|
||||
} else {
|
||||
Ok(vm.ctx.not_implemented())
|
||||
}
|
||||
|
||||
@@ -36,26 +36,26 @@ impl<T: IntoPyObject> IntoPyObject for Option<T> {
|
||||
}
|
||||
|
||||
#[pyimpl]
|
||||
impl PyNoneRef {
|
||||
impl PyNone {
|
||||
#[pyslot(new)]
|
||||
fn tp_new(_: PyClassRef, vm: &VirtualMachine) -> PyNoneRef {
|
||||
vm.ctx.none.clone()
|
||||
}
|
||||
|
||||
#[pymethod(name = "__repr__")]
|
||||
fn repr(self, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
fn repr(&self, _vm: &VirtualMachine) -> PyResult<String> {
|
||||
Ok("None".to_string())
|
||||
}
|
||||
|
||||
#[pymethod(name = "__bool__")]
|
||||
fn bool(self, _vm: &VirtualMachine) -> PyResult<bool> {
|
||||
fn bool(&self, _vm: &VirtualMachine) -> PyResult<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
#[pymethod(name = "__getattribute__")]
|
||||
fn get_attribute(self, name: PyStringRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn get_attribute(zelf: PyRef<Self>, name: PyStringRef, vm: &VirtualMachine) -> PyResult {
|
||||
vm_trace!("None.__getattribute__({:?}, {:?})", self, name);
|
||||
let cls = self.class();
|
||||
let cls = zelf.class();
|
||||
|
||||
// Properties use a comparision with None to determine if they are either invoked by am
|
||||
// instance binding or a class binding. But if the object itself is None then this detection
|
||||
@@ -86,7 +86,7 @@ impl PyNoneRef {
|
||||
return call_descriptor(
|
||||
attr,
|
||||
get_func,
|
||||
self.into_object(),
|
||||
zelf.into_object(),
|
||||
cls.into_object(),
|
||||
vm,
|
||||
);
|
||||
@@ -95,25 +95,25 @@ impl PyNoneRef {
|
||||
}
|
||||
|
||||
// None has no attributes and cannot have attributes set on it.
|
||||
// if let Some(obj_attr) = self.as_object().get_attr(name.as_str()) {
|
||||
// if let Some(obj_attr) = zelf.as_object().get_attr(name.as_str()) {
|
||||
// Ok(obj_attr)
|
||||
// } else
|
||||
if let Some(attr) = class_get_attr(&cls, name.as_str()) {
|
||||
let attr_class = attr.class();
|
||||
if let Some(get_func) = class_get_attr(&attr_class, "__get__") {
|
||||
call_descriptor(attr, get_func, self.into_object(), cls.into_object(), vm)
|
||||
call_descriptor(attr, get_func, zelf.into_object(), cls.into_object(), vm)
|
||||
} else {
|
||||
Ok(attr)
|
||||
}
|
||||
} else if let Some(getter) = class_get_attr(&cls, "__getattr__") {
|
||||
vm.invoke(&getter, vec![self.into_object(), name.into_object()])
|
||||
vm.invoke(&getter, vec![zelf.into_object(), name.into_object()])
|
||||
} else {
|
||||
Err(vm.new_attribute_error(format!("{} has no attribute '{}'", self.as_object(), name)))
|
||||
Err(vm.new_attribute_error(format!("{} has no attribute '{}'", zelf.as_object(), name)))
|
||||
}
|
||||
}
|
||||
|
||||
#[pymethod(name = "__eq__")]
|
||||
fn eq(self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn eq(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
if vm.is_none(&rhs) {
|
||||
vm.ctx.new_bool(true)
|
||||
} else {
|
||||
@@ -122,7 +122,7 @@ impl PyNoneRef {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ne__")]
|
||||
fn ne(self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
fn ne(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyObjectRef {
|
||||
if vm.is_none(&rhs) {
|
||||
vm.ctx.new_bool(false)
|
||||
} else {
|
||||
@@ -132,5 +132,5 @@ impl PyNoneRef {
|
||||
}
|
||||
|
||||
pub fn init(context: &PyContext) {
|
||||
PyNoneRef::extend_class(context, &context.none.class());
|
||||
PyNone::extend_class(context, &context.none.class());
|
||||
}
|
||||
|
||||
@@ -280,39 +280,23 @@ impl PyString {
|
||||
}
|
||||
|
||||
#[pymethod(name = "__gt__")]
|
||||
fn gt(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
if objtype::isinstance(&rhs, &vm.ctx.str_type()) {
|
||||
Ok(self.value > get_value(&rhs))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", self, rhs)))
|
||||
}
|
||||
fn gt(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
self.value > other.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__ge__")]
|
||||
fn ge(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
if objtype::isinstance(&rhs, &vm.ctx.str_type()) {
|
||||
Ok(self.value >= get_value(&rhs))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", self, rhs)))
|
||||
}
|
||||
fn ge(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
self.value >= other.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__lt__")]
|
||||
fn lt(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
if objtype::isinstance(&rhs, &vm.ctx.str_type()) {
|
||||
Ok(self.value < get_value(&rhs))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", self, rhs)))
|
||||
}
|
||||
fn lt(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
self.value < other.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__le__")]
|
||||
fn le(&self, rhs: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
if objtype::isinstance(&rhs, &vm.ctx.str_type()) {
|
||||
Ok(self.value <= get_value(&rhs))
|
||||
} else {
|
||||
Err(vm.new_type_error(format!("Cannot compare {} and {}", self, rhs)))
|
||||
}
|
||||
fn le(&self, other: PyStringRef, _vm: &VirtualMachine) -> bool {
|
||||
self.value <= other.value
|
||||
}
|
||||
|
||||
#[pymethod(name = "__hash__")]
|
||||
|
||||
@@ -225,7 +225,7 @@ fn math_trunc(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&value, &vm.ctx.float_type()) {
|
||||
let v = objfloat::get_value(&value);
|
||||
let v = objfloat::try_to_bigint(v.ceil(), vm)?;
|
||||
let v = objfloat::try_bigint(v.ceil(), vm)?;
|
||||
Ok(vm.ctx.new_int(v))
|
||||
} else {
|
||||
try_magic_method("__ceil__", vm, &value)
|
||||
@@ -241,7 +241,7 @@ fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn math_floor(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
if objtype::isinstance(&value, &vm.ctx.float_type()) {
|
||||
let v = objfloat::get_value(&value);
|
||||
let v = objfloat::try_to_bigint(v.floor(), vm)?;
|
||||
let v = objfloat::try_bigint(v.floor(), vm)?;
|
||||
Ok(vm.ctx.new_int(v))
|
||||
} else {
|
||||
try_magic_method("__floor__", vm, &value)
|
||||
|
||||
Reference in New Issue
Block a user