Replace vm.extract_elements with TryFromBorrowedObject

This commit is contained in:
Jeong Yunwon
2022-04-17 06:01:35 +09:00
parent fac28934f6
commit 828c28ebb8
23 changed files with 64 additions and 66 deletions

View File

@@ -649,7 +649,7 @@ fn get_importer(path: &str, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>
let path = vm.ctx.new_str(path);
let path_hooks = vm.sys_module.clone().get_attr("path_hooks", vm)?;
let mut importer = None;
let path_hooks: Vec<PyObjectRef> = vm.extract_elements(&path_hooks)?;
let path_hooks: Vec<PyObjectRef> = path_hooks.try_into_value(vm)?;
for path_hook in path_hooks {
match vm.invoke(&path_hook, (path.clone(),)) {
Ok(imp) => {

View File

@@ -4,7 +4,7 @@ pub(crate) use math::make_module;
mod math {
use crate::vm::{
builtins::{try_bigint_to_f64, try_f64_to_bigint, PyFloat, PyInt, PyIntRef},
function::{ArgIntoFloat, ArgIterable, ArgSequence, OptionalArg, PosArgs},
function::{ArgIntoFloat, ArgIterable, OptionalArg, PosArgs},
utils::Either,
PyObject, PyObjectRef, PyRef, PyResult, TypeProtocol, VirtualMachine,
};
@@ -288,16 +288,12 @@ mod math {
}
#[pyfunction]
fn dist(
p: ArgSequence<ArgIntoFloat>,
q: ArgSequence<ArgIntoFloat>,
vm: &VirtualMachine,
) -> PyResult<f64> {
fn dist(p: Vec<ArgIntoFloat>, q: Vec<ArgIntoFloat>, vm: &VirtualMachine) -> PyResult<f64> {
let mut max = 0.0;
let mut has_nan = false;
let p = ArgIntoFloat::vec_into_f64(p.into_vec());
let q = ArgIntoFloat::vec_into_f64(q.into_vec());
let p = ArgIntoFloat::vec_into_f64(p);
let q = ArgIntoFloat::vec_into_f64(q);
let mut diffs = vec![];
if p.len() != q.len() {

View File

@@ -130,7 +130,7 @@ mod resource {
struct Limits(libc::rlimit);
impl TryFromBorrowedObject for Limits {
fn try_from_borrowed_object(vm: &VirtualMachine, obj: &PyObject) -> PyResult<Self> {
let seq = vm.extract_elements::<libc::rlim_t>(obj)?;
let seq: Vec<libc::rlim_t> = obj.try_to_value(vm)?;
match *seq {
[cur, max] => Ok(Self(libc::rlimit {
rlim_cur: cur & RLIM_INFINITY,

View File

@@ -1,4 +1,6 @@
use crate::vm::{builtins::PyListRef, PyObjectRef, PyResult, TryFromObject, VirtualMachine};
use crate::vm::{
builtins::PyListRef, PyObject, PyObjectRef, PyResult, TryFromObject, VirtualMachine,
};
use std::{io, mem};
pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef {
@@ -182,8 +184,8 @@ mod decl {
}
let deadline = timeout.map(|s| time::time(vm).unwrap() + s);
let seq2set = |list| -> PyResult<(Vec<Selectable>, FdSet)> {
let v = vm.extract_elements::<Selectable>(list)?;
let seq2set = |list: &PyObject| -> PyResult<(Vec<Selectable>, FdSet)> {
let v: Vec<Selectable> = list.try_to_value(vm)?;
let mut fds = FdSet::new();
for fd in &v {
fds.insert(fd.fno);

View File

@@ -99,7 +99,7 @@ impl PyList {
#[pymethod]
pub(crate) fn extend(&self, x: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
let mut new_elements = vm.extract_elements(&x)?;
let mut new_elements = x.try_to_value(vm)?;
self.borrow_vec_mut().append(&mut new_elements);
Ok(())
}
@@ -350,7 +350,7 @@ impl PyList {
#[pymethod(magic)]
fn init(&self, iterable: OptionalArg<PyObjectRef>, vm: &VirtualMachine) -> PyResult<()> {
let mut elements = if let OptionalArg::Present(iterable) = iterable {
vm.extract_elements(&iterable)?
iterable.try_to_value(vm)?
} else {
vec![]
};

View File

@@ -704,7 +704,7 @@ impl Constructor for PyFrozenSet {
} else {
iterable
};
vm.extract_elements(&iterable)?
iterable.try_to_value(vm)?
} else {
vec![]
};

View File

@@ -102,7 +102,7 @@ impl Constructor for PyTuple {
} else {
iterable
};
vm.extract_elements(&iterable)?
iterable.try_to_value(vm)?
} else {
vec![]
};

View File

@@ -119,3 +119,9 @@ impl<T: TryFromObject> TryFromObject for Option<T> {
}
}
}
impl<T: TryFromObject> TryFromBorrowedObject for Vec<T> {
fn try_from_borrowed_object(vm: &VirtualMachine, value: &PyObject) -> PyResult<Self> {
vm.extract_elements_with(value, |obj| T::try_from_object(vm, obj))
}
}

View File

@@ -1032,7 +1032,7 @@ impl ExecutingFrame<'_> {
}
bytecode::Instruction::UnpackSequence { size } => {
let value = self.pop_value();
let elements = vm.extract_elements(&value).map_err(|e| {
let elements: Vec<_> = value.try_to_value(vm).map_err(|e| {
if e.class().is(&vm.ctx.exceptions.type_error) {
vm.new_type_error(format!(
"cannot unpack non-iterable {} object",
@@ -1121,9 +1121,10 @@ impl ExecutingFrame<'_> {
) -> PyResult<Vec<PyObjectRef>> {
let elements = self.pop_multiple(size);
if unpack {
let mut result: Vec<PyObjectRef> = vec![];
let mut result = Vec::<PyObjectRef>::new();
for element in elements {
result.extend(vm.extract_elements(&element)?);
let items: Vec<_> = element.try_to_value(vm)?;
result.extend(items);
}
Ok(result)
} else {
@@ -1172,7 +1173,7 @@ impl ExecutingFrame<'_> {
if let Some(dict) = module.dict() {
let filter_pred: Box<dyn Fn(&str) -> bool> =
if let Ok(all) = dict.get_item("__all__", vm) {
let all: Vec<PyStrRef> = vm.extract_elements(&all)?;
let all: Vec<PyStrRef> = all.try_to_value(vm)?;
let all: Vec<String> = all
.into_iter()
.map(|name| name.as_str().to_owned())
@@ -1384,7 +1385,7 @@ impl ExecutingFrame<'_> {
IndexMap::new()
};
let args = self.pop_value();
let args = vm.extract_elements(&args)?;
let args = args.try_to_value(vm)?;
Ok(FuncArgs { args, kwargs })
}
@@ -1497,7 +1498,7 @@ impl ExecutingFrame<'_> {
fn execute_unpack_ex(&mut self, vm: &VirtualMachine, before: u8, after: u8) -> FrameResult {
let (before, after) = (before as usize, after as usize);
let value = self.pop_value();
let mut elements = vm.extract_elements::<PyObjectRef>(&value)?;
let elements: Vec<_> = value.try_to_value(vm)?;
let min_expected = before + after;
let middle = elements.len().checked_sub(min_expected).ok_or_else(|| {
@@ -1508,6 +1509,7 @@ impl ExecutingFrame<'_> {
))
})?;
let mut elements = elements;
// Elements on stack from right-to-left:
self.state
.stack

View File

@@ -150,8 +150,9 @@ impl<T> ArgSequence<T> {
&self.0
}
}
impl<T: TryFromObject> TryFromObject for ArgSequence<T> {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
vm.extract_elements(&obj).map(Self)
obj.try_to_value(vm).map(Self)
}
}

View File

@@ -155,8 +155,6 @@ impl PyMapping<'_> {
// TODO
// PySequence::from(&iter).list(vm).map(|x| x.into())
vm.ctx
.new_list(vm.extract_elements(&iter)?)
.into_pyresult(vm)
vm.ctx.new_list(iter.try_to_value(vm)?).into_pyresult(vm)
}
}

View File

@@ -289,7 +289,7 @@ impl PySequence<'_> {
}
pub fn list(&self, vm: &VirtualMachine) -> PyResult<PyListRef> {
let list = vm.ctx.new_list(vm.extract_elements(self.obj)?);
let list = vm.ctx.new_list(self.obj.try_to_value(vm)?);
Ok(list)
}

View File

@@ -36,7 +36,7 @@ mod _ast {
fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
let obj: PyObjectRef = zelf.clone_class().into();
let fields = obj.get_attr("_fields", vm)?;
let fields = vm.extract_elements::<PyStrRef>(&fields)?;
let fields: Vec<PyStrRef> = fields.try_to_value(vm)?;
let numargs = args.args.len();
if numargs > fields.len() {
return Err(vm.new_type_error(format!(

View File

@@ -457,7 +457,7 @@ mod builtins {
}
args.args
}
std::cmp::Ordering::Equal => vm.extract_elements(&args.args[0])?,
std::cmp::Ordering::Equal => args.args[0].try_to_value(vm)?,
std::cmp::Ordering::Less => {
// zero arguments means type error:
return Err(vm.new_type_error("Expected 1 or more arguments".to_owned()));
@@ -735,7 +735,7 @@ mod builtins {
#[pyfunction]
fn sorted(iterable: PyObjectRef, opts: SortOptions, vm: &VirtualMachine) -> PyResult<PyList> {
let items = vm.extract_elements(&iterable)?;
let items: Vec<_> = iterable.try_to_value(vm)?;
let lst = PyList::from(items);
lst.sort(opts, vm)?;
Ok(lst)

View File

@@ -91,7 +91,7 @@ mod _collections {
let elements = iterable
.into_option()
.map(|iter| {
let mut elements: Vec<PyObjectRef> = vm.extract_elements(&iter)?;
let mut elements: Vec<PyObjectRef> = iter.try_to_value(vm)?;
if let Some(maxlen) = maxlen {
elements.drain(..elements.len().saturating_sub(maxlen));
}
@@ -177,7 +177,7 @@ mod _collections {
fn _extend(&self, iter: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
self.state.fetch_add(1);
let max_len = self.maxlen;
let mut elements: Vec<PyObjectRef> = vm.extract_elements(iter)?;
let mut elements: Vec<PyObjectRef> = iter.try_to_value(vm)?;
if let Some(max_len) = max_len {
if max_len > elements.len() {
let mut deque = self.borrow_deque_mut();
@@ -195,7 +195,7 @@ mod _collections {
#[pymethod]
fn extendleft(&self, iter: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
let max_len = self.maxlen;
let mut elements: Vec<PyObjectRef> = vm.extract_elements(&iter)?;
let mut elements: Vec<PyObjectRef> = iter.try_to_value(vm)?;
elements.reverse();
if let Some(max_len) = max_len {

View File

@@ -451,7 +451,7 @@ mod _io {
) -> PyResult<Vec<PyObjectRef>> {
let hint = hint.flatten().unwrap_or(-1);
if hint <= 0 {
return vm.extract_elements(&instance);
return instance.try_to_value(vm);
}
let hint = hint as usize;
let mut ret = Vec::new();

View File

@@ -48,7 +48,7 @@ mod decl {
vm: &VirtualMachine,
) -> PyResult<PyRef<Self>> {
PyItertoolsChain {
iterables: vm.extract_elements(&iterable)?,
iterables: iterable.try_to_value(vm)?,
cur_idx: AtomicCell::new(0),
cached_iter: PyRwLock::new(None),
}
@@ -366,7 +366,8 @@ mod decl {
let function = &zelf.function;
match obj {
PyIterReturn::Return(obj) => {
PyIterReturn::from_pyresult(vm.invoke(function, vm.extract_elements(&obj)?), vm)
let args: Vec<_> = obj.try_to_value(vm)?;
PyIterReturn::from_pyresult(vm.invoke(function, args), vm)
}
PyIterReturn::StopIteration(v) => Ok(PyIterReturn::StopIteration(v)),
}
@@ -1075,7 +1076,7 @@ mod decl {
let repeat = args.repeat.unwrap_or(1);
let mut pools = Vec::new();
for arg in iterables.iter() {
pools.push(vm.extract_elements(arg)?);
pools.push(arg.try_to_value(vm)?);
}
let pools = std::iter::repeat(pools)
.take(repeat)
@@ -1176,7 +1177,7 @@ mod decl {
Self::Args { iterable, r }: Self::Args,
vm: &VirtualMachine,
) -> PyResult {
let pool = vm.extract_elements(&iterable)?;
let pool: Vec<_> = iterable.try_to_value(vm)?;
let r = r.as_bigint();
if r.is_negative() {
@@ -1267,7 +1268,7 @@ mod decl {
Self::Args { iterable, r }: Self::Args,
vm: &VirtualMachine,
) -> PyResult {
let pool = vm.extract_elements(&iterable)?;
let pool: Vec<_> = iterable.try_to_value(vm)?;
let r = r.as_bigint();
if r.is_negative() {
return Err(vm.new_value_error("r must be non-negative".to_owned()));
@@ -1363,7 +1364,7 @@ mod decl {
Self::Args { iterable, r }: Self::Args,
vm: &VirtualMachine,
) -> PyResult {
let pool = vm.extract_elements(&iterable)?;
let pool: Vec<_> = iterable.try_to_value(vm)?;
let n = pool.len();
// If r is not provided, r == n. If provided, r must be a positive integer, or None.

View File

@@ -30,7 +30,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef {
pub mod module {
use crate::{
builtins::{PyDictRef, PyInt, PyIntRef, PyListRef, PyStrRef, PyTupleRef, PyTypeRef},
function::{IntoPyException, IntoPyObject, OptionalArg},
function::{ArgBytesLike, IntoPyException, IntoPyObject, OptionalArg},
stdlib::os::{
errno_err, DirFd, FollowSymlinks, PathOrFd, PyPathLike, SupportFunc, TargetIsDirectory,
_os, fs_metadata, IOErrorBuilder,
@@ -1929,19 +1929,14 @@ pub mod module {
fn _extract_vec_bytes(
x: OptionalArg,
vm: &VirtualMachine,
) -> PyResult<Option<Vec<crate::function::ArgBytesLike>>> {
let inner = match x.into_option() {
Some(v) => {
let v = vm.extract_elements::<crate::function::ArgBytesLike>(&v)?;
if v.is_empty() {
None
} else {
Some(v)
}
}
None => None,
};
Ok(inner)
) -> PyResult<Option<Vec<ArgBytesLike>>> {
x.into_option()
.map(|x| {
let v: Vec<ArgBytesLike> = x.try_to_value(vm)?;
Ok(if v.is_empty() { None } else { Some(v) })
})
.transpose()
.map(Option::flatten)
}
#[cfg(target_os = "macos")]

View File

@@ -83,13 +83,14 @@ mod _sre {
// isbytes will be hanging (-1)
// here is just a hack to let re.Scanner works only with str not bytes
let isbytes = !vm.is_none(&pattern) && !pattern.payload_is::<PyStr>();
let code = code.try_to_value(vm)?;
Ok(Pattern {
pattern,
flags: SreFlag::from_bits_truncate(flags),
code: vm.extract_elements::<u32>(&code)?,
code,
groups,
groupindex,
indexgroup: vm.extract_elements(&indexgroup)?,
indexgroup: indexgroup.try_to_value(vm)?,
isbytes,
})
}

View File

@@ -377,7 +377,7 @@ mod time {
impl TryFromObject for PyStructTime {
fn try_from_object(vm: &VirtualMachine, seq: PyObjectRef) -> PyResult<Self> {
let seq = vm.extract_elements::<PyObjectRef>(&seq)?;
let seq: Vec<_> = seq.try_to_value(vm)?;
if seq.len() != 9 {
return Err(
vm.new_type_error("time.struct_time() takes a sequence of length 9".to_owned())

View File

@@ -62,12 +62,12 @@ pub fn offer_suggestions(exc: &PyBaseExceptionRef, vm: &VirtualMachine) -> Optio
return Some(suggestions);
};
let globals = vm.extract_elements(tb.frame.globals.as_object()).ok()?;
let globals: Vec<_> = tb.frame.globals.as_object().try_to_value(vm).ok()?;
if let Some(suggestions) = calculate_suggestions(globals.as_slice().iter(), &name) {
return Some(suggestions);
};
let builtins = vm.extract_elements(tb.frame.builtins.as_object()).ok()?;
let builtins: Vec<_> = tb.frame.builtins.as_object().try_to_value(vm).ok()?;
calculate_suggestions(builtins.as_slice().iter(), &name)
} else {
None

View File

@@ -25,7 +25,7 @@ use crate::{
pyobject::PyLease,
scope::Scope,
signal, stdlib, IdProtocol, PyContext, PyObject, PyObjectRef, PyObjectWrap, PyRef, PyRefExact,
PyResult, PyValue, TryFromObject, TypeProtocol,
PyResult, PyValue, TypeProtocol,
};
use crossbeam_utils::atomic::AtomicCell;
use std::{
@@ -648,10 +648,6 @@ impl VirtualMachine {
slice.iter().map(|obj| func(obj.clone())).collect()
}
pub fn extract_elements<T: TryFromObject>(&self, value: &PyObject) -> PyResult<Vec<T>> {
self.extract_elements_with(value, |obj| T::try_from_object(self, obj))
}
pub fn map_iterable_object<F, R>(&self, obj: &PyObject, mut f: F) -> PyResult<PyResult<Vec<R>>>
where
F: FnMut(PyObjectRef) -> PyResult<R>,

View File

@@ -133,7 +133,7 @@ impl VirtualMachine {
.invoke((), self)?,
None => self.call_method(self.current_locals()?.as_object(), "keys", ())?,
};
let items = self.extract_elements(&seq)?;
let items: Vec<_> = seq.try_to_value(self)?;
let lst = PyList::from(items);
lst.sort(Default::default(), self)?;
Ok(lst)