8000 Add __length_hint__ support for iterators by coolreader18 · Pull Request #1666 · RustPython/RustPython · GitHub
[go: up one dir, main page]

Skip to content

Add __length_hint__ support for iterators #1666

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jan 10, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add objsequence::{opt_,}len
  • Loading branch information
coolreader18 committed Jan 10, 2020
commit 6b537f15e5cb358812a27a9c82a878730b7f5c26
8 changes: 3 additions & 5 deletions vm/src/builtins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use crate::obj::objdict::PyDictRef;
use crate::obj::objfunction::PyFunctionRef;
use crate::obj::objint::{self, PyIntRef};
use crate::obj::objiter;
use crate::obj::objsequence;
use crate::obj::objstr::{PyString, PyStringRef};
use crate::obj::objtype::{self, PyClassRef};
use crate::pyhash;
Expand Down Expand Up @@ -384,11 +385,8 @@ fn builtin_iter(iter_target: PyObjectRef, vm: &VirtualMachine) -> PyResult {
objiter::get_iter(vm, &iter_target)
}

fn builtin_len(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult {
let method = vm.get_method_or_type_error(obj.clone(), "__len__", || {
format!("object of type '{}' has no len()", obj.class().name)
})?;
vm.invoke(&method, PyFuncArgs::default())
fn builtin_len(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
objsequence::len(&obj, vm)
}

fn builtin_locals(vm: &VirtualMachine) -> PyDictRef {
Expand Down
2 changes: 0 additions & 2 deletions vm/src/exceptions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,8 +250,6 @@ pub fn write_exception_inner<W: Write>(
write_traceback_entry(output, traceback)?;
tb = traceback.next.as_ref();
}
} else {
writeln!(output, "No traceback set on exception")?;
}

let varargs = exc.args();
Expand Down
30 changes: 30 additions & 0 deletions vm/src/obj/objsequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,3 +263,33 @@ pub fn is_valid_slice_arg(
Ok(None)
}
}

pub fn opt_len(obj: &PyObjectRef, vm: &VirtualMachine) -> Option<PyResult<usize>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be in VirutalMachine?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally had it there, but I called it get_len which seemed like a weird name (does it get the length of the VirtualMachine itself?), and it seemed slightly niche to be on VirtualMachine. Idk, it relates to the sequence protocol, so I figured it would best fit in objsequence.

vm.get_method(obj.clone(), "__len__").map(|len| {
let len = vm.invoke(&len?, vec![])?;
let len = len
.payload_if_subclass::<PyInt>(vm)
.ok_or_else(|| {
vm.new_type_error(format!(
"'{}' object cannot be interpreted as an integer",
len.class().name
))
})?
.as_bigint();
if len.is_negative() {
return Err(vm.new_value_error("__len__() should return >= 0".to_string()));
}
len.to_usize().ok_or_else(|| {
vm.new_overflow_error("cannot fit __len__() result into usize".to_string())
})
})
}

pub fn len(obj: &PyObjectRef, vm: &VirtualMachine) -> PyResult<usize> {
opt_len(obj, vm).unwrap_or_else(|| {
Err(vm.new_type_error(format!(
"object of type '{}' has no len()",
obj.class().name
)))
})
}
0