forked from Rust-related/RustPython
try to types utility functions to PyObjectRef methods
This commit is contained in:
@@ -446,7 +446,7 @@ fn try_complex(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<(Compl
|
||||
if let Some(complex) = obj.payload_if_subclass::<PyComplex>(vm) {
|
||||
return Ok(Some((complex.value, true)));
|
||||
}
|
||||
if let Some(float) = float::try_float_opt(obj, vm)? {
|
||||
if let Some(float) = obj.try_to_f64(vm)? {
|
||||
return Ok(Some((Complex64::new(float, 0.0), false)));
|
||||
}
|
||||
Ok(None)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use super::{int, PyBytes, PyInt, PyIntRef, PyStr, PyStrRef, PyTypeRef};
|
||||
use super::{try_bigint_to_f64, PyBytes, PyInt, PyIntRef, PyStr, PyStrRef, PyTypeRef};
|
||||
use crate::common::{float_ops, hash};
|
||||
use crate::format::FormatSpec;
|
||||
use crate::function::{OptionalArg, OptionalOption};
|
||||
@@ -51,29 +51,31 @@ impl From<f64> for PyFloat {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_float_opt(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Option<f64>> {
|
||||
if let Some(float) = obj.payload_if_exact::<PyFloat>(vm) {
|
||||
return Ok(Some(float.value));
|
||||
impl PyObjectRef {
|
||||
pub fn try_to_f64(&self, vm: &VirtualMachine) -> PyResult<Option<f64>> {
|
||||
if let Some(float) = self.payload_if_exact::<PyFloat>(vm) {
|
||||
return Ok(Some(float.value));
|
||||
}
|
||||
if let Some(method) = vm.get_method(self.clone(), "__float__") {
|
||||
let result = vm.invoke(&method?, ())?;
|
||||
// TODO: returning strict subclasses of float in __float__ is deprecated
|
||||
return match result.payload::<PyFloat>() {
|
||||
Some(float_obj) => Ok(Some(float_obj.value)),
|
||||
None => Err(vm.new_type_error(format!(
|
||||
"__float__ returned non-float (type '{}')",
|
||||
result.class().name()
|
||||
))),
|
||||
};
|
||||
}
|
||||
if let Some(r) = vm.to_index_opt(self.clone()).transpose()? {
|
||||
return Ok(Some(try_bigint_to_f64(r.as_bigint(), vm)?));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
if let Some(method) = vm.get_method(obj.clone(), "__float__") {
|
||||
let result = vm.invoke(&method?, ())?;
|
||||
// TODO: returning strict subclasses of float in __float__ is deprecated
|
||||
return match result.payload::<PyFloat>() {
|
||||
Some(float_obj) => Ok(Some(float_obj.value)),
|
||||
None => Err(vm.new_type_error(format!(
|
||||
"__float__ returned non-float (type '{}')",
|
||||
result.class().name()
|
||||
))),
|
||||
};
|
||||
}
|
||||
if let Some(r) = vm.to_index_opt(obj.clone()).transpose()? {
|
||||
return Ok(Some(int::to_float(r.as_bigint(), vm)?));
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
pub fn try_float(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
try_float_opt(obj, vm)?.ok_or_else(|| {
|
||||
obj.try_to_f64(vm)?.ok_or_else(|| {
|
||||
vm.new_type_error(format!("must be real number, not {}", obj.class().name()))
|
||||
})
|
||||
}
|
||||
@@ -82,7 +84,7 @@ pub(crate) fn to_op_float(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<Op
|
||||
let v = if let Some(float) = obj.payload_if_subclass::<PyFloat>(vm) {
|
||||
Some(float.value)
|
||||
} else if let Some(int) = obj.payload_if_subclass::<PyInt>(vm) {
|
||||
Some(int::to_float(int.as_bigint(), vm)?)
|
||||
Some(try_bigint_to_f64(int.as_bigint(), vm)?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -111,7 +113,7 @@ fn inner_mod(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
.ok_or_else(|| vm.new_zero_division_error("float mod by zero".to_owned()))
|
||||
}
|
||||
|
||||
pub fn try_bigint(value: f64, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
pub fn try_to_bigint(value: f64, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
match value.to_bigint() {
|
||||
Some(int) => Ok(int),
|
||||
None => {
|
||||
@@ -171,7 +173,7 @@ impl SlotConstructor for PyFloat {
|
||||
val
|
||||
};
|
||||
|
||||
if let Some(f) = try_float_opt(&val, vm)? {
|
||||
if let Some(f) = val.try_to_f64(vm)? {
|
||||
f
|
||||
} else if let Some(s) = val.payload_if_subclass::<PyStr>(vm) {
|
||||
float_ops::parse_str(s.as_str().trim()).ok_or_else(|| {
|
||||
@@ -379,17 +381,17 @@ impl PyFloat {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn trunc(&self, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
try_bigint(self.value, vm)
|
||||
try_to_bigint(self.value, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn floor(&self, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
try_bigint(self.value.floor(), vm)
|
||||
try_to_bigint(self.value.floor(), vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn ceil(&self, vm: &VirtualMachine) -> PyResult<BigInt> {
|
||||
try_bigint(self.value.ceil(), vm)
|
||||
try_to_bigint(self.value.ceil(), vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
@@ -417,7 +419,7 @@ impl PyFloat {
|
||||
} else {
|
||||
self.value.round()
|
||||
};
|
||||
let int = try_bigint(value, vm)?;
|
||||
let int = try_to_bigint(value, vm)?;
|
||||
vm.ctx.new_int(int)
|
||||
};
|
||||
Ok(value)
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use super::{float, IntoPyBool, PyByteArray, PyBytes, PyStr, PyStrRef, PyTypeRef};
|
||||
use crate::bytesinner::PyBytesInner;
|
||||
use crate::common::hash;
|
||||
use crate::format::FormatSpec;
|
||||
use crate::function::{OptionalArg, OptionalOption};
|
||||
use crate::slots::{Comparable, Hashable, PyComparisonOp, SlotConstructor};
|
||||
use crate::VirtualMachine;
|
||||
use crate::{bytesinner::PyBytesInner, byteslike::try_bytes_like};
|
||||
use crate::{
|
||||
try_value_from_borrowed_object, IdProtocol, IntoPyObject, IntoPyResult, PyArithmaticValue,
|
||||
PyClassImpl, PyComparisonValue, PyContext, PyObjectRef, PyRef, PyResult, PyValue,
|
||||
@@ -142,8 +142,8 @@ pub fn bigint_unsigned_mask(v: &BigInt) -> u32 {
|
||||
|
||||
fn inner_pow(int1: &BigInt, int2: &BigInt, vm: &VirtualMachine) -> PyResult {
|
||||
if int2.is_negative() {
|
||||
let v1 = to_float(int1, vm)?;
|
||||
let v2 = to_float(int2, vm)?;
|
||||
let v1 = try_to_float(int1, vm)?;
|
||||
let v2 = try_to_float(int2, vm)?;
|
||||
float::float_pow(v1, v2, vm).into_pyresult(vm)
|
||||
} else {
|
||||
Ok(if let Some(v2) = int2.to_u64() {
|
||||
@@ -541,7 +541,7 @@ impl PyInt {
|
||||
|
||||
#[pymethod(magic)]
|
||||
fn float(&self, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
to_float(&self.value, vm)
|
||||
try_to_float(&self.value, vm)
|
||||
}
|
||||
|
||||
#[pymethod(magic)]
|
||||
@@ -914,7 +914,7 @@ pub(crate) fn get_value(obj: &PyObjectRef) -> &BigInt {
|
||||
&obj.payload::<PyInt>().unwrap().value
|
||||
}
|
||||
|
||||
pub fn to_float(int: &BigInt, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
pub fn try_to_float(int: &BigInt, vm: &VirtualMachine) -> PyResult<f64> {
|
||||
i2f(int).ok_or_else(|| vm.new_overflow_error("int too large to convert to float".to_owned()))
|
||||
}
|
||||
// num-bigint now returns Some(inf) for to_f64() in some cases, so just keep that the same for now
|
||||
@@ -939,7 +939,7 @@ pub(crate) fn try_int(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<BigInt
|
||||
if let Some(s) = obj.downcast_ref::<PyStr>() {
|
||||
return try_convert(obj, s.as_str().as_bytes(), vm);
|
||||
}
|
||||
if let Ok(r) = try_bytes_like(vm, obj, |x| try_convert(obj, x, vm)) {
|
||||
if let Ok(r) = obj.try_bytes_like(vm, |x| try_convert(obj, x, vm)) {
|
||||
return r;
|
||||
}
|
||||
// strict `int` check
|
||||
|
||||
@@ -80,5 +80,8 @@ pub(crate) mod zip;
|
||||
pub use zip::PyZip;
|
||||
pub(crate) mod genericalias;
|
||||
|
||||
pub use float::try_to_bigint as try_f64_to_bigint;
|
||||
pub use int::try_to_float as try_bigint_to_f64;
|
||||
|
||||
mod make_module;
|
||||
pub use make_module::{ascii, make_module, print};
|
||||
|
||||
@@ -29,8 +29,14 @@ impl TryFromBorrowedObject for bool {
|
||||
}
|
||||
}
|
||||
|
||||
impl PyObjectRef {
|
||||
pub fn try_into_bool(self, vm: &VirtualMachine) -> PyResult<bool> {
|
||||
boolval(vm, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert Python bool into Rust bool.
|
||||
pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
|
||||
pub(crate) fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
|
||||
if obj.is(&vm.ctx.true_value) {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ use crate::builtins::bytes::{PyBytes, PyBytesRef};
|
||||
use crate::builtins::int::{PyInt, PyIntRef};
|
||||
use crate::builtins::pystr::{self, PyStr, PyStrRef};
|
||||
use crate::builtins::PyTypeRef;
|
||||
use crate::byteslike::try_bytes_like;
|
||||
use crate::cformat::CFormatBytes;
|
||||
use crate::function::{OptionalArg, OptionalOption};
|
||||
use crate::sliceable::PySliceableSequence;
|
||||
@@ -320,10 +319,9 @@ impl PyBytesInner {
|
||||
// TODO: bytes can compare with any object implemented buffer protocol
|
||||
// but not memoryview, and not equal if compare with unicode str(PyStr)
|
||||
PyComparisonValue::from_option(
|
||||
try_bytes_like(vm, other, |other| {
|
||||
op.eval_ord(self.elements.as_slice().cmp(other))
|
||||
})
|
||||
.ok(),
|
||||
other
|
||||
.try_bytes_like(vm, |other| op.eval_ord(self.elements.as_slice().cmp(other)))
|
||||
.ok(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1238,7 +1236,7 @@ pub const fn is_py_ascii_whitespace(b: u8) -> bool {
|
||||
}
|
||||
|
||||
pub fn bytes_from_object(vm: &VirtualMachine, obj: &PyObjectRef) -> PyResult<Vec<u8>> {
|
||||
if let Ok(elements) = try_bytes_like(vm, obj, |bytes| bytes.to_vec()) {
|
||||
if let Ok(elements) = obj.try_bytes_like(vm, |bytes| bytes.to_vec()) {
|
||||
return Ok(elements);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,27 +77,31 @@ impl TryFromBorrowedObject for ArgBytesLike {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn try_bytes_like<R>(
|
||||
vm: &VirtualMachine,
|
||||
obj: &PyObjectRef,
|
||||
f: impl FnOnce(&[u8]) -> R,
|
||||
) -> PyResult<R> {
|
||||
let buffer = PyBuffer::try_from_borrowed_object(vm, obj)?;
|
||||
buffer.as_contiguous().map(|x| f(&*x)).ok_or_else(|| {
|
||||
vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned())
|
||||
})
|
||||
}
|
||||
impl PyObjectRef {
|
||||
pub fn try_bytes_like<R>(
|
||||
&self,
|
||||
vm: &VirtualMachine,
|
||||
f: impl FnOnce(&[u8]) -> R,
|
||||
) -> PyResult<R> {
|
||||
let buffer = PyBuffer::try_from_borrowed_object(vm, self)?;
|
||||
buffer.as_contiguous().map(|x| f(&*x)).ok_or_else(|| {
|
||||
vm.new_type_error("non-contiguous buffer is not a bytes-like object".to_owned())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_rw_bytes_like<R>(
|
||||
vm: &VirtualMachine,
|
||||
obj: &PyObjectRef,
|
||||
f: impl FnOnce(&mut [u8]) -> R,
|
||||
) -> PyResult<R> {
|
||||
let buffer = PyBuffer::try_from_borrowed_object(vm, obj)?;
|
||||
buffer
|
||||
.as_contiguous_mut()
|
||||
.map(|mut x| f(&mut *x))
|
||||
.ok_or_else(|| vm.new_type_error("buffer is not a read-write bytes-like object".to_owned()))
|
||||
pub fn try_rw_bytes_like<R>(
|
||||
&self,
|
||||
vm: &VirtualMachine,
|
||||
f: impl FnOnce(&mut [u8]) -> R,
|
||||
) -> PyResult<R> {
|
||||
let buffer = PyBuffer::try_from_borrowed_object(vm, self)?;
|
||||
buffer
|
||||
.as_contiguous_mut()
|
||||
.map(|mut x| f(&mut *x))
|
||||
.ok_or_else(|| {
|
||||
vm.new_type_error("buffer is not a read-write bytes-like object".to_owned())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ArgMemoryBuffer {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
//! Implementation of Printf-Style string formatting
|
||||
//! [https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting]
|
||||
|
||||
use crate::buffer::PyBuffer;
|
||||
/// Implementation of Printf-Style string formatting
|
||||
/// [https://docs.python.org/3/library/stdtypes.html#printf-style-string-formatting]
|
||||
use crate::builtins::float::{try_bigint, IntoPyFloat, PyFloat};
|
||||
use crate::builtins::int::{self, PyInt};
|
||||
use crate::builtins::pystr::PyStr;
|
||||
use crate::builtins::{tuple, PyBytes};
|
||||
use crate::builtins::{
|
||||
float::IntoPyFloat, int, try_f64_to_bigint, tuple, PyBytes, PyFloat, PyInt, PyStr,
|
||||
};
|
||||
use crate::common::float_ops;
|
||||
use crate::vm::VirtualMachine;
|
||||
use crate::{
|
||||
ItemProtocol, PyObjectRef, PyResult, TryFromBorrowedObject, TryFromObject, TypeProtocol,
|
||||
VirtualMachine,
|
||||
};
|
||||
use itertools::Itertools;
|
||||
use num_bigint::{BigInt, Sign};
|
||||
@@ -403,7 +403,7 @@ impl CFormatSpec {
|
||||
}
|
||||
ref f @ PyFloat => {
|
||||
Ok(self
|
||||
.format_number(&try_bigint(f.to_f64(), vm)?)
|
||||
.format_number(&try_f64_to_bigint(f.to_f64(), vm)?)
|
||||
.into_bytes())
|
||||
}
|
||||
obj => {
|
||||
@@ -477,7 +477,7 @@ impl CFormatSpec {
|
||||
Ok(self.format_number(i.as_bigint()))
|
||||
}
|
||||
ref f @ PyFloat => {
|
||||
Ok(self.format_number(&try_bigint(f.to_f64(), vm)?))
|
||||
Ok(self.format_number(&try_f64_to_bigint(f.to_f64(), vm)?))
|
||||
}
|
||||
obj => {
|
||||
if let Some(method) = vm.get_method(obj.clone(), "__int__") {
|
||||
|
||||
@@ -16,7 +16,7 @@ mod array {
|
||||
use crate::builtins::pytype::PyTypeRef;
|
||||
use crate::builtins::slice::PySliceRef;
|
||||
use crate::builtins::{PyByteArray, PyBytes, PyBytesRef, PyIntRef};
|
||||
use crate::byteslike::{try_bytes_like, ArgBytesLike};
|
||||
use crate::byteslike::ArgBytesLike;
|
||||
use crate::common::borrow::{BorrowedValue, BorrowedValueMut};
|
||||
use crate::common::lock::{
|
||||
PyMappedRwLockReadGuard, PyMappedRwLockWriteGuard, PyRwLock, PyRwLockReadGuard,
|
||||
@@ -657,13 +657,13 @@ mod array {
|
||||
)));
|
||||
}
|
||||
} else if init.payload_is::<PyBytes>() || init.payload_is::<PyByteArray>() {
|
||||
try_bytes_like(vm, &init, |x| array.frombytes(x))?;
|
||||
init.try_bytes_like(vm, |x| array.frombytes(x))?;
|
||||
} else if let Ok(iter) = PyIterable::try_from_object(vm, init.clone()) {
|
||||
for obj in iter.iter(vm)? {
|
||||
array.push(obj?, vm)?;
|
||||
}
|
||||
} else {
|
||||
try_bytes_like(vm, &init, |x| array.frombytes(x))?;
|
||||
init.try_bytes_like(vm, |x| array.frombytes(x))?;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,9 @@ use num_bigint::BigInt;
|
||||
use num_traits::{One, Signed, Zero};
|
||||
use puruspe::{erf, erfc, gamma, ln_gamma};
|
||||
|
||||
use crate::builtins::float::{self, IntoPyFloat, PyFloatRef};
|
||||
use crate::builtins::int::{self, PyInt, PyIntRef};
|
||||
use crate::builtins::{
|
||||
float::IntoPyFloat, try_bigint_to_f64, try_f64_to_bigint, PyFloatRef, PyInt, PyIntRef,
|
||||
};
|
||||
use crate::function::{Args, OptionalArg};
|
||||
use crate::utils::Either;
|
||||
use crate::vm::VirtualMachine;
|
||||
@@ -359,8 +360,8 @@ fn math_trunc(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let result_or_err = try_magic_method("__ceil__", vm, &value);
|
||||
if result_or_err.is_err() {
|
||||
if let Ok(Some(v)) = float::try_float_opt(&value, vm) {
|
||||
let v = float::try_bigint(v.ceil(), vm)?;
|
||||
if let Ok(Some(v)) = value.try_to_f64(vm) {
|
||||
let v = try_f64_to_bigint(v.ceil(), vm)?;
|
||||
return Ok(vm.ctx.new_int(v));
|
||||
}
|
||||
}
|
||||
@@ -376,8 +377,8 @@ fn math_ceil(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
fn math_floor(value: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
||||
let result_or_err = try_magic_method("__floor__", vm, &value);
|
||||
if result_or_err.is_err() {
|
||||
if let Ok(Some(v)) = float::try_float_opt(&value, vm) {
|
||||
let v = float::try_bigint(v.floor(), vm)?;
|
||||
if let Ok(Some(v)) = value.try_to_f64(vm) {
|
||||
let v = try_f64_to_bigint(v.floor(), vm)?;
|
||||
return Ok(vm.ctx.new_int(v));
|
||||
}
|
||||
}
|
||||
@@ -401,14 +402,14 @@ fn math_ldexp(
|
||||
) -> PyResult<f64> {
|
||||
let value = match value {
|
||||
Either::A(f) => f.to_f64(),
|
||||
Either::B(z) => int::to_float(z.as_bigint(), vm)?,
|
||||
Either::B(z) => try_bigint_to_f64(z.as_bigint(), vm)?,
|
||||
};
|
||||
|
||||
if value == 0_f64 || !value.is_finite() {
|
||||
// NaNs, zeros and infinities are returned unchanged
|
||||
Ok(value)
|
||||
} else {
|
||||
let result = value * (2_f64).powf(int::to_float(i.as_bigint(), vm)?);
|
||||
let result = value * (2_f64).powf(try_bigint_to_f64(i.as_bigint(), vm)?);
|
||||
result_or_overflow(value, result, vm)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user