Use __setitem__ to store elements in list. Also refactor get_elements to return a reference to the elements, not a copy.

This commit is contained in:
Windel Bouwman
2018-10-31 23:18:26 +01:00
parent 2aa763867c
commit 89cfdbe3dd
12 changed files with 90 additions and 89 deletions

View File

@@ -25,8 +25,8 @@ fn bytes_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
);
let val = if objtype::isinstance(arg, &vm.ctx.list_type()) {
let mut data_bytes = vec![];
for elem in objlist::get_elements(arg) {
let v = objint::to_int(vm, &elem, 10)?;
for elem in objlist::get_elements(arg).iter() {
let v = objint::to_int(vm, elem, 10)?;
data_bytes.push(v.to_u8().unwrap());
}
data_bytes

View File

@@ -51,13 +51,9 @@ fn dict_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let elements = get_elements(o);
let mut str_parts = vec![];
for elem in elements {
match vm.to_repr(elem.1) {
Ok(s) => {
let value_str = objstr::get_value(&s);
str_parts.push(format!("{}: {}", elem.0, value_str));
}
Err(err) => return Err(err),
}
let s = vm.to_repr(&elem.1)?;
let value_str = objstr::get_value(&s);
str_parts.push(format!("{}: {}", elem.0, value_str));
}
let s = format!("{{ {} }}", str_parts.join(", "));

View File

@@ -11,9 +11,11 @@ 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:
pub fn set_item(
fn set_item(
vm: &mut VirtualMachine,
l: &mut Vec<PyObjectRef>,
idx: PyObjectRef,
@@ -32,12 +34,26 @@ pub fn set_item(
}
}
pub fn get_elements(obj: &PyObjectRef) -> Vec<PyObjectRef> {
if let PyObjectKind::List { elements } = &obj.borrow().kind {
elements.to_vec()
} else {
panic!("Cannot extract list elements from non-list");
}
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 {
@@ -76,7 +92,7 @@ fn list_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let result = if objtype::isinstance(other, &vm.ctx.list_type()) {
let zelf = get_elements(zelf);
let other = get_elements(other);
seq_equal(vm, zelf, other)?
seq_equal(vm, &zelf, &other)?
} else {
false
};
@@ -105,7 +121,7 @@ fn list_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let elements = get_elements(o);
let mut str_parts = vec![];
for elem in elements {
for elem in elements.iter() {
let s = vm.to_repr(elem)?;
str_parts.push(objstr::get_value(&s));
}
@@ -121,25 +137,17 @@ pub fn list_append(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
args,
required = [(list, Some(vm.ctx.list_type())), (x, None)]
);
let mut list_obj = list.borrow_mut();
if let PyObjectKind::List { ref mut elements } = list_obj.kind {
elements.push(x.clone());
Ok(vm.get_none())
} else {
Err(vm.new_type_error("list.append is called with no list".to_string()))
}
let mut elements = get_mut_elements(list);
elements.push(x.clone());
Ok(vm.get_none())
}
fn list_clear(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
trace!("list.clear called with: {:?}", args);
arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]);
let mut list_obj = list.borrow_mut();
if let PyObjectKind::List { ref mut elements } = list_obj.kind {
elements.clear();
Ok(vm.get_none())
} else {
Err(vm.new_type_error("list.clear is called with no list".to_string()))
}
let mut elements = get_mut_elements(list);
elements.clear();
Ok(vm.get_none())
}
pub fn list_extend(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -149,13 +157,9 @@ pub fn list_extend(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
required = [(list, Some(vm.ctx.list_type())), (x, None)]
);
let mut new_elements = vm.extract_elements(x)?;
let mut list_obj = list.borrow_mut();
if let PyObjectKind::List { ref mut elements } = list_obj.kind {
elements.append(&mut new_elements);
Ok(vm.get_none())
} else {
Err(vm.new_type_error("list.extend is called with no list".to_string()))
}
let mut elements = get_mut_elements(list);
elements.append(&mut new_elements);
Ok(vm.get_none())
}
fn list_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -168,13 +172,9 @@ fn list_len(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
fn list_reverse(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
trace!("list.reverse called with: {:?}", args);
arg_check!(vm, args, required = [(list, Some(vm.ctx.list_type()))]);
let mut list_obj = list.borrow_mut();
if let PyObjectKind::List { ref mut elements } = list_obj.kind {
elements.reverse();
Ok(vm.get_none())
} else {
Err(vm.new_type_error("list.reverse is called with no list".to_string()))
}
let mut elements = get_mut_elements(list);
elements.reverse();
Ok(vm.get_none())
}
fn list_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -208,12 +208,23 @@ fn list_getitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
get_item(vm, list, &get_elements(list), needle.clone())
}
fn list_setitem(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(
vm,
args,
required = [(list, Some(vm.ctx.list_type())), (key, None), (value, None)]
);
let mut elements = get_mut_elements(list);
set_item(vm, &mut elements, key.clone(), value.clone())
}
pub fn init(context: &PyContext) {
let ref list_type = context.list_type;
list_type.set_attr("__add__", context.new_rustfunc(list_add));
list_type.set_attr("__contains__", context.new_rustfunc(list_contains));
list_type.set_attr("__eq__", context.new_rustfunc(list_eq));
list_type.set_attr("__getitem__", context.new_rustfunc(list_getitem));
list_type.set_attr("__setitem__", context.new_rustfunc(list_setitem));
list_type.set_attr("__len__", context.new_rustfunc(list_len));
list_type.set_attr("__new__", context.new_rustfunc(list_new));
list_type.set_attr("__repr__", context.new_rustfunc(list_repr));

View File

@@ -104,8 +104,8 @@ pub fn get_item(
pub fn seq_equal(
vm: &mut VirtualMachine,
zelf: Vec<PyObjectRef>,
other: Vec<PyObjectRef>,
zelf: &Vec<PyObjectRef>,
other: &Vec<PyObjectRef>,
) -> Result<bool, PyObjectRef> {
if zelf.len() == other.len() {
for (a, b) in Iterator::zip(zelf.iter(), other.iter()) {

View File

@@ -100,7 +100,7 @@ fn set_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let elements = get_elements(o);
let mut str_parts = vec![];
for elem in elements.values() {
let part = vm.to_repr(elem.clone())?;
let part = vm.to_repr(elem)?;
str_parts.push(objstr::get_value(&part));
}

View File

@@ -9,6 +9,8 @@ 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!(
@@ -20,7 +22,7 @@ fn tuple_eq(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let result = if objtype::isinstance(other, &vm.ctx.tuple_type()) {
let zelf = get_elements(zelf);
let other = get_elements(other);
seq_equal(vm, zelf, other)?
seq_equal(vm, &zelf, &other)?
} else {
false
};
@@ -35,7 +37,7 @@ fn tuple_hash(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let len: usize = elements.len();
let mut mult = 0xf4243;
for elem in &elements {
for elem in elements.iter() {
let y: usize = objint::get_value(&vm.call_method(elem, "__hash__", vec![])?)
.to_usize()
.unwrap();
@@ -59,7 +61,7 @@ fn tuple_repr(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
let elements = get_elements(zelf);
let mut str_parts = vec![];
for elem in elements {
for elem in elements.iter() {
match vm.to_repr(elem) {
Ok(s) => str_parts.push(objstr::get_value(&s)),
Err(err) => return Err(err),
@@ -103,12 +105,14 @@ pub fn tuple_contains(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
Ok(vm.new_bool(false))
}
pub fn get_elements(obj: &PyObjectRef) -> Vec<PyObjectRef> {
if let PyObjectKind::Tuple { elements } = &obj.borrow().kind {
elements.to_vec()
} else {
panic!("Cannot extract elements from non-tuple");
}
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) {