Unify object kinds tuple and list into sequence.

This commit is contained in:
Windel Bouwman committed 2018-11-03 12:26:31 +01:00
1 parent b6a88cc3d5
commit d72abebdd0
12 files changed
+72 -117

No files matched your search

+10 -20
View File
@@ -297,26 +297,16 @@ fn builtin_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
fn builtin_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(obj, None)]);
match obj.borrow().kind {
PyObjectKind::Dict { ref elements } => {
Ok(vm.context().new_int(elements.len().to_bigint().unwrap()))
}
PyObjectKind::Tuple { ref elements } => {
Ok(vm.context().new_int(elements.len().to_bigint().unwrap()))
}
_ => {
let len_method_name = "__len__".to_string();
match vm.get_method(obj.clone(), &len_method_name) {
Ok(value) => vm.invoke(value, PyFuncArgs::default()),
Err(..) => Err(vm.context().new_str(
format!(
"TypeError: object of this {:?} type has no method {:?}",
obj, len_method_name
)
.to_string(),
)),
}
}
let len_method_name = "__len__".to_string();
match vm.get_method(obj.clone(), &len_method_name) {
Ok(value) => vm.invoke(value, PyFuncArgs::default()),
Err(..) => Err(vm.context().new_str(
format!(
"TypeError: object of this {:?} type has no method {:?}",
obj, len_method_name
)
.to_string(),
)),
}
}
+3 -4
View File
@@ -1,6 +1,5 @@
use super::obj::objlist;
use super::obj::objsequence;
use super::obj::objstr;
use super::obj::objtuple;
use super::obj::objtype;
use super::pyobject::{
create_type, AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
@@ -25,11 +24,11 @@ pub fn print_exception(vm: &mut VirtualMachine, exc: &PyObjectRef) {
if let Some(tb) = exc.get_attr("__traceback__") {
println!("Traceback (most recent call last):");
if objtype::isinstance(&tb, &vm.ctx.list_type()) {
let mut elements = objlist::get_elements(&tb).to_vec();
let mut elements = objsequence::get_elements(&tb).to_vec();
elements.reverse();
for element in elements.iter() {
if objtype::isinstance(&element, &vm.ctx.tuple_type()) {
let element = objtuple::get_elements(&element);
let element = objsequence::get_elements(&element);
let filename = if let Ok(x) = vm.to_str(&element[0]) {
objstr::get_value(&x)
} else {
+6 -11
View File
@@ -8,8 +8,9 @@ use std::path::PathBuf;
use self::rustpython_parser::parser;
use super::compile;
use super::pyobject::{DictProtocol, PyObjectKind, PyResult};
use super::pyobject::{DictProtocol, PyResult};
use super::vm::VirtualMachine;
use obj::{objsequence, objstr};
fn import_uncached_module(
vm: &mut VirtualMachine,
@@ -78,16 +79,10 @@ pub fn import(
fn find_source(vm: &VirtualMachine, current_path: PathBuf, name: &str) -> Result<PathBuf, String> {
let sys_path = vm.sys_module.get_item("path").unwrap();
let mut paths: Vec<PathBuf> = match sys_path.borrow().kind {
PyObjectKind::List { ref elements } => elements
.iter()
.filter_map(|item| match item.borrow().kind {
PyObjectKind::String { ref value } => Some(PathBuf::from(value)),
_ => None,
})
.collect(),
_ => panic!("sys.path unexpectedly not a list"),
};
let mut paths: Vec<PathBuf> = objsequence::get_elements(&sys_path)
.iter()
.map(|item| PathBuf::from(objstr::get_value(item)))
.collect();
paths.insert(0, current_path);
+1 -2
View File
@@ -9,8 +9,7 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
let result = match obj.borrow().kind {
PyObjectKind::Integer { ref value } => !value.is_zero(),
PyObjectKind::Float { value } => value != 0.0,
PyObjectKind::List { ref elements } => !elements.is_empty(),
PyObjectKind::Tuple { ref elements } => !elements.is_empty(),
PyObjectKind::Sequence { ref elements } => !elements.is_empty(),
PyObjectKind::Dict { ref elements } => !elements.is_empty(),
PyObjectKind::String { ref value } => !value.is_empty(),
PyObjectKind::None { .. } => false,
+1 -1
View File
@@ -127,7 +127,7 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
{
let iterated_obj = &*iterated_obj_ref.borrow_mut();
match iterated_obj.kind {
PyObjectKind::List { ref elements } => {
PyObjectKind::Sequence { ref elements } => {
if *position < elements.len() {
let obj_ref = elements[*position].clone();
*position += 1;
+4 -26
View File
@@ -5,13 +5,13 @@ use super::super::pyobject::{
use super::super::vm::VirtualMachine;
use super::objbool;
use super::objint;
use super::objsequence::{get_item, seq_equal, PySliceableSequence};
use super::objsequence::{
get_elements, get_item, get_mut_elements, seq_equal, PySliceableSequence,
};
use super::objstr;
use super::objtype;
use num_bigint::ToBigInt;
use num_traits::ToPrimitive;
use std::cell::{Ref, RefMut};
use std::ops::{Deref, DerefMut};
// set_item:
fn set_item(
@@ -33,28 +33,6 @@ fn set_item(
}
}
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
Ref::map(obj.borrow(), |x| {
if let PyObjectKind::List { ref elements } = x.kind {
elements
} else {
panic!("Cannot extract list elements from non-list");
}
})
}
pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<PyObjectRef>> + 'a {
RefMut::map(obj.borrow_mut(), |x| {
if let PyObjectKind::List { ref mut elements } = x.kind {
elements
} else {
panic!("Cannot extract list elements from non-list");
// TODO: raise proper error?
// Err(vm.new_type_error("list.append is called with no list".to_string()))
}
})
}
fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
@@ -74,7 +52,7 @@ fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
};
Ok(PyObject::new(
PyObjectKind::List { elements: elements },
PyObjectKind::Sequence { elements: elements },
cls.clone(),
))
}
+25 -4
View File
@@ -2,7 +2,9 @@ use super::super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult, Type
use super::super::vm::VirtualMachine;
use super::objbool;
use num_traits::ToPrimitive;
use std::cell::{Ref, RefMut};
use std::marker::Sized;
use std::ops::{Deref, DerefMut};
pub trait PySliceableSequence {
fn do_slice(&self, start: usize, stop: usize) -> Self;
@@ -85,10 +87,7 @@ pub fn get_item(
step: _,
} => Ok(PyObject::new(
match &(sequence.borrow()).kind {
PyObjectKind::Tuple { elements: _ } => PyObjectKind::Tuple {
elements: elements.to_vec().get_slice_items(&subscript),
},
PyObjectKind::List { elements: _ } => PyObjectKind::List {
PyObjectKind::Sequence { elements: _ } => PyObjectKind::Sequence {
elements: elements.to_vec().get_slice_items(&subscript),
},
ref kind => panic!("sequence get_item called for non-sequence: {:?}", kind),
@@ -120,3 +119,25 @@ pub fn seq_equal(
Ok(false)
}
}
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
Ref::map(obj.borrow(), |x| {
if let PyObjectKind::Sequence { ref elements } = x.kind {
elements
} else {
panic!("Cannot extract elements from non-sequence");
}
})
}
pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<PyObjectRef>> + 'a {
RefMut::map(obj.borrow_mut(), |x| {
if let PyObjectKind::Sequence { ref mut elements } = x.kind {
elements
} else {
panic!("Cannot extract list elements from non-sequence");
// TODO: raise proper error?
// Err(vm.new_type_error("list.append is called with no list".to_string()))
}
})
}
+2 -14
View File
@@ -5,13 +5,11 @@ use super::super::pyobject::{
use super::super::vm::VirtualMachine;
use super::objbool;
use super::objint;
use super::objsequence::{get_item, seq_equal};
use super::objsequence::{get_elements, get_item, seq_equal};
use super::objstr;
use super::objtype;
use num_bigint::ToBigInt;
use num_traits::ToPrimitive;
use std::cell::Ref;
use std::ops::Deref;
fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
@@ -75,7 +73,7 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
};
Ok(PyObject::new(
PyObjectKind::Tuple { elements: elements },
PyObjectKind::Sequence { elements: elements },
cls.clone(),
))
}
@@ -128,16 +126,6 @@ pub fn tuple_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.new_bool(false))
}
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
Ref::map(obj.borrow(), |x| {
if let PyObjectKind::Tuple { ref elements } = x.kind {
elements
} else {
panic!("Cannot extract elements from non-tuple");
}
})
}
pub fn init(context: &PyContext) {
let ref tuple_type = context.tuple_type;
tuple_type.set_attr("__eq__", context.new_rustfunc(tuple_eq));
+10 -25
View File
@@ -323,13 +323,16 @@ impl PyContext {
pub fn new_tuple(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
PyObject::new(
PyObjectKind::Tuple { elements: elements },
PyObjectKind::Sequence { elements: elements },
self.tuple_type(),
)
}
pub fn new_list(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
PyObject::new(PyObjectKind::List { elements: elements }, self.list_type())
PyObject::new(
PyObjectKind::Sequence { elements: elements },
self.list_type(),
)
}
pub fn new_set(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
@@ -673,10 +676,7 @@ pub enum PyObjectKind {
Bytes {
value: Vec<u8>,
},
List {
elements: Vec<PyObjectRef>,
},
Tuple {
Sequence {
elements: Vec<PyObjectRef>,
},
Dict {
@@ -737,9 +737,8 @@ impl fmt::Debug for PyObjectKind {
&PyObjectKind::Integer { ref value } => write!(f, "int {}", value),
&PyObjectKind::Float { ref value } => write!(f, "float {}", value),
&PyObjectKind::Complex { ref value } => write!(f, "complex {}", value),
&PyObjectKind::Bytes { ref value } => write!(f, "bytes {:?}", value),
&PyObjectKind::List { elements: _ } => write!(f, "list"),
&PyObjectKind::Tuple { elements: _ } => write!(f, "tuple"),
&PyObjectKind::Bytes { ref value } => write!(f, "bytes/bytearray {:?}", value),
&PyObjectKind::Sequence { elements: _ } => write!(f, "list or tuple"),
&PyObjectKind::Dict { elements: _ } => write!(f, "dict"),
&PyObjectKind::Set { elements: _ } => write!(f, "set"),
&PyObjectKind::Iterator {
@@ -790,28 +789,14 @@ impl PyObject {
PyObjectKind::Float { ref value } => format!("{:?}", value),
PyObjectKind::Complex { ref value } => format!("{:?}", value),
PyObjectKind::Bytes { ref value } => format!("b'{:?}'", value),
PyObjectKind::List { ref elements } => format!(
"[{}]",
PyObjectKind::Sequence { ref elements } => format!(
"(/[{}]/)",
elements
.iter()
.map(|elem| elem.borrow().str())
.collect::<Vec<_>>()
.join(", ")
),
PyObjectKind::Tuple { ref elements } => {
if elements.len() == 1 {
format!("({},)", elements[0].borrow().str())
} else {
format!(
"({})",
elements
.iter()
.map(|elem| elem.borrow().str())
.collect::<Vec<_>>()
.join(", ")
)
}
}
PyObjectKind::Dict { ref elements } => format!(
"{{ {} }}",
elements
+3 -3
View File
@@ -5,7 +5,7 @@ use serde::de::{DeserializeSeed, Visitor};
use serde::ser::{SerializeMap, SerializeSeq};
use serde_json;
use super::super::obj::{objbool, objdict, objfloat, objint, objlist, objstr, objtuple, objtype};
use super::super::obj::{objbool, objdict, objfloat, objint, objsequence, objstr, objtype};
use super::super::pyobject::{
DictProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
};
@@ -54,10 +54,10 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
// Allthough this may seem nice, it does not give the right result:
// v.serialize(serializer)
} else if objtype::isinstance(self.pyobject, &self.ctx.list_type()) {
let elements = objlist::get_elements(self.pyobject);
let elements = objsequence::get_elements(self.pyobject);
serialize_seq_elements(serializer, &elements)
} else if objtype::isinstance(self.pyobject, &self.ctx.tuple_type()) {
let elements = objtuple::get_elements(self.pyobject);
let elements = objsequence::get_elements(self.pyobject);
serialize_seq_elements(serializer, &elements)
} else if objtype::isinstance(self.pyobject, &self.ctx.dict_type()) {
let elements = objdict::get_elements(self.pyobject);
+3 -2
View File
@@ -2,7 +2,7 @@
* Dynamic type creation and names for built in types.
*/
use super::super::obj::{objstr, objtuple, objtype};
use super::super::obj::{objsequence, objstr, objtype};
use super::super::pyobject::{
DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
};
@@ -22,7 +22,7 @@ fn types_new_class(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let bases = match bases {
Some(b) => {
if objtype::isinstance(b, &vm.ctx.tuple_type()) {
objtuple::get_elements(b).to_vec()
objsequence::get_elements(b).to_vec()
} else {
return Err(vm.new_type_error("Bases must be a tuple".to_string()));
}
@@ -39,6 +39,7 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
// Number theory functions:
py_mod.set_item("new_class", ctx.new_rustfunc(types_new_class));
py_mod.set_item("FunctionType", ctx.function_type());
py_mod.set_item("LambdaType", ctx.function_type());
py_mod
}
+4 -5
View File
@@ -13,9 +13,8 @@ use super::bytecode;
use super::frame::{copy_code, Frame};
use super::obj::objgenerator;
use super::obj::objiter;
use super::obj::objlist;
use super::obj::objsequence;
use super::obj::objstr;
use super::obj::objtuple;
use super::obj::objtype;
use super::pyobject::{
AttributeProtocol, DictProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult,
@@ -344,7 +343,7 @@ impl VirtualMachine {
// function definition calls for
if nargs < nexpected_args {
let available_defaults = match defaults.borrow().kind {
PyObjectKind::Tuple { ref elements } => elements.clone(),
PyObjectKind::Sequence { ref elements } => elements.clone(),
PyObjectKind::None => vec![],
_ => panic!("function defaults not tuple or None"),
};
@@ -405,9 +404,9 @@ impl VirtualMachine {
) -> Result<Vec<PyObjectRef>, PyObjectRef> {
// Extract elements from item, if possible:
let elements = if objtype::isinstance(value, &self.ctx.tuple_type()) {
objtuple::get_elements(value).to_vec()
objsequence::get_elements(value).to_vec()
} else if objtype::isinstance(value, &self.ctx.list_type()) {
objlist::get_elements(value).to_vec()
objsequence::get_elements(value).to_vec()
} else {
let iter = objiter::get_iter(self, value)?;
objiter::get_all(self, &iter)?