Skip to content

Commit d72abeb

Browse files
committed
Unify object kinds tuple and list into sequence.
1 parent b6a88cc commit d72abeb

12 files changed

+72
-117
lines changed

vm/src/builtins.rs

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -297,26 +297,16 @@ fn builtin_iter(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
297297

298298
fn builtin_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
299299
arg_check!(vm, args, required = [(obj, None)]);
300-
match obj.borrow().kind {
301-
PyObjectKind::Dict { ref elements } => {
302-
Ok(vm.context().new_int(elements.len().to_bigint().unwrap()))
303-
}
304-
PyObjectKind::Tuple { ref elements } => {
305-
Ok(vm.context().new_int(elements.len().to_bigint().unwrap()))
306-
}
307-
_ => {
308-
let len_method_name = "__len__".to_string();
309-
match vm.get_method(obj.clone(), &len_method_name) {
310-
Ok(value) => vm.invoke(value, PyFuncArgs::default()),
311-
Err(..) => Err(vm.context().new_str(
312-
format!(
313-
"TypeError: object of this {:?} type has no method {:?}",
314-
obj, len_method_name
315-
)
316-
.to_string(),
317-
)),
318-
}
319-
}
300+
let len_method_name = "__len__".to_string();
301+
match vm.get_method(obj.clone(), &len_method_name) {
302+
Ok(value) => vm.invoke(value, PyFuncArgs::default()),
303+
Err(..) => Err(vm.context().new_str(
304+
format!(
305+
"TypeError: object of this {:?} type has no method {:?}",
306+
obj, len_method_name
307+
)
308+
.to_string(),
309+
)),
320310
}
321311
}
322312

vm/src/exceptions.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
use super::obj::objlist;
1+
use super::obj::objsequence;
22
use super::obj::objstr;
3-
use super::obj::objtuple;
43
use super::obj::objtype;
54
use super::pyobject::{
65
create_type, AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
@@ -25,11 +24,11 @@ pub fn print_exception(vm: &mut VirtualMachine, exc: &PyObjectRef) {
2524
if let Some(tb) = exc.get_attr("__traceback__") {
2625
println!("Traceback (most recent call last):");
2726
if objtype::isinstance(&tb, &vm.ctx.list_type()) {
28-
let mut elements = objlist::get_elements(&tb).to_vec();
27+
let mut elements = objsequence::get_elements(&tb).to_vec();
2928
elements.reverse();
3029
for element in elements.iter() {
3130
if objtype::isinstance(&element, &vm.ctx.tuple_type()) {
32-
let element = objtuple::get_elements(&element);
31+
let element = objsequence::get_elements(&element);
3332
let filename = if let Ok(x) = vm.to_str(&element[0]) {
3433
objstr::get_value(&x)
3534
} else {

vm/src/import.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ use std::path::PathBuf;
88

99
use self::rustpython_parser::parser;
1010
use super::compile;
11-
use super::pyobject::{DictProtocol, PyObjectKind, PyResult};
11+
use super::pyobject::{DictProtocol, PyResult};
1212
use super::vm::VirtualMachine;
13+
use obj::{objsequence, objstr};
1314

1415
fn import_uncached_module(
1516
vm: &mut VirtualMachine,
@@ -78,16 +79,10 @@ pub fn import(
7879

7980
fn find_source(vm: &VirtualMachine, current_path: PathBuf, name: &str) -> Result<PathBuf, String> {
8081
let sys_path = vm.sys_module.get_item("path").unwrap();
81-
let mut paths: Vec<PathBuf> = match sys_path.borrow().kind {
82-
PyObjectKind::List { ref elements } => elements
83-
.iter()
84-
.filter_map(|item| match item.borrow().kind {
85-
PyObjectKind::String { ref value } => Some(PathBuf::from(value)),
86-
_ => None,
87-
})
88-
.collect(),
89-
_ => panic!("sys.path unexpectedly not a list"),
90-
};
82+
let mut paths: Vec<PathBuf> = objsequence::get_elements(&sys_path)
83+
.iter()
84+
.map(|item| PathBuf::from(objstr::get_value(item)))
85+
.collect();
9186

9287
paths.insert(0, current_path);
9388

vm/src/obj/objbool.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ pub fn boolval(vm: &mut VirtualMachine, obj: PyObjectRef) -> Result<bool, PyObje
99
let result = match obj.borrow().kind {
1010
PyObjectKind::Integer { ref value } => !value.is_zero(),
1111
PyObjectKind::Float { value } => value != 0.0,
12-
PyObjectKind::List { ref elements } => !elements.is_empty(),
13-
PyObjectKind::Tuple { ref elements } => !elements.is_empty(),
12+
PyObjectKind::Sequence { ref elements } => !elements.is_empty(),
1413
PyObjectKind::Dict { ref elements } => !elements.is_empty(),
1514
PyObjectKind::String { ref value } => !value.is_empty(),
1615
PyObjectKind::None { .. } => false,

vm/src/obj/objiter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ fn iter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
127127
{
128128
let iterated_obj = &*iterated_obj_ref.borrow_mut();
129129
match iterated_obj.kind {
130-
PyObjectKind::List { ref elements } => {
130+
PyObjectKind::Sequence { ref elements } => {
131131
if *position < elements.len() {
132132
let obj_ref = elements[*position].clone();
133133
*position += 1;

vm/src/obj/objlist.rs

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ use super::super::pyobject::{
55
use super::super::vm::VirtualMachine;
66
use super::objbool;
77
use super::objint;
8-
use super::objsequence::{get_item, seq_equal, PySliceableSequence};
8+
use super::objsequence::{
9+
get_elements, get_item, get_mut_elements, seq_equal, PySliceableSequence,
10+
};
911
use super::objstr;
1012
use super::objtype;
1113
use num_bigint::ToBigInt;
1214
use num_traits::ToPrimitive;
13-
use std::cell::{Ref, RefMut};
14-
use std::ops::{Deref, DerefMut};
1515

1616
// set_item:
1717
fn set_item(
@@ -33,28 +33,6 @@ fn set_item(
3333
}
3434
}
3535

36-
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
37-
Ref::map(obj.borrow(), |x| {
38-
if let PyObjectKind::List { ref elements } = x.kind {
39-
elements
40-
} else {
41-
panic!("Cannot extract list elements from non-list");
42-
}
43-
})
44-
}
45-
46-
pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<PyObjectRef>> + 'a {
47-
RefMut::map(obj.borrow_mut(), |x| {
48-
if let PyObjectKind::List { ref mut elements } = x.kind {
49-
elements
50-
} else {
51-
panic!("Cannot extract list elements from non-list");
52-
// TODO: raise proper error?
53-
// Err(vm.new_type_error("list.append is called with no list".to_string()))
54-
}
55-
})
56-
}
57-
5836
fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
5937
arg_check!(
6038
vm,
@@ -74,7 +52,7 @@ fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
7452
};
7553

7654
Ok(PyObject::new(
77-
PyObjectKind::List { elements: elements },
55+
PyObjectKind::Sequence { elements: elements },
7856
cls.clone(),
7957
))
8058
}

vm/src/obj/objsequence.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ use super::super::pyobject::{PyObject, PyObjectKind, PyObjectRef, PyResult, Type
22
use super::super::vm::VirtualMachine;
33
use super::objbool;
44
use num_traits::ToPrimitive;
5+
use std::cell::{Ref, RefMut};
56
use std::marker::Sized;
7+
use std::ops::{Deref, DerefMut};
68

79
pub trait PySliceableSequence {
810
fn do_slice(&self, start: usize, stop: usize) -> Self;
@@ -85,10 +87,7 @@ pub fn get_item(
8587
step: _,
8688
} => Ok(PyObject::new(
8789
match &(sequence.borrow()).kind {
88-
PyObjectKind::Tuple { elements: _ } => PyObjectKind::Tuple {
89-
elements: elements.to_vec().get_slice_items(&subscript),
90-
},
91-
PyObjectKind::List { elements: _ } => PyObjectKind::List {
90+
PyObjectKind::Sequence { elements: _ } => PyObjectKind::Sequence {
9291
elements: elements.to_vec().get_slice_items(&subscript),
9392
},
9493
ref kind => panic!("sequence get_item called for non-sequence: {:?}", kind),
@@ -120,3 +119,25 @@ pub fn seq_equal(
120119
Ok(false)
121120
}
122121
}
122+
123+
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
124+
Ref::map(obj.borrow(), |x| {
125+
if let PyObjectKind::Sequence { ref elements } = x.kind {
126+
elements
127+
} else {
128+
panic!("Cannot extract elements from non-sequence");
129+
}
130+
})
131+
}
132+
133+
pub fn get_mut_elements<'a>(obj: &'a PyObjectRef) -> impl DerefMut<Target = Vec<PyObjectRef>> + 'a {
134+
RefMut::map(obj.borrow_mut(), |x| {
135+
if let PyObjectKind::Sequence { ref mut elements } = x.kind {
136+
elements
137+
} else {
138+
panic!("Cannot extract list elements from non-sequence");
139+
// TODO: raise proper error?
140+
// Err(vm.new_type_error("list.append is called with no list".to_string()))
141+
}
142+
})
143+
}

vm/src/obj/objtuple.rs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,11 @@ use super::super::pyobject::{
55
use super::super::vm::VirtualMachine;
66
use super::objbool;
77
use super::objint;
8-
use super::objsequence::{get_item, seq_equal};
8+
use super::objsequence::{get_elements, get_item, seq_equal};
99
use super::objstr;
1010
use super::objtype;
1111
use num_bigint::ToBigInt;
1212
use num_traits::ToPrimitive;
13-
use std::cell::Ref;
14-
use std::ops::Deref;
1513

1614
fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
1715
arg_check!(
@@ -75,7 +73,7 @@ fn tuple_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
7573
};
7674

7775
Ok(PyObject::new(
78-
PyObjectKind::Tuple { elements: elements },
76+
PyObjectKind::Sequence { elements: elements },
7977
cls.clone(),
8078
))
8179
}
@@ -128,16 +126,6 @@ pub fn tuple_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
128126
Ok(vm.new_bool(false))
129127
}
130128

131-
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
132-
Ref::map(obj.borrow(), |x| {
133-
if let PyObjectKind::Tuple { ref elements } = x.kind {
134-
elements
135-
} else {
136-
panic!("Cannot extract elements from non-tuple");
137-
}
138-
})
139-
}
140-
141129
pub fn init(context: &PyContext) {
142130
let ref tuple_type = context.tuple_type;
143131
tuple_type.set_attr("__eq__", context.new_rustfunc(tuple_eq));

vm/src/pyobject.rs

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,16 @@ impl PyContext {
323323

324324
pub fn new_tuple(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
325325
PyObject::new(
326-
PyObjectKind::Tuple { elements: elements },
326+
PyObjectKind::Sequence { elements: elements },
327327
self.tuple_type(),
328328
)
329329
}
330330

331331
pub fn new_list(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
332-
PyObject::new(PyObjectKind::List { elements: elements }, self.list_type())
332+
PyObject::new(
333+
PyObjectKind::Sequence { elements: elements },
334+
self.list_type(),
335+
)
333336
}
334337

335338
pub fn new_set(&self, elements: Vec<PyObjectRef>) -> PyObjectRef {
@@ -673,10 +676,7 @@ pub enum PyObjectKind {
673676
Bytes {
674677
value: Vec<u8>,
675678
},
676-
List {
677-
elements: Vec<PyObjectRef>,
678-
},
679-
Tuple {
679+
Sequence {
680680
elements: Vec<PyObjectRef>,
681681
},
682682
Dict {
@@ -737,9 +737,8 @@ impl fmt::Debug for PyObjectKind {
737737
&PyObjectKind::Integer { ref value } => write!(f, "int {}", value),
738738
&PyObjectKind::Float { ref value } => write!(f, "float {}", value),
739739
&PyObjectKind::Complex { ref value } => write!(f, "complex {}", value),
740-
&PyObjectKind::Bytes { ref value } => write!(f, "bytes {:?}", value),
741-
&PyObjectKind::List { elements: _ } => write!(f, "list"),
742-
&PyObjectKind::Tuple { elements: _ } => write!(f, "tuple"),
740+
&PyObjectKind::Bytes { ref value } => write!(f, "bytes/bytearray {:?}", value),
741+
&PyObjectKind::Sequence { elements: _ } => write!(f, "list or tuple"),
743742
&PyObjectKind::Dict { elements: _ } => write!(f, "dict"),
744743
&PyObjectKind::Set { elements: _ } => write!(f, "set"),
745744
&PyObjectKind::Iterator {
@@ -790,28 +789,14 @@ impl PyObject {
790789
PyObjectKind::Float { ref value } => format!("{:?}", value),
791790
PyObjectKind::Complex { ref value } => format!("{:?}", value),
792791
PyObjectKind::Bytes { ref value } => format!("b'{:?}'", value),
793-
PyObjectKind::List { ref elements } => format!(
794-
"[{}]",
792+
PyObjectKind::Sequence { ref elements } => format!(
793+
"(/[{}]/)",
795794
elements
796795
.iter()
797796
.map(|elem| elem.borrow().str())
798797
.collect::<Vec<_>>()
799798
.join(", ")
800799
),
801-
PyObjectKind::Tuple { ref elements } => {
802-
if elements.len() == 1 {
803-
format!("({},)", elements[0].borrow().str())
804-
} else {
805-
format!(
806-
"({})",
807-
elements
808-
.iter()
809-
.map(|elem| elem.borrow().str())
810-
.collect::<Vec<_>>()
811-
.join(", ")
812-
)
813-
}
814-
}
815800
PyObjectKind::Dict { ref elements } => format!(
816801
"{{ {} }}",
817802
elements

vm/src/stdlib/json.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use serde::de::{DeserializeSeed, Visitor};
55
use serde::ser::{SerializeMap, SerializeSeq};
66
use serde_json;
77

8-
use super::super::obj::{objbool, objdict, objfloat, objint, objlist, objstr, objtuple, objtype};
8+
use super::super::obj::{objbool, objdict, objfloat, objint, objsequence, objstr, objtype};
99
use super::super::pyobject::{
1010
DictProtocol, PyContext, PyFuncArgs, PyObjectKind, PyObjectRef, PyResult, TypeProtocol,
1111
};
@@ -54,10 +54,10 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
5454
// Allthough this may seem nice, it does not give the right result:
5555
// v.serialize(serializer)
5656
} else if objtype::isinstance(self.pyobject, &self.ctx.list_type()) {
57-
let elements = objlist::get_elements(self.pyobject);
57+
let elements = objsequence::get_elements(self.pyobject);
5858
serialize_seq_elements(serializer, &elements)
5959
} else if objtype::isinstance(self.pyobject, &self.ctx.tuple_type()) {
60-
let elements = objtuple::get_elements(self.pyobject);
60+
let elements = objsequence::get_elements(self.pyobject);
6161
serialize_seq_elements(serializer, &elements)
6262
} else if objtype::isinstance(self.pyobject, &self.ctx.dict_type()) {
6363
let elements = objdict::get_elements(self.pyobject);

vm/src/stdlib/types.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Dynamic type creation and names for built in types.
33
*/
44

5-
use super::super::obj::{objstr, objtuple, objtype};
5+
use super::super::obj::{objsequence, objstr, objtype};
66
use super::super::pyobject::{
77
DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
88
};
@@ -22,7 +22,7 @@ fn types_new_class(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
2222
let bases = match bases {
2323
Some(b) => {
2424
if objtype::isinstance(b, &vm.ctx.tuple_type()) {
25-
objtuple::get_elements(b).to_vec()
25+
objsequence::get_elements(b).to_vec()
2626
} else {
2727
return Err(vm.new_type_error("Bases must be a tuple".to_string()));
2828
}
@@ -39,6 +39,7 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
3939
// Number theory functions:
4040
py_mod.set_item("new_class", ctx.new_rustfunc(types_new_class));
4141
py_mod.set_item("FunctionType", ctx.function_type());
42+
py_mod.set_item("LambdaType", ctx.function_type());
4243

4344
py_mod
4445
}

0 commit comments

Comments
 (0)