1# mode: run
2# tag: cpp, werror
3
4from cython.operator import (preincrement, predecrement,
5                             postincrement, postdecrement)
6from libcpp cimport bool
7
8cdef extern from "cpp_operator_exc_handling_helper.hpp" nogil:
9    cppclass wrapped_int:
10        long long val
11        wrapped_int()
12        wrapped_int(long long val)
13        wrapped_int(long long v1, long long v2) except +
14        wrapped_int operator+(wrapped_int &other) except +ValueError
15        wrapped_int operator+() except +RuntimeError
16        wrapped_int operator-(wrapped_int &other) except +
17        wrapped_int operator-() except +
18        wrapped_int operator*(wrapped_int &other) except +OverflowError
19        wrapped_int operator/(wrapped_int &other) except +
20        wrapped_int operator%(wrapped_int &other) except +
21        long long operator^(wrapped_int &other) except +
22        long long operator&(wrapped_int &other) except +
23        long long operator|(wrapped_int &other) except +
24        wrapped_int operator~() except +
25        long long operator&() except +
26        long long operator==(wrapped_int &other) except +
27        long long operator!=(wrapped_int &other) except +
28        long long operator<(wrapped_int &other) except +
29        long long operator<=(wrapped_int &other) except +
30        long long operator>(wrapped_int &other) except +
31        long long operator>=(wrapped_int &other) except +
32        wrapped_int operator<<(long long shift) except +
33        wrapped_int operator>>(long long shift) except +
34        wrapped_int &operator++() except +
35        wrapped_int &operator--() except +
36        wrapped_int operator++(int) except +
37        wrapped_int operator--(int) except +
38        wrapped_int operator!() except +
39        bool operator bool() except +
40        wrapped_int &operator[](long long &index) except +IndexError
41        long long &operator()() except +AttributeError
42        wrapped_int &operator=(const wrapped_int &other) except +ArithmeticError
43        wrapped_int &operator=(const long long &vao) except +
44
45    cdef cppclass second_call_is_different:
46        second_call_is_different()
47        bool operator<(const second_call_is_different&) except +
48
49
50def assert_raised(f, *args, **kwargs):
51    err = kwargs.get('err', None)
52    if err is None:
53        try:
54            f(*args)
55            raised = False
56        except:
57            raised = True
58    else:
59        try:
60            f(*args)
61            raised = False
62        except err:
63            raised = True
64    assert raised
65
66def initialization(long long a, long long b):
67    cdef wrapped_int w = wrapped_int(a, b)
68    return w.val
69
70def addition(long long a, long long b):
71    cdef wrapped_int wa = wrapped_int(a)
72    cdef wrapped_int wb = wrapped_int(b)
73    return (wa + wb).val
74
75def subtraction(long long a, long long b):
76    cdef wrapped_int wa = wrapped_int(a)
77    cdef wrapped_int wb = wrapped_int(b)
78    return (wa - wb).val
79
80def multiplication(long long a, long long b):
81    cdef wrapped_int wa = wrapped_int(a)
82    cdef wrapped_int wb = wrapped_int(b)
83    return (wa * wb).val
84
85def division(long long a, long long b):
86    cdef wrapped_int wa = wrapped_int(a)
87    cdef wrapped_int wb = wrapped_int(b)
88    return (wa / wb).val
89
90def mod(long long a, long long b):
91    cdef wrapped_int wa = wrapped_int(a)
92    cdef wrapped_int wb = wrapped_int(b)
93    return (wa % wb).val
94
95def minus(long long a):
96    cdef wrapped_int wa = wrapped_int(a)
97    return (-wa).val
98
99def plus(long long a):
100    cdef wrapped_int wa = wrapped_int(a)
101    return (+wa).val
102
103def xor(long long a, long long b):
104    cdef wrapped_int wa = wrapped_int(a)
105    cdef wrapped_int wb = wrapped_int(b)
106    return wa ^ wb
107
108def bitwise_and(long long a, long long b):
109    cdef wrapped_int wa = wrapped_int(a)
110    cdef wrapped_int wb = wrapped_int(b)
111    return wa & wb
112
113def bitwise_or(long long a, long long b):
114    cdef wrapped_int wa = wrapped_int(a)
115    cdef wrapped_int wb = wrapped_int(b)
116    return wa | wb
117
118def bitwise_not(long long a):
119    cdef wrapped_int wa = wrapped_int(a)
120    return (~a).val
121
122def address(long long a):
123    cdef wrapped_int wa = wrapped_int(a)
124    return &wa
125
126def iseq(long long a, long long b):
127    cdef wrapped_int wa = wrapped_int(a)
128    cdef wrapped_int wb = wrapped_int(b)
129    return wa == wb
130
131def neq(long long a, long long b):
132    cdef wrapped_int wa = wrapped_int(a)
133    cdef wrapped_int wb = wrapped_int(b)
134    return wa != wb
135
136def less(long long a, long long b):
137    cdef wrapped_int wa = wrapped_int(a)
138    cdef wrapped_int wb = wrapped_int(b)
139    return wa < wb
140
141def leq(long long a, long long b):
142    cdef wrapped_int wa = wrapped_int(a)
143    cdef wrapped_int wb = wrapped_int(b)
144    return wa <= wb
145
146def greater(long long a, long long b):
147    cdef wrapped_int wa = wrapped_int(a)
148    cdef wrapped_int wb = wrapped_int(b)
149    return wa > wb
150
151def geq(long long a, long long b):
152    cdef wrapped_int wa = wrapped_int(a)
153    cdef wrapped_int wb = wrapped_int(b)
154    return wa < wb
155
156def left_shift(long long a, long long b):
157    cdef wrapped_int wa = wrapped_int(a)
158    return (wa << b).val
159
160def right_shift(long long a, long long b):
161    cdef wrapped_int wa = wrapped_int(a)
162    return (wa >> b).val
163
164def cpp_preincrement(long long a):
165    cdef wrapped_int wa = wrapped_int(a)
166    return preincrement(wa).val
167
168def cpp_predecrement(long long a):
169    cdef wrapped_int wa = wrapped_int(a)
170    return predecrement(wa).val
171
172def cpp_postincrement(long long a):
173    cdef wrapped_int wa = wrapped_int(a)
174    return postincrement(wa).val
175
176def cpp_postdecrement(long long a):
177    cdef wrapped_int wa = wrapped_int(a)
178    return postdecrement(wa).val
179
180def negate(long long a):
181    cdef wrapped_int wa = wrapped_int(a)
182    return (not wa).val
183
184def bool_cast(long long a):
185    cdef wrapped_int wa = wrapped_int(a)
186    if wa:
187        return True
188    else:
189        return False
190
191def index(long long a, long long b):
192    cdef wrapped_int wa = wrapped_int(a)
193    return wa[b].val
194
195def assign_index(long long a, long long b, long long c):
196    cdef wrapped_int wa = wrapped_int(a)
197    cdef wrapped_int wb = wrapped_int(b)
198    wb[c] = wa
199    return wb.val
200
201def call(long long a):
202    cdef wrapped_int wa = wrapped_int(a)
203    return wa()
204
205def assign_same(long long a, long long b):
206    cdef wrapped_int wa = wrapped_int(a)
207    cdef wrapped_int wb = wrapped_int(b)
208    wa = wb
209    return wa.val
210
211def assign_different(long long a, long long b):
212    cdef wrapped_int wa = wrapped_int(a)
213    wa = b
214    return wa.val
215
216def cascaded_assign(long long a, long long b, long long c):
217    cdef wrapped_int wa = wrapped_int(a)
218    a = b = c
219    return a.val
220
221def separate_exceptions(long long a, long long b, long long c, long long d, long long e):
222    cdef:
223        wrapped_int wa = wrapped_int(a)
224        wrapped_int wc = wrapped_int(c)
225        wrapped_int wd = wrapped_int(d)
226        wrapped_int we = wrapped_int(e)
227    wa[b] = (+wc) * wd + we
228    return a.val
229
230def call_temp_separation(long long a, long long b, long long c):
231    cdef:
232        wrapped_int wa = wrapped_int(a)
233        wrapped_int wc = wrapped_int(c)
234    wa[b] = wc()
235    return wa.val
236
237def test_operator_exception_handling():
238    """
239    >>> test_operator_exception_handling()
240    """
241    assert_raised(initialization, 1, 4)
242    assert_raised(addition, 1, 4)
243    assert_raised(subtraction, 1, 4)
244    assert_raised(multiplication, 1, 4)
245    assert_raised(division, 1, 4)
246    assert_raised(mod, 1, 4)
247    assert_raised(minus, 4)
248    assert_raised(plus, 4)
249    assert_raised(xor, 1, 4)
250    assert_raised(address, 4)
251    assert_raised(iseq, 1, 4)
252    assert_raised(neq, 1, 4)
253    assert_raised(left_shift, 1, 4)
254    assert_raised(right_shift, 1, 4)
255    assert_raised(cpp_preincrement, 4)
256    assert_raised(cpp_predecrement, 4)
257    assert_raised(cpp_postincrement, 4)
258    assert_raised(cpp_postdecrement, 4)
259    assert_raised(negate, 4)
260    assert_raised(bool_cast, 4)
261    assert_raised(index, 1, 4)
262    assert_raised(assign_index, 1, 4, 4)
263    assert_raised(call, 4)
264    assert_raised(assign_same, 4, 4)
265    assert_raised(assign_different, 4, 4)
266    assert_raised(cascaded_assign, 4, 4, 1)
267    assert_raised(cascaded_assign, 4, 1, 4)
268    assert_raised(separate_exceptions, 1, 1, 1, 1, 4, err=ValueError)
269    assert_raised(separate_exceptions, 1, 1, 1, 4, 1, err=OverflowError)
270    assert_raised(separate_exceptions, 1, 1, 4, 1, 1, err=RuntimeError)
271    assert_raised(separate_exceptions, 1, 4, 1, 1, 1, err=IndexError)
272    assert_raised(separate_exceptions, 4, 1, 1, 1, 3, err=ArithmeticError)
273    assert_raised(call_temp_separation, 2, 1, 4, err=AttributeError)
274    assert_raised(call_temp_separation, 2, 4, 1, err=IndexError)
275
276def test_only_single_call():
277    """
278    Previous version of the operator handling code called the operator twice
279    (Resulting in a crash)
280    >>> test_only_single_call()
281    False
282    """
283    cdef second_call_is_different inst
284    return inst<inst
285