Skip to content

Convert more objects to Any payload #586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion vm/src/obj/objbool.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use super::objfloat::PyFloat;
use super::objstr::PyString;
use super::objtype;
use crate::pyobject::{
Expand All @@ -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,
Expand Down
49 changes: 37 additions & 12 deletions vm/src/obj/objbytearray.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down Expand Up @@ -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(),
))
Expand Down Expand Up @@ -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 {
Expand Down
49 changes: 31 additions & 18 deletions vm/src/obj/objbytes.rs
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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(),
))
Expand Down Expand Up @@ -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 {
Expand Down
34 changes: 27 additions & 7 deletions vm/src/obj/objfloat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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> {
Expand Down
72 changes: 40 additions & 32 deletions vm/src/obj/objiter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 {
Expand Down
Loading