Nuitka
The Python compiler
Loading...
Searching...
No Matches
HelpersOperationInplaceMod.c
1// Copyright 2025, Kay Hayen, mailto:kay.hayen@gmail.com find license text at end of file
2
3/* WARNING, this code is GENERATED. Modify the template HelperOperationInplace.c.j2 instead! */
4
5/* This file is included from another C file, help IDEs to still parse it on its own. */
6#ifdef __IDE_ONLY__
7#include "nuitka/prelude.h"
8#endif
9
10/* C helpers for type in-place "%" (MOD) operations */
11
12#if PYTHON_VERSION < 0x300
13/* Code referring to "INT" corresponds to Python2 'int' and "INT" to Python2 'int'. */
14static inline bool _INPLACE_OPERATION_MOD_INT_INT(PyObject **operand1, PyObject *operand2) {
15 assert(operand1); // Pointer must be non-null.
16
17 CHECK_OBJECT(*operand1);
18 assert(PyInt_CheckExact(*operand1));
19 CHECK_OBJECT(operand2);
20 assert(PyInt_CheckExact(operand2));
21
22 // Not every code path will make use of all possible results.
23#if defined(_MSC_VER)
24#pragma warning(push)
25#pragma warning(disable : 4101)
26#endif
27 NUITKA_MAY_BE_UNUSED bool cbool_result;
28 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
29 NUITKA_MAY_BE_UNUSED long clong_result;
30 NUITKA_MAY_BE_UNUSED double cfloat_result;
31#if defined(_MSC_VER)
32#pragma warning(pop)
33#endif
34
35 CHECK_OBJECT(*operand1);
36 assert(PyInt_CheckExact(*operand1));
37 CHECK_OBJECT(operand2);
38 assert(PyInt_CheckExact(operand2));
39
40 const long a = PyInt_AS_LONG(*operand1);
41 const long b = PyInt_AS_LONG(operand2);
42
43 /* TODO: Isn't this a very specific value only, of which we could
44 * hardcode the constant result. Not sure how well the C compiler
45 * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by
46 * -1 has to be rare anyway.
47 */
48
49 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
50 long r = a % b;
51
52 // Sign handling.
53 if (r != 0 && ((b ^ r) < 0)) {
54 r += b;
55 }
56
57 clong_result = r;
58 goto exit_result_ok_clong;
59 }
60
61 {
62 PyObject *operand1_object = *operand1;
63 PyObject *operand2_object = operand2;
64
65 PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object);
66 assert(r != Py_NotImplemented);
67
68 obj_result = r;
69 goto exit_result_object;
70 }
71
72exit_result_ok_clong:
73
74 // We got an object handed, that we have to release.
75 Py_DECREF(*operand1);
76
77 // That's our return value then. As we use a dedicated variable, it's
78 // OK that way.
79 *operand1 = Nuitka_PyInt_FromLong(clong_result);
80 goto exit_result_ok;
81
82exit_result_object:
83 if (unlikely(obj_result == NULL)) {
84 goto exit_result_exception;
85 }
86 // We got an object handed, that we have to release.
87 Py_DECREF(*operand1);
88
89 *operand1 = obj_result;
90 goto exit_result_ok;
91
92exit_result_ok:
93 return true;
94
95exit_result_exception:
96 return false;
97}
98
99bool INPLACE_OPERATION_MOD_INT_INT(PyObject **operand1, PyObject *operand2) {
100 return _INPLACE_OPERATION_MOD_INT_INT(operand1, operand2);
101}
102#endif
103
104#if PYTHON_VERSION < 0x300
105/* Code referring to "OBJECT" corresponds to any Python object and "INT" to Python2 'int'. */
106static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_OBJECT_INT(PyObject **operand1, PyObject *operand2) {
107 PyTypeObject *type1 = Py_TYPE(*operand1);
108
109#if defined(_MSC_VER)
110#pragma warning(push)
111#pragma warning(disable : 4101)
112#endif
113 NUITKA_MAY_BE_UNUSED bool cbool_result;
114 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
115#if defined(_MSC_VER)
116#pragma warning(pop)
117#endif
118
119 binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1))
120 ? type1->tp_as_number->nb_inplace_remainder
121 : NULL;
122
123 if (islot != NULL) {
124 PyObject *x = islot(*operand1, operand2);
125
126 if (x != Py_NotImplemented) {
127 obj_result = x;
128 goto exit_inplace_result_object;
129 }
130
131 Py_DECREF_IMMORTAL(x);
132 }
133
134 {
135 binaryfunc slot1 =
136 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL;
137 binaryfunc slot2 = NULL;
138
139 if (!(type1 == &PyInt_Type)) {
140 // Different types, need to consider second value slot.
141
142 slot2 = PyInt_Type.tp_as_number->nb_remainder;
143
144 if (slot1 == slot2) {
145 slot2 = NULL;
146 }
147 }
148
149 if (slot1 != NULL) {
150 PyObject *x = slot1(*operand1, operand2);
151
152 if (x != Py_NotImplemented) {
153 obj_result = x;
154 goto exit_inplace_result_object;
155 }
156
157 Py_DECREF_IMMORTAL(x);
158 }
159
160 if (slot2 != NULL) {
161 PyObject *x = slot2(*operand1, operand2);
162
163 if (x != Py_NotImplemented) {
164 obj_result = x;
165 goto exit_inplace_result_object;
166 }
167
168 Py_DECREF_IMMORTAL(x);
169 }
170
171#if PYTHON_VERSION < 0x300
172 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
173 coercion c1 =
174 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
175
176 if (c1 != NULL) {
177 PyObject *coerced1 = *operand1;
178 PyObject *coerced2 = operand2;
179
180 int err = c1(&coerced1, &coerced2);
181
182 if (unlikely(err < 0)) {
183 goto exit_inplace_exception;
184 }
185
186 if (err == 0) {
187 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
188
189 if (likely(mv == NULL)) {
190 binaryfunc slot = mv->nb_remainder;
191
192 if (likely(slot != NULL)) {
193 PyObject *x = slot(coerced1, coerced2);
194
195 Py_DECREF(coerced1);
196 Py_DECREF(coerced2);
197
198 obj_result = x;
199 goto exit_inplace_result_object;
200 }
201 }
202
203 // nb_coerce took a reference.
204 Py_DECREF(coerced1);
205 Py_DECREF(coerced2);
206 }
207 }
208 coercion c2 = PyInt_Type.tp_as_number->nb_coerce;
209
210 if (c2 != NULL) {
211 PyObject *coerced1 = *operand1;
212 PyObject *coerced2 = operand2;
213
214 int err = c2(&coerced2, &coerced1);
215
216 if (unlikely(err < 0)) {
217 goto exit_inplace_exception;
218 }
219
220 if (err == 0) {
221 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
222
223 if (likely(mv == NULL)) {
224 binaryfunc slot = mv->nb_remainder;
225
226 if (likely(slot != NULL)) {
227 PyObject *x = slot(coerced1, coerced2);
228
229 Py_DECREF(coerced1);
230 Py_DECREF(coerced2);
231
232 obj_result = x;
233 goto exit_inplace_result_object;
234 }
235 }
236
237 // nb_coerce took a reference.
238 Py_DECREF(coerced1);
239 Py_DECREF(coerced2);
240 }
241 }
242 }
243#endif
244
245 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: '%s' and 'int'", type1->tp_name);
246 goto exit_inplace_exception;
247 }
248
249exit_inplace_result_object:
250 if (unlikely(obj_result == NULL)) {
251 return false;
252 }
253
254 // We got an object handed, that we have to release.
255 Py_DECREF(*operand1);
256
257 // That's our return value then. As we use a dedicated variable, it's
258 // OK that way.
259 *operand1 = obj_result;
260
261 return true;
262
263exit_inplace_exception:
264 return false;
265}
266static inline bool _INPLACE_OPERATION_MOD_OBJECT_INT(PyObject **operand1, PyObject *operand2) {
267 assert(operand1); // Pointer must be non-null.
268
269 CHECK_OBJECT(*operand1);
270 CHECK_OBJECT(operand2);
271 assert(PyInt_CheckExact(operand2));
272
273 PyTypeObject *type1 = Py_TYPE(*operand1);
274
275 if (type1 == &PyInt_Type) {
276 // return _BINARY_OPERATION_MOD_INT_INT_INPLACE(operand1, operand2);
277
278 // Not every code path will make use of all possible results.
279#if defined(_MSC_VER)
280#pragma warning(push)
281#pragma warning(disable : 4101)
282#endif
283 NUITKA_MAY_BE_UNUSED bool cbool_result;
284 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
285 NUITKA_MAY_BE_UNUSED long clong_result;
286 NUITKA_MAY_BE_UNUSED double cfloat_result;
287#if defined(_MSC_VER)
288#pragma warning(pop)
289#endif
290
291 CHECK_OBJECT(*operand1);
292 assert(PyInt_CheckExact(*operand1));
293 CHECK_OBJECT(operand2);
294 assert(PyInt_CheckExact(operand2));
295
296 const long a = PyInt_AS_LONG(*operand1);
297 const long b = PyInt_AS_LONG(operand2);
298
299 /* TODO: Isn't this a very specific value only, of which we could
300 * hardcode the constant result. Not sure how well the C compiler
301 * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by
302 * -1 has to be rare anyway.
303 */
304
305 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
306 long r = a % b;
307
308 // Sign handling.
309 if (r != 0 && ((b ^ r) < 0)) {
310 r += b;
311 }
312
313 clong_result = r;
314 goto exit_result_ok_clong;
315 }
316
317 {
318 PyObject *operand1_object = *operand1;
319 PyObject *operand2_object = operand2;
320
321 PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object);
322 assert(r != Py_NotImplemented);
323
324 obj_result = r;
325 goto exit_result_object;
326 }
327
328 exit_result_ok_clong:
329
330 // We got an object handed, that we have to release.
331 Py_DECREF(*operand1);
332
333 // That's our return value then. As we use a dedicated variable, it's
334 // OK that way.
335 *operand1 = Nuitka_PyInt_FromLong(clong_result);
336 goto exit_result_ok;
337
338 exit_result_object:
339 if (unlikely(obj_result == NULL)) {
340 goto exit_result_exception;
341 }
342 // We got an object handed, that we have to release.
343 Py_DECREF(*operand1);
344
345 *operand1 = obj_result;
346 goto exit_result_ok;
347
348 exit_result_ok:
349 return true;
350
351 exit_result_exception:
352 return false;
353 }
354
355 return __INPLACE_OPERATION_MOD_OBJECT_INT(operand1, operand2);
356}
357
358bool INPLACE_OPERATION_MOD_OBJECT_INT(PyObject **operand1, PyObject *operand2) {
359 return _INPLACE_OPERATION_MOD_OBJECT_INT(operand1, operand2);
360}
361#endif
362
363#if PYTHON_VERSION < 0x300
364/* Code referring to "INT" corresponds to Python2 'int' and "OBJECT" to any Python object. */
365static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_INT_OBJECT(PyObject **operand1, PyObject *operand2) {
366 PyTypeObject *type2 = Py_TYPE(operand2);
367
368#if defined(_MSC_VER)
369#pragma warning(push)
370#pragma warning(disable : 4101)
371#endif
372 NUITKA_MAY_BE_UNUSED bool cbool_result;
373 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
374#if defined(_MSC_VER)
375#pragma warning(pop)
376#endif
377
378 // No inplace number slot nb_inplace_remainder available for this type.
379
380 {
381 binaryfunc slot1 = PyInt_Type.tp_as_number->nb_remainder;
382 binaryfunc slot2 = NULL;
383
384 if (!(&PyInt_Type == type2)) {
385 // Different types, need to consider second value slot.
386
387 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder
388 : NULL;
389
390 if (slot1 == slot2) {
391 slot2 = NULL;
392 }
393 }
394
395 if (slot1 != NULL) {
396 if (slot2 != NULL) {
397 if (Nuitka_Type_IsSubtype(type2, &PyInt_Type)) {
398 PyObject *x = slot2(*operand1, operand2);
399
400 if (x != Py_NotImplemented) {
401 obj_result = x;
402 goto exit_inplace_result_object;
403 }
404
405 Py_DECREF_IMMORTAL(x);
406 slot2 = NULL;
407 }
408 }
409
410 PyObject *x = slot1(*operand1, operand2);
411
412 if (x != Py_NotImplemented) {
413 obj_result = x;
414 goto exit_inplace_result_object;
415 }
416
417 Py_DECREF_IMMORTAL(x);
418 }
419
420 if (slot2 != NULL) {
421 PyObject *x = slot2(*operand1, operand2);
422
423 if (x != Py_NotImplemented) {
424 obj_result = x;
425 goto exit_inplace_result_object;
426 }
427
428 Py_DECREF_IMMORTAL(x);
429 }
430
431#if PYTHON_VERSION < 0x300
432 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
433 coercion c1 = PyInt_Type.tp_as_number->nb_coerce;
434
435 if (c1 != NULL) {
436 PyObject *coerced1 = *operand1;
437 PyObject *coerced2 = operand2;
438
439 int err = c1(&coerced1, &coerced2);
440
441 if (unlikely(err < 0)) {
442 goto exit_inplace_exception;
443 }
444
445 if (err == 0) {
446 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
447
448 if (likely(mv == NULL)) {
449 binaryfunc slot = mv->nb_remainder;
450
451 if (likely(slot != NULL)) {
452 PyObject *x = slot(coerced1, coerced2);
453
454 Py_DECREF(coerced1);
455 Py_DECREF(coerced2);
456
457 obj_result = x;
458 goto exit_inplace_result_object;
459 }
460 }
461
462 // nb_coerce took a reference.
463 Py_DECREF(coerced1);
464 Py_DECREF(coerced2);
465 }
466 }
467 coercion c2 =
468 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
469
470 if (c2 != NULL) {
471 PyObject *coerced1 = *operand1;
472 PyObject *coerced2 = operand2;
473
474 int err = c2(&coerced2, &coerced1);
475
476 if (unlikely(err < 0)) {
477 goto exit_inplace_exception;
478 }
479
480 if (err == 0) {
481 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
482
483 if (likely(mv == NULL)) {
484 binaryfunc slot = mv->nb_remainder;
485
486 if (likely(slot != NULL)) {
487 PyObject *x = slot(coerced1, coerced2);
488
489 Py_DECREF(coerced1);
490 Py_DECREF(coerced2);
491
492 obj_result = x;
493 goto exit_inplace_result_object;
494 }
495 }
496
497 // nb_coerce took a reference.
498 Py_DECREF(coerced1);
499 Py_DECREF(coerced2);
500 }
501 }
502 }
503#endif
504
505 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'int' and '%s'", type2->tp_name);
506 goto exit_inplace_exception;
507 }
508
509exit_inplace_result_object:
510 if (unlikely(obj_result == NULL)) {
511 return false;
512 }
513
514 // We got an object handed, that we have to release.
515 Py_DECREF(*operand1);
516
517 // That's our return value then. As we use a dedicated variable, it's
518 // OK that way.
519 *operand1 = obj_result;
520
521 return true;
522
523exit_inplace_exception:
524 return false;
525}
526static inline bool _INPLACE_OPERATION_MOD_INT_OBJECT(PyObject **operand1, PyObject *operand2) {
527 assert(operand1); // Pointer must be non-null.
528
529 CHECK_OBJECT(*operand1);
530 assert(PyInt_CheckExact(*operand1));
531 CHECK_OBJECT(operand2);
532
533 PyTypeObject *type2 = Py_TYPE(operand2);
534
535 if (&PyInt_Type == type2) {
536 // return _BINARY_OPERATION_MOD_INT_INT_INPLACE(operand1, operand2);
537
538 // Not every code path will make use of all possible results.
539#if defined(_MSC_VER)
540#pragma warning(push)
541#pragma warning(disable : 4101)
542#endif
543 NUITKA_MAY_BE_UNUSED bool cbool_result;
544 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
545 NUITKA_MAY_BE_UNUSED long clong_result;
546 NUITKA_MAY_BE_UNUSED double cfloat_result;
547#if defined(_MSC_VER)
548#pragma warning(pop)
549#endif
550
551 CHECK_OBJECT(*operand1);
552 assert(PyInt_CheckExact(*operand1));
553 CHECK_OBJECT(operand2);
554 assert(PyInt_CheckExact(operand2));
555
556 const long a = PyInt_AS_LONG(*operand1);
557 const long b = PyInt_AS_LONG(operand2);
558
559 /* TODO: Isn't this a very specific value only, of which we could
560 * hardcode the constant result. Not sure how well the C compiler
561 * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by
562 * -1 has to be rare anyway.
563 */
564
565 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
566 long r = a % b;
567
568 // Sign handling.
569 if (r != 0 && ((b ^ r) < 0)) {
570 r += b;
571 }
572
573 clong_result = r;
574 goto exit_result_ok_clong;
575 }
576
577 {
578 PyObject *operand1_object = *operand1;
579 PyObject *operand2_object = operand2;
580
581 PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object);
582 assert(r != Py_NotImplemented);
583
584 obj_result = r;
585 goto exit_result_object;
586 }
587
588 exit_result_ok_clong:
589
590 // We got an object handed, that we have to release.
591 Py_DECREF(*operand1);
592
593 // That's our return value then. As we use a dedicated variable, it's
594 // OK that way.
595 *operand1 = Nuitka_PyInt_FromLong(clong_result);
596 goto exit_result_ok;
597
598 exit_result_object:
599 if (unlikely(obj_result == NULL)) {
600 goto exit_result_exception;
601 }
602 // We got an object handed, that we have to release.
603 Py_DECREF(*operand1);
604
605 *operand1 = obj_result;
606 goto exit_result_ok;
607
608 exit_result_ok:
609 return true;
610
611 exit_result_exception:
612 return false;
613 }
614
615 return __INPLACE_OPERATION_MOD_INT_OBJECT(operand1, operand2);
616}
617
618bool INPLACE_OPERATION_MOD_INT_OBJECT(PyObject **operand1, PyObject *operand2) {
619 return _INPLACE_OPERATION_MOD_INT_OBJECT(operand1, operand2);
620}
621#endif
622
623/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "LONG" to Python2 'long', Python3 'int'. */
624static inline bool _INPLACE_OPERATION_MOD_LONG_LONG(PyObject **operand1, PyObject *operand2) {
625 assert(operand1); // Pointer must be non-null.
626
627 CHECK_OBJECT(*operand1);
628 assert(PyLong_CheckExact(*operand1));
629 CHECK_OBJECT(operand2);
630 assert(PyLong_CheckExact(operand2));
631
632 // Not every code path will make use of all possible results.
633#if defined(_MSC_VER)
634#pragma warning(push)
635#pragma warning(disable : 4101)
636#endif
637 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
638 NUITKA_MAY_BE_UNUSED long clong_result;
639#if defined(_MSC_VER)
640#pragma warning(pop)
641#endif
642
643 PyObject *x = PyLong_Type.tp_as_number->nb_remainder(*operand1, operand2);
644 assert(x != Py_NotImplemented);
645
646 obj_result = x;
647 goto exit_result_object;
648
649exit_result_object:
650 if (unlikely(obj_result == NULL)) {
651 goto exit_result_exception;
652 }
653 // We got an object handed, that we have to release.
654 Py_DECREF(*operand1);
655 *operand1 = obj_result;
656 goto exit_result_ok;
657
658exit_result_ok:
659 return true;
660
661exit_result_exception:
662 return false;
663}
664
665bool INPLACE_OPERATION_MOD_LONG_LONG(PyObject **operand1, PyObject *operand2) {
666 return _INPLACE_OPERATION_MOD_LONG_LONG(operand1, operand2);
667}
668
669/* Code referring to "OBJECT" corresponds to any Python object and "LONG" to Python2 'long', Python3 'int'. */
670static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_OBJECT_LONG(PyObject **operand1, PyObject *operand2) {
671 PyTypeObject *type1 = Py_TYPE(*operand1);
672
673#if defined(_MSC_VER)
674#pragma warning(push)
675#pragma warning(disable : 4101)
676#endif
677 NUITKA_MAY_BE_UNUSED bool cbool_result;
678 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
679#if defined(_MSC_VER)
680#pragma warning(pop)
681#endif
682
683 binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1))
684 ? type1->tp_as_number->nb_inplace_remainder
685 : NULL;
686
687 if (islot != NULL) {
688 PyObject *x = islot(*operand1, operand2);
689
690 if (x != Py_NotImplemented) {
691 obj_result = x;
692 goto exit_inplace_result_object;
693 }
694
695 Py_DECREF_IMMORTAL(x);
696 }
697
698 {
699 binaryfunc slot1 =
700 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL;
701 binaryfunc slot2 = NULL;
702
703 if (!(type1 == &PyLong_Type)) {
704 // Different types, need to consider second value slot.
705
706 slot2 = PyLong_Type.tp_as_number->nb_remainder;
707
708 if (slot1 == slot2) {
709 slot2 = NULL;
710 }
711 }
712
713 if (slot1 != NULL) {
714 PyObject *x = slot1(*operand1, operand2);
715
716 if (x != Py_NotImplemented) {
717 obj_result = x;
718 goto exit_inplace_result_object;
719 }
720
721 Py_DECREF_IMMORTAL(x);
722 }
723
724 if (slot2 != NULL) {
725 PyObject *x = slot2(*operand1, operand2);
726
727 if (x != Py_NotImplemented) {
728 obj_result = x;
729 goto exit_inplace_result_object;
730 }
731
732 Py_DECREF_IMMORTAL(x);
733 }
734
735#if PYTHON_VERSION < 0x300
736 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
737 coercion c1 =
738 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
739
740 if (c1 != NULL) {
741 PyObject *coerced1 = *operand1;
742 PyObject *coerced2 = operand2;
743
744 int err = c1(&coerced1, &coerced2);
745
746 if (unlikely(err < 0)) {
747 goto exit_inplace_exception;
748 }
749
750 if (err == 0) {
751 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
752
753 if (likely(mv == NULL)) {
754 binaryfunc slot = mv->nb_remainder;
755
756 if (likely(slot != NULL)) {
757 PyObject *x = slot(coerced1, coerced2);
758
759 Py_DECREF(coerced1);
760 Py_DECREF(coerced2);
761
762 obj_result = x;
763 goto exit_inplace_result_object;
764 }
765 }
766
767 // nb_coerce took a reference.
768 Py_DECREF(coerced1);
769 Py_DECREF(coerced2);
770 }
771 }
772 coercion c2 = PyLong_Type.tp_as_number->nb_coerce;
773
774 if (c2 != NULL) {
775 PyObject *coerced1 = *operand1;
776 PyObject *coerced2 = operand2;
777
778 int err = c2(&coerced2, &coerced1);
779
780 if (unlikely(err < 0)) {
781 goto exit_inplace_exception;
782 }
783
784 if (err == 0) {
785 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
786
787 if (likely(mv == NULL)) {
788 binaryfunc slot = mv->nb_remainder;
789
790 if (likely(slot != NULL)) {
791 PyObject *x = slot(coerced1, coerced2);
792
793 Py_DECREF(coerced1);
794 Py_DECREF(coerced2);
795
796 obj_result = x;
797 goto exit_inplace_result_object;
798 }
799 }
800
801 // nb_coerce took a reference.
802 Py_DECREF(coerced1);
803 Py_DECREF(coerced2);
804 }
805 }
806 }
807#endif
808
809#if PYTHON_VERSION < 0x300
810 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: '%s' and 'long'", type1->tp_name);
811#else
812 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: '%s' and 'int'", type1->tp_name);
813#endif
814 goto exit_inplace_exception;
815 }
816
817exit_inplace_result_object:
818 if (unlikely(obj_result == NULL)) {
819 return false;
820 }
821
822 // We got an object handed, that we have to release.
823 Py_DECREF(*operand1);
824
825 // That's our return value then. As we use a dedicated variable, it's
826 // OK that way.
827 *operand1 = obj_result;
828
829 return true;
830
831exit_inplace_exception:
832 return false;
833}
834static inline bool _INPLACE_OPERATION_MOD_OBJECT_LONG(PyObject **operand1, PyObject *operand2) {
835 assert(operand1); // Pointer must be non-null.
836
837 CHECK_OBJECT(*operand1);
838 CHECK_OBJECT(operand2);
839 assert(PyLong_CheckExact(operand2));
840
841 PyTypeObject *type1 = Py_TYPE(*operand1);
842
843 if (type1 == &PyLong_Type) {
844 // return _BINARY_OPERATION_MOD_LONG_LONG_INPLACE(operand1, operand2);
845
846 // Not every code path will make use of all possible results.
847#if defined(_MSC_VER)
848#pragma warning(push)
849#pragma warning(disable : 4101)
850#endif
851 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
852 NUITKA_MAY_BE_UNUSED long clong_result;
853#if defined(_MSC_VER)
854#pragma warning(pop)
855#endif
856
857 PyObject *x = PyLong_Type.tp_as_number->nb_remainder(*operand1, operand2);
858 assert(x != Py_NotImplemented);
859
860 obj_result = x;
861 goto exit_result_object;
862
863 exit_result_object:
864 if (unlikely(obj_result == NULL)) {
865 goto exit_result_exception;
866 }
867 // We got an object handed, that we have to release.
868 Py_DECREF(*operand1);
869 *operand1 = obj_result;
870 goto exit_result_ok;
871
872 exit_result_ok:
873 return true;
874
875 exit_result_exception:
876 return false;
877 }
878
879 return __INPLACE_OPERATION_MOD_OBJECT_LONG(operand1, operand2);
880}
881
882bool INPLACE_OPERATION_MOD_OBJECT_LONG(PyObject **operand1, PyObject *operand2) {
883 return _INPLACE_OPERATION_MOD_OBJECT_LONG(operand1, operand2);
884}
885
886/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "OBJECT" to any Python object. */
887static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_LONG_OBJECT(PyObject **operand1, PyObject *operand2) {
888 PyTypeObject *type2 = Py_TYPE(operand2);
889
890#if defined(_MSC_VER)
891#pragma warning(push)
892#pragma warning(disable : 4101)
893#endif
894 NUITKA_MAY_BE_UNUSED bool cbool_result;
895 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
896#if defined(_MSC_VER)
897#pragma warning(pop)
898#endif
899
900 // No inplace number slot nb_inplace_remainder available for this type.
901
902 {
903 binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder;
904 binaryfunc slot2 = NULL;
905
906 if (!(&PyLong_Type == type2)) {
907 // Different types, need to consider second value slot.
908
909 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder
910 : NULL;
911
912 if (slot1 == slot2) {
913 slot2 = NULL;
914 }
915 }
916
917 if (slot1 != NULL) {
918 if (slot2 != NULL) {
919 if (Nuitka_Type_IsSubtype(type2, &PyLong_Type)) {
920 PyObject *x = slot2(*operand1, operand2);
921
922 if (x != Py_NotImplemented) {
923 obj_result = x;
924 goto exit_inplace_result_object;
925 }
926
927 Py_DECREF_IMMORTAL(x);
928 slot2 = NULL;
929 }
930 }
931
932 PyObject *x = slot1(*operand1, operand2);
933
934 if (x != Py_NotImplemented) {
935 obj_result = x;
936 goto exit_inplace_result_object;
937 }
938
939 Py_DECREF_IMMORTAL(x);
940 }
941
942 if (slot2 != NULL) {
943 PyObject *x = slot2(*operand1, operand2);
944
945 if (x != Py_NotImplemented) {
946 obj_result = x;
947 goto exit_inplace_result_object;
948 }
949
950 Py_DECREF_IMMORTAL(x);
951 }
952
953#if PYTHON_VERSION < 0x300
954 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
955 coercion c1 = PyLong_Type.tp_as_number->nb_coerce;
956
957 if (c1 != NULL) {
958 PyObject *coerced1 = *operand1;
959 PyObject *coerced2 = operand2;
960
961 int err = c1(&coerced1, &coerced2);
962
963 if (unlikely(err < 0)) {
964 goto exit_inplace_exception;
965 }
966
967 if (err == 0) {
968 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
969
970 if (likely(mv == NULL)) {
971 binaryfunc slot = mv->nb_remainder;
972
973 if (likely(slot != NULL)) {
974 PyObject *x = slot(coerced1, coerced2);
975
976 Py_DECREF(coerced1);
977 Py_DECREF(coerced2);
978
979 obj_result = x;
980 goto exit_inplace_result_object;
981 }
982 }
983
984 // nb_coerce took a reference.
985 Py_DECREF(coerced1);
986 Py_DECREF(coerced2);
987 }
988 }
989 coercion c2 =
990 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
991
992 if (c2 != NULL) {
993 PyObject *coerced1 = *operand1;
994 PyObject *coerced2 = operand2;
995
996 int err = c2(&coerced2, &coerced1);
997
998 if (unlikely(err < 0)) {
999 goto exit_inplace_exception;
1000 }
1001
1002 if (err == 0) {
1003 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1004
1005 if (likely(mv == NULL)) {
1006 binaryfunc slot = mv->nb_remainder;
1007
1008 if (likely(slot != NULL)) {
1009 PyObject *x = slot(coerced1, coerced2);
1010
1011 Py_DECREF(coerced1);
1012 Py_DECREF(coerced2);
1013
1014 obj_result = x;
1015 goto exit_inplace_result_object;
1016 }
1017 }
1018
1019 // nb_coerce took a reference.
1020 Py_DECREF(coerced1);
1021 Py_DECREF(coerced2);
1022 }
1023 }
1024 }
1025#endif
1026
1027#if PYTHON_VERSION < 0x300
1028 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'long' and '%s'", type2->tp_name);
1029#else
1030 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'int' and '%s'", type2->tp_name);
1031#endif
1032 goto exit_inplace_exception;
1033 }
1034
1035exit_inplace_result_object:
1036 if (unlikely(obj_result == NULL)) {
1037 return false;
1038 }
1039
1040 // We got an object handed, that we have to release.
1041 Py_DECREF(*operand1);
1042
1043 // That's our return value then. As we use a dedicated variable, it's
1044 // OK that way.
1045 *operand1 = obj_result;
1046
1047 return true;
1048
1049exit_inplace_exception:
1050 return false;
1051}
1052static inline bool _INPLACE_OPERATION_MOD_LONG_OBJECT(PyObject **operand1, PyObject *operand2) {
1053 assert(operand1); // Pointer must be non-null.
1054
1055 CHECK_OBJECT(*operand1);
1056 assert(PyLong_CheckExact(*operand1));
1057 CHECK_OBJECT(operand2);
1058
1059 PyTypeObject *type2 = Py_TYPE(operand2);
1060
1061 if (&PyLong_Type == type2) {
1062 // return _BINARY_OPERATION_MOD_LONG_LONG_INPLACE(operand1, operand2);
1063
1064 // Not every code path will make use of all possible results.
1065#if defined(_MSC_VER)
1066#pragma warning(push)
1067#pragma warning(disable : 4101)
1068#endif
1069 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1070 NUITKA_MAY_BE_UNUSED long clong_result;
1071#if defined(_MSC_VER)
1072#pragma warning(pop)
1073#endif
1074
1075 PyObject *x = PyLong_Type.tp_as_number->nb_remainder(*operand1, operand2);
1076 assert(x != Py_NotImplemented);
1077
1078 obj_result = x;
1079 goto exit_result_object;
1080
1081 exit_result_object:
1082 if (unlikely(obj_result == NULL)) {
1083 goto exit_result_exception;
1084 }
1085 // We got an object handed, that we have to release.
1086 Py_DECREF(*operand1);
1087 *operand1 = obj_result;
1088 goto exit_result_ok;
1089
1090 exit_result_ok:
1091 return true;
1092
1093 exit_result_exception:
1094 return false;
1095 }
1096
1097 return __INPLACE_OPERATION_MOD_LONG_OBJECT(operand1, operand2);
1098}
1099
1100bool INPLACE_OPERATION_MOD_LONG_OBJECT(PyObject **operand1, PyObject *operand2) {
1101 return _INPLACE_OPERATION_MOD_LONG_OBJECT(operand1, operand2);
1102}
1103
1104/* Code referring to "FLOAT" corresponds to Python 'float' and "FLOAT" to Python 'float'. */
1105static inline bool _INPLACE_OPERATION_MOD_FLOAT_FLOAT(PyObject **operand1, PyObject *operand2) {
1106 assert(operand1); // Pointer must be non-null.
1107
1108 CHECK_OBJECT(*operand1);
1109 assert(PyFloat_CheckExact(*operand1));
1110 CHECK_OBJECT(operand2);
1111 assert(PyFloat_CheckExact(operand2));
1112
1113#if defined(_MSC_VER)
1114#pragma warning(push)
1115#pragma warning(disable : 4101)
1116#endif
1117 // Not every code path will make use of all possible results.
1118 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1119 NUITKA_MAY_BE_UNUSED long clong_result;
1120 NUITKA_MAY_BE_UNUSED double cfloat_result;
1121#if defined(_MSC_VER)
1122#pragma warning(pop)
1123#endif
1124
1125 CHECK_OBJECT(*operand1);
1126 assert(PyFloat_CheckExact(*operand1));
1127 CHECK_OBJECT(operand2);
1128 assert(PyFloat_CheckExact(operand2));
1129
1130 const double a = PyFloat_AS_DOUBLE(*operand1);
1131 const double b = PyFloat_AS_DOUBLE(operand2);
1132
1133 if (unlikely(b == 0.0)) {
1134 PyThreadState *tstate = PyThreadState_GET();
1135
1136 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
1137 goto exit_result_exception;
1138 }
1139
1140 {
1141 double mod = fmod(a, b);
1142 if (mod) {
1143 if ((b < 0) != (mod < 0)) {
1144 mod += b;
1145 }
1146 } else {
1147 mod = copysign(0.0, b);
1148 }
1149
1150 cfloat_result = mod;
1151 goto exit_result_ok_cfloat;
1152 }
1153
1154exit_result_ok_cfloat:
1155 if (Py_REFCNT(*operand1) == 1) {
1156 PyFloat_SET_DOUBLE(*operand1, cfloat_result);
1157 } else {
1158 // We got an object handed, that we have to release.
1159 Py_DECREF(*operand1);
1160
1161 *operand1 = MAKE_FLOAT_FROM_DOUBLE(cfloat_result);
1162 }
1163 goto exit_result_ok;
1164
1165exit_result_ok:
1166 return true;
1167
1168exit_result_exception:
1169 return false;
1170}
1171
1172bool INPLACE_OPERATION_MOD_FLOAT_FLOAT(PyObject **operand1, PyObject *operand2) {
1173 return _INPLACE_OPERATION_MOD_FLOAT_FLOAT(operand1, operand2);
1174}
1175
1176/* Code referring to "OBJECT" corresponds to any Python object and "FLOAT" to Python 'float'. */
1177static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_OBJECT_FLOAT(PyObject **operand1, PyObject *operand2) {
1178 PyTypeObject *type1 = Py_TYPE(*operand1);
1179
1180#if defined(_MSC_VER)
1181#pragma warning(push)
1182#pragma warning(disable : 4101)
1183#endif
1184 NUITKA_MAY_BE_UNUSED bool cbool_result;
1185 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1186#if defined(_MSC_VER)
1187#pragma warning(pop)
1188#endif
1189
1190 binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1))
1191 ? type1->tp_as_number->nb_inplace_remainder
1192 : NULL;
1193
1194 if (islot != NULL) {
1195 PyObject *x = islot(*operand1, operand2);
1196
1197 if (x != Py_NotImplemented) {
1198 obj_result = x;
1199 goto exit_inplace_result_object;
1200 }
1201
1202 Py_DECREF_IMMORTAL(x);
1203 }
1204
1205 {
1206 binaryfunc slot1 =
1207 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL;
1208 binaryfunc slot2 = NULL;
1209
1210 if (!(type1 == &PyFloat_Type)) {
1211 // Different types, need to consider second value slot.
1212
1213 slot2 = PyFloat_Type.tp_as_number->nb_remainder;
1214
1215 if (slot1 == slot2) {
1216 slot2 = NULL;
1217 }
1218 }
1219
1220 if (slot1 != NULL) {
1221 PyObject *x = slot1(*operand1, operand2);
1222
1223 if (x != Py_NotImplemented) {
1224 obj_result = x;
1225 goto exit_inplace_result_object;
1226 }
1227
1228 Py_DECREF_IMMORTAL(x);
1229 }
1230
1231 if (slot2 != NULL) {
1232 PyObject *x = slot2(*operand1, operand2);
1233
1234 if (x != Py_NotImplemented) {
1235 obj_result = x;
1236 goto exit_inplace_result_object;
1237 }
1238
1239 Py_DECREF_IMMORTAL(x);
1240 }
1241
1242#if PYTHON_VERSION < 0x300
1243 if (!NEW_STYLE_NUMBER_TYPE(type1) || !1) {
1244 coercion c1 =
1245 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
1246
1247 if (c1 != NULL) {
1248 PyObject *coerced1 = *operand1;
1249 PyObject *coerced2 = operand2;
1250
1251 int err = c1(&coerced1, &coerced2);
1252
1253 if (unlikely(err < 0)) {
1254 goto exit_inplace_exception;
1255 }
1256
1257 if (err == 0) {
1258 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1259
1260 if (likely(mv == NULL)) {
1261 binaryfunc slot = mv->nb_remainder;
1262
1263 if (likely(slot != NULL)) {
1264 PyObject *x = slot(coerced1, coerced2);
1265
1266 Py_DECREF(coerced1);
1267 Py_DECREF(coerced2);
1268
1269 obj_result = x;
1270 goto exit_inplace_result_object;
1271 }
1272 }
1273
1274 // nb_coerce took a reference.
1275 Py_DECREF(coerced1);
1276 Py_DECREF(coerced2);
1277 }
1278 }
1279 coercion c2 = PyFloat_Type.tp_as_number->nb_coerce;
1280
1281 if (c2 != NULL) {
1282 PyObject *coerced1 = *operand1;
1283 PyObject *coerced2 = operand2;
1284
1285 int err = c2(&coerced2, &coerced1);
1286
1287 if (unlikely(err < 0)) {
1288 goto exit_inplace_exception;
1289 }
1290
1291 if (err == 0) {
1292 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1293
1294 if (likely(mv == NULL)) {
1295 binaryfunc slot = mv->nb_remainder;
1296
1297 if (likely(slot != NULL)) {
1298 PyObject *x = slot(coerced1, coerced2);
1299
1300 Py_DECREF(coerced1);
1301 Py_DECREF(coerced2);
1302
1303 obj_result = x;
1304 goto exit_inplace_result_object;
1305 }
1306 }
1307
1308 // nb_coerce took a reference.
1309 Py_DECREF(coerced1);
1310 Py_DECREF(coerced2);
1311 }
1312 }
1313 }
1314#endif
1315
1316 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: '%s' and 'float'", type1->tp_name);
1317 goto exit_inplace_exception;
1318 }
1319
1320exit_inplace_result_object:
1321 if (unlikely(obj_result == NULL)) {
1322 return false;
1323 }
1324
1325 // We got an object handed, that we have to release.
1326 Py_DECREF(*operand1);
1327
1328 // That's our return value then. As we use a dedicated variable, it's
1329 // OK that way.
1330 *operand1 = obj_result;
1331
1332 return true;
1333
1334exit_inplace_exception:
1335 return false;
1336}
1337static inline bool _INPLACE_OPERATION_MOD_OBJECT_FLOAT(PyObject **operand1, PyObject *operand2) {
1338 assert(operand1); // Pointer must be non-null.
1339
1340 CHECK_OBJECT(*operand1);
1341 CHECK_OBJECT(operand2);
1342 assert(PyFloat_CheckExact(operand2));
1343
1344 PyTypeObject *type1 = Py_TYPE(*operand1);
1345
1346 if (type1 == &PyFloat_Type) {
1347 // return _BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(operand1, operand2);
1348
1349#if defined(_MSC_VER)
1350#pragma warning(push)
1351#pragma warning(disable : 4101)
1352#endif
1353 // Not every code path will make use of all possible results.
1354 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1355 NUITKA_MAY_BE_UNUSED long clong_result;
1356 NUITKA_MAY_BE_UNUSED double cfloat_result;
1357#if defined(_MSC_VER)
1358#pragma warning(pop)
1359#endif
1360
1361 CHECK_OBJECT(*operand1);
1362 assert(PyFloat_CheckExact(*operand1));
1363 CHECK_OBJECT(operand2);
1364 assert(PyFloat_CheckExact(operand2));
1365
1366 const double a = PyFloat_AS_DOUBLE(*operand1);
1367 const double b = PyFloat_AS_DOUBLE(operand2);
1368
1369 if (unlikely(b == 0.0)) {
1370 PyThreadState *tstate = PyThreadState_GET();
1371
1372 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
1373 goto exit_result_exception;
1374 }
1375
1376 {
1377 double mod = fmod(a, b);
1378 if (mod) {
1379 if ((b < 0) != (mod < 0)) {
1380 mod += b;
1381 }
1382 } else {
1383 mod = copysign(0.0, b);
1384 }
1385
1386 cfloat_result = mod;
1387 goto exit_result_ok_cfloat;
1388 }
1389
1390 exit_result_ok_cfloat:
1391 if (Py_REFCNT(*operand1) == 1) {
1392 PyFloat_SET_DOUBLE(*operand1, cfloat_result);
1393 } else {
1394 // We got an object handed, that we have to release.
1395 Py_DECREF(*operand1);
1396
1397 *operand1 = MAKE_FLOAT_FROM_DOUBLE(cfloat_result);
1398 }
1399 goto exit_result_ok;
1400
1401 exit_result_ok:
1402 return true;
1403
1404 exit_result_exception:
1405 return false;
1406 }
1407
1408 return __INPLACE_OPERATION_MOD_OBJECT_FLOAT(operand1, operand2);
1409}
1410
1411bool INPLACE_OPERATION_MOD_OBJECT_FLOAT(PyObject **operand1, PyObject *operand2) {
1412 return _INPLACE_OPERATION_MOD_OBJECT_FLOAT(operand1, operand2);
1413}
1414
1415/* Code referring to "FLOAT" corresponds to Python 'float' and "OBJECT" to any Python object. */
1416static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_FLOAT_OBJECT(PyObject **operand1, PyObject *operand2) {
1417 PyTypeObject *type2 = Py_TYPE(operand2);
1418
1419#if defined(_MSC_VER)
1420#pragma warning(push)
1421#pragma warning(disable : 4101)
1422#endif
1423 NUITKA_MAY_BE_UNUSED bool cbool_result;
1424 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1425#if defined(_MSC_VER)
1426#pragma warning(pop)
1427#endif
1428
1429 // No inplace number slot nb_inplace_remainder available for this type.
1430
1431 {
1432 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder;
1433 binaryfunc slot2 = NULL;
1434
1435 if (!(&PyFloat_Type == type2)) {
1436 // Different types, need to consider second value slot.
1437
1438 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder
1439 : NULL;
1440
1441 if (slot1 == slot2) {
1442 slot2 = NULL;
1443 }
1444 }
1445
1446 if (slot1 != NULL) {
1447 if (slot2 != NULL) {
1448 if (Nuitka_Type_IsSubtype(type2, &PyFloat_Type)) {
1449 PyObject *x = slot2(*operand1, operand2);
1450
1451 if (x != Py_NotImplemented) {
1452 obj_result = x;
1453 goto exit_inplace_result_object;
1454 }
1455
1456 Py_DECREF_IMMORTAL(x);
1457 slot2 = NULL;
1458 }
1459 }
1460
1461 PyObject *x = slot1(*operand1, operand2);
1462
1463 if (x != Py_NotImplemented) {
1464 obj_result = x;
1465 goto exit_inplace_result_object;
1466 }
1467
1468 Py_DECREF_IMMORTAL(x);
1469 }
1470
1471 if (slot2 != NULL) {
1472 PyObject *x = slot2(*operand1, operand2);
1473
1474 if (x != Py_NotImplemented) {
1475 obj_result = x;
1476 goto exit_inplace_result_object;
1477 }
1478
1479 Py_DECREF_IMMORTAL(x);
1480 }
1481
1482#if PYTHON_VERSION < 0x300
1483 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
1484 coercion c1 = PyFloat_Type.tp_as_number->nb_coerce;
1485
1486 if (c1 != NULL) {
1487 PyObject *coerced1 = *operand1;
1488 PyObject *coerced2 = operand2;
1489
1490 int err = c1(&coerced1, &coerced2);
1491
1492 if (unlikely(err < 0)) {
1493 goto exit_inplace_exception;
1494 }
1495
1496 if (err == 0) {
1497 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1498
1499 if (likely(mv == NULL)) {
1500 binaryfunc slot = mv->nb_remainder;
1501
1502 if (likely(slot != NULL)) {
1503 PyObject *x = slot(coerced1, coerced2);
1504
1505 Py_DECREF(coerced1);
1506 Py_DECREF(coerced2);
1507
1508 obj_result = x;
1509 goto exit_inplace_result_object;
1510 }
1511 }
1512
1513 // nb_coerce took a reference.
1514 Py_DECREF(coerced1);
1515 Py_DECREF(coerced2);
1516 }
1517 }
1518 coercion c2 =
1519 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
1520
1521 if (c2 != NULL) {
1522 PyObject *coerced1 = *operand1;
1523 PyObject *coerced2 = operand2;
1524
1525 int err = c2(&coerced2, &coerced1);
1526
1527 if (unlikely(err < 0)) {
1528 goto exit_inplace_exception;
1529 }
1530
1531 if (err == 0) {
1532 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
1533
1534 if (likely(mv == NULL)) {
1535 binaryfunc slot = mv->nb_remainder;
1536
1537 if (likely(slot != NULL)) {
1538 PyObject *x = slot(coerced1, coerced2);
1539
1540 Py_DECREF(coerced1);
1541 Py_DECREF(coerced2);
1542
1543 obj_result = x;
1544 goto exit_inplace_result_object;
1545 }
1546 }
1547
1548 // nb_coerce took a reference.
1549 Py_DECREF(coerced1);
1550 Py_DECREF(coerced2);
1551 }
1552 }
1553 }
1554#endif
1555
1556 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'float' and '%s'", type2->tp_name);
1557 goto exit_inplace_exception;
1558 }
1559
1560exit_inplace_result_object:
1561 if (unlikely(obj_result == NULL)) {
1562 return false;
1563 }
1564
1565 // We got an object handed, that we have to release.
1566 Py_DECREF(*operand1);
1567
1568 // That's our return value then. As we use a dedicated variable, it's
1569 // OK that way.
1570 *operand1 = obj_result;
1571
1572 return true;
1573
1574exit_inplace_exception:
1575 return false;
1576}
1577static inline bool _INPLACE_OPERATION_MOD_FLOAT_OBJECT(PyObject **operand1, PyObject *operand2) {
1578 assert(operand1); // Pointer must be non-null.
1579
1580 CHECK_OBJECT(*operand1);
1581 assert(PyFloat_CheckExact(*operand1));
1582 CHECK_OBJECT(operand2);
1583
1584 PyTypeObject *type2 = Py_TYPE(operand2);
1585
1586 if (&PyFloat_Type == type2) {
1587 // return _BINARY_OPERATION_MOD_FLOAT_FLOAT_INPLACE(operand1, operand2);
1588
1589#if defined(_MSC_VER)
1590#pragma warning(push)
1591#pragma warning(disable : 4101)
1592#endif
1593 // Not every code path will make use of all possible results.
1594 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1595 NUITKA_MAY_BE_UNUSED long clong_result;
1596 NUITKA_MAY_BE_UNUSED double cfloat_result;
1597#if defined(_MSC_VER)
1598#pragma warning(pop)
1599#endif
1600
1601 CHECK_OBJECT(*operand1);
1602 assert(PyFloat_CheckExact(*operand1));
1603 CHECK_OBJECT(operand2);
1604 assert(PyFloat_CheckExact(operand2));
1605
1606 const double a = PyFloat_AS_DOUBLE(*operand1);
1607 const double b = PyFloat_AS_DOUBLE(operand2);
1608
1609 if (unlikely(b == 0.0)) {
1610 PyThreadState *tstate = PyThreadState_GET();
1611
1612 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
1613 goto exit_result_exception;
1614 }
1615
1616 {
1617 double mod = fmod(a, b);
1618 if (mod) {
1619 if ((b < 0) != (mod < 0)) {
1620 mod += b;
1621 }
1622 } else {
1623 mod = copysign(0.0, b);
1624 }
1625
1626 cfloat_result = mod;
1627 goto exit_result_ok_cfloat;
1628 }
1629
1630 exit_result_ok_cfloat:
1631 if (Py_REFCNT(*operand1) == 1) {
1632 PyFloat_SET_DOUBLE(*operand1, cfloat_result);
1633 } else {
1634 // We got an object handed, that we have to release.
1635 Py_DECREF(*operand1);
1636
1637 *operand1 = MAKE_FLOAT_FROM_DOUBLE(cfloat_result);
1638 }
1639 goto exit_result_ok;
1640
1641 exit_result_ok:
1642 return true;
1643
1644 exit_result_exception:
1645 return false;
1646 }
1647
1648 return __INPLACE_OPERATION_MOD_FLOAT_OBJECT(operand1, operand2);
1649}
1650
1651bool INPLACE_OPERATION_MOD_FLOAT_OBJECT(PyObject **operand1, PyObject *operand2) {
1652 return _INPLACE_OPERATION_MOD_FLOAT_OBJECT(operand1, operand2);
1653}
1654
1655/* Code referring to "FLOAT" corresponds to Python 'float' and "LONG" to Python2 'long', Python3 'int'. */
1656static inline bool _INPLACE_OPERATION_MOD_FLOAT_LONG(PyObject **operand1, PyObject *operand2) {
1657 assert(operand1); // Pointer must be non-null.
1658
1659 CHECK_OBJECT(*operand1);
1660 assert(PyFloat_CheckExact(*operand1));
1661 CHECK_OBJECT(operand2);
1662 assert(PyLong_CheckExact(operand2));
1663
1664#if defined(_MSC_VER)
1665#pragma warning(push)
1666#pragma warning(disable : 4101)
1667#endif
1668 NUITKA_MAY_BE_UNUSED bool cbool_result;
1669 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1670#if defined(_MSC_VER)
1671#pragma warning(pop)
1672#endif
1673
1674 // No inplace number slot nb_inplace_remainder available for this type.
1675
1676 {
1677 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder;
1678 // Slot2 ignored on purpose, type1 takes precedence.
1679
1680 if (slot1 != NULL) {
1681 PyObject *x = slot1(*operand1, operand2);
1682
1683 if (x != Py_NotImplemented) {
1684 obj_result = x;
1685 goto exit_inplace_result_object;
1686 }
1687
1688 Py_DECREF_IMMORTAL(x);
1689 }
1690
1691 // Statically recognized that coercion is not possible with these types
1692
1693#if PYTHON_VERSION < 0x300
1694 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'float' and 'long'");
1695#else
1696 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'float' and 'int'");
1697#endif
1698 goto exit_inplace_exception;
1699 }
1700
1701exit_inplace_result_object:
1702 if (unlikely(obj_result == NULL)) {
1703 return false;
1704 }
1705
1706 // We got an object handed, that we have to release.
1707 Py_DECREF(*operand1);
1708
1709 // That's our return value then. As we use a dedicated variable, it's
1710 // OK that way.
1711 *operand1 = obj_result;
1712
1713 return true;
1714
1715exit_inplace_exception:
1716 return false;
1717}
1718
1719bool INPLACE_OPERATION_MOD_FLOAT_LONG(PyObject **operand1, PyObject *operand2) {
1720 return _INPLACE_OPERATION_MOD_FLOAT_LONG(operand1, operand2);
1721}
1722
1723/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "FLOAT" to Python 'float'. */
1724static inline bool _INPLACE_OPERATION_MOD_LONG_FLOAT(PyObject **operand1, PyObject *operand2) {
1725 assert(operand1); // Pointer must be non-null.
1726
1727 CHECK_OBJECT(*operand1);
1728 assert(PyLong_CheckExact(*operand1));
1729 CHECK_OBJECT(operand2);
1730 assert(PyFloat_CheckExact(operand2));
1731
1732#if defined(_MSC_VER)
1733#pragma warning(push)
1734#pragma warning(disable : 4101)
1735#endif
1736 NUITKA_MAY_BE_UNUSED bool cbool_result;
1737 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1738#if defined(_MSC_VER)
1739#pragma warning(pop)
1740#endif
1741
1742 // No inplace number slot nb_inplace_remainder available for this type.
1743
1744 {
1745 // Slot1 ignored on purpose, type2 takes precedence.
1746 binaryfunc slot2 = NULL;
1747
1748 if (!(0)) {
1749 // Different types, need to consider second value slot.
1750
1751 slot2 = PyFloat_Type.tp_as_number->nb_remainder;
1752 }
1753
1754 if (slot2 != NULL) {
1755 PyObject *x = slot2(*operand1, operand2);
1756
1757 if (x != Py_NotImplemented) {
1758 obj_result = x;
1759 goto exit_inplace_result_object;
1760 }
1761
1762 Py_DECREF_IMMORTAL(x);
1763 }
1764
1765 // Statically recognized that coercion is not possible with these types
1766
1767#if PYTHON_VERSION < 0x300
1768 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'long' and 'float'");
1769#else
1770 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'int' and 'float'");
1771#endif
1772 goto exit_inplace_exception;
1773 }
1774
1775exit_inplace_result_object:
1776 if (unlikely(obj_result == NULL)) {
1777 return false;
1778 }
1779
1780 // We got an object handed, that we have to release.
1781 Py_DECREF(*operand1);
1782
1783 // That's our return value then. As we use a dedicated variable, it's
1784 // OK that way.
1785 *operand1 = obj_result;
1786
1787 return true;
1788
1789exit_inplace_exception:
1790 return false;
1791}
1792
1793bool INPLACE_OPERATION_MOD_LONG_FLOAT(PyObject **operand1, PyObject *operand2) {
1794 return _INPLACE_OPERATION_MOD_LONG_FLOAT(operand1, operand2);
1795}
1796
1797#if PYTHON_VERSION < 0x300
1798/* Code referring to "FLOAT" corresponds to Python 'float' and "INT" to Python2 'int'. */
1799static inline bool _INPLACE_OPERATION_MOD_FLOAT_INT(PyObject **operand1, PyObject *operand2) {
1800 assert(operand1); // Pointer must be non-null.
1801
1802 CHECK_OBJECT(*operand1);
1803 assert(PyFloat_CheckExact(*operand1));
1804 CHECK_OBJECT(operand2);
1805 assert(PyInt_CheckExact(operand2));
1806
1807#if defined(_MSC_VER)
1808#pragma warning(push)
1809#pragma warning(disable : 4101)
1810#endif
1811 NUITKA_MAY_BE_UNUSED bool cbool_result;
1812 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1813#if defined(_MSC_VER)
1814#pragma warning(pop)
1815#endif
1816
1817 // No inplace number slot nb_inplace_remainder available for this type.
1818
1819 {
1820 binaryfunc slot1 = PyFloat_Type.tp_as_number->nb_remainder;
1821 // Slot2 ignored on purpose, type1 takes precedence.
1822
1823 if (slot1 != NULL) {
1824 PyObject *x = slot1(*operand1, operand2);
1825
1826 if (x != Py_NotImplemented) {
1827 obj_result = x;
1828 goto exit_inplace_result_object;
1829 }
1830
1831 Py_DECREF_IMMORTAL(x);
1832 }
1833
1834 // Statically recognized that coercion is not possible with these types
1835
1836 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'float' and 'int'");
1837 goto exit_inplace_exception;
1838 }
1839
1840exit_inplace_result_object:
1841 if (unlikely(obj_result == NULL)) {
1842 return false;
1843 }
1844
1845 // We got an object handed, that we have to release.
1846 Py_DECREF(*operand1);
1847
1848 // That's our return value then. As we use a dedicated variable, it's
1849 // OK that way.
1850 *operand1 = obj_result;
1851
1852 return true;
1853
1854exit_inplace_exception:
1855 return false;
1856}
1857
1858bool INPLACE_OPERATION_MOD_FLOAT_INT(PyObject **operand1, PyObject *operand2) {
1859 return _INPLACE_OPERATION_MOD_FLOAT_INT(operand1, operand2);
1860}
1861#endif
1862
1863#if PYTHON_VERSION < 0x300
1864/* Code referring to "INT" corresponds to Python2 'int' and "FLOAT" to Python 'float'. */
1865static inline bool _INPLACE_OPERATION_MOD_INT_FLOAT(PyObject **operand1, PyObject *operand2) {
1866 assert(operand1); // Pointer must be non-null.
1867
1868 CHECK_OBJECT(*operand1);
1869 assert(PyInt_CheckExact(*operand1));
1870 CHECK_OBJECT(operand2);
1871 assert(PyFloat_CheckExact(operand2));
1872
1873#if defined(_MSC_VER)
1874#pragma warning(push)
1875#pragma warning(disable : 4101)
1876#endif
1877 NUITKA_MAY_BE_UNUSED bool cbool_result;
1878 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1879#if defined(_MSC_VER)
1880#pragma warning(pop)
1881#endif
1882
1883 // No inplace number slot nb_inplace_remainder available for this type.
1884
1885 {
1886 // Slot1 ignored on purpose, type2 takes precedence.
1887 binaryfunc slot2 = NULL;
1888
1889 if (!(0)) {
1890 // Different types, need to consider second value slot.
1891
1892 slot2 = PyFloat_Type.tp_as_number->nb_remainder;
1893 }
1894
1895 if (slot2 != NULL) {
1896 PyObject *x = slot2(*operand1, operand2);
1897
1898 if (x != Py_NotImplemented) {
1899 obj_result = x;
1900 goto exit_inplace_result_object;
1901 }
1902
1903 Py_DECREF_IMMORTAL(x);
1904 }
1905
1906 // Statically recognized that coercion is not possible with these types
1907
1908 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'int' and 'float'");
1909 goto exit_inplace_exception;
1910 }
1911
1912exit_inplace_result_object:
1913 if (unlikely(obj_result == NULL)) {
1914 return false;
1915 }
1916
1917 // We got an object handed, that we have to release.
1918 Py_DECREF(*operand1);
1919
1920 // That's our return value then. As we use a dedicated variable, it's
1921 // OK that way.
1922 *operand1 = obj_result;
1923
1924 return true;
1925
1926exit_inplace_exception:
1927 return false;
1928}
1929
1930bool INPLACE_OPERATION_MOD_INT_FLOAT(PyObject **operand1, PyObject *operand2) {
1931 return _INPLACE_OPERATION_MOD_INT_FLOAT(operand1, operand2);
1932}
1933#endif
1934
1935#if PYTHON_VERSION < 0x300
1936/* Code referring to "LONG" corresponds to Python2 'long', Python3 'int' and "INT" to Python2 'int'. */
1937static inline bool _INPLACE_OPERATION_MOD_LONG_INT(PyObject **operand1, PyObject *operand2) {
1938 assert(operand1); // Pointer must be non-null.
1939
1940 CHECK_OBJECT(*operand1);
1941 assert(PyLong_CheckExact(*operand1));
1942 CHECK_OBJECT(operand2);
1943 assert(PyInt_CheckExact(operand2));
1944
1945#if defined(_MSC_VER)
1946#pragma warning(push)
1947#pragma warning(disable : 4101)
1948#endif
1949 NUITKA_MAY_BE_UNUSED bool cbool_result;
1950 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
1951#if defined(_MSC_VER)
1952#pragma warning(pop)
1953#endif
1954
1955 // No inplace number slot nb_inplace_remainder available for this type.
1956
1957 {
1958 binaryfunc slot1 = PyLong_Type.tp_as_number->nb_remainder;
1959 // Slot2 ignored on purpose, type1 takes precedence.
1960
1961 if (slot1 != NULL) {
1962 PyObject *x = slot1(*operand1, operand2);
1963
1964 if (x != Py_NotImplemented) {
1965 obj_result = x;
1966 goto exit_inplace_result_object;
1967 }
1968
1969 Py_DECREF_IMMORTAL(x);
1970 }
1971
1972 // Statically recognized that coercion is not possible with these types
1973
1974 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'long' and 'int'");
1975 goto exit_inplace_exception;
1976 }
1977
1978exit_inplace_result_object:
1979 if (unlikely(obj_result == NULL)) {
1980 return false;
1981 }
1982
1983 // We got an object handed, that we have to release.
1984 Py_DECREF(*operand1);
1985
1986 // That's our return value then. As we use a dedicated variable, it's
1987 // OK that way.
1988 *operand1 = obj_result;
1989
1990 return true;
1991
1992exit_inplace_exception:
1993 return false;
1994}
1995
1996bool INPLACE_OPERATION_MOD_LONG_INT(PyObject **operand1, PyObject *operand2) {
1997 return _INPLACE_OPERATION_MOD_LONG_INT(operand1, operand2);
1998}
1999#endif
2000
2001#if PYTHON_VERSION < 0x300
2002/* Code referring to "INT" corresponds to Python2 'int' and "LONG" to Python2 'long', Python3 'int'. */
2003static inline bool _INPLACE_OPERATION_MOD_INT_LONG(PyObject **operand1, PyObject *operand2) {
2004 assert(operand1); // Pointer must be non-null.
2005
2006 CHECK_OBJECT(*operand1);
2007 assert(PyInt_CheckExact(*operand1));
2008 CHECK_OBJECT(operand2);
2009 assert(PyLong_CheckExact(operand2));
2010
2011#if defined(_MSC_VER)
2012#pragma warning(push)
2013#pragma warning(disable : 4101)
2014#endif
2015 NUITKA_MAY_BE_UNUSED bool cbool_result;
2016 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2017#if defined(_MSC_VER)
2018#pragma warning(pop)
2019#endif
2020
2021 // No inplace number slot nb_inplace_remainder available for this type.
2022
2023 {
2024 // Slot1 ignored on purpose, type2 takes precedence.
2025 binaryfunc slot2 = NULL;
2026
2027 if (!(0)) {
2028 // Different types, need to consider second value slot.
2029
2030 slot2 = PyLong_Type.tp_as_number->nb_remainder;
2031 }
2032
2033 if (slot2 != NULL) {
2034 PyObject *x = slot2(*operand1, operand2);
2035
2036 if (x != Py_NotImplemented) {
2037 obj_result = x;
2038 goto exit_inplace_result_object;
2039 }
2040
2041 Py_DECREF_IMMORTAL(x);
2042 }
2043
2044 // Statically recognized that coercion is not possible with these types
2045
2046 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'int' and 'long'");
2047 goto exit_inplace_exception;
2048 }
2049
2050exit_inplace_result_object:
2051 if (unlikely(obj_result == NULL)) {
2052 return false;
2053 }
2054
2055 // We got an object handed, that we have to release.
2056 Py_DECREF(*operand1);
2057
2058 // That's our return value then. As we use a dedicated variable, it's
2059 // OK that way.
2060 *operand1 = obj_result;
2061
2062 return true;
2063
2064exit_inplace_exception:
2065 return false;
2066}
2067
2068bool INPLACE_OPERATION_MOD_INT_LONG(PyObject **operand1, PyObject *operand2) {
2069 return _INPLACE_OPERATION_MOD_INT_LONG(operand1, operand2);
2070}
2071#endif
2072
2073#if PYTHON_VERSION < 0x300
2074/* Code referring to "INT" corresponds to Python2 'int' and "CLONG" to C platform long value. */
2075static inline bool _INPLACE_OPERATION_MOD_INT_CLONG(PyObject **operand1, long operand2) {
2076 assert(operand1); // Pointer must be non-null.
2077
2078 CHECK_OBJECT(*operand1);
2079 assert(PyInt_CheckExact(*operand1));
2080
2081 // Not every code path will make use of all possible results.
2082#if defined(_MSC_VER)
2083#pragma warning(push)
2084#pragma warning(disable : 4101)
2085#endif
2086 NUITKA_MAY_BE_UNUSED bool cbool_result;
2087 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2088 NUITKA_MAY_BE_UNUSED long clong_result;
2089 NUITKA_MAY_BE_UNUSED double cfloat_result;
2090#if defined(_MSC_VER)
2091#pragma warning(pop)
2092#endif
2093
2094 CHECK_OBJECT(*operand1);
2095 assert(PyInt_CheckExact(*operand1));
2096
2097 const long a = PyInt_AS_LONG(*operand1);
2098 const long b = operand2;
2099
2100 /* TODO: Isn't this a very specific value only, of which we could
2101 * hardcode the constant result. Not sure how well the C compiler
2102 * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by
2103 * -1 has to be rare anyway.
2104 */
2105
2106 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
2107 long r = a % b;
2108
2109 // Sign handling.
2110 if (r != 0 && ((b ^ r) < 0)) {
2111 r += b;
2112 }
2113
2114 clong_result = r;
2115 goto exit_result_ok_clong;
2116 }
2117
2118 {
2119 PyObject *operand1_object = *operand1;
2120 PyObject *operand2_object = Nuitka_PyLong_FromLong(operand2);
2121
2122 PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object);
2123 assert(r != Py_NotImplemented);
2124
2125 Py_DECREF(operand2_object);
2126
2127 obj_result = r;
2128 goto exit_result_object;
2129 }
2130
2131exit_result_ok_clong:
2132
2133 // We got an object handed, that we have to release.
2134 Py_DECREF(*operand1);
2135
2136 // That's our return value then. As we use a dedicated variable, it's
2137 // OK that way.
2138 *operand1 = Nuitka_PyInt_FromLong(clong_result);
2139 goto exit_result_ok;
2140
2141exit_result_object:
2142 if (unlikely(obj_result == NULL)) {
2143 goto exit_result_exception;
2144 }
2145 // We got an object handed, that we have to release.
2146 Py_DECREF(*operand1);
2147
2148 *operand1 = obj_result;
2149 goto exit_result_ok;
2150
2151exit_result_ok:
2152 return true;
2153
2154exit_result_exception:
2155 return false;
2156}
2157
2158bool INPLACE_OPERATION_MOD_INT_CLONG(PyObject **operand1, long operand2) {
2159 return _INPLACE_OPERATION_MOD_INT_CLONG(operand1, operand2);
2160}
2161#endif
2162
2163/* Code referring to "FLOAT" corresponds to Python 'float' and "CFLOAT" to C platform float value. */
2164static inline bool _INPLACE_OPERATION_MOD_FLOAT_CFLOAT(PyObject **operand1, double operand2) {
2165 assert(operand1); // Pointer must be non-null.
2166
2167 CHECK_OBJECT(*operand1);
2168 assert(PyFloat_CheckExact(*operand1));
2169
2170#if defined(_MSC_VER)
2171#pragma warning(push)
2172#pragma warning(disable : 4101)
2173#endif
2174 // Not every code path will make use of all possible results.
2175 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2176 NUITKA_MAY_BE_UNUSED long clong_result;
2177 NUITKA_MAY_BE_UNUSED double cfloat_result;
2178#if defined(_MSC_VER)
2179#pragma warning(pop)
2180#endif
2181
2182 CHECK_OBJECT(*operand1);
2183 assert(PyFloat_CheckExact(*operand1));
2184
2185 const double a = PyFloat_AS_DOUBLE(*operand1);
2186 const double b = operand2;
2187
2188 if (unlikely(b == 0.0)) {
2189 PyThreadState *tstate = PyThreadState_GET();
2190
2191 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_ZeroDivisionError, "float modulo");
2192 goto exit_result_exception;
2193 }
2194
2195 {
2196 double mod = fmod(a, b);
2197 if (mod) {
2198 if ((b < 0) != (mod < 0)) {
2199 mod += b;
2200 }
2201 } else {
2202 mod = copysign(0.0, b);
2203 }
2204
2205 cfloat_result = mod;
2206 goto exit_result_ok_cfloat;
2207 }
2208
2209exit_result_ok_cfloat:
2210 if (Py_REFCNT(*operand1) == 1) {
2211 PyFloat_SET_DOUBLE(*operand1, cfloat_result);
2212 } else {
2213 // We got an object handed, that we have to release.
2214 Py_DECREF(*operand1);
2215
2216 *operand1 = MAKE_FLOAT_FROM_DOUBLE(cfloat_result);
2217 }
2218 goto exit_result_ok;
2219
2220exit_result_ok:
2221 return true;
2222
2223exit_result_exception:
2224 return false;
2225}
2226
2227bool INPLACE_OPERATION_MOD_FLOAT_CFLOAT(PyObject **operand1, double operand2) {
2228 return _INPLACE_OPERATION_MOD_FLOAT_CFLOAT(operand1, operand2);
2229}
2230
2231#if PYTHON_VERSION < 0x300
2232/* Code referring to "STR" corresponds to Python2 'str' and "INT" to Python2 'int'. */
2233static inline bool _INPLACE_OPERATION_MOD_STR_INT(PyObject **operand1, PyObject *operand2) {
2234 assert(operand1); // Pointer must be non-null.
2235
2236 CHECK_OBJECT(*operand1);
2237 assert(PyString_CheckExact(*operand1));
2238 CHECK_OBJECT(operand2);
2239 assert(PyInt_CheckExact(operand2));
2240
2241#if defined(_MSC_VER)
2242#pragma warning(push)
2243#pragma warning(disable : 4101)
2244#endif
2245 NUITKA_MAY_BE_UNUSED bool cbool_result;
2246 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2247#if defined(_MSC_VER)
2248#pragma warning(pop)
2249#endif
2250
2251 // No inplace number slot nb_inplace_remainder available for this type.
2252
2253 {
2254 binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder;
2255 binaryfunc slot2 = NULL;
2256
2257 if (!(0)) {
2258 // Different types, need to consider second value slot.
2259
2260 slot2 = PyInt_Type.tp_as_number->nb_remainder;
2261 }
2262
2263 if (slot1 != NULL) {
2264 PyObject *x = slot1(*operand1, operand2);
2265
2266 if (x != Py_NotImplemented) {
2267 obj_result = x;
2268 goto exit_inplace_result_object;
2269 }
2270
2271 Py_DECREF_IMMORTAL(x);
2272 }
2273
2274 if (slot2 != NULL) {
2275 PyObject *x = slot2(*operand1, operand2);
2276
2277 if (x != Py_NotImplemented) {
2278 obj_result = x;
2279 goto exit_inplace_result_object;
2280 }
2281
2282 Py_DECREF_IMMORTAL(x);
2283 }
2284
2285 // Statically recognized that coercion is not possible with these types
2286
2287 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'int'");
2288 goto exit_inplace_exception;
2289 }
2290
2291exit_inplace_result_object:
2292 if (unlikely(obj_result == NULL)) {
2293 return false;
2294 }
2295
2296 // We got an object handed, that we have to release.
2297 Py_DECREF(*operand1);
2298
2299 // That's our return value then. As we use a dedicated variable, it's
2300 // OK that way.
2301 *operand1 = obj_result;
2302
2303 return true;
2304
2305exit_inplace_exception:
2306 return false;
2307}
2308
2309bool INPLACE_OPERATION_MOD_STR_INT(PyObject **operand1, PyObject *operand2) {
2310 return _INPLACE_OPERATION_MOD_STR_INT(operand1, operand2);
2311}
2312#endif
2313
2314#if PYTHON_VERSION < 0x300
2315/* Code referring to "STR" corresponds to Python2 'str' and "LONG" to Python2 'long', Python3 'int'. */
2316static inline bool _INPLACE_OPERATION_MOD_STR_LONG(PyObject **operand1, PyObject *operand2) {
2317 assert(operand1); // Pointer must be non-null.
2318
2319 CHECK_OBJECT(*operand1);
2320 assert(PyString_CheckExact(*operand1));
2321 CHECK_OBJECT(operand2);
2322 assert(PyLong_CheckExact(operand2));
2323
2324#if defined(_MSC_VER)
2325#pragma warning(push)
2326#pragma warning(disable : 4101)
2327#endif
2328 NUITKA_MAY_BE_UNUSED bool cbool_result;
2329 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2330#if defined(_MSC_VER)
2331#pragma warning(pop)
2332#endif
2333
2334 // No inplace number slot nb_inplace_remainder available for this type.
2335
2336 {
2337 binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder;
2338 binaryfunc slot2 = NULL;
2339
2340 if (!(0)) {
2341 // Different types, need to consider second value slot.
2342
2343 slot2 = PyLong_Type.tp_as_number->nb_remainder;
2344 }
2345
2346 if (slot1 != NULL) {
2347 PyObject *x = slot1(*operand1, operand2);
2348
2349 if (x != Py_NotImplemented) {
2350 obj_result = x;
2351 goto exit_inplace_result_object;
2352 }
2353
2354 Py_DECREF_IMMORTAL(x);
2355 }
2356
2357 if (slot2 != NULL) {
2358 PyObject *x = slot2(*operand1, operand2);
2359
2360 if (x != Py_NotImplemented) {
2361 obj_result = x;
2362 goto exit_inplace_result_object;
2363 }
2364
2365 Py_DECREF_IMMORTAL(x);
2366 }
2367
2368 // Statically recognized that coercion is not possible with these types
2369
2370 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'long'");
2371 goto exit_inplace_exception;
2372 }
2373
2374exit_inplace_result_object:
2375 if (unlikely(obj_result == NULL)) {
2376 return false;
2377 }
2378
2379 // We got an object handed, that we have to release.
2380 Py_DECREF(*operand1);
2381
2382 // That's our return value then. As we use a dedicated variable, it's
2383 // OK that way.
2384 *operand1 = obj_result;
2385
2386 return true;
2387
2388exit_inplace_exception:
2389 return false;
2390}
2391
2392bool INPLACE_OPERATION_MOD_STR_LONG(PyObject **operand1, PyObject *operand2) {
2393 return _INPLACE_OPERATION_MOD_STR_LONG(operand1, operand2);
2394}
2395#endif
2396
2397#if PYTHON_VERSION < 0x300
2398/* Code referring to "STR" corresponds to Python2 'str' and "FLOAT" to Python 'float'. */
2399static inline bool _INPLACE_OPERATION_MOD_STR_FLOAT(PyObject **operand1, PyObject *operand2) {
2400 assert(operand1); // Pointer must be non-null.
2401
2402 CHECK_OBJECT(*operand1);
2403 assert(PyString_CheckExact(*operand1));
2404 CHECK_OBJECT(operand2);
2405 assert(PyFloat_CheckExact(operand2));
2406
2407#if defined(_MSC_VER)
2408#pragma warning(push)
2409#pragma warning(disable : 4101)
2410#endif
2411 NUITKA_MAY_BE_UNUSED bool cbool_result;
2412 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2413#if defined(_MSC_VER)
2414#pragma warning(pop)
2415#endif
2416
2417 // No inplace number slot nb_inplace_remainder available for this type.
2418
2419 {
2420 binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder;
2421 binaryfunc slot2 = NULL;
2422
2423 if (!(0)) {
2424 // Different types, need to consider second value slot.
2425
2426 slot2 = PyFloat_Type.tp_as_number->nb_remainder;
2427 }
2428
2429 if (slot1 != NULL) {
2430 PyObject *x = slot1(*operand1, operand2);
2431
2432 if (x != Py_NotImplemented) {
2433 obj_result = x;
2434 goto exit_inplace_result_object;
2435 }
2436
2437 Py_DECREF_IMMORTAL(x);
2438 }
2439
2440 if (slot2 != NULL) {
2441 PyObject *x = slot2(*operand1, operand2);
2442
2443 if (x != Py_NotImplemented) {
2444 obj_result = x;
2445 goto exit_inplace_result_object;
2446 }
2447
2448 Py_DECREF_IMMORTAL(x);
2449 }
2450
2451 // Statically recognized that coercion is not possible with these types
2452
2453 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'float'");
2454 goto exit_inplace_exception;
2455 }
2456
2457exit_inplace_result_object:
2458 if (unlikely(obj_result == NULL)) {
2459 return false;
2460 }
2461
2462 // We got an object handed, that we have to release.
2463 Py_DECREF(*operand1);
2464
2465 // That's our return value then. As we use a dedicated variable, it's
2466 // OK that way.
2467 *operand1 = obj_result;
2468
2469 return true;
2470
2471exit_inplace_exception:
2472 return false;
2473}
2474
2475bool INPLACE_OPERATION_MOD_STR_FLOAT(PyObject **operand1, PyObject *operand2) {
2476 return _INPLACE_OPERATION_MOD_STR_FLOAT(operand1, operand2);
2477}
2478#endif
2479
2480#if PYTHON_VERSION < 0x300
2481/* Code referring to "STR" corresponds to Python2 'str' and "STR" to Python2 'str'. */
2482static inline bool _INPLACE_OPERATION_MOD_STR_STR(PyObject **operand1, PyObject *operand2) {
2483 assert(operand1); // Pointer must be non-null.
2484
2485 CHECK_OBJECT(*operand1);
2486 assert(PyString_CheckExact(*operand1));
2487 CHECK_OBJECT(operand2);
2488 assert(PyString_CheckExact(operand2));
2489
2490 // Not every code path will make use of all possible results.
2491 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2492
2493 PyObject *x = PyString_Format(*operand1, operand2);
2494
2495 obj_result = x;
2496 goto exit_result_object;
2497
2498exit_result_object:
2499 if (unlikely(obj_result == NULL)) {
2500 goto exit_result_exception;
2501 }
2502 // We got an object handed, that we have to release.
2503 Py_DECREF(*operand1);
2504
2505 *operand1 = obj_result;
2506 goto exit_result_ok;
2507
2508exit_result_ok:
2509 return true;
2510
2511exit_result_exception:
2512 return false;
2513}
2514
2515bool INPLACE_OPERATION_MOD_STR_STR(PyObject **operand1, PyObject *operand2) {
2516 return _INPLACE_OPERATION_MOD_STR_STR(operand1, operand2);
2517}
2518#endif
2519
2520#if PYTHON_VERSION < 0x300
2521/* Code referring to "STR" corresponds to Python2 'str' and "UNICODE" to Python2 'unicode', Python3 'str'. */
2522static inline bool _INPLACE_OPERATION_MOD_STR_UNICODE(PyObject **operand1, PyObject *operand2) {
2523 assert(operand1); // Pointer must be non-null.
2524
2525 CHECK_OBJECT(*operand1);
2526 assert(PyString_CheckExact(*operand1));
2527 CHECK_OBJECT(operand2);
2528 assert(PyUnicode_CheckExact(operand2));
2529
2530#if defined(_MSC_VER)
2531#pragma warning(push)
2532#pragma warning(disable : 4101)
2533#endif
2534 NUITKA_MAY_BE_UNUSED bool cbool_result;
2535 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2536#if defined(_MSC_VER)
2537#pragma warning(pop)
2538#endif
2539
2540 // No inplace number slot nb_inplace_remainder available for this type.
2541
2542 {
2543 binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder;
2544 binaryfunc slot2 = NULL;
2545
2546 if (!(0)) {
2547 // Different types, need to consider second value slot.
2548
2549 slot2 = PyUnicode_Type.tp_as_number->nb_remainder;
2550 }
2551
2552 if (slot1 != NULL) {
2553 PyObject *x = slot1(*operand1, operand2);
2554
2555 if (x != Py_NotImplemented) {
2556 obj_result = x;
2557 goto exit_inplace_result_object;
2558 }
2559
2560 Py_DECREF_IMMORTAL(x);
2561 }
2562
2563 if (slot2 != NULL) {
2564 PyObject *x = slot2(*operand1, operand2);
2565
2566 if (x != Py_NotImplemented) {
2567 obj_result = x;
2568 goto exit_inplace_result_object;
2569 }
2570
2571 Py_DECREF_IMMORTAL(x);
2572 }
2573
2574 // Statically recognized that coercion is not possible with these types
2575
2576 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'unicode'");
2577 goto exit_inplace_exception;
2578 }
2579
2580exit_inplace_result_object:
2581 if (unlikely(obj_result == NULL)) {
2582 return false;
2583 }
2584
2585 // We got an object handed, that we have to release.
2586 Py_DECREF(*operand1);
2587
2588 // That's our return value then. As we use a dedicated variable, it's
2589 // OK that way.
2590 *operand1 = obj_result;
2591
2592 return true;
2593
2594exit_inplace_exception:
2595 return false;
2596}
2597
2598bool INPLACE_OPERATION_MOD_STR_UNICODE(PyObject **operand1, PyObject *operand2) {
2599 return _INPLACE_OPERATION_MOD_STR_UNICODE(operand1, operand2);
2600}
2601#endif
2602
2603#if PYTHON_VERSION < 0x300
2604/* Code referring to "STR" corresponds to Python2 'str' and "TUPLE" to Python 'tuple'. */
2605static inline bool _INPLACE_OPERATION_MOD_STR_TUPLE(PyObject **operand1, PyObject *operand2) {
2606 assert(operand1); // Pointer must be non-null.
2607
2608 CHECK_OBJECT(*operand1);
2609 assert(PyString_CheckExact(*operand1));
2610 CHECK_OBJECT(operand2);
2611 assert(PyTuple_CheckExact(operand2));
2612
2613#if defined(_MSC_VER)
2614#pragma warning(push)
2615#pragma warning(disable : 4101)
2616#endif
2617 NUITKA_MAY_BE_UNUSED bool cbool_result;
2618 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2619#if defined(_MSC_VER)
2620#pragma warning(pop)
2621#endif
2622
2623 // No inplace number slot nb_inplace_remainder available for this type.
2624
2625 {
2626 binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder;
2627
2628 if (slot1 != NULL) {
2629 PyObject *x = slot1(*operand1, operand2);
2630
2631 if (x != Py_NotImplemented) {
2632 obj_result = x;
2633 goto exit_inplace_result_object;
2634 }
2635
2636 Py_DECREF_IMMORTAL(x);
2637 }
2638
2639 // Statically recognized that coercion is not possible with these types
2640
2641 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'tuple'");
2642 goto exit_inplace_exception;
2643 }
2644
2645exit_inplace_result_object:
2646 if (unlikely(obj_result == NULL)) {
2647 return false;
2648 }
2649
2650 // We got an object handed, that we have to release.
2651 Py_DECREF(*operand1);
2652
2653 // That's our return value then. As we use a dedicated variable, it's
2654 // OK that way.
2655 *operand1 = obj_result;
2656
2657 return true;
2658
2659exit_inplace_exception:
2660 return false;
2661}
2662
2663bool INPLACE_OPERATION_MOD_STR_TUPLE(PyObject **operand1, PyObject *operand2) {
2664 return _INPLACE_OPERATION_MOD_STR_TUPLE(operand1, operand2);
2665}
2666#endif
2667
2668#if PYTHON_VERSION < 0x300
2669/* Code referring to "STR" corresponds to Python2 'str' and "LIST" to Python 'list'. */
2670static inline bool _INPLACE_OPERATION_MOD_STR_LIST(PyObject **operand1, PyObject *operand2) {
2671 assert(operand1); // Pointer must be non-null.
2672
2673 CHECK_OBJECT(*operand1);
2674 assert(PyString_CheckExact(*operand1));
2675 CHECK_OBJECT(operand2);
2676 assert(PyList_CheckExact(operand2));
2677
2678#if defined(_MSC_VER)
2679#pragma warning(push)
2680#pragma warning(disable : 4101)
2681#endif
2682 NUITKA_MAY_BE_UNUSED bool cbool_result;
2683 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2684#if defined(_MSC_VER)
2685#pragma warning(pop)
2686#endif
2687
2688 // No inplace number slot nb_inplace_remainder available for this type.
2689
2690 {
2691 binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder;
2692
2693 if (slot1 != NULL) {
2694 PyObject *x = slot1(*operand1, operand2);
2695
2696 if (x != Py_NotImplemented) {
2697 obj_result = x;
2698 goto exit_inplace_result_object;
2699 }
2700
2701 Py_DECREF_IMMORTAL(x);
2702 }
2703
2704 // Statically recognized that coercion is not possible with these types
2705
2706 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'list'");
2707 goto exit_inplace_exception;
2708 }
2709
2710exit_inplace_result_object:
2711 if (unlikely(obj_result == NULL)) {
2712 return false;
2713 }
2714
2715 // We got an object handed, that we have to release.
2716 Py_DECREF(*operand1);
2717
2718 // That's our return value then. As we use a dedicated variable, it's
2719 // OK that way.
2720 *operand1 = obj_result;
2721
2722 return true;
2723
2724exit_inplace_exception:
2725 return false;
2726}
2727
2728bool INPLACE_OPERATION_MOD_STR_LIST(PyObject **operand1, PyObject *operand2) {
2729 return _INPLACE_OPERATION_MOD_STR_LIST(operand1, operand2);
2730}
2731#endif
2732
2733#if PYTHON_VERSION < 0x300
2734/* Code referring to "STR" corresponds to Python2 'str' and "DICT" to Python 'dict'. */
2735static inline bool _INPLACE_OPERATION_MOD_STR_DICT(PyObject **operand1, PyObject *operand2) {
2736 assert(operand1); // Pointer must be non-null.
2737
2738 CHECK_OBJECT(*operand1);
2739 assert(PyString_CheckExact(*operand1));
2740 CHECK_OBJECT(operand2);
2741 assert(PyDict_CheckExact(operand2));
2742
2743#if defined(_MSC_VER)
2744#pragma warning(push)
2745#pragma warning(disable : 4101)
2746#endif
2747 NUITKA_MAY_BE_UNUSED bool cbool_result;
2748 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2749#if defined(_MSC_VER)
2750#pragma warning(pop)
2751#endif
2752
2753 // No inplace number slot nb_inplace_remainder available for this type.
2754
2755 {
2756 binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder;
2757
2758 if (slot1 != NULL) {
2759 PyObject *x = slot1(*operand1, operand2);
2760
2761 if (x != Py_NotImplemented) {
2762 obj_result = x;
2763 goto exit_inplace_result_object;
2764 }
2765
2766 Py_DECREF_IMMORTAL(x);
2767 }
2768
2769 // Statically recognized that coercion is not possible with these types
2770
2771 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'dict'");
2772 goto exit_inplace_exception;
2773 }
2774
2775exit_inplace_result_object:
2776 if (unlikely(obj_result == NULL)) {
2777 return false;
2778 }
2779
2780 // We got an object handed, that we have to release.
2781 Py_DECREF(*operand1);
2782
2783 // That's our return value then. As we use a dedicated variable, it's
2784 // OK that way.
2785 *operand1 = obj_result;
2786
2787 return true;
2788
2789exit_inplace_exception:
2790 return false;
2791}
2792
2793bool INPLACE_OPERATION_MOD_STR_DICT(PyObject **operand1, PyObject *operand2) {
2794 return _INPLACE_OPERATION_MOD_STR_DICT(operand1, operand2);
2795}
2796#endif
2797
2798#if PYTHON_VERSION < 0x300
2799/* Code referring to "STR" corresponds to Python2 'str' and "OBJECT" to any Python object. */
2800static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_STR_OBJECT(PyObject **operand1, PyObject *operand2) {
2801 PyTypeObject *type2 = Py_TYPE(operand2);
2802
2803#if defined(_MSC_VER)
2804#pragma warning(push)
2805#pragma warning(disable : 4101)
2806#endif
2807 NUITKA_MAY_BE_UNUSED bool cbool_result;
2808 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2809#if defined(_MSC_VER)
2810#pragma warning(pop)
2811#endif
2812
2813 // No inplace number slot nb_inplace_remainder available for this type.
2814
2815 {
2816 binaryfunc slot1 = PyString_Type.tp_as_number->nb_remainder;
2817 binaryfunc slot2 = NULL;
2818
2819 if (!(&PyString_Type == type2)) {
2820 // Different types, need to consider second value slot.
2821
2822 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder
2823 : NULL;
2824
2825 if (slot1 == slot2) {
2826 slot2 = NULL;
2827 }
2828 }
2829
2830 if (slot1 != NULL) {
2831 if (slot2 != NULL) {
2832 if (Nuitka_Type_IsSubtype(type2, &PyString_Type)) {
2833 PyObject *x = slot2(*operand1, operand2);
2834
2835 if (x != Py_NotImplemented) {
2836 obj_result = x;
2837 goto exit_inplace_result_object;
2838 }
2839
2840 Py_DECREF_IMMORTAL(x);
2841 slot2 = NULL;
2842 }
2843 }
2844
2845 PyObject *x = slot1(*operand1, operand2);
2846
2847 if (x != Py_NotImplemented) {
2848 obj_result = x;
2849 goto exit_inplace_result_object;
2850 }
2851
2852 Py_DECREF_IMMORTAL(x);
2853 }
2854
2855 if (slot2 != NULL) {
2856 PyObject *x = slot2(*operand1, operand2);
2857
2858 if (x != Py_NotImplemented) {
2859 obj_result = x;
2860 goto exit_inplace_result_object;
2861 }
2862
2863 Py_DECREF_IMMORTAL(x);
2864 }
2865
2866#if PYTHON_VERSION < 0x300
2867 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
2868 coercion c2 =
2869 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
2870
2871 if (c2 != NULL) {
2872 PyObject *coerced1 = *operand1;
2873 PyObject *coerced2 = operand2;
2874
2875 int err = c2(&coerced2, &coerced1);
2876
2877 if (unlikely(err < 0)) {
2878 goto exit_inplace_exception;
2879 }
2880
2881 if (err == 0) {
2882 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
2883
2884 if (likely(mv == NULL)) {
2885 binaryfunc slot = mv->nb_remainder;
2886
2887 if (likely(slot != NULL)) {
2888 PyObject *x = slot(coerced1, coerced2);
2889
2890 Py_DECREF(coerced1);
2891 Py_DECREF(coerced2);
2892
2893 obj_result = x;
2894 goto exit_inplace_result_object;
2895 }
2896 }
2897
2898 // nb_coerce took a reference.
2899 Py_DECREF(coerced1);
2900 Py_DECREF(coerced2);
2901 }
2902 }
2903 }
2904#endif
2905
2906 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and '%s'", type2->tp_name);
2907 goto exit_inplace_exception;
2908 }
2909
2910exit_inplace_result_object:
2911 if (unlikely(obj_result == NULL)) {
2912 return false;
2913 }
2914
2915 // We got an object handed, that we have to release.
2916 Py_DECREF(*operand1);
2917
2918 // That's our return value then. As we use a dedicated variable, it's
2919 // OK that way.
2920 *operand1 = obj_result;
2921
2922 return true;
2923
2924exit_inplace_exception:
2925 return false;
2926}
2927static inline bool _INPLACE_OPERATION_MOD_STR_OBJECT(PyObject **operand1, PyObject *operand2) {
2928 assert(operand1); // Pointer must be non-null.
2929
2930 CHECK_OBJECT(*operand1);
2931 assert(PyString_CheckExact(*operand1));
2932 CHECK_OBJECT(operand2);
2933
2934 PyTypeObject *type2 = Py_TYPE(operand2);
2935
2936 if (&PyString_Type == type2) {
2937 // return _BINARY_OPERATION_MOD_STR_STR_INPLACE(operand1, operand2);
2938
2939 // Not every code path will make use of all possible results.
2940 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2941
2942 PyObject *x = PyString_Format(*operand1, operand2);
2943
2944 obj_result = x;
2945 goto exit_result_object;
2946
2947 exit_result_object:
2948 if (unlikely(obj_result == NULL)) {
2949 goto exit_result_exception;
2950 }
2951 // We got an object handed, that we have to release.
2952 Py_DECREF(*operand1);
2953
2954 *operand1 = obj_result;
2955 goto exit_result_ok;
2956
2957 exit_result_ok:
2958 return true;
2959
2960 exit_result_exception:
2961 return false;
2962 }
2963
2964 return __INPLACE_OPERATION_MOD_STR_OBJECT(operand1, operand2);
2965}
2966
2967bool INPLACE_OPERATION_MOD_STR_OBJECT(PyObject **operand1, PyObject *operand2) {
2968 return _INPLACE_OPERATION_MOD_STR_OBJECT(operand1, operand2);
2969}
2970#endif
2971
2972#if PYTHON_VERSION < 0x300
2973/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "INT" to Python2 'int'. */
2974static inline bool _INPLACE_OPERATION_MOD_UNICODE_INT(PyObject **operand1, PyObject *operand2) {
2975 assert(operand1); // Pointer must be non-null.
2976
2977 CHECK_OBJECT(*operand1);
2978 assert(PyUnicode_CheckExact(*operand1));
2979 CHECK_OBJECT(operand2);
2980 assert(PyInt_CheckExact(operand2));
2981
2982#if defined(_MSC_VER)
2983#pragma warning(push)
2984#pragma warning(disable : 4101)
2985#endif
2986 NUITKA_MAY_BE_UNUSED bool cbool_result;
2987 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
2988#if defined(_MSC_VER)
2989#pragma warning(pop)
2990#endif
2991
2992 // No inplace number slot nb_inplace_remainder available for this type.
2993
2994 {
2995 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
2996 binaryfunc slot2 = NULL;
2997
2998 if (!(0)) {
2999 // Different types, need to consider second value slot.
3000
3001 slot2 = PyInt_Type.tp_as_number->nb_remainder;
3002 }
3003
3004 if (slot1 != NULL) {
3005 PyObject *x = slot1(*operand1, operand2);
3006
3007 if (x != Py_NotImplemented) {
3008 obj_result = x;
3009 goto exit_inplace_result_object;
3010 }
3011
3012 Py_DECREF_IMMORTAL(x);
3013 }
3014
3015 if (slot2 != NULL) {
3016 PyObject *x = slot2(*operand1, operand2);
3017
3018 if (x != Py_NotImplemented) {
3019 obj_result = x;
3020 goto exit_inplace_result_object;
3021 }
3022
3023 Py_DECREF_IMMORTAL(x);
3024 }
3025
3026 // Statically recognized that coercion is not possible with these types
3027
3028 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'unicode' and 'int'");
3029 goto exit_inplace_exception;
3030 }
3031
3032exit_inplace_result_object:
3033 if (unlikely(obj_result == NULL)) {
3034 return false;
3035 }
3036
3037 // We got an object handed, that we have to release.
3038 Py_DECREF(*operand1);
3039
3040 // That's our return value then. As we use a dedicated variable, it's
3041 // OK that way.
3042 *operand1 = obj_result;
3043
3044 return true;
3045
3046exit_inplace_exception:
3047 return false;
3048}
3049
3050bool INPLACE_OPERATION_MOD_UNICODE_INT(PyObject **operand1, PyObject *operand2) {
3051 return _INPLACE_OPERATION_MOD_UNICODE_INT(operand1, operand2);
3052}
3053#endif
3054
3055/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LONG" to Python2 'long', Python3
3056 * 'int'. */
3057static inline bool _INPLACE_OPERATION_MOD_UNICODE_LONG(PyObject **operand1, PyObject *operand2) {
3058 assert(operand1); // Pointer must be non-null.
3059
3060 CHECK_OBJECT(*operand1);
3061 assert(PyUnicode_CheckExact(*operand1));
3062 CHECK_OBJECT(operand2);
3063 assert(PyLong_CheckExact(operand2));
3064
3065#if defined(_MSC_VER)
3066#pragma warning(push)
3067#pragma warning(disable : 4101)
3068#endif
3069 NUITKA_MAY_BE_UNUSED bool cbool_result;
3070 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3071#if defined(_MSC_VER)
3072#pragma warning(pop)
3073#endif
3074
3075 // No inplace number slot nb_inplace_remainder available for this type.
3076
3077 {
3078 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
3079 binaryfunc slot2 = NULL;
3080
3081 if (!(0)) {
3082 // Different types, need to consider second value slot.
3083
3084 slot2 = PyLong_Type.tp_as_number->nb_remainder;
3085 }
3086
3087 if (slot1 != NULL) {
3088 PyObject *x = slot1(*operand1, operand2);
3089
3090 if (x != Py_NotImplemented) {
3091 obj_result = x;
3092 goto exit_inplace_result_object;
3093 }
3094
3095 Py_DECREF_IMMORTAL(x);
3096 }
3097
3098 if (slot2 != NULL) {
3099 PyObject *x = slot2(*operand1, operand2);
3100
3101 if (x != Py_NotImplemented) {
3102 obj_result = x;
3103 goto exit_inplace_result_object;
3104 }
3105
3106 Py_DECREF_IMMORTAL(x);
3107 }
3108
3109 // Statically recognized that coercion is not possible with these types
3110
3111#if PYTHON_VERSION < 0x300
3112 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'unicode' and 'long'");
3113#else
3114 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'int'");
3115#endif
3116 goto exit_inplace_exception;
3117 }
3118
3119exit_inplace_result_object:
3120 if (unlikely(obj_result == NULL)) {
3121 return false;
3122 }
3123
3124 // We got an object handed, that we have to release.
3125 Py_DECREF(*operand1);
3126
3127 // That's our return value then. As we use a dedicated variable, it's
3128 // OK that way.
3129 *operand1 = obj_result;
3130
3131 return true;
3132
3133exit_inplace_exception:
3134 return false;
3135}
3136
3137bool INPLACE_OPERATION_MOD_UNICODE_LONG(PyObject **operand1, PyObject *operand2) {
3138 return _INPLACE_OPERATION_MOD_UNICODE_LONG(operand1, operand2);
3139}
3140
3141/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "FLOAT" to Python 'float'. */
3142static inline bool _INPLACE_OPERATION_MOD_UNICODE_FLOAT(PyObject **operand1, PyObject *operand2) {
3143 assert(operand1); // Pointer must be non-null.
3144
3145 CHECK_OBJECT(*operand1);
3146 assert(PyUnicode_CheckExact(*operand1));
3147 CHECK_OBJECT(operand2);
3148 assert(PyFloat_CheckExact(operand2));
3149
3150#if defined(_MSC_VER)
3151#pragma warning(push)
3152#pragma warning(disable : 4101)
3153#endif
3154 NUITKA_MAY_BE_UNUSED bool cbool_result;
3155 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3156#if defined(_MSC_VER)
3157#pragma warning(pop)
3158#endif
3159
3160 // No inplace number slot nb_inplace_remainder available for this type.
3161
3162 {
3163 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
3164 binaryfunc slot2 = NULL;
3165
3166 if (!(0)) {
3167 // Different types, need to consider second value slot.
3168
3169 slot2 = PyFloat_Type.tp_as_number->nb_remainder;
3170 }
3171
3172 if (slot1 != NULL) {
3173 PyObject *x = slot1(*operand1, operand2);
3174
3175 if (x != Py_NotImplemented) {
3176 obj_result = x;
3177 goto exit_inplace_result_object;
3178 }
3179
3180 Py_DECREF_IMMORTAL(x);
3181 }
3182
3183 if (slot2 != NULL) {
3184 PyObject *x = slot2(*operand1, operand2);
3185
3186 if (x != Py_NotImplemented) {
3187 obj_result = x;
3188 goto exit_inplace_result_object;
3189 }
3190
3191 Py_DECREF_IMMORTAL(x);
3192 }
3193
3194 // Statically recognized that coercion is not possible with these types
3195
3196#if PYTHON_VERSION < 0x300
3197 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'unicode' and 'float'");
3198#else
3199 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'float'");
3200#endif
3201 goto exit_inplace_exception;
3202 }
3203
3204exit_inplace_result_object:
3205 if (unlikely(obj_result == NULL)) {
3206 return false;
3207 }
3208
3209 // We got an object handed, that we have to release.
3210 Py_DECREF(*operand1);
3211
3212 // That's our return value then. As we use a dedicated variable, it's
3213 // OK that way.
3214 *operand1 = obj_result;
3215
3216 return true;
3217
3218exit_inplace_exception:
3219 return false;
3220}
3221
3222bool INPLACE_OPERATION_MOD_UNICODE_FLOAT(PyObject **operand1, PyObject *operand2) {
3223 return _INPLACE_OPERATION_MOD_UNICODE_FLOAT(operand1, operand2);
3224}
3225
3226#if PYTHON_VERSION < 0x300
3227/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "STR" to Python2 'str'. */
3228static inline bool _INPLACE_OPERATION_MOD_UNICODE_STR(PyObject **operand1, PyObject *operand2) {
3229 assert(operand1); // Pointer must be non-null.
3230
3231 CHECK_OBJECT(*operand1);
3232 assert(PyUnicode_CheckExact(*operand1));
3233 CHECK_OBJECT(operand2);
3234 assert(PyString_CheckExact(operand2));
3235
3236#if defined(_MSC_VER)
3237#pragma warning(push)
3238#pragma warning(disable : 4101)
3239#endif
3240 NUITKA_MAY_BE_UNUSED bool cbool_result;
3241 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3242#if defined(_MSC_VER)
3243#pragma warning(pop)
3244#endif
3245
3246 // No inplace number slot nb_inplace_remainder available for this type.
3247
3248 {
3249 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
3250 binaryfunc slot2 = NULL;
3251
3252 if (!(0)) {
3253 // Different types, need to consider second value slot.
3254
3255 slot2 = PyString_Type.tp_as_number->nb_remainder;
3256 }
3257
3258 if (slot1 != NULL) {
3259 PyObject *x = slot1(*operand1, operand2);
3260
3261 if (x != Py_NotImplemented) {
3262 obj_result = x;
3263 goto exit_inplace_result_object;
3264 }
3265
3266 Py_DECREF_IMMORTAL(x);
3267 }
3268
3269 if (slot2 != NULL) {
3270 PyObject *x = slot2(*operand1, operand2);
3271
3272 if (x != Py_NotImplemented) {
3273 obj_result = x;
3274 goto exit_inplace_result_object;
3275 }
3276
3277 Py_DECREF_IMMORTAL(x);
3278 }
3279
3280 // Statically recognized that coercion is not possible with these types
3281
3282 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'unicode' and 'str'");
3283 goto exit_inplace_exception;
3284 }
3285
3286exit_inplace_result_object:
3287 if (unlikely(obj_result == NULL)) {
3288 return false;
3289 }
3290
3291 // We got an object handed, that we have to release.
3292 Py_DECREF(*operand1);
3293
3294 // That's our return value then. As we use a dedicated variable, it's
3295 // OK that way.
3296 *operand1 = obj_result;
3297
3298 return true;
3299
3300exit_inplace_exception:
3301 return false;
3302}
3303
3304bool INPLACE_OPERATION_MOD_UNICODE_STR(PyObject **operand1, PyObject *operand2) {
3305 return _INPLACE_OPERATION_MOD_UNICODE_STR(operand1, operand2);
3306}
3307#endif
3308
3309#if PYTHON_VERSION >= 0x300
3310/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "BYTES" to Python3 'bytes'. */
3311static inline bool _INPLACE_OPERATION_MOD_UNICODE_BYTES(PyObject **operand1, PyObject *operand2) {
3312 assert(operand1); // Pointer must be non-null.
3313
3314 CHECK_OBJECT(*operand1);
3315 assert(PyUnicode_CheckExact(*operand1));
3316 CHECK_OBJECT(operand2);
3317 assert(PyBytes_CheckExact(operand2));
3318
3319#if defined(_MSC_VER)
3320#pragma warning(push)
3321#pragma warning(disable : 4101)
3322#endif
3323 NUITKA_MAY_BE_UNUSED bool cbool_result;
3324 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3325#if defined(_MSC_VER)
3326#pragma warning(pop)
3327#endif
3328
3329 // No inplace number slot nb_inplace_remainder available for this type.
3330
3331 {
3332 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
3333 binaryfunc slot2 = NULL;
3334
3335 if (!(0)) {
3336 // Different types, need to consider second value slot.
3337
3338 slot2 = PyBytes_Type.tp_as_number->nb_remainder;
3339 }
3340
3341 if (slot1 != NULL) {
3342 PyObject *x = slot1(*operand1, operand2);
3343
3344 if (x != Py_NotImplemented) {
3345 obj_result = x;
3346 goto exit_inplace_result_object;
3347 }
3348
3349 Py_DECREF_IMMORTAL(x);
3350 }
3351
3352 if (slot2 != NULL) {
3353 PyObject *x = slot2(*operand1, operand2);
3354
3355 if (x != Py_NotImplemented) {
3356 obj_result = x;
3357 goto exit_inplace_result_object;
3358 }
3359
3360 Py_DECREF_IMMORTAL(x);
3361 }
3362
3363 // Statically recognized that coercion is not possible with these types
3364
3365 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'bytes'");
3366 goto exit_inplace_exception;
3367 }
3368
3369exit_inplace_result_object:
3370 if (unlikely(obj_result == NULL)) {
3371 return false;
3372 }
3373
3374 // We got an object handed, that we have to release.
3375 Py_DECREF(*operand1);
3376
3377 // That's our return value then. As we use a dedicated variable, it's
3378 // OK that way.
3379 *operand1 = obj_result;
3380
3381 return true;
3382
3383exit_inplace_exception:
3384 return false;
3385}
3386
3387bool INPLACE_OPERATION_MOD_UNICODE_BYTES(PyObject **operand1, PyObject *operand2) {
3388 return _INPLACE_OPERATION_MOD_UNICODE_BYTES(operand1, operand2);
3389}
3390#endif
3391
3392/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "UNICODE" to Python2 'unicode',
3393 * Python3 'str'. */
3394static inline bool _INPLACE_OPERATION_MOD_UNICODE_UNICODE(PyObject **operand1, PyObject *operand2) {
3395 assert(operand1); // Pointer must be non-null.
3396
3397 CHECK_OBJECT(*operand1);
3398 assert(PyUnicode_CheckExact(*operand1));
3399 CHECK_OBJECT(operand2);
3400 assert(PyUnicode_CheckExact(operand2));
3401
3402 // Not every code path will make use of all possible results.
3403 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3404
3405 PyObject *x = PyUnicode_Format(*operand1, operand2);
3406
3407 obj_result = x;
3408 goto exit_result_object;
3409
3410exit_result_object:
3411 if (unlikely(obj_result == NULL)) {
3412 goto exit_result_exception;
3413 }
3414 // We got an object handed, that we have to release.
3415 Py_DECREF(*operand1);
3416
3417 *operand1 = obj_result;
3418 goto exit_result_ok;
3419
3420exit_result_ok:
3421 return true;
3422
3423exit_result_exception:
3424 return false;
3425}
3426
3427bool INPLACE_OPERATION_MOD_UNICODE_UNICODE(PyObject **operand1, PyObject *operand2) {
3428 return _INPLACE_OPERATION_MOD_UNICODE_UNICODE(operand1, operand2);
3429}
3430
3431/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "TUPLE" to Python 'tuple'. */
3432static inline bool _INPLACE_OPERATION_MOD_UNICODE_TUPLE(PyObject **operand1, PyObject *operand2) {
3433 assert(operand1); // Pointer must be non-null.
3434
3435 CHECK_OBJECT(*operand1);
3436 assert(PyUnicode_CheckExact(*operand1));
3437 CHECK_OBJECT(operand2);
3438 assert(PyTuple_CheckExact(operand2));
3439
3440#if defined(_MSC_VER)
3441#pragma warning(push)
3442#pragma warning(disable : 4101)
3443#endif
3444 NUITKA_MAY_BE_UNUSED bool cbool_result;
3445 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3446#if defined(_MSC_VER)
3447#pragma warning(pop)
3448#endif
3449
3450 // No inplace number slot nb_inplace_remainder available for this type.
3451
3452 {
3453 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
3454
3455 if (slot1 != NULL) {
3456 PyObject *x = slot1(*operand1, operand2);
3457
3458 if (x != Py_NotImplemented) {
3459 obj_result = x;
3460 goto exit_inplace_result_object;
3461 }
3462
3463 Py_DECREF_IMMORTAL(x);
3464 }
3465
3466 // Statically recognized that coercion is not possible with these types
3467
3468#if PYTHON_VERSION < 0x300
3469 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'unicode' and 'tuple'");
3470#else
3471 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'tuple'");
3472#endif
3473 goto exit_inplace_exception;
3474 }
3475
3476exit_inplace_result_object:
3477 if (unlikely(obj_result == NULL)) {
3478 return false;
3479 }
3480
3481 // We got an object handed, that we have to release.
3482 Py_DECREF(*operand1);
3483
3484 // That's our return value then. As we use a dedicated variable, it's
3485 // OK that way.
3486 *operand1 = obj_result;
3487
3488 return true;
3489
3490exit_inplace_exception:
3491 return false;
3492}
3493
3494bool INPLACE_OPERATION_MOD_UNICODE_TUPLE(PyObject **operand1, PyObject *operand2) {
3495 return _INPLACE_OPERATION_MOD_UNICODE_TUPLE(operand1, operand2);
3496}
3497
3498/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "LIST" to Python 'list'. */
3499static inline bool _INPLACE_OPERATION_MOD_UNICODE_LIST(PyObject **operand1, PyObject *operand2) {
3500 assert(operand1); // Pointer must be non-null.
3501
3502 CHECK_OBJECT(*operand1);
3503 assert(PyUnicode_CheckExact(*operand1));
3504 CHECK_OBJECT(operand2);
3505 assert(PyList_CheckExact(operand2));
3506
3507#if defined(_MSC_VER)
3508#pragma warning(push)
3509#pragma warning(disable : 4101)
3510#endif
3511 NUITKA_MAY_BE_UNUSED bool cbool_result;
3512 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3513#if defined(_MSC_VER)
3514#pragma warning(pop)
3515#endif
3516
3517 // No inplace number slot nb_inplace_remainder available for this type.
3518
3519 {
3520 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
3521
3522 if (slot1 != NULL) {
3523 PyObject *x = slot1(*operand1, operand2);
3524
3525 if (x != Py_NotImplemented) {
3526 obj_result = x;
3527 goto exit_inplace_result_object;
3528 }
3529
3530 Py_DECREF_IMMORTAL(x);
3531 }
3532
3533 // Statically recognized that coercion is not possible with these types
3534
3535#if PYTHON_VERSION < 0x300
3536 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'unicode' and 'list'");
3537#else
3538 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'list'");
3539#endif
3540 goto exit_inplace_exception;
3541 }
3542
3543exit_inplace_result_object:
3544 if (unlikely(obj_result == NULL)) {
3545 return false;
3546 }
3547
3548 // We got an object handed, that we have to release.
3549 Py_DECREF(*operand1);
3550
3551 // That's our return value then. As we use a dedicated variable, it's
3552 // OK that way.
3553 *operand1 = obj_result;
3554
3555 return true;
3556
3557exit_inplace_exception:
3558 return false;
3559}
3560
3561bool INPLACE_OPERATION_MOD_UNICODE_LIST(PyObject **operand1, PyObject *operand2) {
3562 return _INPLACE_OPERATION_MOD_UNICODE_LIST(operand1, operand2);
3563}
3564
3565/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "DICT" to Python 'dict'. */
3566static inline bool _INPLACE_OPERATION_MOD_UNICODE_DICT(PyObject **operand1, PyObject *operand2) {
3567 assert(operand1); // Pointer must be non-null.
3568
3569 CHECK_OBJECT(*operand1);
3570 assert(PyUnicode_CheckExact(*operand1));
3571 CHECK_OBJECT(operand2);
3572 assert(PyDict_CheckExact(operand2));
3573
3574#if defined(_MSC_VER)
3575#pragma warning(push)
3576#pragma warning(disable : 4101)
3577#endif
3578 NUITKA_MAY_BE_UNUSED bool cbool_result;
3579 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3580#if defined(_MSC_VER)
3581#pragma warning(pop)
3582#endif
3583
3584 // No inplace number slot nb_inplace_remainder available for this type.
3585
3586 {
3587 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
3588
3589 if (slot1 != NULL) {
3590 PyObject *x = slot1(*operand1, operand2);
3591
3592 if (x != Py_NotImplemented) {
3593 obj_result = x;
3594 goto exit_inplace_result_object;
3595 }
3596
3597 Py_DECREF_IMMORTAL(x);
3598 }
3599
3600 // Statically recognized that coercion is not possible with these types
3601
3602#if PYTHON_VERSION < 0x300
3603 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'unicode' and 'dict'");
3604#else
3605 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and 'dict'");
3606#endif
3607 goto exit_inplace_exception;
3608 }
3609
3610exit_inplace_result_object:
3611 if (unlikely(obj_result == NULL)) {
3612 return false;
3613 }
3614
3615 // We got an object handed, that we have to release.
3616 Py_DECREF(*operand1);
3617
3618 // That's our return value then. As we use a dedicated variable, it's
3619 // OK that way.
3620 *operand1 = obj_result;
3621
3622 return true;
3623
3624exit_inplace_exception:
3625 return false;
3626}
3627
3628bool INPLACE_OPERATION_MOD_UNICODE_DICT(PyObject **operand1, PyObject *operand2) {
3629 return _INPLACE_OPERATION_MOD_UNICODE_DICT(operand1, operand2);
3630}
3631
3632/* Code referring to "UNICODE" corresponds to Python2 'unicode', Python3 'str' and "OBJECT" to any Python object. */
3633static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_UNICODE_OBJECT(PyObject **operand1, PyObject *operand2) {
3634 PyTypeObject *type2 = Py_TYPE(operand2);
3635
3636#if defined(_MSC_VER)
3637#pragma warning(push)
3638#pragma warning(disable : 4101)
3639#endif
3640 NUITKA_MAY_BE_UNUSED bool cbool_result;
3641 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3642#if defined(_MSC_VER)
3643#pragma warning(pop)
3644#endif
3645
3646 // No inplace number slot nb_inplace_remainder available for this type.
3647
3648 {
3649 binaryfunc slot1 = PyUnicode_Type.tp_as_number->nb_remainder;
3650 binaryfunc slot2 = NULL;
3651
3652 if (!(&PyUnicode_Type == type2)) {
3653 // Different types, need to consider second value slot.
3654
3655 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder
3656 : NULL;
3657
3658 if (slot1 == slot2) {
3659 slot2 = NULL;
3660 }
3661 }
3662
3663 if (slot1 != NULL) {
3664 if (slot2 != NULL) {
3665 if (Nuitka_Type_IsSubtype(type2, &PyUnicode_Type)) {
3666 PyObject *x = slot2(*operand1, operand2);
3667
3668 if (x != Py_NotImplemented) {
3669 obj_result = x;
3670 goto exit_inplace_result_object;
3671 }
3672
3673 Py_DECREF_IMMORTAL(x);
3674 slot2 = NULL;
3675 }
3676 }
3677
3678 PyObject *x = slot1(*operand1, operand2);
3679
3680 if (x != Py_NotImplemented) {
3681 obj_result = x;
3682 goto exit_inplace_result_object;
3683 }
3684
3685 Py_DECREF_IMMORTAL(x);
3686 }
3687
3688 if (slot2 != NULL) {
3689 PyObject *x = slot2(*operand1, operand2);
3690
3691 if (x != Py_NotImplemented) {
3692 obj_result = x;
3693 goto exit_inplace_result_object;
3694 }
3695
3696 Py_DECREF_IMMORTAL(x);
3697 }
3698
3699#if PYTHON_VERSION < 0x300
3700 if (!1 || !NEW_STYLE_NUMBER_TYPE(type2)) {
3701 coercion c2 =
3702 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
3703
3704 if (c2 != NULL) {
3705 PyObject *coerced1 = *operand1;
3706 PyObject *coerced2 = operand2;
3707
3708 int err = c2(&coerced2, &coerced1);
3709
3710 if (unlikely(err < 0)) {
3711 goto exit_inplace_exception;
3712 }
3713
3714 if (err == 0) {
3715 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
3716
3717 if (likely(mv == NULL)) {
3718 binaryfunc slot = mv->nb_remainder;
3719
3720 if (likely(slot != NULL)) {
3721 PyObject *x = slot(coerced1, coerced2);
3722
3723 Py_DECREF(coerced1);
3724 Py_DECREF(coerced2);
3725
3726 obj_result = x;
3727 goto exit_inplace_result_object;
3728 }
3729 }
3730
3731 // nb_coerce took a reference.
3732 Py_DECREF(coerced1);
3733 Py_DECREF(coerced2);
3734 }
3735 }
3736 }
3737#endif
3738
3739#if PYTHON_VERSION < 0x300
3740 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'unicode' and '%s'", type2->tp_name);
3741#else
3742 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'str' and '%s'", type2->tp_name);
3743#endif
3744 goto exit_inplace_exception;
3745 }
3746
3747exit_inplace_result_object:
3748 if (unlikely(obj_result == NULL)) {
3749 return false;
3750 }
3751
3752 // We got an object handed, that we have to release.
3753 Py_DECREF(*operand1);
3754
3755 // That's our return value then. As we use a dedicated variable, it's
3756 // OK that way.
3757 *operand1 = obj_result;
3758
3759 return true;
3760
3761exit_inplace_exception:
3762 return false;
3763}
3764static inline bool _INPLACE_OPERATION_MOD_UNICODE_OBJECT(PyObject **operand1, PyObject *operand2) {
3765 assert(operand1); // Pointer must be non-null.
3766
3767 CHECK_OBJECT(*operand1);
3768 assert(PyUnicode_CheckExact(*operand1));
3769 CHECK_OBJECT(operand2);
3770
3771 PyTypeObject *type2 = Py_TYPE(operand2);
3772
3773 if (&PyUnicode_Type == type2) {
3774 // return _BINARY_OPERATION_MOD_UNICODE_UNICODE_INPLACE(operand1, operand2);
3775
3776 // Not every code path will make use of all possible results.
3777 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3778
3779 PyObject *x = PyUnicode_Format(*operand1, operand2);
3780
3781 obj_result = x;
3782 goto exit_result_object;
3783
3784 exit_result_object:
3785 if (unlikely(obj_result == NULL)) {
3786 goto exit_result_exception;
3787 }
3788 // We got an object handed, that we have to release.
3789 Py_DECREF(*operand1);
3790
3791 *operand1 = obj_result;
3792 goto exit_result_ok;
3793
3794 exit_result_ok:
3795 return true;
3796
3797 exit_result_exception:
3798 return false;
3799 }
3800
3801 return __INPLACE_OPERATION_MOD_UNICODE_OBJECT(operand1, operand2);
3802}
3803
3804bool INPLACE_OPERATION_MOD_UNICODE_OBJECT(PyObject **operand1, PyObject *operand2) {
3805 return _INPLACE_OPERATION_MOD_UNICODE_OBJECT(operand1, operand2);
3806}
3807
3808#if PYTHON_VERSION >= 0x300
3809/* Code referring to "BYTES" corresponds to Python3 'bytes' and "LONG" to Python2 'long', Python3 'int'. */
3810static inline bool _INPLACE_OPERATION_MOD_BYTES_LONG(PyObject **operand1, PyObject *operand2) {
3811 assert(operand1); // Pointer must be non-null.
3812
3813 CHECK_OBJECT(*operand1);
3814 assert(PyBytes_CheckExact(*operand1));
3815 CHECK_OBJECT(operand2);
3816 assert(PyLong_CheckExact(operand2));
3817
3818#if defined(_MSC_VER)
3819#pragma warning(push)
3820#pragma warning(disable : 4101)
3821#endif
3822 NUITKA_MAY_BE_UNUSED bool cbool_result;
3823 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3824#if defined(_MSC_VER)
3825#pragma warning(pop)
3826#endif
3827
3828 // No inplace number slot nb_inplace_remainder available for this type.
3829
3830 {
3831 binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder;
3832 binaryfunc slot2 = NULL;
3833
3834 if (!(0)) {
3835 // Different types, need to consider second value slot.
3836
3837 slot2 = PyLong_Type.tp_as_number->nb_remainder;
3838 }
3839
3840 if (slot1 != NULL) {
3841 PyObject *x = slot1(*operand1, operand2);
3842
3843 if (x != Py_NotImplemented) {
3844 obj_result = x;
3845 goto exit_inplace_result_object;
3846 }
3847
3848 Py_DECREF_IMMORTAL(x);
3849 }
3850
3851 if (slot2 != NULL) {
3852 PyObject *x = slot2(*operand1, operand2);
3853
3854 if (x != Py_NotImplemented) {
3855 obj_result = x;
3856 goto exit_inplace_result_object;
3857 }
3858
3859 Py_DECREF_IMMORTAL(x);
3860 }
3861
3862 // Statically recognized that coercion is not possible with these types
3863
3864 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'bytes' and 'int'");
3865 goto exit_inplace_exception;
3866 }
3867
3868exit_inplace_result_object:
3869 if (unlikely(obj_result == NULL)) {
3870 return false;
3871 }
3872
3873 // We got an object handed, that we have to release.
3874 Py_DECREF(*operand1);
3875
3876 // That's our return value then. As we use a dedicated variable, it's
3877 // OK that way.
3878 *operand1 = obj_result;
3879
3880 return true;
3881
3882exit_inplace_exception:
3883 return false;
3884}
3885
3886bool INPLACE_OPERATION_MOD_BYTES_LONG(PyObject **operand1, PyObject *operand2) {
3887 return _INPLACE_OPERATION_MOD_BYTES_LONG(operand1, operand2);
3888}
3889#endif
3890
3891#if PYTHON_VERSION >= 0x300
3892/* Code referring to "BYTES" corresponds to Python3 'bytes' and "FLOAT" to Python 'float'. */
3893static inline bool _INPLACE_OPERATION_MOD_BYTES_FLOAT(PyObject **operand1, PyObject *operand2) {
3894 assert(operand1); // Pointer must be non-null.
3895
3896 CHECK_OBJECT(*operand1);
3897 assert(PyBytes_CheckExact(*operand1));
3898 CHECK_OBJECT(operand2);
3899 assert(PyFloat_CheckExact(operand2));
3900
3901#if defined(_MSC_VER)
3902#pragma warning(push)
3903#pragma warning(disable : 4101)
3904#endif
3905 NUITKA_MAY_BE_UNUSED bool cbool_result;
3906 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3907#if defined(_MSC_VER)
3908#pragma warning(pop)
3909#endif
3910
3911 // No inplace number slot nb_inplace_remainder available for this type.
3912
3913 {
3914 binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder;
3915 binaryfunc slot2 = NULL;
3916
3917 if (!(0)) {
3918 // Different types, need to consider second value slot.
3919
3920 slot2 = PyFloat_Type.tp_as_number->nb_remainder;
3921 }
3922
3923 if (slot1 != NULL) {
3924 PyObject *x = slot1(*operand1, operand2);
3925
3926 if (x != Py_NotImplemented) {
3927 obj_result = x;
3928 goto exit_inplace_result_object;
3929 }
3930
3931 Py_DECREF_IMMORTAL(x);
3932 }
3933
3934 if (slot2 != NULL) {
3935 PyObject *x = slot2(*operand1, operand2);
3936
3937 if (x != Py_NotImplemented) {
3938 obj_result = x;
3939 goto exit_inplace_result_object;
3940 }
3941
3942 Py_DECREF_IMMORTAL(x);
3943 }
3944
3945 // Statically recognized that coercion is not possible with these types
3946
3947 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'bytes' and 'float'");
3948 goto exit_inplace_exception;
3949 }
3950
3951exit_inplace_result_object:
3952 if (unlikely(obj_result == NULL)) {
3953 return false;
3954 }
3955
3956 // We got an object handed, that we have to release.
3957 Py_DECREF(*operand1);
3958
3959 // That's our return value then. As we use a dedicated variable, it's
3960 // OK that way.
3961 *operand1 = obj_result;
3962
3963 return true;
3964
3965exit_inplace_exception:
3966 return false;
3967}
3968
3969bool INPLACE_OPERATION_MOD_BYTES_FLOAT(PyObject **operand1, PyObject *operand2) {
3970 return _INPLACE_OPERATION_MOD_BYTES_FLOAT(operand1, operand2);
3971}
3972#endif
3973
3974#if PYTHON_VERSION >= 0x300
3975/* Code referring to "BYTES" corresponds to Python3 'bytes' and "BYTES" to Python3 'bytes'. */
3976static inline bool _INPLACE_OPERATION_MOD_BYTES_BYTES(PyObject **operand1, PyObject *operand2) {
3977 assert(operand1); // Pointer must be non-null.
3978
3979 CHECK_OBJECT(*operand1);
3980 assert(PyBytes_CheckExact(*operand1));
3981 CHECK_OBJECT(operand2);
3982 assert(PyBytes_CheckExact(operand2));
3983
3984 // Not every code path will make use of all possible results.
3985 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
3986
3987 PyObject *x = PyBytes_Type.tp_as_number->nb_remainder(*operand1, operand2);
3988 assert(x != Py_NotImplemented);
3989
3990 obj_result = x;
3991 goto exit_result_object;
3992
3993exit_result_object:
3994 if (unlikely(obj_result == NULL)) {
3995 goto exit_result_exception;
3996 }
3997 // We got an object handed, that we have to release.
3998 Py_DECREF(*operand1);
3999
4000 *operand1 = obj_result;
4001 goto exit_result_ok;
4002
4003exit_result_ok:
4004 return true;
4005
4006exit_result_exception:
4007 return false;
4008}
4009
4010bool INPLACE_OPERATION_MOD_BYTES_BYTES(PyObject **operand1, PyObject *operand2) {
4011 return _INPLACE_OPERATION_MOD_BYTES_BYTES(operand1, operand2);
4012}
4013#endif
4014
4015#if PYTHON_VERSION >= 0x300
4016/* Code referring to "BYTES" corresponds to Python3 'bytes' and "UNICODE" to Python2 'unicode', Python3 'str'. */
4017static inline bool _INPLACE_OPERATION_MOD_BYTES_UNICODE(PyObject **operand1, PyObject *operand2) {
4018 assert(operand1); // Pointer must be non-null.
4019
4020 CHECK_OBJECT(*operand1);
4021 assert(PyBytes_CheckExact(*operand1));
4022 CHECK_OBJECT(operand2);
4023 assert(PyUnicode_CheckExact(operand2));
4024
4025#if defined(_MSC_VER)
4026#pragma warning(push)
4027#pragma warning(disable : 4101)
4028#endif
4029 NUITKA_MAY_BE_UNUSED bool cbool_result;
4030 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4031#if defined(_MSC_VER)
4032#pragma warning(pop)
4033#endif
4034
4035 // No inplace number slot nb_inplace_remainder available for this type.
4036
4037 {
4038 binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder;
4039 binaryfunc slot2 = NULL;
4040
4041 if (!(0)) {
4042 // Different types, need to consider second value slot.
4043
4044 slot2 = PyUnicode_Type.tp_as_number->nb_remainder;
4045 }
4046
4047 if (slot1 != NULL) {
4048 PyObject *x = slot1(*operand1, operand2);
4049
4050 if (x != Py_NotImplemented) {
4051 obj_result = x;
4052 goto exit_inplace_result_object;
4053 }
4054
4055 Py_DECREF_IMMORTAL(x);
4056 }
4057
4058 if (slot2 != NULL) {
4059 PyObject *x = slot2(*operand1, operand2);
4060
4061 if (x != Py_NotImplemented) {
4062 obj_result = x;
4063 goto exit_inplace_result_object;
4064 }
4065
4066 Py_DECREF_IMMORTAL(x);
4067 }
4068
4069 // Statically recognized that coercion is not possible with these types
4070
4071 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'bytes' and 'str'");
4072 goto exit_inplace_exception;
4073 }
4074
4075exit_inplace_result_object:
4076 if (unlikely(obj_result == NULL)) {
4077 return false;
4078 }
4079
4080 // We got an object handed, that we have to release.
4081 Py_DECREF(*operand1);
4082
4083 // That's our return value then. As we use a dedicated variable, it's
4084 // OK that way.
4085 *operand1 = obj_result;
4086
4087 return true;
4088
4089exit_inplace_exception:
4090 return false;
4091}
4092
4093bool INPLACE_OPERATION_MOD_BYTES_UNICODE(PyObject **operand1, PyObject *operand2) {
4094 return _INPLACE_OPERATION_MOD_BYTES_UNICODE(operand1, operand2);
4095}
4096#endif
4097
4098#if PYTHON_VERSION >= 0x300
4099/* Code referring to "BYTES" corresponds to Python3 'bytes' and "TUPLE" to Python 'tuple'. */
4100static inline bool _INPLACE_OPERATION_MOD_BYTES_TUPLE(PyObject **operand1, PyObject *operand2) {
4101 assert(operand1); // Pointer must be non-null.
4102
4103 CHECK_OBJECT(*operand1);
4104 assert(PyBytes_CheckExact(*operand1));
4105 CHECK_OBJECT(operand2);
4106 assert(PyTuple_CheckExact(operand2));
4107
4108#if defined(_MSC_VER)
4109#pragma warning(push)
4110#pragma warning(disable : 4101)
4111#endif
4112 NUITKA_MAY_BE_UNUSED bool cbool_result;
4113 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4114#if defined(_MSC_VER)
4115#pragma warning(pop)
4116#endif
4117
4118 // No inplace number slot nb_inplace_remainder available for this type.
4119
4120 {
4121 binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder;
4122
4123 if (slot1 != NULL) {
4124 PyObject *x = slot1(*operand1, operand2);
4125
4126 if (x != Py_NotImplemented) {
4127 obj_result = x;
4128 goto exit_inplace_result_object;
4129 }
4130
4131 Py_DECREF_IMMORTAL(x);
4132 }
4133
4134 // Statically recognized that coercion is not possible with these types
4135
4136 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'bytes' and 'tuple'");
4137 goto exit_inplace_exception;
4138 }
4139
4140exit_inplace_result_object:
4141 if (unlikely(obj_result == NULL)) {
4142 return false;
4143 }
4144
4145 // We got an object handed, that we have to release.
4146 Py_DECREF(*operand1);
4147
4148 // That's our return value then. As we use a dedicated variable, it's
4149 // OK that way.
4150 *operand1 = obj_result;
4151
4152 return true;
4153
4154exit_inplace_exception:
4155 return false;
4156}
4157
4158bool INPLACE_OPERATION_MOD_BYTES_TUPLE(PyObject **operand1, PyObject *operand2) {
4159 return _INPLACE_OPERATION_MOD_BYTES_TUPLE(operand1, operand2);
4160}
4161#endif
4162
4163#if PYTHON_VERSION >= 0x300
4164/* Code referring to "BYTES" corresponds to Python3 'bytes' and "LIST" to Python 'list'. */
4165static inline bool _INPLACE_OPERATION_MOD_BYTES_LIST(PyObject **operand1, PyObject *operand2) {
4166 assert(operand1); // Pointer must be non-null.
4167
4168 CHECK_OBJECT(*operand1);
4169 assert(PyBytes_CheckExact(*operand1));
4170 CHECK_OBJECT(operand2);
4171 assert(PyList_CheckExact(operand2));
4172
4173#if defined(_MSC_VER)
4174#pragma warning(push)
4175#pragma warning(disable : 4101)
4176#endif
4177 NUITKA_MAY_BE_UNUSED bool cbool_result;
4178 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4179#if defined(_MSC_VER)
4180#pragma warning(pop)
4181#endif
4182
4183 // No inplace number slot nb_inplace_remainder available for this type.
4184
4185 {
4186 binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder;
4187
4188 if (slot1 != NULL) {
4189 PyObject *x = slot1(*operand1, operand2);
4190
4191 if (x != Py_NotImplemented) {
4192 obj_result = x;
4193 goto exit_inplace_result_object;
4194 }
4195
4196 Py_DECREF_IMMORTAL(x);
4197 }
4198
4199 // Statically recognized that coercion is not possible with these types
4200
4201 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'bytes' and 'list'");
4202 goto exit_inplace_exception;
4203 }
4204
4205exit_inplace_result_object:
4206 if (unlikely(obj_result == NULL)) {
4207 return false;
4208 }
4209
4210 // We got an object handed, that we have to release.
4211 Py_DECREF(*operand1);
4212
4213 // That's our return value then. As we use a dedicated variable, it's
4214 // OK that way.
4215 *operand1 = obj_result;
4216
4217 return true;
4218
4219exit_inplace_exception:
4220 return false;
4221}
4222
4223bool INPLACE_OPERATION_MOD_BYTES_LIST(PyObject **operand1, PyObject *operand2) {
4224 return _INPLACE_OPERATION_MOD_BYTES_LIST(operand1, operand2);
4225}
4226#endif
4227
4228#if PYTHON_VERSION >= 0x300
4229/* Code referring to "BYTES" corresponds to Python3 'bytes' and "DICT" to Python 'dict'. */
4230static inline bool _INPLACE_OPERATION_MOD_BYTES_DICT(PyObject **operand1, PyObject *operand2) {
4231 assert(operand1); // Pointer must be non-null.
4232
4233 CHECK_OBJECT(*operand1);
4234 assert(PyBytes_CheckExact(*operand1));
4235 CHECK_OBJECT(operand2);
4236 assert(PyDict_CheckExact(operand2));
4237
4238#if defined(_MSC_VER)
4239#pragma warning(push)
4240#pragma warning(disable : 4101)
4241#endif
4242 NUITKA_MAY_BE_UNUSED bool cbool_result;
4243 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4244#if defined(_MSC_VER)
4245#pragma warning(pop)
4246#endif
4247
4248 // No inplace number slot nb_inplace_remainder available for this type.
4249
4250 {
4251 binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder;
4252
4253 if (slot1 != NULL) {
4254 PyObject *x = slot1(*operand1, operand2);
4255
4256 if (x != Py_NotImplemented) {
4257 obj_result = x;
4258 goto exit_inplace_result_object;
4259 }
4260
4261 Py_DECREF_IMMORTAL(x);
4262 }
4263
4264 // Statically recognized that coercion is not possible with these types
4265
4266 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'bytes' and 'dict'");
4267 goto exit_inplace_exception;
4268 }
4269
4270exit_inplace_result_object:
4271 if (unlikely(obj_result == NULL)) {
4272 return false;
4273 }
4274
4275 // We got an object handed, that we have to release.
4276 Py_DECREF(*operand1);
4277
4278 // That's our return value then. As we use a dedicated variable, it's
4279 // OK that way.
4280 *operand1 = obj_result;
4281
4282 return true;
4283
4284exit_inplace_exception:
4285 return false;
4286}
4287
4288bool INPLACE_OPERATION_MOD_BYTES_DICT(PyObject **operand1, PyObject *operand2) {
4289 return _INPLACE_OPERATION_MOD_BYTES_DICT(operand1, operand2);
4290}
4291#endif
4292
4293#if PYTHON_VERSION >= 0x300
4294/* Code referring to "BYTES" corresponds to Python3 'bytes' and "OBJECT" to any Python object. */
4295static HEDLEY_NEVER_INLINE bool __INPLACE_OPERATION_MOD_BYTES_OBJECT(PyObject **operand1, PyObject *operand2) {
4296 PyTypeObject *type2 = Py_TYPE(operand2);
4297
4298#if defined(_MSC_VER)
4299#pragma warning(push)
4300#pragma warning(disable : 4101)
4301#endif
4302 NUITKA_MAY_BE_UNUSED bool cbool_result;
4303 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4304#if defined(_MSC_VER)
4305#pragma warning(pop)
4306#endif
4307
4308 // No inplace number slot nb_inplace_remainder available for this type.
4309
4310 {
4311 binaryfunc slot1 = PyBytes_Type.tp_as_number->nb_remainder;
4312 binaryfunc slot2 = NULL;
4313
4314 if (!(&PyBytes_Type == type2)) {
4315 // Different types, need to consider second value slot.
4316
4317 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder
4318 : NULL;
4319
4320 if (slot1 == slot2) {
4321 slot2 = NULL;
4322 }
4323 }
4324
4325 if (slot1 != NULL) {
4326 if (slot2 != NULL) {
4327 if (Nuitka_Type_IsSubtype(type2, &PyBytes_Type)) {
4328 PyObject *x = slot2(*operand1, operand2);
4329
4330 if (x != Py_NotImplemented) {
4331 obj_result = x;
4332 goto exit_inplace_result_object;
4333 }
4334
4335 Py_DECREF_IMMORTAL(x);
4336 slot2 = NULL;
4337 }
4338 }
4339
4340 PyObject *x = slot1(*operand1, operand2);
4341
4342 if (x != Py_NotImplemented) {
4343 obj_result = x;
4344 goto exit_inplace_result_object;
4345 }
4346
4347 Py_DECREF_IMMORTAL(x);
4348 }
4349
4350 if (slot2 != NULL) {
4351 PyObject *x = slot2(*operand1, operand2);
4352
4353 if (x != Py_NotImplemented) {
4354 obj_result = x;
4355 goto exit_inplace_result_object;
4356 }
4357
4358 Py_DECREF_IMMORTAL(x);
4359 }
4360
4361#if PYTHON_VERSION < 0x300
4362 if (!0 || !NEW_STYLE_NUMBER_TYPE(type2)) {
4363 coercion c2 =
4364 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
4365
4366 if (c2 != NULL) {
4367 PyObject *coerced1 = *operand1;
4368 PyObject *coerced2 = operand2;
4369
4370 int err = c2(&coerced2, &coerced1);
4371
4372 if (unlikely(err < 0)) {
4373 goto exit_inplace_exception;
4374 }
4375
4376 if (err == 0) {
4377 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
4378
4379 if (likely(mv == NULL)) {
4380 binaryfunc slot = mv->nb_remainder;
4381
4382 if (likely(slot != NULL)) {
4383 PyObject *x = slot(coerced1, coerced2);
4384
4385 Py_DECREF(coerced1);
4386 Py_DECREF(coerced2);
4387
4388 obj_result = x;
4389 goto exit_inplace_result_object;
4390 }
4391 }
4392
4393 // nb_coerce took a reference.
4394 Py_DECREF(coerced1);
4395 Py_DECREF(coerced2);
4396 }
4397 }
4398 }
4399#endif
4400
4401 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: 'bytes' and '%s'", type2->tp_name);
4402 goto exit_inplace_exception;
4403 }
4404
4405exit_inplace_result_object:
4406 if (unlikely(obj_result == NULL)) {
4407 return false;
4408 }
4409
4410 // We got an object handed, that we have to release.
4411 Py_DECREF(*operand1);
4412
4413 // That's our return value then. As we use a dedicated variable, it's
4414 // OK that way.
4415 *operand1 = obj_result;
4416
4417 return true;
4418
4419exit_inplace_exception:
4420 return false;
4421}
4422static inline bool _INPLACE_OPERATION_MOD_BYTES_OBJECT(PyObject **operand1, PyObject *operand2) {
4423 assert(operand1); // Pointer must be non-null.
4424
4425 CHECK_OBJECT(*operand1);
4426 assert(PyBytes_CheckExact(*operand1));
4427 CHECK_OBJECT(operand2);
4428
4429 PyTypeObject *type2 = Py_TYPE(operand2);
4430
4431 if (&PyBytes_Type == type2) {
4432 // return _BINARY_OPERATION_MOD_BYTES_BYTES_INPLACE(operand1, operand2);
4433
4434 // Not every code path will make use of all possible results.
4435 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4436
4437 PyObject *x = PyBytes_Type.tp_as_number->nb_remainder(*operand1, operand2);
4438 assert(x != Py_NotImplemented);
4439
4440 obj_result = x;
4441 goto exit_result_object;
4442
4443 exit_result_object:
4444 if (unlikely(obj_result == NULL)) {
4445 goto exit_result_exception;
4446 }
4447 // We got an object handed, that we have to release.
4448 Py_DECREF(*operand1);
4449
4450 *operand1 = obj_result;
4451 goto exit_result_ok;
4452
4453 exit_result_ok:
4454 return true;
4455
4456 exit_result_exception:
4457 return false;
4458 }
4459
4460 return __INPLACE_OPERATION_MOD_BYTES_OBJECT(operand1, operand2);
4461}
4462
4463bool INPLACE_OPERATION_MOD_BYTES_OBJECT(PyObject **operand1, PyObject *operand2) {
4464 return _INPLACE_OPERATION_MOD_BYTES_OBJECT(operand1, operand2);
4465}
4466#endif
4467
4468/* Code referring to "OBJECT" corresponds to any Python object and "OBJECT" to any Python object. */
4469static inline bool _INPLACE_OPERATION_MOD_OBJECT_OBJECT(PyObject **operand1, PyObject *operand2) {
4470 assert(operand1); // Pointer must be non-null.
4471
4472 CHECK_OBJECT(*operand1);
4473 CHECK_OBJECT(operand2);
4474
4475#if PYTHON_VERSION < 0x300
4476 if (PyInt_CheckExact(*operand1) && PyInt_CheckExact(operand2)) {
4477
4478 // Not every code path will make use of all possible results.
4479#if defined(_MSC_VER)
4480#pragma warning(push)
4481#pragma warning(disable : 4101)
4482#endif
4483 NUITKA_MAY_BE_UNUSED bool cbool_result;
4484 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4485 NUITKA_MAY_BE_UNUSED long clong_result;
4486 NUITKA_MAY_BE_UNUSED double cfloat_result;
4487#if defined(_MSC_VER)
4488#pragma warning(pop)
4489#endif
4490
4491 CHECK_OBJECT(*operand1);
4492 assert(PyInt_CheckExact(*operand1));
4493 CHECK_OBJECT(operand2);
4494 assert(PyInt_CheckExact(operand2));
4495
4496 const long a = PyInt_AS_LONG(*operand1);
4497 const long b = PyInt_AS_LONG(operand2);
4498
4499 /* TODO: Isn't this a very specific value only, of which we could
4500 * hardcode the constant result. Not sure how well the C compiler
4501 * optimizes UNARY_NEG_WOULD_OVERFLOW to this, but dividing by
4502 * -1 has to be rare anyway.
4503 */
4504
4505 if (likely(b != -1 || !UNARY_NEG_WOULD_OVERFLOW(a))) {
4506 long r = a % b;
4507
4508 // Sign handling.
4509 if (r != 0 && ((b ^ r) < 0)) {
4510 r += b;
4511 }
4512
4513 clong_result = r;
4514 goto exit_result_ok_clong;
4515 }
4516
4517 {
4518 PyObject *operand1_object = *operand1;
4519 PyObject *operand2_object = operand2;
4520
4521 PyObject *r = PyLong_Type.tp_as_number->nb_remainder(operand1_object, operand2_object);
4522 assert(r != Py_NotImplemented);
4523
4524 obj_result = r;
4525 goto exit_result_object;
4526 }
4527
4528 exit_result_ok_clong:
4529
4530 // We got an object handed, that we have to release.
4531 Py_DECREF(*operand1);
4532
4533 // That's our return value then. As we use a dedicated variable, it's
4534 // OK that way.
4535 *operand1 = Nuitka_PyInt_FromLong(clong_result);
4536 goto exit_result_ok;
4537
4538 exit_result_object:
4539 if (unlikely(obj_result == NULL)) {
4540 goto exit_result_exception;
4541 }
4542 // We got an object handed, that we have to release.
4543 Py_DECREF(*operand1);
4544
4545 *operand1 = obj_result;
4546 goto exit_result_ok;
4547
4548 exit_result_ok:
4549 return true;
4550
4551 exit_result_exception:
4552 return false;
4553 }
4554#endif
4555
4556 if (Py_TYPE(*operand1) == Py_TYPE(operand2)) {
4557 if (PyFloat_CheckExact(operand2)) {
4558 return _INPLACE_OPERATION_MOD_FLOAT_FLOAT(operand1, operand2);
4559 }
4560#if PYTHON_VERSION >= 0x300
4561 if (PyLong_CheckExact(operand2)) {
4562 return _INPLACE_OPERATION_MOD_LONG_LONG(operand1, operand2);
4563 }
4564#endif
4565 }
4566
4567 PyTypeObject *type1 = Py_TYPE(*operand1);
4568 PyTypeObject *type2 = Py_TYPE(operand2);
4569
4570#if defined(_MSC_VER)
4571#pragma warning(push)
4572#pragma warning(disable : 4101)
4573#endif
4574 NUITKA_MAY_BE_UNUSED bool cbool_result;
4575 NUITKA_MAY_BE_UNUSED PyObject *obj_result;
4576#if defined(_MSC_VER)
4577#pragma warning(pop)
4578#endif
4579
4580 binaryfunc islot = (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1))
4581 ? type1->tp_as_number->nb_inplace_remainder
4582 : NULL;
4583
4584 if (islot != NULL) {
4585 PyObject *x = islot(*operand1, operand2);
4586
4587 if (x != Py_NotImplemented) {
4588 obj_result = x;
4589 goto exit_inplace_result_object;
4590 }
4591
4592 Py_DECREF_IMMORTAL(x);
4593 }
4594
4595 {
4596 binaryfunc slot1 =
4597 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_remainder : NULL;
4598 binaryfunc slot2 = NULL;
4599
4600 if (!(type1 == type2)) {
4601 // Different types, need to consider second value slot.
4602
4603 slot2 = (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_remainder
4604 : NULL;
4605
4606 if (slot1 == slot2) {
4607 slot2 = NULL;
4608 }
4609 }
4610
4611 if (slot1 != NULL) {
4612 if (slot2 != NULL) {
4613 if (Nuitka_Type_IsSubtype(type2, type1)) {
4614 PyObject *x = slot2(*operand1, operand2);
4615
4616 if (x != Py_NotImplemented) {
4617 obj_result = x;
4618 goto exit_inplace_result_object;
4619 }
4620
4621 Py_DECREF_IMMORTAL(x);
4622 slot2 = NULL;
4623 }
4624 }
4625
4626 PyObject *x = slot1(*operand1, operand2);
4627
4628 if (x != Py_NotImplemented) {
4629 obj_result = x;
4630 goto exit_inplace_result_object;
4631 }
4632
4633 Py_DECREF_IMMORTAL(x);
4634 }
4635
4636 if (slot2 != NULL) {
4637 PyObject *x = slot2(*operand1, operand2);
4638
4639 if (x != Py_NotImplemented) {
4640 obj_result = x;
4641 goto exit_inplace_result_object;
4642 }
4643
4644 Py_DECREF_IMMORTAL(x);
4645 }
4646
4647#if PYTHON_VERSION < 0x300
4648 if (!NEW_STYLE_NUMBER_TYPE(type1) || !NEW_STYLE_NUMBER_TYPE(type2)) {
4649 coercion c1 =
4650 (type1->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type1)) ? type1->tp_as_number->nb_coerce : NULL;
4651
4652 if (c1 != NULL) {
4653 PyObject *coerced1 = *operand1;
4654 PyObject *coerced2 = operand2;
4655
4656 int err = c1(&coerced1, &coerced2);
4657
4658 if (unlikely(err < 0)) {
4659 goto exit_inplace_exception;
4660 }
4661
4662 if (err == 0) {
4663 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
4664
4665 if (likely(mv == NULL)) {
4666 binaryfunc slot = mv->nb_remainder;
4667
4668 if (likely(slot != NULL)) {
4669 PyObject *x = slot(coerced1, coerced2);
4670
4671 Py_DECREF(coerced1);
4672 Py_DECREF(coerced2);
4673
4674 obj_result = x;
4675 goto exit_inplace_result_object;
4676 }
4677 }
4678
4679 // nb_coerce took a reference.
4680 Py_DECREF(coerced1);
4681 Py_DECREF(coerced2);
4682 }
4683 }
4684 coercion c2 =
4685 (type2->tp_as_number != NULL && NEW_STYLE_NUMBER_TYPE(type2)) ? type2->tp_as_number->nb_coerce : NULL;
4686
4687 if (c2 != NULL) {
4688 PyObject *coerced1 = *operand1;
4689 PyObject *coerced2 = operand2;
4690
4691 int err = c2(&coerced2, &coerced1);
4692
4693 if (unlikely(err < 0)) {
4694 goto exit_inplace_exception;
4695 }
4696
4697 if (err == 0) {
4698 PyNumberMethods *mv = Py_TYPE(coerced1)->tp_as_number;
4699
4700 if (likely(mv == NULL)) {
4701 binaryfunc slot = mv->nb_remainder;
4702
4703 if (likely(slot != NULL)) {
4704 PyObject *x = slot(coerced1, coerced2);
4705
4706 Py_DECREF(coerced1);
4707 Py_DECREF(coerced2);
4708
4709 obj_result = x;
4710 goto exit_inplace_result_object;
4711 }
4712 }
4713
4714 // nb_coerce took a reference.
4715 Py_DECREF(coerced1);
4716 Py_DECREF(coerced2);
4717 }
4718 }
4719 }
4720#endif
4721
4722 PyErr_Format(PyExc_TypeError, "unsupported operand type(s) for %%=: '%s' and '%s'", type1->tp_name,
4723 type2->tp_name);
4724 goto exit_inplace_exception;
4725 }
4726
4727exit_inplace_result_object:
4728 if (unlikely(obj_result == NULL)) {
4729 return false;
4730 }
4731
4732 // We got an object handed, that we have to release.
4733 Py_DECREF(*operand1);
4734
4735 // That's our return value then. As we use a dedicated variable, it's
4736 // OK that way.
4737 *operand1 = obj_result;
4738
4739 return true;
4740
4741exit_inplace_exception:
4742 return false;
4743}
4744
4745bool INPLACE_OPERATION_MOD_OBJECT_OBJECT(PyObject **operand1, PyObject *operand2) {
4746 return _INPLACE_OPERATION_MOD_OBJECT_OBJECT(operand1, operand2);
4747}
4748
4749// Part of "Nuitka", an optimizing Python compiler that is compatible and
4750// integrates with CPython, but also works on its own.
4751//
4752// Licensed under the Apache License, Version 2.0 (the "License");
4753// you may not use this file except in compliance with the License.
4754// You may obtain a copy of the License at
4755//
4756// http://www.apache.org/licenses/LICENSE-2.0
4757//
4758// Unless required by applicable law or agreed to in writing, software
4759// distributed under the License is distributed on an "AS IS" BASIS,
4760// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4761// See the License for the specific language governing permissions and
4762// limitations under the License.