From 7bfd2e6e844e331fe4cd7eeaaf96715deb8ed512 Mon Sep 17 00:00:00 2001 From: Joey Date: Fri, 15 Mar 2019 21:27:11 -0700 Subject: [PATCH] Move function items out of pyobject module --- vm/src/builtins.rs | 9 +- vm/src/exceptions.rs | 3 +- vm/src/frame.rs | 5 +- vm/src/function.rs | 436 +++++++++++++++++++++++++++++++++ vm/src/lib.rs | 1 + vm/src/obj/objbool.rs | 3 +- vm/src/obj/objbuiltinfunc.rs | 3 +- vm/src/obj/objbytearray.rs | 11 +- vm/src/obj/objbytes.rs | 11 +- vm/src/obj/objclassmethod.rs | 3 +- vm/src/obj/objcode.rs | 10 +- vm/src/obj/objcomplex.rs | 13 +- vm/src/obj/objdict.rs | 5 +- vm/src/obj/objellipsis.rs | 3 +- vm/src/obj/objenumerate.rs | 13 +- vm/src/obj/objfilter.rs | 3 +- vm/src/obj/objframe.rs | 3 +- vm/src/obj/objfunction.rs | 5 +- vm/src/obj/objgenerator.rs | 5 +- vm/src/obj/objint.rs | 5 +- vm/src/obj/objiter.rs | 5 +- vm/src/obj/objlist.rs | 17 +- vm/src/obj/objmap.rs | 5 +- vm/src/obj/objmemory.rs | 5 +- vm/src/obj/objnone.rs | 3 +- vm/src/obj/objobject.rs | 14 +- vm/src/obj/objproperty.rs | 8 +- vm/src/obj/objrange.rs | 3 +- vm/src/obj/objset.rs | 10 +- vm/src/obj/objslice.rs | 11 +- vm/src/obj/objstaticmethod.rs | 3 +- vm/src/obj/objstr.rs | 5 +- vm/src/obj/objsuper.rs | 6 +- vm/src/obj/objtuple.rs | 4 +- vm/src/obj/objtype.rs | 5 +- vm/src/obj/objzip.rs | 5 +- vm/src/pyobject.rs | 436 +-------------------------------- vm/src/stdlib/ast.rs | 16 +- vm/src/stdlib/dis.rs | 3 +- vm/src/stdlib/io.rs | 10 +- vm/src/stdlib/json.rs | 4 +- vm/src/stdlib/keyword.rs | 9 +- vm/src/stdlib/math.rs | 9 +- vm/src/stdlib/os.rs | 9 +- vm/src/stdlib/platform.rs | 7 +- vm/src/stdlib/pystruct.rs | 13 +- vm/src/stdlib/random.rs | 8 +- vm/src/stdlib/re.rs | 6 +- vm/src/stdlib/socket.rs | 5 +- vm/src/stdlib/time_module.rs | 8 +- vm/src/stdlib/tokenize.rs | 8 +- vm/src/stdlib/types.rs | 3 +- vm/src/sysmodule.rs | 11 +- vm/src/vm.rs | 4 +- wasm/lib/src/browser_module.rs | 19 +- wasm/lib/src/convert.rs | 21 +- wasm/lib/src/vm_class.rs | 22 +- wasm/lib/src/wasm_builtins.rs | 8 +- 58 files changed, 670 insertions(+), 628 deletions(-) create mode 100644 vm/src/function.rs diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index 86f6e8472..7e27d9f26 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -7,6 +7,8 @@ use std::char; use std::io::{self, Write}; use std::path::PathBuf; +use num_traits::{Signed, ToPrimitive}; + use crate::compile; use crate::import::import_module; use crate::obj::objbool; @@ -17,16 +19,15 @@ use crate::obj::objstr; use crate::obj::objtype; use crate::frame::Scope; +use crate::function::PyFuncArgs; use crate::pyobject::{ - AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol, + AttributeProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol, }; +use crate::vm::VirtualMachine; #[cfg(not(target_arch = "wasm32"))] use crate::stdlib::io::io_open; -use crate::vm::VirtualMachine; -use num_traits::{Signed, ToPrimitive}; - fn get_locals(vm: &mut VirtualMachine) -> PyObjectRef { let d = vm.new_dict(); // TODO: implement dict_iter_items? diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index 94853d5d0..419033808 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -1,8 +1,9 @@ +use crate::function::PyFuncArgs; use crate::obj::objsequence; use crate::obj::objstr; use crate::obj::objtype; use crate::pyobject::{ - create_type, AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol, + create_type, AttributeProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/frame.rs b/vm/src/frame.rs index 5be248d06..98369efd8 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -8,6 +8,7 @@ use rustpython_parser::ast; use crate::builtins; use crate::bytecode; +use crate::function::PyFuncArgs; use crate::obj::objbool; use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objcode; @@ -20,8 +21,8 @@ use crate::obj::objslice::PySlice; use crate::obj::objstr; use crate::obj::objtype; use crate::pyobject::{ - AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, - PyResult, PyValue, TryFromObject, TypeProtocol, + AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyObject, PyObjectRef, PyResult, + PyValue, TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/function.rs b/vm/src/function.rs new file mode 100644 index 000000000..7b4adebd0 --- /dev/null +++ b/vm/src/function.rs @@ -0,0 +1,436 @@ +use std::collections::HashMap; +use std::iter; +use std::ops::RangeInclusive; + +use crate::obj::objtype; +use crate::pyobject::{IntoPyObject, PyObjectRef, PyResult, TryFromObject, TypeProtocol}; +use crate::vm::VirtualMachine; + +use self::OptionalArg::*; + +/// The `PyFuncArgs` struct is one of the most used structs then creating +/// a rust function that can be called from python. It holds both positional +/// arguments, as well as keyword arguments passed to the function. +#[derive(Debug, Default, Clone)] +pub struct PyFuncArgs { + pub args: Vec, + pub kwargs: Vec<(String, PyObjectRef)>, +} + +/// Conversion from vector of python objects to function arguments. +impl From> for PyFuncArgs { + fn from(args: Vec) -> Self { + PyFuncArgs { + args: args, + kwargs: vec![], + } + } +} + +impl From for PyFuncArgs { + fn from(arg: PyObjectRef) -> Self { + PyFuncArgs { + args: vec![arg], + kwargs: vec![], + } + } +} + +impl PyFuncArgs { + pub fn new(mut args: Vec, kwarg_names: Vec) -> PyFuncArgs { + let mut kwargs = vec![]; + for name in kwarg_names.iter().rev() { + kwargs.push((name.clone(), args.pop().unwrap())); + } + PyFuncArgs { args, kwargs } + } + + pub fn insert(&self, item: PyObjectRef) -> PyFuncArgs { + let mut args = PyFuncArgs { + args: self.args.clone(), + kwargs: self.kwargs.clone(), + }; + args.args.insert(0, item); + args + } + + pub fn shift(&mut self) -> PyObjectRef { + self.args.remove(0) + } + + pub fn get_kwarg(&self, key: &str, default: PyObjectRef) -> PyObjectRef { + for (arg_name, arg_value) in self.kwargs.iter() { + if arg_name == key { + return arg_value.clone(); + } + } + default.clone() + } + + pub fn get_optional_kwarg(&self, key: &str) -> Option { + for (arg_name, arg_value) in self.kwargs.iter() { + if arg_name == key { + return Some(arg_value.clone()); + } + } + None + } + + pub fn get_optional_kwarg_with_type( + &self, + key: &str, + ty: PyObjectRef, + vm: &mut VirtualMachine, + ) -> Result, PyObjectRef> { + match self.get_optional_kwarg(key) { + Some(kwarg) => { + if objtype::isinstance(&kwarg, &ty) { + Ok(Some(kwarg)) + } else { + let expected_ty_name = vm.to_pystr(&ty)?; + let actual_ty_name = vm.to_pystr(&kwarg.typ())?; + Err(vm.new_type_error(format!( + "argument of type {} is required for named parameter `{}` (got: {})", + expected_ty_name, key, actual_ty_name + ))) + } + } + None => Ok(None), + } + } + + /// Serializes these arguments into an iterator starting with the positional + /// arguments followed by keyword arguments. + fn into_iter(self) -> impl Iterator { + self.args.into_iter().map(PyArg::Positional).chain( + self.kwargs + .into_iter() + .map(|(name, value)| PyArg::Keyword(name, value)), + ) + } + + /// Binds these arguments to their respective values. + /// + /// If there is an insufficient number of arguments, there are leftover + /// arguments after performing the binding, or if an argument is not of + /// the expected type, a TypeError is raised. + /// + /// If the given `FromArgs` includes any conversions, exceptions raised + /// during the conversion will halt the binding and return the error. + fn bind(self, vm: &mut VirtualMachine) -> PyResult { + let given_args = self.args.len(); + let mut args = self.into_iter().peekable(); + let bound = match T::from_args(vm, &mut args) { + Ok(args) => args, + Err(ArgumentError::TooFewArgs) => { + return Err(vm.new_type_error(format!( + "Expected at least {} arguments ({} given)", + T::arity().start(), + given_args, + ))); + } + Err(ArgumentError::Exception(ex)) => { + return Err(ex); + } + }; + + match args.next() { + None => Ok(bound), + Some(PyArg::Positional(_)) => Err(vm.new_type_error(format!( + "Expected at most {} arguments ({} given)", + T::arity().end(), + given_args, + ))), + Some(PyArg::Keyword(name, _)) => { + Err(vm.new_type_error(format!("Unexpected keyword argument {}", name))) + } + } + } +} + +pub enum PyArg { + Positional(PyObjectRef), + Keyword(String, PyObjectRef), +} + +pub enum ArgumentError { + TooFewArgs, + Exception(PyObjectRef), +} + +impl From for ArgumentError { + fn from(ex: PyObjectRef) -> Self { + ArgumentError::Exception(ex) + } +} + +/// Implemented by any type that can be accepted as a parameter to a built-in +/// function. +/// +pub trait FromArgs: Sized { + /// The range of positional arguments permitted by the function signature. + /// + /// Returns an empty range if not applicable. + fn arity() -> RangeInclusive { + 0..=0 + } + + /// Extracts this item from the next argument(s). + fn from_args( + vm: &mut VirtualMachine, + args: &mut iter::Peekable, + ) -> Result + where + I: Iterator; +} +/// A map of keyword arguments to their values. +/// +/// A built-in function with a `KwArgs` parameter is analagous to a Python +/// function with `*kwargs`. All remaining keyword arguments are extracted +/// (and hence the function will permit an arbitrary number of them). +/// +/// `KwArgs` optionally accepts a generic type parameter to allow type checks +/// or conversions of each argument. +pub struct KwArgs(HashMap); + +impl FromArgs for KwArgs +where + T: TryFromObject, +{ + fn from_args( + vm: &mut VirtualMachine, + args: &mut iter::Peekable, + ) -> Result + where + I: Iterator, + { + let mut kwargs = HashMap::new(); + while let Some(PyArg::Keyword(name, value)) = args.next() { + kwargs.insert(name, T::try_from_object(vm, value)?); + } + Ok(KwArgs(kwargs)) + } +} + +/// A list of positional argument values. +/// +/// A built-in function with a `Args` parameter is analagous to a Python +/// function with `*args`. All remaining positional arguments are extracted +/// (and hence the function will permit an arbitrary number of them). +/// +/// `Args` optionally accepts a generic type parameter to allow type checks +/// or conversions of each argument. +pub struct Args(Vec); + +impl FromArgs for Args +where + T: TryFromObject, +{ + fn from_args( + vm: &mut VirtualMachine, + args: &mut iter::Peekable, + ) -> Result + where + I: Iterator, + { + let mut varargs = Vec::new(); + while let Some(PyArg::Positional(value)) = args.next() { + varargs.push(T::try_from_object(vm, value)?); + } + Ok(Args(varargs)) + } +} + +impl FromArgs for T +where + T: TryFromObject, +{ + fn arity() -> RangeInclusive { + 1..=1 + } + + fn from_args( + vm: &mut VirtualMachine, + args: &mut iter::Peekable, + ) -> Result + where + I: Iterator, + { + if let Some(PyArg::Positional(value)) = args.next() { + Ok(T::try_from_object(vm, value)?) + } else { + Err(ArgumentError::TooFewArgs) + } + } +} + +/// An argument that may or may not be provided by the caller. +/// +/// This style of argument is not possible in pure Python. +pub enum OptionalArg { + Present(T), + Missing, +} + +impl OptionalArg { + pub fn into_option(self) -> Option { + match self { + Present(value) => Some(value), + Missing => None, + } + } +} + +impl FromArgs for OptionalArg +where + T: TryFromObject, +{ + fn arity() -> RangeInclusive { + 0..=1 + } + + fn from_args( + vm: &mut VirtualMachine, + args: &mut iter::Peekable, + ) -> Result + where + I: Iterator, + { + Ok(if let Some(PyArg::Positional(_)) = args.peek() { + let value = if let Some(PyArg::Positional(value)) = args.next() { + value + } else { + unreachable!() + }; + Present(T::try_from_object(vm, value)?) + } else { + Missing + }) + } +} + +// For functions that accept no arguments. Implemented explicitly instead of via +// macro below to avoid unused warnings. +impl FromArgs for () { + fn from_args( + _vm: &mut VirtualMachine, + _args: &mut iter::Peekable, + ) -> Result + where + I: Iterator, + { + Ok(()) + } +} + +// A tuple of types that each implement `FromArgs` represents a sequence of +// arguments that can be bound and passed to a built-in function. +// +// Technically, a tuple can contain tuples, which can contain tuples, and so on, +// so this actually represents a tree of values to be bound from arguments, but +// in practice this is only used for the top-level parameters. +macro_rules! tuple_from_py_func_args { + ($($T:ident),+) => { + impl<$($T),+> FromArgs for ($($T,)+) + where + $($T: FromArgs),+ + { + fn arity() -> RangeInclusive { + let mut min = 0; + let mut max = 0; + $( + let (start, end) = $T::arity().into_inner(); + min += start; + max += end; + )+ + min..=max + } + + fn from_args( + vm: &mut VirtualMachine, + args: &mut iter::Peekable + ) -> Result + where + I: Iterator + { + Ok(($($T::from_args(vm, args)?,)+)) + } + } + }; +} + +// Implement `FromArgs` for up to 5-tuples, allowing built-in functions to bind +// up to 5 top-level parameters (note that `Args`, `KwArgs`, nested tuples, etc. +// count as 1, so this should actually be more than enough). +tuple_from_py_func_args!(A); +tuple_from_py_func_args!(A, B); +tuple_from_py_func_args!(A, B, C); +tuple_from_py_func_args!(A, B, C, D); +tuple_from_py_func_args!(A, B, C, D, E); + +/// A built-in Python function. +pub type PyNativeFunc = Box PyResult + 'static>; + +/// Implemented by types that are or can generate built-in functions. +/// +/// For example, any function that: +/// +/// - Accepts a sequence of types that implement `FromArgs`, followed by a +/// `&mut VirtualMachine` +/// - Returns some type that implements `IntoPyObject` +/// +/// will generate a `PyNativeFunc` that performs the appropriate type and arity +/// checking, any requested conversions, and then if successful call the function +/// with the bound values. +/// +/// A bare `PyNativeFunc` also implements this trait, allowing the above to be +/// done manually, for rare situations that don't fit into this model. +pub trait IntoPyNativeFunc { + fn into_func(self) -> PyNativeFunc; +} + +impl IntoPyNativeFunc for F +where + F: Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult + 'static, +{ + fn into_func(self) -> PyNativeFunc { + Box::new(self) + } +} + +impl IntoPyNativeFunc for PyNativeFunc { + fn into_func(self) -> PyNativeFunc { + self + } +} + +// This is the "magic" that allows rust functions of varying signatures to +// generate native python functions. +// +// Note that this could be done without a macro - it is simply to avoid repetition. +macro_rules! into_py_native_func_tuple { + ($(($n:tt, $T:ident)),*) => { + impl IntoPyNativeFunc<($($T,)*), R> for F + where + F: Fn($($T,)* &mut VirtualMachine) -> R + 'static, + $($T: FromArgs,)* + ($($T,)*): FromArgs, + R: IntoPyObject, + { + fn into_func(self) -> PyNativeFunc { + Box::new(move |vm, args| { + let ($($n,)*) = args.bind::<($($T,)*)>(vm)?; + + (self)($($n,)* vm).into_pyobject(vm) + }) + } + } + }; +} + +into_py_native_func_tuple!(); +into_py_native_func_tuple!((a, A)); +into_py_native_func_tuple!((a, A), (b, B)); +into_py_native_func_tuple!((a, A), (b, B), (c, C)); +into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D)); +into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E)); diff --git a/vm/src/lib.rs b/vm/src/lib.rs index b32b91cb7..78696f9f3 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -41,6 +41,7 @@ pub mod eval; mod exceptions; pub mod format; pub mod frame; +pub mod function; pub mod import; pub mod obj; pub mod pyobject; diff --git a/vm/src/obj/objbool.rs b/vm/src/obj/objbool.rs index 486bb2dd7..815354b94 100644 --- a/vm/src/obj/objbool.rs +++ b/vm/src/obj/objbool.rs @@ -1,6 +1,7 @@ use num_traits::Zero; -use crate::pyobject::{IntoPyObject, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; +use crate::function::PyFuncArgs; +use crate::pyobject::{IntoPyObject, PyContext, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; use super::objdict::PyDict; diff --git a/vm/src/obj/objbuiltinfunc.rs b/vm/src/obj/objbuiltinfunc.rs index ae8dfbf99..ca181fea4 100644 --- a/vm/src/obj/objbuiltinfunc.rs +++ b/vm/src/obj/objbuiltinfunc.rs @@ -1,6 +1,7 @@ use std::fmt; -use crate::pyobject::{PyNativeFunc, PyObjectRef, PyValue}; +use crate::function::PyNativeFunc; +use crate::pyobject::{PyObjectRef, PyValue}; use crate::vm::VirtualMachine; pub struct PyBuiltinFunction { diff --git a/vm/src/obj/objbytearray.rs b/vm/src/obj/objbytearray.rs index d4641ae7d..4863c51d3 100644 --- a/vm/src/obj/objbytearray.rs +++ b/vm/src/obj/objbytearray.rs @@ -4,15 +4,14 @@ use std::cell::RefCell; use std::fmt::Write; use std::ops::{Deref, DerefMut}; -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; +use num_traits::ToPrimitive; + +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; +use crate::vm::VirtualMachine; use super::objint; - use super::objtype; -use crate::vm::VirtualMachine; -use num_traits::ToPrimitive; #[derive(Debug)] pub struct PyByteArray { diff --git a/vm/src/obj/objbytes.rs b/vm/src/obj/objbytes.rs index 5247d35c4..08c80b764 100644 --- a/vm/src/obj/objbytes.rs +++ b/vm/src/obj/objbytes.rs @@ -2,13 +2,16 @@ use std::cell::Cell; use std::hash::{Hash, Hasher}; use std::ops::Deref; -use super::objint; -use super::objtype; +use num_traits::ToPrimitive; + +use crate::function::PyFuncArgs; use crate::pyobject::{ - PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, + PyContext, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; -use num_traits::ToPrimitive; + +use super::objint; +use super::objtype; #[derive(Debug)] pub struct PyBytes { diff --git a/vm/src/obj/objclassmethod.rs b/vm/src/obj/objclassmethod.rs index 9c8ea3f8f..c2322b183 100644 --- a/vm/src/obj/objclassmethod.rs +++ b/vm/src/obj/objclassmethod.rs @@ -1,4 +1,5 @@ -use crate::pyobject::{AttributeProtocol, PyContext, PyFuncArgs, PyResult, TypeProtocol}; +use crate::function::PyFuncArgs; +use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { diff --git a/vm/src/obj/objcode.rs b/vm/src/obj/objcode.rs index 9897a47a0..2b0a4b935 100644 --- a/vm/src/obj/objcode.rs +++ b/vm/src/obj/objcode.rs @@ -2,13 +2,13 @@ */ -use crate::bytecode; -use crate::pyobject::{ - IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; -use crate::vm::VirtualMachine; use std::fmt; +use crate::bytecode; +use crate::function::PyFuncArgs; +use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol}; +use crate::vm::VirtualMachine; + pub struct PyCode { code: bytecode::CodeObject, } diff --git a/vm/src/obj/objcomplex.rs b/vm/src/obj/objcomplex.rs index 0d2d878b0..e5723f156 100644 --- a/vm/src/obj/objcomplex.rs +++ b/vm/src/obj/objcomplex.rs @@ -1,12 +1,13 @@ +use num_complex::Complex64; +use num_traits::ToPrimitive; + +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; +use crate::vm::VirtualMachine; + use super::objfloat; use super::objint; use super::objtype; -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; -use crate::vm::VirtualMachine; -use num_complex::Complex64; -use num_traits::ToPrimitive; #[derive(Debug, Copy, Clone, PartialEq)] pub struct PyComplex { diff --git a/vm/src/obj/objdict.rs b/vm/src/obj/objdict.rs index 3b37a801b..6bd86f651 100644 --- a/vm/src/obj/objdict.rs +++ b/vm/src/obj/objdict.rs @@ -3,9 +3,10 @@ use std::collections::HashMap; use std::fmt; use std::ops::{Deref, DerefMut}; +use crate::function::PyFuncArgs; use crate::pyobject::{ - PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, - PyValue, TypeProtocol, + PyAttributes, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, PyValue, + TypeProtocol, }; use crate::vm::{ReprGuard, VirtualMachine}; diff --git a/vm/src/obj/objellipsis.rs b/vm/src/obj/objellipsis.rs index 48120ea77..a0ed8f644 100644 --- a/vm/src/obj/objellipsis.rs +++ b/vm/src/obj/objellipsis.rs @@ -1,4 +1,5 @@ -use crate::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol}; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { diff --git a/vm/src/obj/objenumerate.rs b/vm/src/obj/objenumerate.rs index 4551edd91..76452e56c 100644 --- a/vm/src/obj/objenumerate.rs +++ b/vm/src/obj/objenumerate.rs @@ -1,15 +1,16 @@ use std::cell::RefCell; use std::ops::AddAssign; -use super::objint; -use super::objiter; -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; -use crate::vm::VirtualMachine; use num_bigint::BigInt; use num_traits::Zero; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; +use crate::vm::VirtualMachine; + +use super::objint; +use super::objiter; + #[derive(Debug)] pub struct PyEnumerate { counter: RefCell, diff --git a/vm/src/obj/objfilter.rs b/vm/src/obj/objfilter.rs index 5533c3e54..da329c809 100644 --- a/vm/src/obj/objfilter.rs +++ b/vm/src/obj/objfilter.rs @@ -1,5 +1,6 @@ +use crate::function::PyFuncArgs; use crate::pyobject::{ - IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, + IdProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; // Required for arg_check! to use isinstance diff --git a/vm/src/obj/objframe.rs b/vm/src/obj/objframe.rs index e77f14359..c3ebad300 100644 --- a/vm/src/obj/objframe.rs +++ b/vm/src/obj/objframe.rs @@ -3,7 +3,8 @@ */ use crate::frame::Frame; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { diff --git a/vm/src/obj/objfunction.rs b/vm/src/obj/objfunction.rs index d9d57cfce..f2c0bbafe 100644 --- a/vm/src/obj/objfunction.rs +++ b/vm/src/obj/objfunction.rs @@ -1,7 +1,6 @@ use crate::frame::Scope; -use crate::pyobject::{ - IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; +use crate::function::PyFuncArgs; +use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol}; use crate::vm::VirtualMachine; #[derive(Debug)] diff --git a/vm/src/obj/objgenerator.rs b/vm/src/obj/objgenerator.rs index 2bdd58195..611b89150 100644 --- a/vm/src/obj/objgenerator.rs +++ b/vm/src/obj/objgenerator.rs @@ -3,9 +3,8 @@ */ use crate::frame::{ExecutionResult, Frame}; -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; use crate::vm::VirtualMachine; #[derive(Debug)] diff --git a/vm/src/obj/objint.rs b/vm/src/obj/objint.rs index f1f81c5c5..d1b1388ce 100644 --- a/vm/src/obj/objint.rs +++ b/vm/src/obj/objint.rs @@ -5,9 +5,10 @@ use num_integer::Integer; use num_traits::{Pow, Signed, ToPrimitive, Zero}; use crate::format::FormatSpec; +use crate::function::{OptionalArg, PyFuncArgs}; use crate::pyobject::{ - IntoPyObject, OptionalArg, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyRef, PyResult, - PyValue, TryFromObject, TypeProtocol, + IntoPyObject, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, + TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/obj/objiter.rs b/vm/src/obj/objiter.rs index 153750fee..4c527776d 100644 --- a/vm/src/obj/objiter.rs +++ b/vm/src/obj/objiter.rs @@ -2,9 +2,8 @@ * Various types to support iteration. */ -use crate::pyobject::{ - PyContext, PyFuncArgs, PyIteratorValue, PyObjectRef, PyResult, TypeProtocol, -}; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyIteratorValue, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; use super::objbool; diff --git a/vm/src/obj/objlist.rs b/vm/src/obj/objlist.rs index f0baedb1b..361e3622d 100644 --- a/vm/src/obj/objlist.rs +++ b/vm/src/obj/objlist.rs @@ -1,4 +1,14 @@ use std::cell::{Cell, RefCell}; +use std::fmt; + +use num_traits::ToPrimitive; + +use crate::function::{OptionalArg, PyFuncArgs}; +use crate::pyobject::{ + IdProtocol, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, PyValue, + TypeProtocol, +}; +use crate::vm::{ReprGuard, VirtualMachine}; use super::objbool; use super::objint; @@ -8,13 +18,6 @@ use super::objsequence::{ }; use super::objstr; use super::objtype; -use crate::pyobject::{ - IdProtocol, OptionalArg, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyRef, - PyResult, PyValue, TypeProtocol, -}; -use crate::vm::{ReprGuard, VirtualMachine}; -use num_traits::ToPrimitive; -use std::fmt; #[derive(Default)] pub struct PyList { diff --git a/vm/src/obj/objmap.rs b/vm/src/obj/objmap.rs index 4ba8fd26b..2de5bc5ef 100644 --- a/vm/src/obj/objmap.rs +++ b/vm/src/obj/objmap.rs @@ -1,6 +1,5 @@ -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; use crate::vm::VirtualMachine; use super::objiter; diff --git a/vm/src/obj/objmemory.rs b/vm/src/obj/objmemory.rs index 5632ccac9..5386faaf2 100644 --- a/vm/src/obj/objmemory.rs +++ b/vm/src/obj/objmemory.rs @@ -1,6 +1,5 @@ -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; use crate::vm::VirtualMachine; #[derive(Debug)] diff --git a/vm/src/obj/objnone.rs b/vm/src/obj/objnone.rs index beb553326..fe63ecd98 100644 --- a/vm/src/obj/objnone.rs +++ b/vm/src/obj/objnone.rs @@ -1,5 +1,6 @@ +use crate::function::PyFuncArgs; use crate::pyobject::{ - IntoPyObject, PyContext, PyFuncArgs, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, + IntoPyObject, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/obj/objobject.rs b/vm/src/obj/objobject.rs index 2423f5e93..bea7737eb 100644 --- a/vm/src/obj/objobject.rs +++ b/vm/src/obj/objobject.rs @@ -1,12 +1,14 @@ +use crate::function::PyFuncArgs; +use crate::obj::objproperty::PropertyBuilder; +use crate::pyobject::{ + AttributeProtocol, DictProtocol, IdProtocol, PyAttributes, PyContext, PyObjectRef, PyRef, + PyResult, PyValue, TypeProtocol, +}; +use crate::vm::VirtualMachine; + use super::objlist::PyList; use super::objstr; use super::objtype; -use crate::obj::objproperty::PropertyBuilder; -use crate::pyobject::{ - AttributeProtocol, DictProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObjectRef, - PyRef, PyResult, PyValue, TypeProtocol, -}; -use crate::vm::VirtualMachine; #[derive(Clone, Debug)] pub struct PyInstance; diff --git a/vm/src/obj/objproperty.rs b/vm/src/obj/objproperty.rs index a66557e95..fae80cec6 100644 --- a/vm/src/obj/objproperty.rs +++ b/vm/src/obj/objproperty.rs @@ -2,12 +2,12 @@ */ +use crate::function::IntoPyNativeFunc; +use crate::function::OptionalArg; use crate::obj::objstr::PyStringRef; use crate::obj::objtype::PyClassRef; -use crate::pyobject::{ - IntoPyNativeFunc, OptionalArg, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, -}; -use crate::VirtualMachine; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue}; +use crate::vm::VirtualMachine; /// Read-only property, doesn't have __set__ or __delete__ #[derive(Debug)] diff --git a/vm/src/obj/objrange.rs b/vm/src/obj/objrange.rs index f5c045928..49f1a9e98 100644 --- a/vm/src/obj/objrange.rs +++ b/vm/src/obj/objrange.rs @@ -5,8 +5,9 @@ use num_bigint::{BigInt, Sign}; use num_integer::Integer; use num_traits::{One, Signed, ToPrimitive, Zero}; +use crate::function::PyFuncArgs; use crate::pyobject::{ - PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, + PyContext, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/obj/objset.rs b/vm/src/obj/objset.rs index f33208915..0e234e3ca 100644 --- a/vm/src/obj/objset.rs +++ b/vm/src/obj/objset.rs @@ -7,15 +7,17 @@ use std::collections::{hash_map::DefaultHasher, HashMap}; use std::fmt; use std::hash::{Hash, Hasher}; +use crate::function::PyFuncArgs; +use crate::pyobject::{ + PyContext, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, +}; +use crate::vm::{ReprGuard, VirtualMachine}; + use super::objbool; use super::objint; use super::objiter; use super::objstr; use super::objtype; -use crate::pyobject::{ - PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; -use crate::vm::{ReprGuard, VirtualMachine}; #[derive(Default)] pub struct PySet { diff --git a/vm/src/obj/objslice.rs b/vm/src/obj/objslice.rs index 3bb55ced2..8d65bc331 100644 --- a/vm/src/obj/objslice.rs +++ b/vm/src/obj/objslice.rs @@ -1,10 +1,11 @@ -use super::objint; -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; -use crate::vm::VirtualMachine; use num_bigint::BigInt; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; +use crate::vm::VirtualMachine; + +use super::objint; + #[derive(Debug)] pub struct PySlice { // TODO: should be private diff --git a/vm/src/obj/objstaticmethod.rs b/vm/src/obj/objstaticmethod.rs index 6807a695c..9d1a96ed2 100644 --- a/vm/src/obj/objstaticmethod.rs +++ b/vm/src/obj/objstaticmethod.rs @@ -1,4 +1,5 @@ -use crate::pyobject::{AttributeProtocol, PyContext, PyFuncArgs, PyResult, TypeProtocol}; +use crate::function::PyFuncArgs; +use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; pub fn init(context: &PyContext) { diff --git a/vm/src/obj/objstr.rs b/vm/src/obj/objstr.rs index 0a969b686..71a0737ca 100644 --- a/vm/src/obj/objstr.rs +++ b/vm/src/obj/objstr.rs @@ -6,9 +6,10 @@ use num_traits::ToPrimitive; use unicode_segmentation::UnicodeSegmentation; use crate::format::{FormatParseError, FormatPart, FormatString}; +use crate::function::{OptionalArg, PyFuncArgs}; use crate::pyobject::{ - IdProtocol, IntoPyObject, OptionalArg, PyContext, PyFuncArgs, PyIterable, PyObjectRef, PyRef, - PyResult, PyValue, TryFromObject, TypeProtocol, + IdProtocol, IntoPyObject, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, PyValue, + TryFromObject, TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/obj/objsuper.rs b/vm/src/obj/objsuper.rs index 79c516d4c..a3d877e14 100644 --- a/vm/src/obj/objsuper.rs +++ b/vm/src/obj/objsuper.rs @@ -6,10 +6,12 @@ https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/ */ -use super::objtype; -use crate::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol}; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; +use super::objtype; + pub fn init(context: &PyContext) { let super_type = &context.super_type; diff --git a/vm/src/obj/objtuple.rs b/vm/src/obj/objtuple.rs index 1702c2237..dc6d7d01c 100644 --- a/vm/src/obj/objtuple.rs +++ b/vm/src/obj/objtuple.rs @@ -2,9 +2,9 @@ use std::cell::{Cell, RefCell}; use std::fmt; use std::hash::{Hash, Hasher}; +use crate::function::OptionalArg; use crate::pyobject::{ - IdProtocol, OptionalArg, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, - PyValue, + IdProtocol, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, PyValue, }; use crate::vm::{ReprGuard, VirtualMachine}; diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 8fd7772f2..860d30da3 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -1,9 +1,10 @@ use std::cell::RefCell; use std::collections::HashMap; +use crate::function::PyFuncArgs; use crate::pyobject::{ - AttributeProtocol, FromPyObjectRef, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject, - PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol, + AttributeProtocol, FromPyObjectRef, IdProtocol, PyAttributes, PyContext, PyObject, PyObjectRef, + PyRef, PyResult, PyValue, TypeProtocol, }; use crate::vm::VirtualMachine; diff --git a/vm/src/obj/objzip.rs b/vm/src/obj/objzip.rs index 35213919d..8250337e0 100644 --- a/vm/src/obj/objzip.rs +++ b/vm/src/obj/objzip.rs @@ -1,6 +1,5 @@ -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; use crate::vm::VirtualMachine; use super::objiter; diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 9bd94ec70..9bfa7d4b3 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -2,10 +2,9 @@ use std::any::Any; use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::fmt; -use std::iter; use std::marker::PhantomData; use std::mem; -use std::ops::{Deref, RangeInclusive}; +use std::ops::Deref; use std::ptr; use std::rc::Rc; @@ -16,6 +15,7 @@ use num_traits::{One, Zero}; use crate::bytecode; use crate::exceptions; use crate::frame::{Frame, Scope}; +use crate::function::{IntoPyNativeFunc, PyFuncArgs}; use crate::obj::objbool; use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objbytearray; @@ -40,6 +40,7 @@ use crate::obj::objmodule::{self, PyModule}; use crate::obj::objnone; use crate::obj::objobject; use crate::obj::objproperty; +use crate::obj::objproperty::PropertyBuilder; use crate::obj::objrange; use crate::obj::objset::{self, PySet}; use crate::obj::objslice; @@ -975,166 +976,6 @@ impl fmt::Debug for PyObject { } } -/// The `PyFuncArgs` struct is one of the most used structs then creating -/// a rust function that can be called from python. It holds both positional -/// arguments, as well as keyword arguments passed to the function. -#[derive(Debug, Default, Clone)] -pub struct PyFuncArgs { - pub args: Vec, - pub kwargs: Vec<(String, PyObjectRef)>, -} - -/// Conversion from vector of python objects to function arguments. -impl From> for PyFuncArgs { - fn from(args: Vec) -> Self { - PyFuncArgs { - args: args, - kwargs: vec![], - } - } -} - -impl From for PyFuncArgs { - fn from(arg: PyObjectRef) -> Self { - PyFuncArgs { - args: vec![arg], - kwargs: vec![], - } - } -} - -impl PyFuncArgs { - pub fn new(mut args: Vec, kwarg_names: Vec) -> PyFuncArgs { - let mut kwargs = vec![]; - for name in kwarg_names.iter().rev() { - kwargs.push((name.clone(), args.pop().unwrap())); - } - PyFuncArgs { args, kwargs } - } - - pub fn insert(&self, item: PyObjectRef) -> PyFuncArgs { - let mut args = PyFuncArgs { - args: self.args.clone(), - kwargs: self.kwargs.clone(), - }; - args.args.insert(0, item); - args - } - - pub fn shift(&mut self) -> PyObjectRef { - self.args.remove(0) - } - - pub fn get_kwarg(&self, key: &str, default: PyObjectRef) -> PyObjectRef { - for (arg_name, arg_value) in self.kwargs.iter() { - if arg_name == key { - return arg_value.clone(); - } - } - default.clone() - } - - pub fn get_optional_kwarg(&self, key: &str) -> Option { - for (arg_name, arg_value) in self.kwargs.iter() { - if arg_name == key { - return Some(arg_value.clone()); - } - } - None - } - - pub fn get_optional_kwarg_with_type( - &self, - key: &str, - ty: PyObjectRef, - vm: &mut VirtualMachine, - ) -> Result, PyObjectRef> { - match self.get_optional_kwarg(key) { - Some(kwarg) => { - if objtype::isinstance(&kwarg, &ty) { - Ok(Some(kwarg)) - } else { - let expected_ty_name = vm.to_pystr(&ty)?; - let actual_ty_name = vm.to_pystr(&kwarg.typ())?; - Err(vm.new_type_error(format!( - "argument of type {} is required for named parameter `{}` (got: {})", - expected_ty_name, key, actual_ty_name - ))) - } - } - None => Ok(None), - } - } - - /// Serializes these arguments into an iterator starting with the positional - /// arguments followed by keyword arguments. - fn into_iter(self) -> impl Iterator { - self.args.into_iter().map(PyArg::Positional).chain( - self.kwargs - .into_iter() - .map(|(name, value)| PyArg::Keyword(name, value)), - ) - } - - /// Binds these arguments to their respective values. - /// - /// If there is an insufficient number of arguments, there are leftover - /// arguments after performing the binding, or if an argument is not of - /// the expected type, a TypeError is raised. - /// - /// If the given `FromArgs` includes any conversions, exceptions raised - /// during the conversion will halt the binding and return the error. - fn bind(self, vm: &mut VirtualMachine) -> PyResult { - let given_args = self.args.len(); - let mut args = self.into_iter().peekable(); - let bound = match T::from_args(vm, &mut args) { - Ok(args) => args, - Err(ArgumentError::TooFewArgs) => { - return Err(vm.new_type_error(format!( - "Expected at least {} arguments ({} given)", - T::arity().start(), - given_args, - ))); - } - Err(ArgumentError::Exception(ex)) => { - return Err(ex); - } - }; - - match args.next() { - None => Ok(bound), - Some(PyArg::Positional(_)) => Err(vm.new_type_error(format!( - "Expected at most {} arguments ({} given)", - T::arity().end(), - given_args, - ))), - Some(PyArg::Keyword(name, _)) => { - Err(vm.new_type_error(format!("Unexpected keyword argument {}", name))) - } - } - } -} - -/// Implemented by any type that can be accepted as a parameter to a built-in -/// function. -/// -pub trait FromArgs: Sized { - /// The range of positional arguments permitted by the function signature. - /// - /// Returns an empty range if not applicable. - fn arity() -> RangeInclusive { - 0..=0 - } - - /// Extracts this item from the next argument(s). - fn from_args( - vm: &mut VirtualMachine, - args: &mut iter::Peekable, - ) -> Result - where - I: Iterator; -} - /// An iterable Python object. /// /// `PyIterable` implements `FromArgs` so that a built-in function can accept @@ -1224,151 +1065,6 @@ impl TryFromObject for Option { } } -/// A map of keyword arguments to their values. -/// -/// A built-in function with a `KwArgs` parameter is analagous to a Python -/// function with `*kwargs`. All remaining keyword arguments are extracted -/// (and hence the function will permit an arbitrary number of them). -/// -/// `KwArgs` optionally accepts a generic type parameter to allow type checks -/// or conversions of each argument. -pub struct KwArgs(HashMap); - -impl FromArgs for KwArgs -where - T: TryFromObject, -{ - fn from_args( - vm: &mut VirtualMachine, - args: &mut iter::Peekable, - ) -> Result - where - I: Iterator, - { - let mut kwargs = HashMap::new(); - while let Some(PyArg::Keyword(name, value)) = args.next() { - kwargs.insert(name, T::try_from_object(vm, value)?); - } - Ok(KwArgs(kwargs)) - } -} - -/// A list of positional argument values. -/// -/// A built-in function with a `Args` parameter is analagous to a Python -/// function with `*args`. All remaining positional arguments are extracted -/// (and hence the function will permit an arbitrary number of them). -/// -/// `Args` optionally accepts a generic type parameter to allow type checks -/// or conversions of each argument. -pub struct Args(Vec); - -impl FromArgs for Args -where - T: TryFromObject, -{ - fn from_args( - vm: &mut VirtualMachine, - args: &mut iter::Peekable, - ) -> Result - where - I: Iterator, - { - let mut varargs = Vec::new(); - while let Some(PyArg::Positional(value)) = args.next() { - varargs.push(T::try_from_object(vm, value)?); - } - Ok(Args(varargs)) - } -} - -impl FromArgs for T -where - T: TryFromObject, -{ - fn arity() -> RangeInclusive { - 1..=1 - } - - fn from_args( - vm: &mut VirtualMachine, - args: &mut iter::Peekable, - ) -> Result - where - I: Iterator, - { - if let Some(PyArg::Positional(value)) = args.next() { - Ok(T::try_from_object(vm, value)?) - } else { - Err(ArgumentError::TooFewArgs) - } - } -} - -/// An argument that may or may not be provided by the caller. -/// -/// This style of argument is not possible in pure Python. -pub enum OptionalArg { - Present(T), - Missing, -} - -use self::OptionalArg::*; -use crate::obj::objproperty::PropertyBuilder; - -impl OptionalArg { - pub fn into_option(self) -> Option { - match self { - Present(value) => Some(value), - Missing => None, - } - } -} - -impl FromArgs for OptionalArg -where - T: TryFromObject, -{ - fn arity() -> RangeInclusive { - 0..=1 - } - - fn from_args( - vm: &mut VirtualMachine, - args: &mut iter::Peekable, - ) -> Result - where - I: Iterator, - { - Ok(if let Some(PyArg::Positional(_)) = args.peek() { - let value = if let Some(PyArg::Positional(value)) = args.next() { - value - } else { - unreachable!() - }; - Present(T::try_from_object(vm, value)?) - } else { - Missing - }) - } -} - -pub enum PyArg { - Positional(PyObjectRef), - Keyword(String, PyObjectRef), -} - -pub enum ArgumentError { - TooFewArgs, - Exception(PyObjectRef), -} - -impl From for ArgumentError { - fn from(ex: PyObjectRef) -> Self { - ArgumentError::Exception(ex) - } -} - /// Implemented by any type that can be created from a Python object. /// /// Any type that implements `TryFromObject` is automatically `FromArgs`, and @@ -1413,132 +1109,6 @@ where } } -// For functions that accept no arguments. Implemented explicitly instead of via -// macro below to avoid unused warnings. -impl FromArgs for () { - fn from_args( - _vm: &mut VirtualMachine, - _args: &mut iter::Peekable, - ) -> Result - where - I: Iterator, - { - Ok(()) - } -} - -// A tuple of types that each implement `FromArgs` represents a sequence of -// arguments that can be bound and passed to a built-in function. -// -// Technically, a tuple can contain tuples, which can contain tuples, and so on, -// so this actually represents a tree of values to be bound from arguments, but -// in practice this is only used for the top-level parameters. -macro_rules! tuple_from_py_func_args { - ($($T:ident),+) => { - impl<$($T),+> FromArgs for ($($T,)+) - where - $($T: FromArgs),+ - { - fn arity() -> RangeInclusive { - let mut min = 0; - let mut max = 0; - $( - let (start, end) = $T::arity().into_inner(); - min += start; - max += end; - )+ - min..=max - } - - fn from_args( - vm: &mut VirtualMachine, - args: &mut iter::Peekable - ) -> Result - where - I: Iterator - { - Ok(($($T::from_args(vm, args)?,)+)) - } - } - }; -} - -// Implement `FromArgs` for up to 5-tuples, allowing built-in functions to bind -// up to 5 top-level parameters (note that `Args`, `KwArgs`, nested tuples, etc. -// count as 1, so this should actually be more than enough). -tuple_from_py_func_args!(A); -tuple_from_py_func_args!(A, B); -tuple_from_py_func_args!(A, B, C); -tuple_from_py_func_args!(A, B, C, D); -tuple_from_py_func_args!(A, B, C, D, E); - -/// A built-in Python function. -pub type PyNativeFunc = Box PyResult + 'static>; - -/// Implemented by types that are or can generate built-in functions. -/// -/// For example, any function that: -/// -/// - Accepts a sequence of types that implement `FromArgs`, followed by a -/// `&mut VirtualMachine` -/// - Returns some type that implements `IntoPyObject` -/// -/// will generate a `PyNativeFunc` that performs the appropriate type and arity -/// checking, any requested conversions, and then if successful call the function -/// with the bound values. -/// -/// A bare `PyNativeFunc` also implements this trait, allowing the above to be -/// done manually, for rare situations that don't fit into this model. -pub trait IntoPyNativeFunc { - fn into_func(self) -> PyNativeFunc; -} - -impl IntoPyNativeFunc for F -where - F: Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult + 'static, -{ - fn into_func(self) -> PyNativeFunc { - Box::new(self) - } -} - -impl IntoPyNativeFunc for PyNativeFunc { - fn into_func(self) -> PyNativeFunc { - self - } -} - -// This is the "magic" that allows rust functions of varying signatures to -// generate native python functions. -// -// Note that this could be done without a macro - it is simply to avoid repetition. -macro_rules! into_py_native_func_tuple { - ($(($n:tt, $T:ident)),*) => { - impl IntoPyNativeFunc<($($T,)*), R> for F - where - F: Fn($($T,)* &mut VirtualMachine) -> R + 'static, - $($T: FromArgs,)* - ($($T,)*): FromArgs, - R: IntoPyObject, - { - fn into_func(self) -> PyNativeFunc { - Box::new(move |vm, args| { - let ($($n,)*) = args.bind::<($($T,)*)>(vm)?; - - (self)($($n,)* vm).into_pyobject(vm) - }) - } - } - }; -} - -into_py_native_func_tuple!(); -into_py_native_func_tuple!((a, A)); -into_py_native_func_tuple!((a, A), (b, B)); -into_py_native_func_tuple!((a, A), (b, B), (c, C)); -into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D)); -into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E)); - // TODO: This is a workaround and shouldn't exist. // Each iterable type should have its own distinct iterator type. #[derive(Debug)] diff --git a/vm/src/stdlib/ast.rs b/vm/src/stdlib/ast.rs index 3875157b8..c3c7c3903 100644 --- a/vm/src/stdlib/ast.rs +++ b/vm/src/stdlib/ast.rs @@ -3,15 +3,17 @@ //! This module makes use of the parser logic, and translates all ast nodes //! into python ast.AST objects. -extern crate rustpython_parser; - -use self::rustpython_parser::{ast, parser}; -use crate::obj::objstr; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use crate::VirtualMachine; -use num_complex::Complex64; use std::ops::Deref; +use num_complex::Complex64; + +use rustpython_parser::{ast, parser}; + +use crate::function::PyFuncArgs; +use crate::obj::objstr; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; + /* * Idea: maybe we can create a sort of struct with some helper functions? struct AstToPyAst { diff --git a/vm/src/stdlib/dis.rs b/vm/src/stdlib/dis.rs index 96d727a3f..ccc8930ba 100644 --- a/vm/src/stdlib/dis.rs +++ b/vm/src/stdlib/dis.rs @@ -1,5 +1,6 @@ +use crate::function::PyFuncArgs; use crate::obj::objcode; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; fn dis_dis(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/stdlib/io.rs b/vm/src/stdlib/io.rs index 02171df34..f9231ee23 100644 --- a/vm/src/stdlib/io.rs +++ b/vm/src/stdlib/io.rs @@ -2,29 +2,25 @@ * I/O core tools. */ -//library imports use std::collections::HashSet; use std::fs::File; use std::io::prelude::*; use std::io::BufReader; use std::path::PathBuf; -//3rd party imports use num_bigint::ToBigInt; use num_traits::ToPrimitive; -//custom imports use super::os; +use crate::function::PyFuncArgs; +use crate::import; use crate::obj::objbytearray::PyByteArray; use crate::obj::objbytes; use crate::obj::objint; use crate::obj::objstr; - use crate::pyobject::{ - AttributeProtocol, BufferProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol, + AttributeProtocol, BufferProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol, }; - -use crate::import; use crate::vm::VirtualMachine; fn compute_c_flag(mode: &str) -> u16 { diff --git a/vm/src/stdlib/json.rs b/vm/src/stdlib/json.rs index 7d900de52..84b82389e 100644 --- a/vm/src/stdlib/json.rs +++ b/vm/src/stdlib/json.rs @@ -5,14 +5,14 @@ use serde::de::{DeserializeSeed, Visitor}; use serde::ser::{SerializeMap, SerializeSeq}; use serde_json; +use crate::function::PyFuncArgs; use crate::obj::{ objbool, objdict, objfloat, objint, objsequence, objstr::{self, PyString}, objtype, }; use crate::pyobject::{ - create_type, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, - TypeProtocol, + create_type, DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol, }; use crate::VirtualMachine; use num_traits::cast::ToPrimitive; diff --git a/vm/src/stdlib/keyword.rs b/vm/src/stdlib/keyword.rs index 362d68ece..ff192cffb 100644 --- a/vm/src/stdlib/keyword.rs +++ b/vm/src/stdlib/keyword.rs @@ -2,11 +2,12 @@ * Testing if a string is a keyword. */ -extern crate rustpython_parser; -use self::rustpython_parser::lexer; +use rustpython_parser::lexer; + +use crate::function::PyFuncArgs; use crate::obj::objstr; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use crate::VirtualMachine; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; fn keyword_iskeyword(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]); diff --git a/vm/src/stdlib/math.rs b/vm/src/stdlib/math.rs index 19e5899a2..a8f035625 100644 --- a/vm/src/stdlib/math.rs +++ b/vm/src/stdlib/math.rs @@ -3,12 +3,13 @@ * */ -use crate::obj::objfloat; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use crate::VirtualMachine; use statrs::function::erf::{erf, erfc}; use statrs::function::gamma::{gamma, ln_gamma}; -use std; + +use crate::function::PyFuncArgs; +use crate::obj::objfloat; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; // Helper macro: macro_rules! make_math_func { diff --git a/vm/src/stdlib/os.rs b/vm/src/stdlib/os.rs index 7745ca205..0bb616ff0 100644 --- a/vm/src/stdlib/os.rs +++ b/vm/src/stdlib/os.rs @@ -1,18 +1,13 @@ -//library imports use std::fs::File; use std::fs::OpenOptions; use std::io::ErrorKind; -// use std::env; -//3rd party imports use num_traits::cast::ToPrimitive; -//custom imports +use crate::function::PyFuncArgs; use crate::obj::objint; use crate::obj::objstr; -// use crate::obj::objdict; - -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; use crate::vm::VirtualMachine; #[cfg(unix)] diff --git a/vm/src/stdlib/platform.rs b/vm/src/stdlib/platform.rs index dd0bc79bc..f22b8be0e 100644 --- a/vm/src/stdlib/platform.rs +++ b/vm/src/stdlib/platform.rs @@ -1,7 +1,6 @@ -extern crate rustc_version_runtime; - -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult}; -use crate::VirtualMachine; +use crate::function::PyFuncArgs; +use crate::pyobject::{PyContext, PyObjectRef, PyResult}; +use crate::vm::VirtualMachine; pub fn make_module(ctx: &PyContext) -> PyObjectRef { py_module!(ctx, "platform", { diff --git a/vm/src/stdlib/pystruct.rs b/vm/src/stdlib/pystruct.rs index 8052492b2..5da654b69 100644 --- a/vm/src/stdlib/pystruct.rs +++ b/vm/src/stdlib/pystruct.rs @@ -7,15 +7,16 @@ * https://docs.rs/byteorder/1.2.6/byteorder/ */ -extern crate byteorder; -use self::byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; +use std::io::{Cursor, Read, Write}; -use crate::obj::{objbool, objbytes, objfloat, objint, objstr, objtype}; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use crate::VirtualMachine; +use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use num_bigint::BigInt; use num_traits::ToPrimitive; -use std::io::{Cursor, Read, Write}; + +use crate::function::PyFuncArgs; +use crate::obj::{objbool, objbytes, objfloat, objint, objstr, objtype}; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::VirtualMachine; #[derive(Debug)] struct FormatCode { diff --git a/vm/src/stdlib/random.rs b/vm/src/stdlib/random.rs index 31b016283..2ad1e51c0 100644 --- a/vm/src/stdlib/random.rs +++ b/vm/src/stdlib/random.rs @@ -1,11 +1,11 @@ //! Random module. -extern crate rand; +use rand::distributions::{Distribution, Normal}; +use crate::function::PyFuncArgs; use crate::obj::objfloat; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use crate::stdlib::random::rand::distributions::{Distribution, Normal}; -use crate::VirtualMachine; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; pub fn make_module(ctx: &PyContext) -> PyObjectRef { py_module!(ctx, "random", { diff --git a/vm/src/stdlib/re.rs b/vm/src/stdlib/re.rs index 5b992b877..afbb40dc7 100644 --- a/vm/src/stdlib/re.rs +++ b/vm/src/stdlib/re.rs @@ -9,13 +9,13 @@ use std::path::PathBuf; use regex::{Match, Regex}; +use crate::function::PyFuncArgs; use crate::import; use crate::obj::objstr; use crate::pyobject::{ - AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, - TypeProtocol, + AttributeProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; -use crate::VirtualMachine; +use crate::vm::VirtualMachine; impl PyValue for Regex { fn class(vm: &mut VirtualMachine) -> PyObjectRef { diff --git a/vm/src/stdlib/socket.rs b/vm/src/stdlib/socket.rs index 91097217e..f09a52f55 100644 --- a/vm/src/stdlib/socket.rs +++ b/vm/src/stdlib/socket.rs @@ -5,13 +5,12 @@ use std::io::Write; use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket}; use std::ops::Deref; +use crate::function::PyFuncArgs; use crate::obj::objbytes; use crate::obj::objint; use crate::obj::objsequence::get_elements; use crate::obj::objstr; -use crate::pyobject::{ - PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, -}; +use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol}; use crate::vm::VirtualMachine; use num_traits::ToPrimitive; diff --git a/vm/src/stdlib/time_module.rs b/vm/src/stdlib/time_module.rs index 05c9b640c..c43ae037e 100644 --- a/vm/src/stdlib/time_module.rs +++ b/vm/src/stdlib/time_module.rs @@ -1,11 +1,13 @@ //! The python `time` module. -use crate::obj::objfloat; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use crate::VirtualMachine; use std::thread; use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use crate::function::PyFuncArgs; +use crate::obj::objfloat; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; + fn time_sleep(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(seconds, Some(vm.ctx.float_type()))]); let seconds = objfloat::get_value(seconds); diff --git a/vm/src/stdlib/tokenize.rs b/vm/src/stdlib/tokenize.rs index 1da20655d..1027e1f03 100644 --- a/vm/src/stdlib/tokenize.rs +++ b/vm/src/stdlib/tokenize.rs @@ -2,14 +2,14 @@ * python tokenize module. */ -extern crate rustpython_parser; use std::iter::FromIterator; -use self::rustpython_parser::lexer; +use rustpython_parser::lexer; +use crate::function::PyFuncArgs; use crate::obj::objstr; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use crate::VirtualMachine; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; fn tokenize_tokenize(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(readline, Some(vm.ctx.str_type()))]); diff --git a/vm/src/stdlib/types.rs b/vm/src/stdlib/types.rs index 0a340188f..208dc1bc2 100644 --- a/vm/src/stdlib/types.rs +++ b/vm/src/stdlib/types.rs @@ -2,8 +2,9 @@ * Dynamic type creation and names for built in types. */ +use crate::function::PyFuncArgs; use crate::obj::objtype; -use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; +use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol}; use crate::VirtualMachine; fn types_new_class(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { diff --git a/vm/src/sysmodule.rs b/vm/src/sysmodule.rs index cc82792ce..e2713d783 100644 --- a/vm/src/sysmodule.rs +++ b/vm/src/sysmodule.rs @@ -1,10 +1,13 @@ -use crate::obj::objint; -use crate::pyobject::{DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use crate::vm::VirtualMachine; -use num_traits::ToPrimitive; use std::rc::Rc; use std::{env, mem}; +use num_traits::ToPrimitive; + +use crate::function::PyFuncArgs; +use crate::obj::objint; +use crate::pyobject::{DictProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol}; +use crate::vm::VirtualMachine; + /* * The magic sys module. */ diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 26e6e57ba..f10e193be 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -14,6 +14,7 @@ use std::sync::{Mutex, MutexGuard}; use crate::builtins; use crate::bytecode; use crate::frame::{ExecutionResult, Frame, Scope}; +use crate::function::PyFuncArgs; use crate::obj::objbool; use crate::obj::objbuiltinfunc::PyBuiltinFunction; use crate::obj::objcode; @@ -27,8 +28,7 @@ use crate::obj::objstr; use crate::obj::objtuple::PyTuple; use crate::obj::objtype; use crate::pyobject::{ - AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, - TypeProtocol, + AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol, }; use crate::stdlib; use crate::sysmodule; diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index 11ea35ea2..3130289d7 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -1,16 +1,21 @@ -use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window}; +use std::path::PathBuf; + use futures::Future; use js_sys::Promise; use num_traits::cast::ToPrimitive; +use wasm_bindgen::prelude::*; +use wasm_bindgen::JsCast; +use wasm_bindgen_futures::{future_to_promise, JsFuture}; + +use rustpython_vm::function::PyFuncArgs; +use rustpython_vm::import::import_module; use rustpython_vm::obj::{objint, objstr}; use rustpython_vm::pyobject::{ - AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, - TypeProtocol, + AttributeProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol, }; -use rustpython_vm::{import::import_module, VirtualMachine}; -use std::path::PathBuf; -use wasm_bindgen::{prelude::*, JsCast}; -use wasm_bindgen_futures::{future_to_promise, JsFuture}; +use rustpython_vm::VirtualMachine; + +use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window}; enum FetchResponseFormat { Json, diff --git a/wasm/lib/src/convert.rs b/wasm/lib/src/convert.rs index a76f80244..27383bea9 100644 --- a/wasm/lib/src/convert.rs +++ b/wasm/lib/src/convert.rs @@ -1,14 +1,15 @@ -use crate::browser_module; -use crate::vm_class::{AccessibleVM, WASMVirtualMachine}; use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, Uint8Array}; use num_traits::cast::ToPrimitive; -use rustpython_vm::obj::{objbytes, objint, objsequence, objtype}; -use rustpython_vm::pyobject::{ - self, AttributeProtocol, DictProtocol, PyFuncArgs, PyObjectRef, PyResult, -}; -use rustpython_vm::VirtualMachine; use wasm_bindgen::{closure::Closure, prelude::*, JsCast}; +use rustpython_vm::function::PyFuncArgs; +use rustpython_vm::obj::{objbytes, objint, objsequence, objtype}; +use rustpython_vm::pyobject::{AttributeProtocol, DictProtocol, PyObjectRef, PyResult}; +use rustpython_vm::VirtualMachine; + +use crate::browser_module; +use crate::vm_class::{AccessibleVM, WASMVirtualMachine}; + pub fn py_err_to_js_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> JsValue { macro_rules! map_exceptions { ($py_exc:ident, $msg:expr, { $($py_exc_ty:expr => $js_err_new:expr),*$(,)? }) => { @@ -83,7 +84,7 @@ pub fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue { let vm = &mut acc_vm .upgrade() .expect("acc. VM to be invalid when WASM vm is valid"); - let mut py_func_args = rustpython_vm::pyobject::PyFuncArgs::default(); + let mut py_func_args = PyFuncArgs::default(); if let Some(ref args) = args { for arg in args.values() { py_func_args.args.push(js_to_py(vm, arg?)); @@ -132,7 +133,7 @@ pub fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue { .expect("Couldn't get json module") .get_attr("dumps".into()) .expect("Couldn't get json dumps"); - match vm.invoke(dumps, pyobject::PyFuncArgs::new(vec![py_obj], vec![])) { + match vm.invoke(dumps, PyFuncArgs::new(vec![py_obj], vec![])) { Ok(value) => { let json = vm.to_pystr(&value).unwrap(); js_sys::JSON::parse(&json).unwrap_or(JsValue::UNDEFINED) @@ -239,7 +240,7 @@ pub fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef { }; let py_json = vm.new_str(json); - vm.invoke(loads, pyobject::PyFuncArgs::new(vec![py_json], vec![])) + vm.invoke(loads, PyFuncArgs::new(vec![py_json], vec![])) // can safely unwrap because we know it's valid JSON .unwrap() } diff --git a/wasm/lib/src/vm_class.rs b/wasm/lib/src/vm_class.rs index b3ef50627..d3bfa8307 100644 --- a/wasm/lib/src/vm_class.rs +++ b/wasm/lib/src/vm_class.rs @@ -1,18 +1,20 @@ -use crate::browser_module::setup_browser_module; -use crate::convert; -use crate::wasm_builtins; -use js_sys::{Object, Reflect, SyntaxError, TypeError}; -use rustpython_vm::{ - compile, - frame::{NameProtocol, Scope}, - pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult}, - VirtualMachine, -}; use std::cell::RefCell; use std::collections::HashMap; use std::rc::{Rc, Weak}; + +use js_sys::{Object, Reflect, SyntaxError, TypeError}; use wasm_bindgen::{prelude::*, JsCast}; +use rustpython_vm::compile; +use rustpython_vm::frame::{NameProtocol, Scope}; +use rustpython_vm::function::PyFuncArgs; +use rustpython_vm::pyobject::{PyContext, PyObjectRef, PyResult}; +use rustpython_vm::VirtualMachine; + +use crate::browser_module::setup_browser_module; +use crate::convert; +use crate::wasm_builtins; + pub trait HeldRcInner {} impl HeldRcInner for T {} diff --git a/wasm/lib/src/wasm_builtins.rs b/wasm/lib/src/wasm_builtins.rs index 8bb6a2db2..cc3435bba 100644 --- a/wasm/lib/src/wasm_builtins.rs +++ b/wasm/lib/src/wasm_builtins.rs @@ -5,11 +5,13 @@ //! Implements functions listed here: https://docs.python.org/3/library/builtins.html. use js_sys::{self, Array}; -use rustpython_vm::obj::{objstr, objtype}; -use rustpython_vm::pyobject::{IdProtocol, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol}; -use rustpython_vm::VirtualMachine; use web_sys::{self, console}; +use rustpython_vm::function::PyFuncArgs; +use rustpython_vm::obj::{objstr, objtype}; +use rustpython_vm::pyobject::{IdProtocol, PyObjectRef, PyResult, TypeProtocol}; +use rustpython_vm::VirtualMachine; + pub(crate) fn window() -> web_sys::Window { web_sys::window().expect("Window to be available") }