Fix short-circuit for and/or, preserve type.
authorRobert Bradshaw <robertwb@math.washington.edu>
Thu, 15 Oct 2009 10:58:28 +0000 (03:58 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Thu, 15 Oct 2009 10:58:28 +0000 (03:58 -0700)
Cython/Compiler/ExprNodes.py
runtests.py
tests/errors/nogil.pyx
tests/run/boolop.pyx
tests/run/short_circuit_T404.pyx

index bbc6f3263dbb6175f60b02c9238e23e6992d3d28..fe21d650408221c8ba2b7e61399943a8eedf0898 100644 (file)
@@ -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)
index efb4d4216654a53850d45eb5128690a665718f67..b0345d1ddbc8a41b2f0564683758b8a7a4716234 100644 (file)
@@ -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
 
index f0c5dfa318ca131d1b45dc352771a86362a41aad..a16386ce00e75b74b3c89485480f0096c078cd06 100644 (file)
@@ -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
index 59e2a0f04d6b5ad7b2cde559de9216e6b54e699a..fdbac10b02cfbcdc335fa5ef0f523b0805debe34 100644 (file)
@@ -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
index 7ef2105b0301f90a62ccbc83230c696f8c3cf59b..b49e328bef088e5b2ebf1b949602ccd416519fd3 100644 (file)
@@ -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)