mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-02 19:39:49 +09:00
Merge pull request #617 from RustPython/joey/int-any
Convert int to Any payload
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
extern crate rustpython_parser;
|
||||
|
||||
use self::rustpython_parser::ast;
|
||||
use std::cell::RefCell;
|
||||
use std::fmt;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
use num_bigint::BigInt;
|
||||
|
||||
use rustpython_parser::ast;
|
||||
|
||||
use crate::builtins;
|
||||
use crate::bytecode;
|
||||
@@ -12,6 +14,7 @@ use crate::obj::objbool;
|
||||
use crate::obj::objcode;
|
||||
use crate::obj::objdict;
|
||||
use crate::obj::objdict::PyDict;
|
||||
use crate::obj::objint::PyInt;
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist;
|
||||
use crate::obj::objstr;
|
||||
@@ -21,8 +24,6 @@ use crate::pyobject::{
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::BigInt;
|
||||
use std::rc::Rc;
|
||||
|
||||
/*
|
||||
* So a scope is a linked list of scopes.
|
||||
@@ -287,12 +288,12 @@ impl Frame {
|
||||
let mut out: Vec<Option<BigInt>> = elements
|
||||
.into_iter()
|
||||
.map(|x| {
|
||||
if x.is(&vm.get_none()) {
|
||||
if x.is(&vm.ctx.none()) {
|
||||
None
|
||||
} else if let PyObjectPayload::Integer { ref value } = x.payload {
|
||||
Some(value.clone())
|
||||
} else if let Some(i) = x.payload::<PyInt>() {
|
||||
Some(i.value.clone())
|
||||
} else {
|
||||
panic!("Expect Int or None as BUILD_SLICE arguments, got {:?}", x);
|
||||
panic!("Expect Int or None as BUILD_SLICE arguments")
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
use super::objdict::PyDict;
|
||||
use super::objfloat::PyFloat;
|
||||
use super::objstr::PyString;
|
||||
use super::objtype;
|
||||
use num_traits::Zero;
|
||||
|
||||
use crate::pyobject::{
|
||||
IntoPyObject, PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_traits::Zero;
|
||||
|
||||
use super::objdict::PyDict;
|
||||
use super::objfloat::PyFloat;
|
||||
use super::objint::PyInt;
|
||||
use super::objstr::PyString;
|
||||
use super::objtype;
|
||||
|
||||
impl IntoPyObject for bool {
|
||||
fn into_pyobject(self, ctx: &PyContext) -> PyResult {
|
||||
@@ -24,15 +27,17 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
|
||||
if let Some(dict) = obj.payload::<PyDict>() {
|
||||
return Ok(!dict.entries.borrow().is_empty());
|
||||
}
|
||||
if let Some(i) = obj.payload::<PyInt>() {
|
||||
return Ok(!i.value.is_zero());
|
||||
}
|
||||
let result = match obj.payload {
|
||||
PyObjectPayload::Integer { ref value } => !value.is_zero(),
|
||||
PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(),
|
||||
_ => {
|
||||
if let Ok(f) = vm.get_method(obj.clone(), "__bool__") {
|
||||
let bool_res = vm.invoke(f, PyFuncArgs::default())?;
|
||||
match bool_res.payload {
|
||||
PyObjectPayload::Integer { ref value } => !value.is_zero(),
|
||||
_ => return Err(vm.new_type_error(String::from("TypeError"))),
|
||||
match bool_res.payload::<PyInt>() {
|
||||
Some(i) => !i.value.is_zero(),
|
||||
None => return Err(vm.new_type_error(String::from("TypeError"))),
|
||||
}
|
||||
} else {
|
||||
true
|
||||
@@ -66,11 +71,7 @@ pub fn not(vm: &mut VirtualMachine, obj: &PyObjectRef) -> PyResult {
|
||||
|
||||
// Retrieve inner int value:
|
||||
pub fn get_value(obj: &PyObjectRef) -> bool {
|
||||
if let PyObjectPayload::Integer { value } = &obj.payload {
|
||||
!value.is_zero()
|
||||
} else {
|
||||
panic!("Inner error getting inner boolean");
|
||||
}
|
||||
!obj.payload::<PyInt>().unwrap().value.is_zero()
|
||||
}
|
||||
|
||||
fn bool_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> Result<PyObjectRef, PyObjectRef> {
|
||||
|
||||
@@ -1,56 +1,86 @@
|
||||
use super::objfloat;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
use crate::format::FormatSpec;
|
||||
use crate::pyobject::{
|
||||
FromPyObjectRef, IntoPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef,
|
||||
PyResult, TryFromObject, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
use num_bigint::{BigInt, ToBigInt};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{Pow, Signed, ToPrimitive, Zero};
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
// This proxy allows for easy switching between types.
|
||||
type IntType = BigInt;
|
||||
use crate::format::FormatSpec;
|
||||
use crate::function::PyRef;
|
||||
use crate::pyobject::{
|
||||
FromPyObjectRef, IntoPyObject, PyContext, PyFuncArgs, PyObject, PyObjectPayload,
|
||||
PyObjectPayload2, PyObjectRef, PyResult, TryFromObject, TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyInt = BigInt;
|
||||
use super::objfloat;
|
||||
use super::objstr;
|
||||
use super::objtype;
|
||||
|
||||
impl IntoPyObject for PyInt {
|
||||
fn into_pyobject(self, ctx: &PyContext) -> PyResult {
|
||||
Ok(ctx.new_int(self))
|
||||
}
|
||||
#[derive(Debug)]
|
||||
pub struct PyInt {
|
||||
// TODO: shouldn't be public
|
||||
pub value: BigInt,
|
||||
}
|
||||
|
||||
// TODO: macro to impl for all primitive ints
|
||||
pub type PyIntRef = PyRef<PyInt>;
|
||||
|
||||
impl IntoPyObject for usize {
|
||||
fn into_pyobject(self, ctx: &PyContext) -> PyResult {
|
||||
Ok(ctx.new_int(self))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromObject for usize {
|
||||
fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
// FIXME: don't use get_value
|
||||
match get_value(&obj).to_usize() {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(vm.new_overflow_error("Int value cannot fit into Rust usize".to_string())),
|
||||
impl PyInt {
|
||||
pub fn new<T: ToBigInt>(i: T) -> Self {
|
||||
PyInt {
|
||||
value: i.to_bigint().unwrap(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromObject for isize {
|
||||
fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
// FIXME: don't use get_value
|
||||
match get_value(&obj).to_isize() {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(vm.new_overflow_error("Int value cannot fit into Rust isize".to_string())),
|
||||
}
|
||||
impl PyObjectPayload2 for PyInt {
|
||||
fn required_type(ctx: &PyContext) -> PyObjectRef {
|
||||
ctx.int_type()
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_into_pyobject_int {
|
||||
($($t:ty)*) => {$(
|
||||
impl IntoPyObject for $t {
|
||||
fn into_pyobject(self, ctx: &PyContext) -> PyResult {
|
||||
Ok(ctx.new_int(self))
|
||||
}
|
||||
}
|
||||
)*};
|
||||
}
|
||||
|
||||
impl_into_pyobject_int!(isize i8 i16 i32 i64 usize u8 u16 u32 u64) ;
|
||||
|
||||
macro_rules! impl_try_from_object_int {
|
||||
($(($t:ty, $to_prim:ident),)*) => {$(
|
||||
impl TryFromObject for $t {
|
||||
fn try_from_object(vm: &mut VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
|
||||
match PyRef::<PyInt>::try_from_object(vm, obj)?.value.$to_prim() {
|
||||
Some(value) => Ok(value),
|
||||
None => Err(
|
||||
vm.new_overflow_error(concat!(
|
||||
"Int value cannot fit into Rust ",
|
||||
stringify!($t)
|
||||
).to_string())
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
)*};
|
||||
}
|
||||
|
||||
impl_try_from_object_int!(
|
||||
(isize, to_isize),
|
||||
(i8, to_i8),
|
||||
(i16, to_i16),
|
||||
(i32, to_i32),
|
||||
(i64, to_i64),
|
||||
(usize, to_usize),
|
||||
(u8, to_u8),
|
||||
(u16, to_u16),
|
||||
(u32, to_u32),
|
||||
(u64, to_u64),
|
||||
);
|
||||
|
||||
fn int_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(int, Some(vm.ctx.int_type()))]);
|
||||
let v = get_value(int);
|
||||
@@ -77,13 +107,15 @@ fn int_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
None => Zero::zero(),
|
||||
};
|
||||
Ok(PyObject::new(
|
||||
PyObjectPayload::Integer { value: val },
|
||||
PyObjectPayload::AnyRustValue {
|
||||
value: Box::new(PyInt::new(val)),
|
||||
},
|
||||
cls.clone(),
|
||||
))
|
||||
}
|
||||
|
||||
// Casting function:
|
||||
pub fn to_int(vm: &mut VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<IntType> {
|
||||
pub fn to_int(vm: &mut VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult<BigInt> {
|
||||
let val = if objtype::isinstance(obj, &vm.ctx.int_type()) {
|
||||
get_value(obj)
|
||||
} else if objtype::isinstance(obj, &vm.ctx.float_type()) {
|
||||
@@ -111,12 +143,8 @@ pub fn to_int(vm: &mut VirtualMachine, obj: &PyObjectRef, base: u32) -> PyResult
|
||||
}
|
||||
|
||||
// Retrieve inner int value:
|
||||
pub fn get_value(obj: &PyObjectRef) -> IntType {
|
||||
if let PyObjectPayload::Integer { value } = &obj.payload {
|
||||
value.clone()
|
||||
} else {
|
||||
panic!("Inner error getting int {:?}", obj);
|
||||
}
|
||||
pub fn get_value(obj: &PyObjectRef) -> BigInt {
|
||||
obj.payload::<PyInt>().unwrap().value.clone()
|
||||
}
|
||||
|
||||
impl FromPyObjectRef for BigInt {
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
use std::cell::Cell;
|
||||
use std::ops::Mul;
|
||||
|
||||
use super::objint;
|
||||
use super::objtype;
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
|
||||
use crate::pyobject::{
|
||||
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
|
||||
TypeProtocol,
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::{BigInt, Sign};
|
||||
use num_integer::Integer;
|
||||
use num_traits::{One, Signed, ToPrimitive, Zero};
|
||||
|
||||
use super::objint::{self, PyInt};
|
||||
use super::objtype;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PyRange {
|
||||
@@ -284,14 +286,15 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
let range = get_value(zelf);
|
||||
|
||||
if let Some(i) = subscript.payload::<PyInt>() {
|
||||
return if let Some(int) = range.get(i.value.clone()) {
|
||||
Ok(vm.ctx.new_int(int))
|
||||
} else {
|
||||
Err(vm.new_index_error("range object index out of range".to_string()))
|
||||
};
|
||||
}
|
||||
|
||||
match subscript.payload {
|
||||
PyObjectPayload::Integer { ref value } => {
|
||||
if let Some(int) = range.get(value) {
|
||||
Ok(vm.ctx.new_int(int))
|
||||
} else {
|
||||
Err(vm.new_index_error("range object index out of range".to_string()))
|
||||
}
|
||||
}
|
||||
PyObjectPayload::Slice {
|
||||
ref start,
|
||||
ref stop,
|
||||
|
||||
@@ -3,7 +3,7 @@ use std::marker::Sized;
|
||||
use std::ops::{Deref, DerefMut, Range};
|
||||
|
||||
use super::objbool;
|
||||
use super::objint;
|
||||
use super::objint::{self, PyInt};
|
||||
use crate::pyobject::{IdProtocol, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol};
|
||||
use crate::vm::VirtualMachine;
|
||||
use num_bigint::BigInt;
|
||||
@@ -141,8 +141,8 @@ pub fn get_item(
|
||||
elements: &[PyObjectRef],
|
||||
subscript: PyObjectRef,
|
||||
) -> PyResult {
|
||||
match &subscript.payload {
|
||||
PyObjectPayload::Integer { value } => match value.to_i32() {
|
||||
if let Some(i) = subscript.payload::<PyInt>() {
|
||||
return match i.value.to_i32() {
|
||||
Some(value) => {
|
||||
if let Some(pos_index) = elements.to_vec().get_pos(value) {
|
||||
let obj = elements[pos_index].clone();
|
||||
@@ -154,8 +154,9 @@ pub fn get_item(
|
||||
None => {
|
||||
Err(vm.new_index_error("cannot fit 'int' into an index-sized integer".to_string()))
|
||||
}
|
||||
},
|
||||
|
||||
};
|
||||
}
|
||||
match &subscript.payload {
|
||||
PyObjectPayload::Slice { .. } => Ok(PyObject::new(
|
||||
match &sequence.payload {
|
||||
PyObjectPayload::Sequence { .. } => PyObjectPayload::Sequence {
|
||||
|
||||
@@ -26,7 +26,7 @@ use crate::obj::objfloat::{self, PyFloat};
|
||||
use crate::obj::objframe;
|
||||
use crate::obj::objfunction;
|
||||
use crate::obj::objgenerator;
|
||||
use crate::obj::objint;
|
||||
use crate::obj::objint::{self, PyInt};
|
||||
use crate::obj::objiter;
|
||||
use crate::obj::objlist;
|
||||
use crate::obj::objmap;
|
||||
@@ -247,12 +247,14 @@ impl PyContext {
|
||||
);
|
||||
|
||||
let true_value = PyObject::new(
|
||||
PyObjectPayload::Integer { value: One::one() },
|
||||
PyObjectPayload::AnyRustValue {
|
||||
value: Box::new(PyInt::new(BigInt::one())),
|
||||
},
|
||||
bool_type.clone(),
|
||||
);
|
||||
let false_value = PyObject::new(
|
||||
PyObjectPayload::Integer {
|
||||
value: Zero::zero(),
|
||||
PyObjectPayload::AnyRustValue {
|
||||
value: Box::new(PyInt::new(BigInt::zero())),
|
||||
},
|
||||
bool_type.clone(),
|
||||
);
|
||||
@@ -485,8 +487,8 @@ impl PyContext {
|
||||
|
||||
pub fn new_int<T: ToBigInt>(&self, i: T) -> PyObjectRef {
|
||||
PyObject::new(
|
||||
PyObjectPayload::Integer {
|
||||
value: i.to_bigint().unwrap(),
|
||||
PyObjectPayload::AnyRustValue {
|
||||
value: Box::new(PyInt::new(i)),
|
||||
},
|
||||
self.int_type(),
|
||||
)
|
||||
@@ -1465,9 +1467,6 @@ into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E));
|
||||
/// of rust data for a particular python object. Determine the python type
|
||||
/// by using for example the `.typ()` method on a python object.
|
||||
pub enum PyObjectPayload {
|
||||
Integer {
|
||||
value: BigInt,
|
||||
},
|
||||
Sequence {
|
||||
elements: RefCell<Vec<PyObjectRef>>,
|
||||
},
|
||||
@@ -1542,7 +1541,6 @@ pub enum PyObjectPayload {
|
||||
impl fmt::Debug for PyObjectPayload {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
PyObjectPayload::Integer { ref value } => write!(f, "int {}", value),
|
||||
PyObjectPayload::MemoryView { ref obj } => write!(f, "bytes/bytearray {:?}", obj),
|
||||
PyObjectPayload::Sequence { .. } => write!(f, "list or tuple"),
|
||||
PyObjectPayload::WeakRef { .. } => write!(f, "weakref"),
|
||||
|
||||
Reference in New Issue
Block a user