summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Bradshaw <robertwb@math.washington.edu>2009-10-15 03:58:28 -0700
committerRobert Bradshaw <robertwb@math.washington.edu>2009-10-15 03:58:28 -0700
commit307a66c292a22cf2ee56712b85b021d3a3948e6b (patch)
tree755a8b5d8e5a67c28e15bed2569bf33c6fb5779f
parentcddc08e4d5e5316a5d1242cd7cd3c2c0def17b61 (diff)
downloadcython-307a66c292a22cf2ee56712b85b021d3a3948e6b.tar.gz
Fix short-circuit for and/or, preserve type.
-rw-r--r--Cython/Compiler/ExprNodes.py34
-rw-r--r--runtests.py2
-rw-r--r--tests/errors/nogil.pyx2
-rw-r--r--tests/run/boolop.pyx11
-rw-r--r--tests/run/short_circuit_T404.pyx16
5 files changed, 25 insertions, 40 deletions
diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py
index bbc6f3263..fe21d6504 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 efb4d4216..b0345d1dd 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 f0c5dfa31..a16386ce0 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 59e2a0f04..fdbac10b0 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 7ef2105b0..b49e328be 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)