Merge pull request #611 from RustPython/pyargs

Less explicit PyFuncArgs is better.
This commit is contained in:
Windel Bouwman
2019-03-06 17:10:13 +01:00
committed by GitHub
6 changed files with 39 additions and 101 deletions

View File

@@ -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())?;

View File

@@ -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);

View File

@@ -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(

View File

@@ -904,6 +904,16 @@ pub struct PyFuncArgs {
pub kwargs: Vec<(String, PyObjectRef)>,
}
/// Conversion from vector of python objects to function arguments.
impl From<Vec<PyObjectRef>> for PyFuncArgs {
fn from(args: Vec<PyObjectRef>) -> Self {
PyFuncArgs {
args: args,
kwargs: vec![],
}
}
}
impl PyFuncArgs {
pub fn new(mut args: Vec<PyObjectRef>, kwarg_names: Vec<String>) -> PyFuncArgs {
let mut kwargs = vec![];

View File

@@ -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<PyObjectRef> = 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<PyObjectRef>,
) -> 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<T>(&mut self, obj: &PyObjectRef, method_name: &str, args: T) -> PyResult
where
T: Into<PyFuncArgs>,
{
// 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<T>(&mut self, func_ref: PyObjectRef, args: T) -> PyResult
where
T: Into<PyFuncArgs>,
{
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);
}

View File

@@ -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();