Skip to content
This repository was archived by the owner on Apr 2, 2020. It is now read-only.

Commit 89cfdbe

Browse files
committed
Use __setitem__ to store elements in list. Also refactor get_elements to return a reference to the elements, not a copy.
1 parent 2aa7638 commit 89cfdbe

12 files changed

+90
-89
lines changed

vm/src/builtins.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -500,7 +500,7 @@ fn builtin_range(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
500500
// builtin_repr
501501
fn builtin_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
502502
arg_check!(vm, args, required = [(obj, None)]);
503-
vm.to_repr(obj.clone())
503+
vm.to_repr(obj)
504504
}
505505
// builtin_reversed
506506
// builtin_round

vm/src/exceptions.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ pub fn print_exception(vm: &mut VirtualMachine, exc: &PyObjectRef) {
2525
if let Some(tb) = exc.get_attr("__traceback__") {
2626
println!("Traceback (most recent call last):");
2727
if objtype::isinstance(&tb, &vm.ctx.list_type()) {
28-
let mut elements = objlist::get_elements(&tb);
28+
let mut elements = objlist::get_elements(&tb).to_vec();
2929
elements.reverse();
30-
for element in elements {
30+
for element in elements.iter() {
3131
if objtype::isinstance(&element, &vm.ctx.tuple_type()) {
3232
let element = objtuple::get_elements(&element);
3333
let filename = if let Ok(x) = vm.to_str(element[0].clone()) {

vm/src/frame.rs

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -556,15 +556,14 @@ impl Frame {
556556
match expr.borrow().kind {
557557
PyObjectKind::None => (),
558558
_ => {
559-
let repr = vm.to_repr(expr.clone()).unwrap();
559+
let repr = vm.to_repr(&expr)?;
560560
builtins::builtin_print(
561561
vm,
562562
PyFuncArgs {
563563
args: vec![repr],
564564
kwargs: vec![],
565565
},
566-
)
567-
.unwrap();
566+
)?;
568567
}
569568
}
570569
Ok(None)
@@ -857,17 +856,8 @@ impl Frame {
857856
let idx = self.pop_value();
858857
let obj = self.pop_value();
859858
let value = self.pop_value();
860-
let a2 = &mut *obj.borrow_mut();
861-
match &mut a2.kind {
862-
PyObjectKind::List { ref mut elements } => {
863-
objlist::set_item(vm, elements, idx, value)?;
864-
Ok(None)
865-
}
866-
_ => Err(vm.new_type_error(format!(
867-
"TypeError: __setitem__ assign type {:?} with index {:?} is not supported (yet?)",
868-
obj, idx
869-
))),
870-
}
859+
vm.call_method(&obj, "__setitem__", vec![idx, value])?;
860+
Ok(None)
871861
}
872862

873863
fn execute_delete_subscript(&mut self, vm: &mut VirtualMachine) -> FrameResult {

vm/src/obj/objbytes.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ fn bytes_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
2525
);
2626
let val = if objtype::isinstance(arg, &vm.ctx.list_type()) {
2727
let mut data_bytes = vec![];
28-
for elem in objlist::get_elements(arg) {
29-
let v = objint::to_int(vm, &elem, 10)?;
28+
for elem in objlist::get_elements(arg).iter() {
29+
let v = objint::to_int(vm, elem, 10)?;
3030
data_bytes.push(v.to_u8().unwrap());
3131
}
3232
data_bytes

vm/src/obj/objdict.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,9 @@ fn dict_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
5151
let elements = get_elements(o);
5252
let mut str_parts = vec![];
5353
for elem in elements {
54-
match vm.to_repr(elem.1) {
55-
Ok(s) => {
56-
let value_str = objstr::get_value(&s);
57-
str_parts.push(format!("{}: {}", elem.0, value_str));
58-
}
59-
Err(err) => return Err(err),
60-
}
54+
let s = vm.to_repr(&elem.1)?;
55+
let value_str = objstr::get_value(&s);
56+
str_parts.push(format!("{}: {}", elem.0, value_str));
6157
}
6258

6359
let s = format!("{{ {} }}", str_parts.join(", "));

vm/src/obj/objlist.rs

Lines changed: 48 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ use super::objstr;
1111
use super::objtype;
1212
use num_bigint::ToBigInt;
1313
use num_traits::ToPrimitive;
14+
use std::cell::{Ref, RefMut};
15+
use std::ops::{Deref, DerefMut};
1416

1517
// set_item:
16-
pub fn set_item(
18+
fn set_item(
1719
vm: &mut VirtualMachine,
1820
l: &mut Vec<PyObjectRef>,
1921
idx: PyObjectRef,
@@ -32,12 +34,26 @@ pub fn set_item(
3234
}
3335
}
3436

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

4359
fn list_new(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -76,7 +92,7 @@ fn list_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
7692
let result = if objtype::isinstance(other, &vm.ctx.list_type()) {
7793
let zelf = get_elements(zelf);
7894
let other = get_elements(other);
79-
seq_equal(vm, zelf, other)?
95+
seq_equal(vm, &zelf, &other)?
8096
} else {
8197
false
8298
};
@@ -105,7 +121,7 @@ fn list_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
105121

106122
let elements = get_elements(o);
107123
let mut str_parts = vec![];
108-
for elem in elements {
124+
for elem in elements.iter() {
109125
let s = vm.to_repr(elem)?;
110126
str_parts.push(objstr::get_value(&s));
111127
}
@@ -121,25 +137,17 @@ pub fn list_append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
121137
args,
122138
required = [(list, Some(vm.ctx.list_type())), (x, None)]
123139
);
124-
let mut list_obj = list.borrow_mut();
125-
if let PyObjectKind::List { ref mut elements } = list_obj.kind {
126-
elements.push(x.clone());
127-
Ok(vm.get_none())
128-
} else {
129-
Err(vm.new_type_error("list.append is called with no list".to_string()))
130-
}
140+
let mut elements = get_mut_elements(list);
141+
elements.push(x.clone());
142+
Ok(vm.get_none())
131143
}
132144

133145
fn list_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
134146
trace!("list.clear called with: {:?}", args);
135147
arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]);
136-
let mut list_obj = list.borrow_mut();
137-
if let PyObjectKind::List { ref mut elements } = list_obj.kind {
138-
elements.clear();
139-
Ok(vm.get_none())
140-
} else {
141-
Err(vm.new_type_error("list.clear is called with no list".to_string()))
142-
}
148+
let mut elements = get_mut_elements(list);
149+
elements.clear();
150+
Ok(vm.get_none())
143151
}
144152

145153
pub fn list_extend(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -149,13 +157,9 @@ pub fn list_extend(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
149157
required = [(list, Some(vm.ctx.list_type())), (x, None)]
150158
);
151159
let mut new_elements = vm.extract_elements(x)?;
152-
let mut list_obj = list.borrow_mut();
153-
if let PyObjectKind::List { ref mut elements } = list_obj.kind {
154-
elements.append(&mut new_elements);
155-
Ok(vm.get_none())
156-
} else {
157-
Err(vm.new_type_error("list.extend is called with no list".to_string()))
158-
}
160+
let mut elements = get_mut_elements(list);
161+
elements.append(&mut new_elements);
162+
Ok(vm.get_none())
159163
}
160164

161165
fn list_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -168,13 +172,9 @@ fn list_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
168172
fn list_reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
169173
trace!("list.reverse called with: {:?}", args);
170174
arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]);
171-
let mut list_obj = list.borrow_mut();
172-
if let PyObjectKind::List { ref mut elements } = list_obj.kind {
173-
elements.reverse();
174-
Ok(vm.get_none())
175-
} else {
176-
Err(vm.new_type_error("list.reverse is called with no list".to_string()))
177-
}
175+
let mut elements = get_mut_elements(list);
176+
elements.reverse();
177+
Ok(vm.get_none())
178178
}
179179

180180
fn list_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -208,12 +208,23 @@ fn list_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
208208
get_item(vm, list, &get_elements(list), needle.clone())
209209
}
210210

211+
fn list_setitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
212+
arg_check!(
213+
vm,
214+
args,
215+
required = [(list, Some(vm.ctx.list_type())), (key, None), (value, None)]
216+
);
217+
let mut elements = get_mut_elements(list);
218+
set_item(vm, &mut elements, key.clone(), value.clone())
219+
}
220+
211221
pub fn init(context: &PyContext) {
212222
let ref list_type = context.list_type;
213223
list_type.set_attr("__add__", context.new_rustfunc(list_add));
214224
list_type.set_attr("__contains__", context.new_rustfunc(list_contains));
215225
list_type.set_attr("__eq__", context.new_rustfunc(list_eq));
216226
list_type.set_attr("__getitem__", context.new_rustfunc(list_getitem));
227+
list_type.set_attr("__setitem__", context.new_rustfunc(list_setitem));
217228
list_type.set_attr("__len__", context.new_rustfunc(list_len));
218229
list_type.set_attr("__new__", context.new_rustfunc(list_new));
219230
list_type.set_attr("__repr__", context.new_rustfunc(list_repr));

vm/src/obj/objsequence.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ pub fn get_item(
104104

105105
pub fn seq_equal(
106106
vm: &mut VirtualMachine,
107-
zelf: Vec<PyObjectRef>,
108-
other: Vec<PyObjectRef>,
107+
zelf: &Vec<PyObjectRef>,
108+
other: &Vec<PyObjectRef>,
109109
) -> Result<bool, PyObjectRef> {
110110
if zelf.len() == other.len() {
111111
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {

vm/src/obj/objset.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ fn set_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
100100
let elements = get_elements(o);
101101
let mut str_parts = vec![];
102102
for elem in elements.values() {
103-
let part = vm.to_repr(elem.clone())?;
103+
let part = vm.to_repr(elem)?;
104104
str_parts.push(objstr::get_value(&part));
105105
}
106106

vm/src/obj/objtuple.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use super::objstr;
99
use super::objtype;
1010
use num_bigint::ToBigInt;
1111
use num_traits::ToPrimitive;
12+
use std::cell::Ref;
13+
use std::ops::Deref;
1214

1315
fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
1416
arg_check!(
@@ -20,7 +22,7 @@ fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
2022
let result = if objtype::isinstance(other, &vm.ctx.tuple_type()) {
2123
let zelf = get_elements(zelf);
2224
let other = get_elements(other);
23-
seq_equal(vm, zelf, other)?
25+
seq_equal(vm, &zelf, &other)?
2426
} else {
2527
false
2628
};
@@ -35,7 +37,7 @@ fn tuple_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
3537
let len: usize = elements.len();
3638
let mut mult = 0xf4243;
3739

38-
for elem in &elements {
40+
for elem in elements.iter() {
3941
let y: usize = objint::get_value(&vm.call_method(elem, "__hash__", vec![])?)
4042
.to_usize()
4143
.unwrap();
@@ -59,7 +61,7 @@ fn tuple_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
5961
let elements = get_elements(zelf);
6062

6163
let mut str_parts = vec![];
62-
for elem in elements {
64+
for elem in elements.iter() {
6365
match vm.to_repr(elem) {
6466
Ok(s) => str_parts.push(objstr::get_value(&s)),
6567
Err(err) => return Err(err),
@@ -103,12 +105,14 @@ pub fn tuple_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
103105
Ok(vm.new_bool(false))
104106
}
105107

106-
pub fn get_elements(obj: &PyObjectRef) -> Vec<PyObjectRef> {
107-
if let PyObjectKind::Tuple { elements } = &obj.borrow().kind {
108-
elements.to_vec()
109-
} else {
110-
panic!("Cannot extract elements from non-tuple");
111-
}
108+
pub fn get_elements<'a>(obj: &'a PyObjectRef) -> impl Deref<Target = Vec<PyObjectRef>> + 'a {
109+
Ref::map(obj.borrow(), |x| {
110+
if let PyObjectKind::Tuple { ref elements } = x.kind {
111+
elements
112+
} else {
113+
panic!("Cannot extract elements from non-tuple");
114+
}
115+
})
112116
}
113117

114118
pub fn init(context: &PyContext) {

vm/src/stdlib/json.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
3535
S: serde::Serializer,
3636
{
3737
let serialize_seq_elements =
38-
|serializer: S, elements: Vec<PyObjectRef>| -> Result<S::Ok, S::Error> {
38+
|serializer: S, elements: &Vec<PyObjectRef>| -> Result<S::Ok, S::Error> {
3939
let mut seq = serializer.serialize_seq(Some(elements.len()))?;
40-
for e in elements {
41-
seq.serialize_element(&self.clone_with_object(&e))?;
40+
for e in elements.iter() {
41+
seq.serialize_element(&self.clone_with_object(e))?;
4242
}
4343
seq.end()
4444
};
@@ -55,10 +55,10 @@ impl<'s> serde::Serialize for PyObjectSerializer<'s> {
5555
// v.serialize(serializer)
5656
} else if objtype::isinstance(self.pyobject, &self.ctx.list_type()) {
5757
let elements = objlist::get_elements(self.pyobject);
58-
serialize_seq_elements(serializer, elements)
58+
serialize_seq_elements(serializer, &elements)
5959
} else if objtype::isinstance(self.pyobject, &self.ctx.tuple_type()) {
6060
let elements = objtuple::get_elements(self.pyobject);
61-
serialize_seq_elements(serializer, elements)
61+
serialize_seq_elements(serializer, &elements)
6262
} else if objtype::isinstance(self.pyobject, &self.ctx.dict_type()) {
6363
let elements = objdict::get_elements(self.pyobject);
6464
let mut map = serializer.serialize_map(Some(elements.len()))?;

vm/src/stdlib/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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)
25+
objtuple::get_elements(b).to_vec()
2626
} else {
2727
return Err(vm.new_type_error("Bases must be a tuple".to_string()));
2828
}

0 commit comments

Comments
 (0)