Commit 9f850fb4 authored by Robert Bradshaw's avatar Robert Bradshaw

Support operator bool() for C++ classes.

parent 3511ed4e
...@@ -68,6 +68,8 @@ Features added ...@@ -68,6 +68,8 @@ Features added
* External C++ classes that overload the assignment operator can be used. * External C++ classes that overload the assignment operator can be used.
Patch by Ian Henriksen. Patch by Ian Henriksen.
* Support operator bool() for C++ classes so they can be used in if statements.
Bugs fixed Bugs fixed
---------- ----------
......
...@@ -846,6 +846,12 @@ class ExprNode(Node): ...@@ -846,6 +846,12 @@ class ExprNode(Node):
return self return self
elif type.is_pyobject or type.is_int or type.is_ptr or type.is_float: elif type.is_pyobject or type.is_int or type.is_ptr or type.is_float:
return CoerceToBooleanNode(self, env) return CoerceToBooleanNode(self, env)
elif type.is_cpp_class:
return SimpleCallNode(
self.pos,
function=AttributeNode(
self.pos, obj=self, attribute='operator bool'),
args=[]).analyse_types(env)
elif type.is_ctuple: elif type.is_ctuple:
bool_value = len(type.components) == 0 bool_value = len(type.components) == 0
return BoolNode(self.pos, value=bool_value, return BoolNode(self.pos, value=bool_value,
......
...@@ -2543,7 +2543,8 @@ supported_overloaded_operators = cython.declare(set, set([ ...@@ -2543,7 +2543,8 @@ supported_overloaded_operators = cython.declare(set, set([
'+', '-', '*', '/', '%', '+', '-', '*', '/', '%',
'++', '--', '~', '|', '&', '^', '<<', '>>', ',', '++', '--', '~', '|', '&', '^', '<<', '>>', ',',
'==', '!=', '>=', '>', '<=', '<', '==', '!=', '>=', '>', '<=', '<',
'[]', '()', '!', '=' '[]', '()', '!', '=',
'bool',
])) ]))
def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag, def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
...@@ -2620,6 +2621,13 @@ def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag, ...@@ -2620,6 +2621,13 @@ def p_c_simple_declarator(s, ctx, empty, is_type, cmethod_flag,
s.error("Overloading operator '%s' not yet supported." % op, s.error("Overloading operator '%s' not yet supported." % op,
fatal=False) fatal=False)
name += op name += op
elif op == 'IDENT':
op = s.systring;
if op not in supported_overloaded_operators:
s.error("Overloading operator '%s' not yet supported." % op,
fatal=False)
name = name + ' ' + op
s.next()
result = Nodes.CNameDeclaratorNode(pos, result = Nodes.CNameDeclaratorNode(pos,
name = name, cname = cname, default = rhs) name = name, cname = cname, default = rhs)
result.calling_convention = calling_convention result.calling_convention = calling_convention
......
...@@ -7,6 +7,7 @@ cimport cython.operator ...@@ -7,6 +7,7 @@ cimport cython.operator
from cython.operator cimport dereference as deref from cython.operator cimport dereference as deref
from libc.string cimport const_char from libc.string cimport const_char
from libcpp cimport bool
cdef out(s, result_type=None): cdef out(s, result_type=None):
print '%s [%s]' % (s.decode('ascii'), result_type) print '%s [%s]' % (s.decode('ascii'), result_type)
...@@ -49,6 +50,12 @@ cdef extern from "cpp_operators_helper.h": ...@@ -49,6 +50,12 @@ cdef extern from "cpp_operators_helper.h":
const_char* operator[](int) const_char* operator[](int)
const_char* operator()(int) const_char* operator()(int)
cppclass TruthClass:
TruthClass()
TruthClass(bool)
bool operator bool()
bool value
def test_unops(): def test_unops():
""" """
>>> test_unops() >>> test_unops()
...@@ -148,3 +155,30 @@ def test_index_call(): ...@@ -148,3 +155,30 @@ def test_index_call():
out(t[0][100], typeof(t[0][100])) out(t[0][100], typeof(t[0][100]))
out(t[0](100), typeof(t[0](100))) out(t[0](100), typeof(t[0](100)))
del t del t
def test_bool_op():
"""
>>> test_bool_op()
"""
cdef TruthClass yes = TruthClass(True)
cdef TruthClass no = TruthClass(False)
if yes:
pass
else:
assert False
if no:
assert False
def test_bool_cond():
"""
>>> test_bool_cond()
"""
assert (TruthClass(False) or TruthClass(False)).value == False
assert (TruthClass(False) or TruthClass(True)).value == True
assert (TruthClass(True) or TruthClass(False)).value == True
assert (TruthClass(True) or TruthClass(True)).value == True
assert (TruthClass(False) and TruthClass(False)).value == False
assert (TruthClass(False) and TruthClass(True)).value == False
assert (TruthClass(True) and TruthClass(False)).value == False
assert (TruthClass(True) and TruthClass(True)).value == True
...@@ -45,3 +45,11 @@ public: ...@@ -45,3 +45,11 @@ public:
BIN_OP(()); BIN_OP(());
}; };
class TruthClass {
public:
TruthClass() : value(false) {}
TruthClass(bool value) : value(value) {}
operator bool() { return value; }
bool value;
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment