Implemented list.__reversed__

This commit is contained in:
Adolfo Gonzalez III
2019-07-19 16:08:16 -05:00
parent 19e783d285
commit b7c035fdde
2 changed files with 52 additions and 2 deletions

View File

@@ -167,6 +167,14 @@ impl PyListRef {
fn reverse(self, _vm: &VirtualMachine) {
self.elements.borrow_mut().reverse();
}
fn reversed(self, _vm: &VirtualMachine) -> PyListReverseIterator {
let final_position = self.elements.borrow().len();
PyListReverseIterator {
position: Cell::new(final_position),
list: self,
}
}
fn getitem(self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
get_item(
@@ -397,7 +405,7 @@ impl PyListRef {
.collect();
vm.ctx.new_list(new_elements)
}
fn imul(self, counter: isize, _vm: &VirtualMachine) -> Self {
let new_elements = seq_mul(&self.elements.borrow().as_slice(), counter)
.cloned()
@@ -405,7 +413,7 @@ impl PyListRef {
self.elements.replace(new_elements);
self
}
fn count(self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
let mut count: usize = 0;
for element in self.elements.borrow().iter() {
@@ -813,6 +821,39 @@ impl PyListIterator {
}
}
#[pyclass]
#[derive(Debug)]
pub struct PyListReverseIterator {
pub position: Cell<usize>,
pub list: PyListRef,
}
impl PyValue for PyListReverseIterator {
fn class(vm: &VirtualMachine) -> PyClassRef {
vm.ctx.listreverseiterator_type()
}
}
#[pyimpl]
impl PyListReverseIterator {
#[pymethod(name = "__next__")]
fn next(&self, vm: &VirtualMachine) -> PyResult {
if self.position.get() > 0 {
let position: usize = self.position.get() - 1;
let ret = self.list.elements.borrow()[position].clone();
self.position.set(position);
Ok(ret)
} else {
Err(objiter::new_stop_iteration(vm))
}
}
#[pymethod(name = "__iter__")]
fn iter(zelf: PyRef<Self>, _vm: &VirtualMachine) -> PyRef<Self> {
zelf
}
}
#[rustfmt::skip] // to avoid line splitting
pub fn init(context: &PyContext) {
let list_type = &context.list_type;
@@ -835,6 +876,7 @@ pub fn init(context: &PyContext) {
"__getitem__" => context.new_rustfunc(PyListRef::getitem),
"__iter__" => context.new_rustfunc(PyListRef::iter),
"__setitem__" => context.new_rustfunc(PyListRef::setitem),
"__reversed__" => context.new_rustfunc(PyListRef::reversed),
"__mul__" => context.new_rustfunc(PyListRef::mul),
"__imul__" => context.new_rustfunc(PyListRef::imul),
"__len__" => context.new_rustfunc(PyListRef::len),
@@ -856,4 +898,5 @@ pub fn init(context: &PyContext) {
});
PyListIterator::extend_class(context, &context.listiterator_type);
PyListReverseIterator::extend_class(context, &context.listreverseiterator_type);
}

View File

@@ -134,6 +134,7 @@ pub struct PyContext {
pub false_value: PyIntRef,
pub list_type: PyClassRef,
pub listiterator_type: PyClassRef,
pub listreverseiterator_type: PyClassRef,
pub dictkeyiterator_type: PyClassRef,
pub dictvalueiterator_type: PyClassRef,
pub dictitemiterator_type: PyClassRef,
@@ -271,6 +272,7 @@ impl PyContext {
let str_type = create_type("str", &type_type, &object_type);
let list_type = create_type("list", &type_type, &object_type);
let listiterator_type = create_type("list_iterator", &type_type, &object_type);
let listreverseiterator_type = create_type("list_reverseiterator", &type_type, &object_type);
let dictkeys_type = create_type("dict_keys", &type_type, &object_type);
let dictvalues_type = create_type("dict_values", &type_type, &object_type);
let dictitems_type = create_type("dict_items", &type_type, &object_type);
@@ -337,6 +339,7 @@ impl PyContext {
staticmethod_type,
list_type,
listiterator_type,
listreverseiterator_type,
dictkeys_type,
dictvalues_type,
dictitems_type,
@@ -467,6 +470,10 @@ impl PyContext {
pub fn listiterator_type(&self) -> PyClassRef {
self.listiterator_type.clone()
}
pub fn listreverseiterator_type(&self) -> PyClassRef {
self.listreverseiterator_type.clone()
}
pub fn module_type(&self) -> PyClassRef {
self.module_type.clone()