From ea7db95a701103ea0897ec2fe75182e42b28f651 Mon Sep 17 00:00:00 2001 From: coolreader18 <33094578+coolreader18@users.noreply.github.com> Date: Tue, 3 Dec 2019 20:37:58 -0600 Subject: [PATCH] Have single_or_tuple_any recursively check for tuples --- tests/snippets/isinstance.py | 2 ++ vm/src/function.rs | 40 ++++++++++++++++++++++++++---------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/tests/snippets/isinstance.py b/tests/snippets/isinstance.py index 52645e9b8..938ba6e9c 100644 --- a/tests/snippets/isinstance.py +++ b/tests/snippets/isinstance.py @@ -52,3 +52,5 @@ class ReturnInt(metaclass=MCReturnInt): assert isinstance("a", ReturnInt) is True + +assert isinstance(1, ((int, float,), str)) diff --git a/vm/src/function.rs b/vm/src/function.rs index ed3a783c6..f189b5b87 100644 --- a/vm/src/function.rs +++ b/vm/src/function.rs @@ -569,17 +569,35 @@ pub fn single_or_tuple_any) -> PyResult>( message: fn(&PyObjectRef) -> String, vm: &VirtualMachine, ) -> PyResult { - match_class!(match obj { - obj @ T => predicate(obj), - tuple @ PyTuple => { - for obj in tuple.elements.iter() { - let inner_val = PyRef::::try_from_object(vm, obj.clone())?; - if predicate(inner_val)? { - return Ok(true); + // TODO: figure out some way to have recursive calls without... this + use std::marker::PhantomData; + struct Checker<'vm, T: PyValue, F: Fn(PyRef) -> PyResult> { + predicate: F, + message: fn(&PyObjectRef) -> String, + vm: &'vm VirtualMachine, + t: PhantomData, + } + impl) -> PyResult> Checker<'_, T, F> { + fn check(&self, obj: PyObjectRef) -> PyResult { + match_class!(match obj { + obj @ T => (self.predicate)(obj), + tuple @ PyTuple => { + for obj in tuple.elements.iter() { + if self.check(obj.clone())? { + return Ok(true); + } + } + Ok(false) } - } - Ok(false) + obj => Err(self.vm.new_type_error((self.message)(&obj))), + }) } - obj => Err(vm.new_type_error(message(&obj))), - }) + } + let checker = Checker { + predicate, + message, + vm, + t: PhantomData, + }; + checker.check(obj) }