Merge pull request #586 from RustPython/joey/float-range-any-payload

Convert more objects to `Any` payload
This commit is contained in:
Adam
2019-03-04 14:40:06 +00:00
committed by GitHub
8 changed files with 185 additions and 115 deletions

View File

@@ -1,3 +1,4 @@
use super::objfloat::PyFloat;
use super::objstr::PyString;
use super::objtype;
use crate::pyobject::{
@@ -16,9 +17,11 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
if let Some(s) = obj.payload::<PyString>() {
return Ok(!s.value.is_empty());
}
if let Some(value) = obj.payload::<PyFloat>() {
return Ok(*value != PyFloat::from(0.0));
}
let result = match obj.payload {
PyObjectPayload::Integer { ref value } => !value.is_zero(),
PyObjectPayload::Float { value } => value != 0.0,
PyObjectPayload::Sequence { ref elements } => !elements.borrow().is_empty(),
PyObjectPayload::Dict { ref elements } => !elements.borrow().is_empty(),
PyObjectPayload::None { .. } => false,

View File

@@ -1,17 +1,47 @@
//! Implementation of the python bytearray object.
use std::cell::RefCell;
use std::ops::{Deref, DerefMut};
use crate::pyobject::{PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyResult, TypeProtocol};
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
TypeProtocol,
};
use super::objint;
use super::objbytes::get_mut_value;
use super::objbytes::get_value;
use super::objtype;
use crate::vm::VirtualMachine;
use num_traits::ToPrimitive;
#[derive(Debug)]
pub struct PyByteArray {
// TODO: shouldn't be public
pub value: RefCell<Vec<u8>>,
}
impl PyByteArray {
pub fn new(data: Vec<u8>) -> Self {
PyByteArray {
value: RefCell::new(data),
}
}
}
impl PyObjectPayload2 for PyByteArray {
fn required_type(ctx: &PyContext) -> PyObjectRef {
ctx.bytearray_type()
}
}
pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a {
obj.payload::<PyByteArray>().unwrap().value.borrow()
}
pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<u8>> + 'a {
obj.payload::<PyByteArray>().unwrap().value.borrow_mut()
}
// Binary data support
/// Fill bytearray class methods dictionary.
@@ -143,8 +173,8 @@ fn bytearray_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
vec![]
};
Ok(PyObject::new(
PyObjectPayload::Bytes {
value: RefCell::new(value),
PyObjectPayload::AnyRustValue {
value: Box::new(PyByteArray::new(value)),
},
cls.clone(),
))
@@ -290,13 +320,8 @@ fn bytearray_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
fn bytearray_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(zelf, Some(vm.ctx.bytearray_type()))]);
match zelf.payload {
PyObjectPayload::Bytes { ref value } => {
value.borrow_mut().clear();
Ok(vm.get_none())
}
_ => panic!("Bytearray has incorrect payload."),
}
get_mut_value(zelf).clear();
Ok(vm.get_none())
}
fn bytearray_pop(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

View File

@@ -1,16 +1,41 @@
use std::cell::{Cell, RefCell};
use std::cell::Cell;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::ops::DerefMut;
use super::objint;
use super::objtype;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_traits::ToPrimitive;
#[derive(Debug)]
pub struct PyBytes {
value: Vec<u8>,
}
impl PyBytes {
pub fn new(data: Vec<u8>) -> Self {
PyBytes { value: data }
}
}
impl Deref for PyBytes {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.value
}
}
impl PyObjectPayload2 for PyBytes {
fn required_type(ctx: &PyContext) -> PyObjectRef {
ctx.bytes_type()
}
}
// Binary data support
// Fill bytes class methods:
@@ -71,8 +96,8 @@ fn bytes_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
};
Ok(PyObject::new(
PyObjectPayload::Bytes {
value: RefCell::new(value),
PyObjectPayload::AnyRustValue {
value: Box::new(PyBytes::new(value)),
},
cls.clone(),
))
@@ -170,19 +195,7 @@ fn bytes_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
}
pub fn get_value<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<u8>> + 'a {
if let PyObjectPayload::Bytes { ref value } = obj.payload {
value.borrow()
} else {
panic!("Inner error getting bytearray {:?}", obj);
}
}
pub fn get_mut_value<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<u8>> + 'a {
if let PyObjectPayload::Bytes { ref value } = obj.payload {
value.borrow_mut()
} else {
panic!("Inner error getting bytearray {:?}", obj);
}
&obj.payload::<PyBytes>().unwrap().value
}
fn bytes_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

View File

@@ -3,12 +3,30 @@ use super::objint;
use super::objstr;
use super::objtype;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_bigint::ToBigInt;
use num_traits::ToPrimitive;
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct PyFloat {
value: f64,
}
impl PyObjectPayload2 for PyFloat {
fn required_type(ctx: &PyContext) -> PyObjectRef {
ctx.float_type()
}
}
impl From<f64> for PyFloat {
fn from(value: f64) -> Self {
PyFloat { value }
}
}
fn float_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(float, Some(vm.ctx.float_type()))]);
let v = get_value(float);
@@ -50,16 +68,18 @@ fn float_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let type_name = objtype::get_type_name(&arg.typ());
return Err(vm.new_type_error(format!("can't convert {} to float", type_name)));
};
Ok(PyObject::new(PyObjectPayload::Float { value }, cls.clone()))
Ok(PyObject::new(
PyObjectPayload::AnyRustValue {
value: Box::new(PyFloat { value }),
},
cls.clone(),
))
}
// Retrieve inner float value:
pub fn get_value(obj: &PyObjectRef) -> f64 {
if let PyObjectPayload::Float { value } = &obj.payload {
*value
} else {
panic!("Inner error getting float: {}", obj);
}
obj.payload::<PyFloat>().unwrap().value
}
pub fn make_float(vm: &mut VirtualMachine, obj: &PyObjectRef) -> PyResult<f64> {

View File

@@ -2,13 +2,16 @@
* Various types to support iteration.
*/
use super::objbool;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
};
use crate::vm::VirtualMachine;
// use super::objstr;
use super::objtype; // Required for arg_check! to use isinstance
use super::objbool;
use super::objbytearray::PyByteArray;
use super::objbytes::PyBytes;
use super::objrange::PyRange;
use super::objtype;
/*
* This helper function is called at multiple places. First, it is called
@@ -129,38 +132,43 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
iterated_obj: ref iterated_obj_ref,
} = iter.payload
{
match iterated_obj_ref.payload {
PyObjectPayload::Sequence { ref elements } => {
if position.get() < elements.borrow().len() {
let obj_ref = elements.borrow()[position.get()].clone();
position.set(position.get() + 1);
Ok(obj_ref)
} else {
Err(new_stop_iteration(vm))
}
if let Some(range) = iterated_obj_ref.payload::<PyRange>() {
if let Some(int) = range.get(position.get()) {
position.set(position.get() + 1);
Ok(vm.ctx.new_int(int))
} else {
Err(new_stop_iteration(vm))
}
PyObjectPayload::Range { ref range } => {
if let Some(int) = range.get(position.get()) {
position.set(position.get() + 1);
Ok(vm.ctx.new_int(int))
} else {
Err(new_stop_iteration(vm))
}
} else if let Some(bytes) = iterated_obj_ref.payload::<PyBytes>() {
if position.get() < bytes.len() {
let obj_ref = vm.ctx.new_int(bytes[position.get()]);
position.set(position.get() + 1);
Ok(obj_ref)
} else {
Err(new_stop_iteration(vm))
}
PyObjectPayload::Bytes { ref value } => {
if position.get() < value.borrow().len() {
let obj_ref = vm.ctx.new_int(value.borrow()[position.get()]);
position.set(position.get() + 1);
Ok(obj_ref)
} else {
Err(new_stop_iteration(vm))
}
} else if let Some(bytes) = iterated_obj_ref.payload::<PyByteArray>() {
if position.get() < bytes.value.borrow().len() {
let obj_ref = vm.ctx.new_int(bytes.value.borrow()[position.get()]);
position.set(position.get() + 1);
Ok(obj_ref)
} else {
Err(new_stop_iteration(vm))
}
_ => {
panic!("NOT IMPL");
} else {
match iterated_obj_ref.payload {
PyObjectPayload::Sequence { ref elements } => {
if position.get() < elements.borrow().len() {
let obj_ref = elements.borrow()[position.get()].clone();
position.set(position.get() + 1);
Ok(obj_ref)
} else {
Err(new_stop_iteration(vm))
}
}
_ => {
panic!("NOT IMPL");
}
}
}
} else {

View File

@@ -4,7 +4,8 @@ use std::ops::Mul;
use super::objint;
use super::objtype;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectRef, PyResult, TypeProtocol,
PyContext, PyFuncArgs, PyObject, PyObjectPayload, PyObjectPayload2, PyObjectRef, PyResult,
TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_bigint::{BigInt, Sign};
@@ -12,7 +13,7 @@ use num_integer::Integer;
use num_traits::{One, Signed, ToPrimitive, Zero};
#[derive(Debug, Clone)]
pub struct RangeType {
pub struct PyRange {
// Unfortunately Rust's built in range type doesn't support things like indexing
// or ranges where start > end so we need to roll our own.
pub start: BigInt,
@@ -20,7 +21,13 @@ pub struct RangeType {
pub step: BigInt,
}
impl RangeType {
impl PyObjectPayload2 for PyRange {
fn required_type(ctx: &PyContext) -> PyObjectRef {
ctx.range_type()
}
}
impl PyRange {
#[inline]
pub fn try_len(&self) -> Option<usize> {
match self.step.sign() {
@@ -116,12 +123,12 @@ impl RangeType {
};
match self.step.sign() {
Sign::Plus => RangeType {
Sign::Plus => PyRange {
start,
end: &self.start - 1,
step: -&self.step,
},
Sign::Minus => RangeType {
Sign::Minus => PyRange {
start,
end: &self.start + 1,
step: -&self.step,
@@ -139,12 +146,8 @@ impl RangeType {
}
}
pub fn get_value(obj: &PyObjectRef) -> RangeType {
if let PyObjectPayload::Range { range } = &obj.payload {
range.clone()
} else {
panic!("Inner error getting range {:?}", obj);
}
pub fn get_value(obj: &PyObjectRef) -> PyRange {
obj.payload::<PyRange>().unwrap().clone()
}
pub fn init(context: &PyContext) {
@@ -223,8 +226,8 @@ fn range_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Err(vm.new_value_error("range with 0 step size".to_string()))
} else {
Ok(PyObject::new(
PyObjectPayload::Range {
range: RangeType { start, end, step },
PyObjectPayload::AnyRustValue {
value: Box::new(PyRange { start, end, step }),
},
cls.clone(),
))
@@ -251,7 +254,12 @@ fn range_reversed(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(PyObject::new(
PyObjectPayload::Iterator {
position: Cell::new(0),
iterated_obj: PyObject::new(PyObjectPayload::Range { range }, vm.ctx.range_type()),
iterated_obj: PyObject::new(
PyObjectPayload::AnyRustValue {
value: Box::new(range),
},
vm.ctx.range_type(),
),
},
vm.ctx.iter_type(),
))
@@ -316,12 +324,12 @@ fn range_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
};
Ok(PyObject::new(
PyObjectPayload::Range {
range: RangeType {
PyObjectPayload::AnyRustValue {
value: Box::new(PyRange {
start: new_start,
end: new_end,
step: new_step,
},
}),
},
vm.ctx.range_type(),
))