diff --git a/vm/src/builtins.rs b/vm/src/builtins.rs index b146fcf91..eee98100e 100644 --- a/vm/src/builtins.rs +++ b/vm/src/builtins.rs @@ -178,7 +178,7 @@ fn builtin_dir(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { fn builtin_divmod(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { arg_check!(vm, args, required = [(x, None), (y, None)]); match vm.get_method(x.clone(), "__divmod__") { - Ok(attrib) => vm.invoke(attrib, PyFuncArgs::new(vec![y.clone()], vec![])), + Ok(attrib) => vm.invoke(attrib, vec![y.clone()]), Err(..) => Err(vm.new_type_error("unsupported operand type(s) for divmod".to_string())), } } @@ -429,16 +429,14 @@ fn builtin_max(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // TODO: this key function looks pretty duplicate. Maybe we can create // a local function? let mut x_key = if let Some(f) = &key_func { - let args = PyFuncArgs::new(vec![x.clone()], vec![]); - vm.invoke(f.clone(), args)? + vm.invoke(f.clone(), vec![x.clone()])? } else { x.clone() }; for y in candidates_iter { let y_key = if let Some(f) = &key_func { - let args = PyFuncArgs::new(vec![y.clone()], vec![]); - vm.invoke(f.clone(), args)? + vm.invoke(f.clone(), vec![y.clone()])? } else { y.clone() }; @@ -479,16 +477,14 @@ fn builtin_min(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { // TODO: this key function looks pretty duplicate. Maybe we can create // a local function? let mut x_key = if let Some(f) = &key_func { - let args = PyFuncArgs::new(vec![x.clone()], vec![]); - vm.invoke(f.clone(), args)? + vm.invoke(f.clone(), vec![x.clone()])? } else { x.clone() }; for y in candidates_iter { let y_key = if let Some(f) = &key_func { - let args = PyFuncArgs::new(vec![y.clone()], vec![]); - vm.invoke(f.clone(), args)? + vm.invoke(f.clone(), vec![y.clone()])? } else { y.clone() }; @@ -566,7 +562,7 @@ fn builtin_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { ); let pow_method_name = "__pow__"; let result = match vm.get_method(x.clone(), pow_method_name) { - Ok(attrib) => vm.invoke(attrib, PyFuncArgs::new(vec![y.clone()], vec![])), + Ok(attrib) => vm.invoke(attrib, vec![y.clone()]), Err(..) => Err(vm.new_type_error("unsupported operand type(s) for pow".to_string())), }; //Check if the 3rd argument is defined and perform modulus on the result @@ -576,7 +572,7 @@ fn builtin_pow(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { Some(mod_value) => { let mod_method_name = "__mod__"; match vm.get_method(result.expect("result not defined").clone(), mod_method_name) { - Ok(value) => vm.invoke(value, PyFuncArgs::new(vec![mod_value.clone()], vec![])), + Ok(value) => vm.invoke(value, vec![mod_value.clone()]), Err(..) => { Err(vm.new_type_error("unsupported operand type(s) for mod".to_string())) } @@ -709,7 +705,7 @@ fn builtin_sorted(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> PyResult { let lst = vm.ctx.new_list(items); args.shift(); - vm.call_method_pyargs(&lst, "sort", args)?; + vm.call_method(&lst, "sort", args)?; Ok(lst) } @@ -843,13 +839,7 @@ pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> Py // Prepare uses full __getattribute__ resolution chain. let prepare_name = vm.new_str("__prepare__".to_string()); let prepare = vm.get_attribute(metaclass.clone(), prepare_name)?; - let namespace = vm.invoke( - prepare, - PyFuncArgs { - args: vec![name_arg.clone(), bases.clone()], - kwargs: vec![], - }, - )?; + let namespace = vm.invoke(prepare, vec![name_arg.clone(), bases.clone()])?; vm.invoke_with_locals(function, namespace.clone())?; diff --git a/vm/src/obj/objfilter.rs b/vm/src/obj/objfilter.rs index 998d51c9b..b4338192f 100644 --- a/vm/src/obj/objfilter.rs +++ b/vm/src/obj/objfilter.rs @@ -36,13 +36,7 @@ fn filter_next(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult { } else { // the predicate itself can raise StopIteration which does stop the filter // iteration - vm.invoke( - predicate.clone(), - PyFuncArgs { - args: vec![next_obj.clone()], - kwargs: vec![], - }, - )? + vm.invoke(predicate.clone(), vec![next_obj.clone()])? }; if objbool::boolval(vm, predicate_value)? { return Ok(next_obj); diff --git a/vm/src/obj/objtype.rs b/vm/src/obj/objtype.rs index 086f7f28f..5364dab3c 100644 --- a/vm/src/obj/objtype.rs +++ b/vm/src/obj/objtype.rs @@ -210,13 +210,7 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult let attr_class = attr.typ(); if attr_class.has_attr("__set__") { if let Some(descriptor) = attr_class.get_attr("__get__") { - return vm.invoke( - descriptor, - PyFuncArgs { - args: vec![attr, cls.clone(), mcl], - kwargs: vec![], - }, - ); + return vm.invoke(descriptor, vec![attr, cls.clone(), mcl]); } } } @@ -225,13 +219,7 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult let attr_class = attr.typ(); if let Some(descriptor) = attr_class.get_attr("__get__") { let none = vm.get_none(); - return vm.invoke( - descriptor, - PyFuncArgs { - args: vec![attr, none, cls.clone()], - kwargs: vec![], - }, - ); + return vm.invoke(descriptor, vec![attr, none, cls.clone()]); } } @@ -240,13 +228,7 @@ pub fn type_getattribute(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult } else if let Some(attr) = mcl.get_attr(&name) { vm.call_get_descriptor(attr, cls.clone()) } else if let Some(getter) = cls.get_attr("__getattr__") { - vm.invoke( - getter, - PyFuncArgs { - args: vec![mcl, name_str.clone()], - kwargs: vec![], - }, - ) + vm.invoke(getter, vec![mcl, name_str.clone()]) } else { let attribute_error = vm.context().exceptions.attribute_error.clone(); Err(vm.new_exception( diff --git a/vm/src/pyobject.rs b/vm/src/pyobject.rs index 6e0ab2701..9fc1c0f48 100644 --- a/vm/src/pyobject.rs +++ b/vm/src/pyobject.rs @@ -904,6 +904,16 @@ pub struct PyFuncArgs { 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 PyFuncArgs { pub fn new(mut args: Vec, kwarg_names: Vec) -> PyFuncArgs { let mut kwargs = vec![]; diff --git a/vm/src/vm.rs b/vm/src/vm.rs index 6c6659d4d..709a9f46c 100644 --- a/vm/src/vm.rs +++ b/vm/src/vm.rs @@ -117,10 +117,7 @@ impl VirtualMachine { pub fn new_empty_exception(&mut self, exc_type: PyObjectRef) -> PyResult { info!("New exception created: no msg"); - let args = PyFuncArgs { - args: vec![], - kwargs: vec![], - }; + let args = PyFuncArgs::default(); self.invoke(exc_type, args) } @@ -130,10 +127,6 @@ impl VirtualMachine { info!("New exception created: {}", msg); let pymsg = self.new_str(msg); let args: Vec = vec![pymsg]; - let args = PyFuncArgs { - args, - kwargs: vec![], - }; // Call function: self.invoke(exc_type, args).unwrap() @@ -264,40 +257,16 @@ impl VirtualMachine { let attr_class = attr.typ(); if let Some(descriptor) = attr_class.get_attr("__get__") { let cls = obj.typ(); - self.invoke( - descriptor, - PyFuncArgs { - args: vec![attr, obj.clone(), cls], - kwargs: vec![], - }, - ) + self.invoke(descriptor, vec![attr, obj.clone(), cls]) } else { Ok(attr) } } - pub fn call_method( - &mut self, - obj: &PyObjectRef, - method_name: &str, - args: Vec, - ) -> PyResult { - self.call_method_pyargs( - obj, - method_name, - PyFuncArgs { - args, - kwargs: vec![], - }, - ) - } - - pub fn call_method_pyargs( - &mut self, - obj: &PyObjectRef, - method_name: &str, - args: PyFuncArgs, - ) -> PyResult { + pub fn call_method(&mut self, obj: &PyObjectRef, method_name: &str, args: T) -> PyResult + where + T: Into, + { // This is only used in the vm for magic methods, which use a greatly simplified attribute lookup. let cls = obj.typ(); match cls.get_attr(method_name) { @@ -316,7 +285,11 @@ impl VirtualMachine { } } - pub fn invoke(&mut self, func_ref: PyObjectRef, args: PyFuncArgs) -> PyResult { + pub fn invoke(&mut self, func_ref: PyObjectRef, args: T) -> PyResult + where + T: Into, + { + let args = args.into(); trace!("Invoke: {:?} {:?}", func_ref, args); match func_ref.payload { PyObjectPayload::RustFunction { ref function } => function(self, args), @@ -325,18 +298,16 @@ impl VirtualMachine { ref scope, ref defaults, } => self.invoke_python_function(code, scope, defaults, args), - PyObjectPayload::Class { .. } => self.call_method_pyargs(&func_ref, "__call__", args), + PyObjectPayload::Class { .. } => self.call_method(&func_ref, "__call__", args), PyObjectPayload::BoundMethod { ref function, ref object, } => self.invoke(function.clone(), args.insert(object.clone())), - PyObjectPayload::Instance { .. } => { - self.call_method_pyargs(&func_ref, "__call__", args) - } + PyObjectPayload::Instance { .. } => self.call_method(&func_ref, "__call__", args), ref payload => { // TODO: is it safe to just invoke __call__ otherwise? trace!("invoke __call__ for: {:?}", payload); - self.call_method_pyargs(&func_ref, "__call__", args) + self.call_method(&func_ref, "__call__", args) } } } @@ -579,13 +550,7 @@ impl VirtualMachine { F: Fn(&mut VirtualMachine, PyObjectRef, PyObjectRef) -> PyResult, { if let Ok(method) = self.get_method(obj.clone(), method) { - let result = self.invoke( - method, - PyFuncArgs { - args: vec![arg.clone()], - kwargs: vec![], - }, - )?; + let result = self.invoke(method, vec![arg.clone()])?; if !result.is(&self.ctx.not_implemented()) { return Ok(result); } diff --git a/wasm/lib/src/browser_module.rs b/wasm/lib/src/browser_module.rs index 9aa600610..ea21d30fd 100644 --- a/wasm/lib/src/browser_module.rs +++ b/wasm/lib/src/browser_module.rs @@ -118,10 +118,7 @@ fn browser_request_animation_frame(vm: &mut VirtualMachine, args: PyFuncArgs) -> .upgrade() .expect("that the vm is valid from inside of request_animation_frame"); let func = func.clone(); - let args = PyFuncArgs { - args: vec![vm.ctx.new_float(time)], - kwargs: vec![], - }; + let args = vec![vm.ctx.new_float(time)]; let _ = vm.invoke(func, args); let closure = f.borrow_mut().take();