Make vm.extract_elements generic

This commit is contained in:
coolreader18
2019-10-20 20:32:21 -05:00
committed by Noah
parent 8542224071
commit 2ea34c8d83
4 changed files with 18 additions and 16 deletions

View File

@@ -1043,7 +1043,7 @@ impl Frame {
fn execute_unpack_ex(&self, vm: &VirtualMachine, before: usize, after: usize) -> FrameResult {
let value = self.pop_value();
let elements = vm.extract_elements(&value)?;
let elements = vm.extract_elements::<PyObjectRef>(&value)?;
let min_expected = before + after;
if elements.len() < min_expected {
Err(vm.new_value_error(format!(

View File

@@ -7,7 +7,7 @@ use std::cell::Cell;
use super::objtuple::PyTuple;
use super::objtype::{self, PyClassRef};
use crate::pyobject::{
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol,
};
use crate::vm::VirtualMachine;
@@ -60,14 +60,10 @@ pub fn get_next_object(
}
/* Retrieve all elements from an iterator */
pub fn get_all(vm: &VirtualMachine, iter_obj: &PyObjectRef) -> PyResult<Vec<PyObjectRef>> {
pub fn get_all<T: TryFromObject>(vm: &VirtualMachine, iter_obj: &PyObjectRef) -> PyResult<Vec<T>> {
let mut elements = vec![];
loop {
let element = get_next_object(vm, iter_obj)?;
match element {
Some(v) => elements.push(v),
None => break,
}
while let Some(element) = get_next_object(vm, iter_obj)? {
elements.push(T::try_from_object(vm, element)?);
}
Ok(elements)
}

View File

@@ -941,6 +941,7 @@ where
}
impl TryFromObject for PyObjectRef {
#[inline]
fn try_from_object(_vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
Ok(obj)
}

View File

@@ -808,17 +808,22 @@ impl VirtualMachine {
Ok(())
}
pub fn extract_elements(&self, value: &PyObjectRef) -> PyResult<Vec<PyObjectRef>> {
pub fn extract_elements<T: TryFromObject>(&self, value: &PyObjectRef) -> PyResult<Vec<T>> {
// Extract elements from item, if possible:
let elements = if objtype::isinstance(value, &self.ctx.tuple_type()) {
objsequence::get_elements_tuple(value).to_vec()
if objtype::isinstance(value, &self.ctx.tuple_type()) {
objsequence::get_elements_tuple(value)
.iter()
.map(|obj| T::try_from_object(self, obj.clone()))
.collect()
} else if objtype::isinstance(value, &self.ctx.list_type()) {
objsequence::get_elements_list(value).to_vec()
objsequence::get_elements_list(value)
.iter()
.map(|obj| T::try_from_object(self, obj.clone()))
.collect()
} else {
let iter = objiter::get_iter(self, value)?;
objiter::get_all(self, &iter)?
};
Ok(elements)
objiter::get_all(self, &iter)
}
}
// get_attribute should be used for full attribute access (usually from user code).