mirror of
https://github.com/RustPython/RustPython.git
synced 2026-06-09 22:49:57 +09:00
move iterator::length_hint to vm
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
use super::PyTypeRef;
|
||||
use crate::{
|
||||
function::PosArgs,
|
||||
iterator,
|
||||
protocol::{PyIter, PyIterReturn},
|
||||
slots::{IteratorIterable, SlotConstructor, SlotIterator},
|
||||
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, VirtualMachine,
|
||||
@@ -38,7 +37,7 @@ impl PyMap {
|
||||
#[pymethod(magic)]
|
||||
fn length_hint(&self, vm: &VirtualMachine) -> PyResult<usize> {
|
||||
self.iterators.iter().try_fold(0, |prev, cur| {
|
||||
let cur = iterator::length_hint(vm, cur.as_object().clone())?.unwrap_or(0);
|
||||
let cur = vm.length_hint(cur.as_object().clone())?.unwrap_or(0);
|
||||
let max = std::cmp::max(prev, cur);
|
||||
Ok(max)
|
||||
})
|
||||
|
||||
@@ -14,7 +14,6 @@ use crate::{
|
||||
coroutine::Coro,
|
||||
exceptions::{self, ExceptionCtor},
|
||||
function::FuncArgs,
|
||||
iterator,
|
||||
protocol::{PyIter, PyIterReturn},
|
||||
scope::Scope,
|
||||
slots::PyComparisonOp,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use super::IntoFuncArgs;
|
||||
use crate::{
|
||||
builtins::iter::PySequenceIterator,
|
||||
iterator,
|
||||
protocol::{PyIter, PyIterReturn},
|
||||
PyObjectRef, PyResult, PyValue, TryFromObject, TypeProtocol, VirtualMachine,
|
||||
};
|
||||
@@ -58,7 +57,7 @@ impl<T> ArgIterable<T> {
|
||||
None => PySequenceIterator::new(self.iterable.clone()).into_object(vm),
|
||||
};
|
||||
|
||||
let length_hint = iterator::length_hint(vm, iter_obj.clone())?;
|
||||
let length_hint = vm.length_hint(iter_obj.clone())?;
|
||||
|
||||
Ok(PyIterator {
|
||||
vm,
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
*/
|
||||
|
||||
use crate::{
|
||||
builtins::{PyBaseExceptionRef, PyInt},
|
||||
protocol::{PyIter, PyIterReturn},
|
||||
IdProtocol, PyObjectRef, PyResult, TypeProtocol, VirtualMachine,
|
||||
PyObjectRef, PyResult, VirtualMachine,
|
||||
};
|
||||
|
||||
pub fn try_map<F, R>(vm: &VirtualMachine, iter: &PyIter, cap: usize, mut f: F) -> PyResult<Vec<R>>
|
||||
@@ -25,52 +24,6 @@ where
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult<Option<usize>> {
|
||||
if let Some(len) = vm.obj_len_opt(&iter) {
|
||||
match len {
|
||||
Ok(len) => return Ok(Some(len)),
|
||||
Err(e) => {
|
||||
if !e.isinstance(&vm.ctx.exceptions.type_error) {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let hint = match vm.get_method(iter, "__length_hint__") {
|
||||
Some(hint) => hint?,
|
||||
None => return Ok(None),
|
||||
};
|
||||
let result = match vm.invoke(&hint, ()) {
|
||||
Ok(res) => {
|
||||
if res.is(&vm.ctx.not_implemented) {
|
||||
return Ok(None);
|
||||
}
|
||||
res
|
||||
}
|
||||
Err(e) => {
|
||||
return if e.isinstance(&vm.ctx.exceptions.type_error) {
|
||||
Ok(None)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
let hint = result
|
||||
.payload_if_subclass::<PyInt>(vm)
|
||||
.ok_or_else(|| {
|
||||
vm.new_type_error(format!(
|
||||
"'{}' object cannot be interpreted as an integer",
|
||||
result.class().name()
|
||||
))
|
||||
})?
|
||||
.try_to_primitive::<isize>(vm)?;
|
||||
if hint.is_negative() {
|
||||
Err(vm.new_value_error("__length_hint__() should return >= 0".to_owned()))
|
||||
} else {
|
||||
Ok(Some(hint as usize))
|
||||
}
|
||||
}
|
||||
|
||||
// pub fn seq_iter_method(obj: PyObjectRef) -> PySequenceIterator {
|
||||
// PySequenceIterator::new_forward(obj)
|
||||
// }
|
||||
|
||||
@@ -13,7 +13,6 @@ mod _operator {
|
||||
use crate::{
|
||||
builtins::{PyInt, PyIntRef, PyStrRef, PyTypeRef},
|
||||
function::{ArgBytesLike, FuncArgs, KwArgs, OptionalArg},
|
||||
iterator,
|
||||
protocol::{PyIter, PyIterReturn},
|
||||
slots::{
|
||||
Callable,
|
||||
@@ -284,7 +283,8 @@ mod _operator {
|
||||
v.payload::<PyInt>().unwrap().try_to_primitive(vm)
|
||||
})
|
||||
.unwrap_or(Ok(0))?;
|
||||
iterator::length_hint(vm, obj).map(|v| vm.ctx.new_int(v.unwrap_or(default)))
|
||||
vm.length_hint(obj)
|
||||
.map(|v| vm.ctx.new_int(v.unwrap_or(default)))
|
||||
}
|
||||
|
||||
// Inplace Operators
|
||||
|
||||
50
vm/src/vm.rs
50
vm/src/vm.rs
@@ -1285,7 +1285,7 @@ impl VirtualMachine {
|
||||
.collect()
|
||||
} else {
|
||||
let iter = value.clone().get_iter(self)?;
|
||||
let cap = match iterator::length_hint(self, value.clone()) {
|
||||
let cap = match self.length_hint(value.clone()) {
|
||||
Err(e) if e.class().is(&self.ctx.exceptions.runtime_error) => return Err(e),
|
||||
Ok(Some(value)) => value,
|
||||
// Use a power of 2 as a default capacity.
|
||||
@@ -1333,7 +1333,7 @@ impl VirtualMachine {
|
||||
// TODO: put internal iterable type
|
||||
obj => {
|
||||
let iter = obj.clone().get_iter(self)?;
|
||||
let cap = match iterator::length_hint(self, obj.clone()) {
|
||||
let cap = match self.length_hint(obj.clone()) {
|
||||
Err(e) if e.class().is(&self.ctx.exceptions.runtime_error) => {
|
||||
return Ok(Err(e))
|
||||
}
|
||||
@@ -1926,6 +1926,52 @@ impl VirtualMachine {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn length_hint(&self, iter: PyObjectRef) -> PyResult<Option<usize>> {
|
||||
if let Some(len) = self.obj_len_opt(&iter) {
|
||||
match len {
|
||||
Ok(len) => return Ok(Some(len)),
|
||||
Err(e) => {
|
||||
if !e.isinstance(&self.ctx.exceptions.type_error) {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let hint = match self.get_method(iter, "__length_hint__") {
|
||||
Some(hint) => hint?,
|
||||
None => return Ok(None),
|
||||
};
|
||||
let result = match self.invoke(&hint, ()) {
|
||||
Ok(res) => {
|
||||
if res.is(&self.ctx.not_implemented) {
|
||||
return Ok(None);
|
||||
}
|
||||
res
|
||||
}
|
||||
Err(e) => {
|
||||
return if e.isinstance(&self.ctx.exceptions.type_error) {
|
||||
Ok(None)
|
||||
} else {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
};
|
||||
let hint = result
|
||||
.payload_if_subclass::<PyInt>(self)
|
||||
.ok_or_else(|| {
|
||||
self.new_type_error(format!(
|
||||
"'{}' object cannot be interpreted as an integer",
|
||||
result.class().name()
|
||||
))
|
||||
})?
|
||||
.try_to_primitive::<isize>(self)?;
|
||||
if hint.is_negative() {
|
||||
Err(self.new_value_error("__length_hint__() should return >= 0".to_owned()))
|
||||
} else {
|
||||
Ok(Some(hint as usize))
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks that the multiplication is able to be performed. On Ok returns the
|
||||
/// index as a usize for sequences to be able to use immediately.
|
||||
pub fn check_repeat_or_memory_error(&self, length: usize, n: isize) -> PyResult<usize> {
|
||||
|
||||
Reference in New Issue
Block a user