diff --git a/vm/src/function.rs b/vm/src/function.rs index aae4eefe8..305c4de5e 100644 --- a/vm/src/function.rs +++ b/vm/src/function.rs @@ -2,7 +2,9 @@ use std::collections::HashMap; use std::ops::RangeInclusive; use crate::obj::objtype::{isinstance, PyClassRef}; -use crate::pyobject::{IntoPyObject, PyObjectRef, PyResult, TryFromObject, TypeProtocol}; +use crate::pyobject::{ + IntoPyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject, TypeProtocol, +}; use crate::vm::VirtualMachine; use self::OptionalArg::*; @@ -403,6 +405,7 @@ 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); +tuple_from_py_func_args!(A, B, C, D, E, F); /// A built-in Python function. pub type PyNativeFunc = Box PyResult + 'static>; @@ -440,17 +443,19 @@ impl IntoPyNativeFunc for PyNativeFunc { } } +pub struct OwnedParam(std::marker::PhantomData); +pub struct RefParam(std::marker::PhantomData); + // 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 + impl IntoPyNativeFunc<($(OwnedParam<$T>,)*), R> for F where F: Fn($($T,)* &VirtualMachine) -> R + 'static, $($T: FromArgs,)* - ($($T,)*): FromArgs, R: IntoPyObject, { fn into_func(self) -> PyNativeFunc { @@ -461,6 +466,22 @@ macro_rules! into_py_native_func_tuple { }) } } + + impl IntoPyNativeFunc<(RefParam, $(OwnedParam<$T>,)*), R> for F + where + F: Fn(&S, $($T,)* &VirtualMachine) -> R + 'static, + S: PyValue, + $($T: FromArgs,)* + R: IntoPyObject, + { + fn into_func(self) -> PyNativeFunc { + Box::new(move |vm, args| { + let (zelf, $($n,)*) = args.bind::<(PyRef, $($T,)*)>(vm)?; + + (self)(&zelf, $($n,)* vm).into_pyobject(vm) + }) + } + } }; } diff --git a/vm/src/obj/objfloat.rs b/vm/src/obj/objfloat.rs index ca6bad9d2..de7c465d3 100644 --- a/vm/src/obj/objfloat.rs +++ b/vm/src/obj/objfloat.rs @@ -34,6 +34,13 @@ impl From for PyFloat { } } +impl PyFloat { + fn is_integer(&self, _vm: &VirtualMachine) -> bool { + let v = self.value; + (v - v.round()).abs() < std::f64::EPSILON + } +} + pub type PyFloatRef = PyRef; impl PyFloatRef { @@ -311,11 +318,6 @@ impl PyFloatRef { } } - fn is_integer(self, _vm: &VirtualMachine) -> bool { - let v = self.value; - (v - v.round()).abs() < std::f64::EPSILON - } - fn real(self, _vm: &VirtualMachine) -> Self { self } @@ -385,7 +387,7 @@ pub fn init(context: &PyContext) { "__mul__" => context.new_rustfunc(PyFloatRef::mul), "__rmul__" => context.new_rustfunc(PyFloatRef::mul), "real" => context.new_property(PyFloatRef::real), - "is_integer" => context.new_rustfunc(PyFloatRef::is_integer), + "is_integer" => context.new_rustfunc(PyFloat::is_integer), "as_integer_ratio" => context.new_rustfunc(PyFloatRef::as_integer_ratio) }); }