From 307a66c292a22cf2ee56712b85b021d3a3948e6b Mon Sep 17 00:00:00 2001 From: Robert Bradshaw Date: Thu, 15 Oct 2009 03:58:28 -0700 Subject: [PATCH] Fix short-circuit for and/or, preserve type. --- Cython/Compiler/ExprNodes.py | 34 ++++++++------------------------ runtests.py | 2 +- tests/errors/nogil.pyx | 2 ++ tests/run/boolop.pyx | 11 ++++++----- tests/run/short_circuit_T404.pyx | 16 +++++++-------- 5 files changed, 25 insertions(+), 40 deletions(-) diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index bbc6f326..fe21d650 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -4825,11 +4825,9 @@ class BoolBinopNode(ExprNode): subexprs = ['operand1', 'operand2'] def infer_type(self, env): - if (self.operand1.infer_type(env).is_pyobject or - self.operand2.infer_type(env).is_pyobject): - return py_object_type - else: - return PyrexTypes.c_bint_type + type1 = self.operand1.infer_type(env) + type2 = self.operand2.infer_type(env) + return PyrexTypes.spanning_type(type1, type2) def calculate_constant_result(self): if self.operator == 'and': @@ -4858,22 +4856,14 @@ class BoolBinopNode(ExprNode): def analyse_types(self, env): self.operand1.analyse_types(env) self.operand2.analyse_types(env) - if self.operand1.type.is_pyobject or \ - self.operand2.type.is_pyobject: - self.operand1 = self.operand1.coerce_to_pyobject(env) - self.operand2 = self.operand2.coerce_to_pyobject(env) - self.type = py_object_type - else: - self.operand1 = self.operand1.coerce_to_boolean(env) - self.operand2 = self.operand2.coerce_to_boolean(env) - self.type = PyrexTypes.c_bint_type - - # Below disabled for + self.type = PyrexTypes.spanning_type(self.operand1.type, self.operand2.type) + self.operand1 = self.operand1.coerce_to(self.type, env) + self.operand2 = self.operand2.coerce_to(self.type, env) # For what we're about to do, it's vital that # both operands be temp nodes. -# self.operand1 = self.operand1.coerce_to_temp(env) #CTT -# self.operand2 = self.operand2.coerce_to_temp(env) + self.operand1 = self.operand1.coerce_to_temp(env) + self.operand2 = self.operand2.coerce_to_temp(env) self.is_temp = 1 gil_message = "Truth-testing Python object" @@ -4882,14 +4872,6 @@ class BoolBinopNode(ExprNode): self.operand1.check_const() self.operand2.check_const() - def calculate_result_code(self): - return "(%s %s %s)" % ( - self.operand1.result(), - self.py_to_c_op[self.operator], - self.operand2.result()) - - py_to_c_op = {'and': "&&", 'or': "||"} - def generate_evaluation_code(self, code): code.mark_pos(self.pos) self.operand1.generate_evaluation_code(code) diff --git a/runtests.py b/runtests.py index efb4d421..b0345d1d 100644 --- a/runtests.py +++ b/runtests.py @@ -387,7 +387,7 @@ class CythonRunTestCase(CythonCompileTestCase): pass def run_doctests(self, module_name, result): - if sys.version_info[0] >= 3 or not hasattr(os, 'fork'): + if sys.version_info[0] >= 3 or not hasattr(os, 'forkx'): doctest.DocTestSuite(module_name).run(result) return diff --git a/tests/errors/nogil.pyx b/tests/errors/nogil.pyx index f0c5dfa3..a16386ce 100644 --- a/tests/errors/nogil.pyx +++ b/tests/errors/nogil.pyx @@ -116,7 +116,9 @@ _ERRORS = u""" 39: 9: Constructing Python tuple not allowed without gil 40: 8: Constructing Python list not allowed without gil 41: 8: Constructing Python dict not allowed without gil +42:12: Creating temporary Python reference not allowed without gil 42:12: Truth-testing Python object not allowed without gil +42:17: Creating temporary Python reference not allowed without gil 43:13: Python type test not allowed without gil 45:10: Operation not allowed without gil 46:8: Operation not allowed without gil diff --git a/tests/run/boolop.pyx b/tests/run/boolop.pyx index 59e2a0f0..fdbac10b 100644 --- a/tests/run/boolop.pyx +++ b/tests/run/boolop.pyx @@ -1,21 +1,22 @@ __doc__ = u""" >>> foo(True, False, 23, 'test', 1) - (0, 1, False, False) + (0.0, 1.0, False, False) """ def foo(obj1, obj2, obj3, obj4, obj5): - cdef int bool1, bool2, bool3, bool4 - cdef char *ptr + cdef int bool1, bool2 + cdef float bool3, bool4 + cdef char *ptr1, *ptr2, *ptr0 cdef float f bool1 = 1 bool2 = 0 - ptr = NULL + ptr1 = ptr2 = NULL f = 0.0 bool3 = bool1 and bool2 bool3 = bool1 or bool2 bool3 = obj1 and obj2 - bool3 = bool1 and ptr + ptr0 = ptr1 and ptr2 bool3 = bool1 and f bool4 = bool1 and bool2 and bool3 bool4 = bool1 or bool2 and bool3 diff --git a/tests/run/short_circuit_T404.pyx b/tests/run/short_circuit_T404.pyx index 7ef2105b..b49e328b 100644 --- a/tests/run/short_circuit_T404.pyx +++ b/tests/run/short_circuit_T404.pyx @@ -6,18 +6,18 @@ def test_or(long a, long b): """ >>> test_or(1,2) foo(1) - True + 1 >>> test_or(1,0) foo(1) - True + 1 >>> test_or(0,2) foo(0) foo(2) - True + 2 >>> test_or(0,0) foo(0) foo(0) - False + 0 """ print foo(a) or foo(b) @@ -26,16 +26,16 @@ def test_and(long a, long b): >>> test_and(1,2) foo(1) foo(2) - True + 2 >>> test_and(1,0) foo(1) foo(0) - False + 0 >>> test_and(0,2) foo(0) - False + 0 >>> test_and(0,0) foo(0) - False + 0 """ print foo(a) and foo(b) -- 2.26.2