mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Support reversed on sequence
This commit is contained in:
1 parent
8b894a11fb
commit
60e799727f
4 files changed
+38
-17
No files matched your search
@@ -1 +1,4 @@
|
||||
assert list(reversed(range(5))) == [4, 3, 2, 1, 0]
|
||||
|
||||
l = [5,4,3,2,1]
|
||||
assert list(reversed(l)) == [1,2,3,4,5]
|
||||
+16
-6
@@ -2,12 +2,13 @@
|
||||
//!
|
||||
//! Implements functions listed here: https://docs.python.org/3/library/builtins.html
|
||||
|
||||
use std::cell::Cell;
|
||||
use std::char;
|
||||
use std::io::{self, Write};
|
||||
use std::str;
|
||||
|
||||
use num_bigint::Sign;
|
||||
use num_traits::{Signed, Zero};
|
||||
use num_traits::{Signed, ToPrimitive, Zero};
|
||||
|
||||
use crate::compile;
|
||||
use crate::obj::objbool;
|
||||
@@ -684,11 +685,20 @@ fn builtin_repr(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyStringRef>
|
||||
fn builtin_reversed(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
arg_check!(vm, args, required = [(obj, None)]);
|
||||
|
||||
// TODO: fallback to using __len__ and __getitem__, if object supports sequence protocol
|
||||
let method = vm.get_method_or_type_error(obj.clone(), "__reversed__", || {
|
||||
format!("argument to reversed() must be a sequence")
|
||||
})?;
|
||||
vm.invoke(method, PyFuncArgs::default())
|
||||
if let Some(reversed_method) = vm.get_method(obj.clone(), "__reversed__") {
|
||||
vm.invoke(reversed_method?, PyFuncArgs::default())
|
||||
} else {
|
||||
vm.get_method_or_type_error(obj.clone(), "__getitem__", || {
|
||||
format!("argument to reversed() must be a sequence")
|
||||
})?;
|
||||
let len = vm.call_method(&obj.clone(), "__len__", PyFuncArgs::default())?;
|
||||
let obj_iterator = objiter::PySequenceIterator {
|
||||
position: Cell::new(objint::get_value(&len).to_isize().unwrap() - 1),
|
||||
obj: obj.clone(),
|
||||
reversed: true,
|
||||
};
|
||||
Ok(obj_iterator.into_ref(vm).into_object())
|
||||
}
|
||||
}
|
||||
|
||||
fn builtin_round(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
|
||||
+18
-11
@@ -28,6 +28,7 @@ pub fn get_iter(vm: &VirtualMachine, iter_target: &PyObjectRef) -> PyResult {
|
||||
let obj_iterator = PySequenceIterator {
|
||||
position: Cell::new(0),
|
||||
obj: iter_target.clone(),
|
||||
reversed: false,
|
||||
};
|
||||
Ok(obj_iterator.into_ref(vm).into_object())
|
||||
}
|
||||
@@ -80,8 +81,9 @@ pub fn new_stop_iteration(vm: &VirtualMachine) -> PyObjectRef {
|
||||
#[pyclass]
|
||||
#[derive(Debug)]
|
||||
pub struct PySequenceIterator {
|
||||
pub position: Cell<usize>,
|
||||
pub position: Cell<isize>,
|
||||
pub obj: PyObjectRef,
|
||||
pub reversed: bool,
|
||||
}
|
||||
|
||||
impl PyValue for PySequenceIterator {
|
||||
@@ -94,17 +96,22 @@ impl PyValue for PySequenceIterator {
|
||||
impl PySequenceIterator {
|
||||
#[pymethod(name = "__next__")]
|
||||
fn next(&self, vm: &VirtualMachine) -> PyResult {
|
||||
let number = vm.ctx.new_int(self.position.get());
|
||||
match vm.call_method(&self.obj, "__getitem__", vec![number]) {
|
||||
Ok(val) => {
|
||||
self.position.set(self.position.get() + 1);
|
||||
Ok(val)
|
||||
if self.position.get() >= 0 {
|
||||
let step: isize = if self.reversed { -1 } else { 1 };
|
||||
let number = vm.ctx.new_int(self.position.get());
|
||||
match vm.call_method(&self.obj, "__getitem__", vec![number]) {
|
||||
Ok(val) => {
|
||||
self.position.set(self.position.get() + step);
|
||||
Ok(val)
|
||||
}
|
||||
Err(ref e) if objtype::isinstance(&e, &vm.ctx.exceptions.index_error) => {
|
||||
Err(new_stop_iteration(vm))
|
||||
}
|
||||
// also catches stop_iteration => stop_iteration
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
Err(ref e) if objtype::isinstance(&e, &vm.ctx.exceptions.index_error) => {
|
||||
Err(new_stop_iteration(vm))
|
||||
}
|
||||
// also catches stop_iteration => stop_iteration
|
||||
Err(e) => Err(e),
|
||||
} else {
|
||||
Err(new_stop_iteration(vm))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1149,6 +1149,7 @@ where
|
||||
objiter::PySequenceIterator {
|
||||
position: Cell::new(0),
|
||||
obj: obj.clone(),
|
||||
reversed: false,
|
||||
}
|
||||
.into_ref(vm)
|
||||
.into_object(),
|
||||
|
||||
Reference in new issue
Block a user