Have single_or_tuple_any recursively check for tuples

This commit is contained in:
coolreader18 committed 2019-12-03 21:39:34 -06:00
1 parent 163127b5e1
commit ea7db95a70
2 files changed
+31 -11

No files matched your search

+2
View File
@@ -52,3 +52,5 @@ class ReturnInt(metaclass=MCReturnInt):
assert isinstance("a", ReturnInt) is True
assert isinstance(1, ((int, float,), str))
+29 -11
View File
@@ -569,17 +569,35 @@ pub fn single_or_tuple_any<T: PyValue, F: Fn(PyRef<T>) -> PyResult<bool>>(
message: fn(&PyObjectRef) -> String,
vm: &VirtualMachine,
) -> PyResult<bool> {
match_class!(match obj {
obj @ T => predicate(obj),
tuple @ PyTuple => {
for obj in tuple.elements.iter() {
let inner_val = PyRef::<T>::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<T>) -> PyResult<bool>> {
predicate: F,
message: fn(&PyObjectRef) -> String,
vm: &'vm VirtualMachine,
t: PhantomData<T>,
}
impl<T: PyValue, F: Fn(PyRef<T>) -> PyResult<bool>> Checker<'_, T, F> {
fn check(&self, obj: PyObjectRef) -> PyResult<bool> {
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)
}