1# mode: run 2# tag: cpp, werror 3 4from __future__ import division 5 6from cython cimport typeof 7 8cimport cython.operator 9from cython.operator cimport typeid, dereference as deref 10 11from libc.string cimport const_char 12from libcpp cimport bool 13 14 15cdef out(s, result_type=None): 16 print '%s [%s]' % (s.decode('ascii'), result_type) 17 18 19cdef iout(int s, result_type=None): 20 print '%s [%s]' % (s, result_type) 21 22 23cdef extern from "cpp_operators_helper.h" nogil: 24 cdef cppclass TestOps: 25 26 const_char* operator+() except + 27 const_char* operator-() except + 28 const_char* operator*() except + 29 const_char* operator~() except + 30 const_char* operator!() except + 31 32 # FIXME: using 'except +' here leads to wrong calls ??? 33 const_char* operator++() 34 const_char* operator--() 35 const_char* operator++(int) 36 const_char* operator--(int) 37 38 const_char* operator+(int) except + 39 const_char* operator+(int,const TestOps&) except + 40 const_char* operator-(int) except + 41 const_char* operator-(int,const TestOps&) except + 42 const_char* operator*(int) except + 43 # deliberately omitted operator* to test case where only defined outside class 44 const_char* operator/(int) except + 45 const_char* operator/(int,const TestOps&) except + 46 const_char* operator%(int) except + 47 const_char* operator%(int,const TestOps&) except + 48 49 const_char* operator|(int) except + 50 const_char* operator|(int,const TestOps&) except + 51 const_char* operator&(int) except + 52 const_char* operator&(int,const TestOps&) except + 53 const_char* operator^(int) except + 54 const_char* operator^(int,const TestOps&) except + 55 const_char* operator,(int) except + 56 const_char* operator,(int,const TestOps&) except + 57 58 const_char* operator<<(int) except + 59 const_char* operator<<(int,const TestOps&) except + 60 const_char* operator>>(int) except + 61 const_char* operator>>(int,const TestOps&) except + 62 63 # FIXME: using 'except +' here leads to invalid C++ code ??? 64 const_char* operator==(int) 65 const_char* operator!=(int) 66 const_char* operator>=(int) 67 const_char* operator<=(int) 68 const_char* operator>(int) 69 const_char* operator<(int) 70 71 const_char* operator[](int) except + 72 const_char* operator()(int) except + 73 74 # Defining the operator outside the class does work 75 # but doesn't help when importing from pxd files 76 # (they don't get imported) 77 const_char* operator+(float,const TestOps&) except + 78 # deliberately omitted operator- to test case where only defined in class 79 const_char* operator*(float,const TestOps&) except + 80 const_char* operator/(float,const TestOps&) except + 81 const_char* operator%(float,const TestOps&) except + 82 83 const_char* operator|(float,const TestOps&) except + 84 const_char* operator&(float,const TestOps&) except + 85 const_char* operator^(float,const TestOps&) except + 86 const_char* operator,(float,const TestOps&) except + 87 88 const_char* operator<<(float,const TestOps&) except + 89 const_char* operator>>(float,const TestOps&) except + 90 91 cdef cppclass RefTestOps: 92 93 int& operator+() except + 94 int& operator-() except + 95 int& operator*() except + 96 int& operator~() except + 97 int& operator!() except + 98 99 int& operator++() except + 100 int& operator--() except + 101 int& operator++(int) except + 102 int& operator--(int) except + 103 104 int& operator+(int) except + 105 int& operator+(int,const TestOps&) except + 106 int& operator-(int) except + 107 int& operator-(int,const TestOps&) except + 108 int& operator*(int) except + 109 # deliberately omitted operator* to test case where only defined outside class 110 int& operator/(int) except + 111 int& operator/(int,const TestOps&) except + 112 int& operator%(int) except + 113 int& operator%(int,const TestOps&) except + 114 115 int& operator|(int) except + 116 int& operator|(int,const TestOps&) except + 117 int& operator&(int) except + 118 int& operator&(int,const TestOps&) except + 119 int& operator^(int) except + 120 int& operator^(int,const TestOps&) except + 121 int& operator,(int) except + 122 int& operator,(int,const TestOps&) except + 123 124 int& operator<<(int) except + 125 int& operator<<(int,const TestOps&) except + 126 int& operator>>(int) except + 127 int& operator>>(int,const TestOps&) except + 128 129 int& operator==(int) except + 130 int& operator!=(int) except + 131 int& operator>=(int) except + 132 int& operator<=(int) except + 133 int& operator>(int) except + 134 int& operator<(int) except + 135 136 int& operator[](int) except + 137 int& operator()(int) except + 138 139 cdef cppclass TruthClass: 140 TruthClass() 141 TruthClass(bool) 142 bool operator bool() 143 bool value 144 145 146cdef cppclass TruthSubClass(TruthClass): 147 pass 148 149 150def test_unops(): 151 """ 152 >>> test_unops() 153 unary + [const_char *] 154 unary - [const_char *] 155 unary ~ [const_char *] 156 unary * [const_char *] 157 unary ! [const_char *] 158 """ 159 cdef TestOps* t = new TestOps() 160 out(+t[0], typeof(+t[0])) 161 out(-t[0], typeof(-t[0])) 162 out(~t[0], typeof(~t[0])) 163 x = deref(t[0]) 164 out(x, typeof(x)) 165 out(not t[0], typeof(not t[0])) 166 del t 167 168def test_incdec(): 169 """ 170 >>> test_incdec() 171 unary ++ [const_char *] 172 unary -- [const_char *] 173 post ++ [const_char *] 174 post -- [const_char *] 175 """ 176 cdef TestOps* t = new TestOps() 177 a = cython.operator.preincrement(t[0]) 178 out(a, typeof(a)) 179 b = cython.operator.predecrement(t[0]) 180 out(b, typeof(b)) 181 c = cython.operator.postincrement(t[0]) 182 out(c, typeof(c)) 183 d = cython.operator.postdecrement(t[0]) 184 out(d, typeof(d)) 185 del t 186 187def test_binop(): 188 """ 189 >>> test_binop() 190 binary + [const_char *] 191 binary - [const_char *] 192 binary * [const_char *] 193 binary / [const_char *] 194 binary % [const_char *] 195 binary & [const_char *] 196 binary | [const_char *] 197 binary ^ [const_char *] 198 binary << [const_char *] 199 binary >> [const_char *] 200 binary COMMA [const_char *] 201 """ 202 cdef TestOps* t = new TestOps() 203 out(t[0] + 1, typeof(t[0] + 1)) 204 out(t[0] - 1, typeof(t[0] - 1)) 205 out(t[0] * 1, typeof(t[0] * 1)) 206 out(t[0] / 1, typeof(t[0] / 1)) 207 out(t[0] % 1, typeof(t[0] % 1)) 208 209 out(t[0] & 1, typeof(t[0] & 1)) 210 out(t[0] | 1, typeof(t[0] | 1)) 211 out(t[0] ^ 1, typeof(t[0] ^ 1)) 212 213 out(t[0] << 1, typeof(t[0] << 1)) 214 out(t[0] >> 1, typeof(t[0] >> 1)) 215 216 x = cython.operator.comma(t[0], 1) 217 out(x, typeof(x)) 218 del t 219 220def test_nonmember_binop(): 221 """ 222 >>> test_nonmember_binop() 223 nonmember binary + [const_char *] 224 nonmember binary - [const_char *] 225 nonmember binary / [const_char *] 226 nonmember binary % [const_char *] 227 nonmember binary & [const_char *] 228 nonmember binary | [const_char *] 229 nonmember binary ^ [const_char *] 230 nonmember binary << [const_char *] 231 nonmember binary >> [const_char *] 232 nonmember binary COMMA [const_char *] 233 nonmember binary2 + [const_char *] 234 nonmember binary2 * [const_char *] 235 nonmember binary2 / [const_char *] 236 nonmember binary2 % [const_char *] 237 nonmember binary2 & [const_char *] 238 nonmember binary2 | [const_char *] 239 nonmember binary2 ^ [const_char *] 240 nonmember binary2 << [const_char *] 241 nonmember binary2 >> [const_char *] 242 nonmember binary2 COMMA [const_char *] 243 """ 244 245 cdef TestOps* t = new TestOps() 246 out(1 + t[0], typeof(1 + t[0])) 247 out(1 - t[0], typeof(1 - t[0])) 248 # * deliberately omitted 249 out(1 / t[0], typeof(1 / t[0])) 250 out(1 % t[0], typeof(1 % t[0])) 251 out(1 & t[0], typeof(1 & t[0])) 252 out(1 | t[0], typeof(1 | t[0])) 253 out(1 ^ t[0], typeof(1 ^ t[0])) 254 out(1 << t[0], typeof(1 << t[0])) 255 out(1 >> t[0], typeof(1 >> t[0])) 256 257 x = cython.operator.comma(1, t[0]) 258 out(x, typeof(x)) 259 260 # now test float operators defined outside class 261 out(1. + t[0], typeof(1. + t[0])) 262 # operator - deliberately omitted 263 out(1. * t[0], typeof(1. * t[0])) 264 out(1. / t[0], typeof(1. / t[0])) 265 out(1. % t[0], typeof(1. % t[0])) 266 out(1. & t[0], typeof(1. & t[0])) 267 out(1. | t[0], typeof(1. | t[0])) 268 out(1. ^ t[0], typeof(1. ^ t[0])) 269 out(1. << t[0], typeof(1. << t[0])) 270 out(1. >> t[0], typeof(1. >> t[0])) 271 272 # for some reason we need a cdef here - not sure this is quite right 273 y = cython.operator.comma(1., t[0]) 274 out(y, typeof(y)) 275 del t 276 277def test_cmp(): 278 """ 279 >>> test_cmp() 280 binary == [const_char *] 281 binary != [const_char *] 282 binary >= [const_char *] 283 binary > [const_char *] 284 binary <= [const_char *] 285 binary < [const_char *] 286 """ 287 cdef TestOps* t = new TestOps() 288 out(t[0] == 1, typeof(t[0] == 1)) 289 out(t[0] != 1, typeof(t[0] != 1)) 290 out(t[0] >= 1, typeof(t[0] >= 1)) 291 out(t[0] > 1, typeof(t[0] > 1)) 292 out(t[0] <= 1, typeof(t[0] <= 1)) 293 out(t[0] < 1, typeof(t[0] < 1)) 294 del t 295 296 297def test_index_call(): 298 """ 299 >>> test_index_call() 300 binary [] [const_char *] 301 binary () [const_char *] 302 """ 303 cdef TestOps* t = new TestOps() 304 out(t[0][100], typeof(t[0][100])) 305 out(t[0](100), typeof(t[0](100))) 306 del t 307 308 309def test_index_assignment(): 310 """ 311 >>> test_index_assignment() 312 0 [int &] 313 123 [int [&]] 314 """ 315 cdef RefTestOps* t = new RefTestOps() 316 iout(t[0][100], typeof(t[0][100])) 317 t[0][99] = 123 318 iout(t[0](100), typeof(t[0](100))) 319 del t 320 321 322def test_bool_op(): 323 """ 324 >>> test_bool_op() 325 """ 326 cdef TruthClass yes = TruthClass(True) 327 cdef TruthClass no = TruthClass(False) 328 if yes: 329 pass 330 else: 331 assert False 332 if no: 333 assert False 334 335def test_bool_cond(): 336 """ 337 >>> test_bool_cond() 338 """ 339 assert (TruthClass(False) or TruthClass(False)).value == False 340 assert (TruthClass(False) or TruthClass(True)).value == True 341 assert (TruthClass(True) or TruthClass(False)).value == True 342 assert (TruthClass(True) or TruthClass(True)).value == True 343 344 assert (TruthClass(False) and TruthClass(False)).value == False 345 assert (TruthClass(False) and TruthClass(True)).value == False 346 assert (TruthClass(True) and TruthClass(False)).value == False 347 assert (TruthClass(True) and TruthClass(True)).value == True 348 349 350ctypedef int* int_ptr 351 352def test_typeid_op(): 353 """ 354 >>> test_typeid_op() 355 """ 356 cdef TruthClass* test_1 = new TruthClass() 357 cdef TruthSubClass* test_2 = new TruthSubClass() 358 cdef TruthClass* test_3 = <TruthClass*> test_2 359 cdef TruthClass* test_4 = <TruthClass*> 0 360 361 assert typeid(TruthClass).name() 362 assert typeid(test_1).name() 363 assert typeid(TruthClass) == typeid(deref(test_1)) 364 365 assert typeid(TruthSubClass).name() 366 assert typeid(test_2).name() 367 assert typeid(TruthSubClass) == typeid(deref(test_2)) 368 assert typeid(TruthSubClass) == typeid(deref(test_3)) 369 assert typeid(TruthClass) != typeid(deref(test_3)) 370 371 assert typeid(TruthClass).name() 372 assert typeid(test_3).name() 373 assert typeid(TruthSubClass).name() 374 assert typeid(deref(test_2)).name() 375 assert typeid(int_ptr).name() 376 377 try: 378 typeid(deref(test_4)) 379 assert False 380 except TypeError: 381 assert True 382 383 del test_1, test_2 384