Convert int to Any payload

This commit is contained in:
Joey committed 2019-03-06 19:25:54 -08:00
1 parent d7f8961a12
commit ecc92ffe33
6 files changed
+91 -75

No files matched your search

+14 -9
View File
@@ -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.
@@ -286,10 +287,14 @@ impl Frame {
let mut out: Vec<Option<BigInt>> = elements
.into_iter()
.map(|x| match x.payload {
PyObjectPayload::Integer { ref value } => Some(value.clone()),
PyObjectPayload::None => None,
_ => panic!("Expect Int or None as BUILD_SLICE arguments, got {:?}", x),
.map(|x| {
if x.is(&vm.ctx.none()) {
None
} else if let Some(i) = x.payload::<PyInt>() {
Some(i.value.clone())
} else {
panic!("Expect Int or None as BUILD_SLICE arguments")
}
})
.collect();
+15 -14
View File
@@ -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,16 +27,18 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
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(),
PyObjectPayload::None { .. } => false,
_ => {
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
@@ -67,11 +72,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> {
+33 -25
View File
@@ -1,29 +1,39 @@
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::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,
}
impl PyInt {
pub fn new<T: ToBigInt>(i: T) -> Self {
PyInt {
value: i.to_bigint().unwrap(),
}
}
}
// TODO: macro to impl for all primitive ints
impl PyObjectPayload2 for PyInt {
fn required_type(ctx: &PyContext) -> PyObjectRef {
ctx.int_type()
}
}
impl IntoPyObject for usize {
fn into_pyobject(self, ctx: &PyContext) -> PyResult {
@@ -77,13 +87,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 +123,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 {
+15 -12
View File
@@ -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,
+6 -5
View File
@@ -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 {
+8 -10
View File
@@ -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;
@@ -236,12 +236,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(),
);
@@ -474,8 +476,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(),
)
@@ -1445,9 +1447,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>>,
},
@@ -1524,7 +1523,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"),