1 //     Copyright 2021, Kay Hayen, mailto:kay.hayen@gmail.com
2 //
3 //     Part of "Nuitka", an optimizing Python compiler that is compatible and
4 //     integrates with CPython, but also works on its own.
5 //
6 //     Licensed under the Apache License, Version 2.0 (the "License");
7 //     you may not use this file except in compliance with the License.
8 //     You may obtain a copy of the License at
9 //
10 //        http://www.apache.org/licenses/LICENSE-2.0
11 //
12 //     Unless required by applicable law or agreed to in writing, software
13 //     distributed under the License is distributed on an "AS IS" BASIS,
14 //     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 //     See the License for the specific language governing permissions and
16 //     limitations under the License.
17 //
18 #ifndef __NUITKA_OPERATIONS_H__
19 #define __NUITKA_OPERATIONS_H__
20 
21 #if PYTHON_VERSION >= 0x300
22 extern PyObject *UNICODE_CONCAT(PyObject *left, PyObject *right);
23 extern bool UNICODE_APPEND(PyObject **p_left, PyObject *right);
24 #else
25 // TODO: Specialize for Python2 too.
UNICODE_CONCAT(PyObject * left,PyObject * right)26 NUITKA_MAY_BE_UNUSED static PyObject *UNICODE_CONCAT(PyObject *left, PyObject *right) {
27     return PyUnicode_Concat(left, right);
28 }
29 #endif
30 
31 // This macro is necessary for Python2 to determine if the "coerce" slot
32 // will have to be considered or not, and if in-place operations are
33 // allowed to be there or not.
34 #if PYTHON_VERSION < 0x300
35 #define NEW_STYLE_NUMBER(o) PyType_HasFeature(Py_TYPE(o), Py_TPFLAGS_CHECKTYPES)
36 #define NEW_STYLE_NUMBER_TYPE(t) PyType_HasFeature(t, Py_TPFLAGS_CHECKTYPES)
37 #define CAN_HAVE_INPLACE(t) PyType_HasFeature(t, Py_TPFLAGS_HAVE_INPLACEOPS)
38 #else
39 #define NEW_STYLE_NUMBER(o) (true)
40 #define NEW_STYLE_NUMBER_TYPE(t) (true)
41 #define CAN_HAVE_INPLACE(t) (true)
42 #endif
43 
44 typedef PyObject *(unary_api)(PyObject *);
45 
UNARY_OPERATION(unary_api api,PyObject * operand)46 NUITKA_MAY_BE_UNUSED static PyObject *UNARY_OPERATION(unary_api api, PyObject *operand) {
47     CHECK_OBJECT(operand);
48     PyObject *result = api(operand);
49 
50     if (unlikely(result == NULL)) {
51         return NULL;
52     }
53 
54     CHECK_OBJECT(result);
55 
56     return result;
57 }
58 
59 // Generated helpers to execute operations on fully or partially known types.
60 #include "nuitka/helper/operations_binary_add.h"
61 #include "nuitka/helper/operations_binary_bitand.h"
62 #include "nuitka/helper/operations_binary_bitor.h"
63 #include "nuitka/helper/operations_binary_bitxor.h"
64 #include "nuitka/helper/operations_binary_divmod.h"
65 #include "nuitka/helper/operations_binary_floordiv.h"
66 #include "nuitka/helper/operations_binary_lshift.h"
67 #include "nuitka/helper/operations_binary_mod.h"
68 #include "nuitka/helper/operations_binary_mult.h"
69 #include "nuitka/helper/operations_binary_pow.h"
70 #include "nuitka/helper/operations_binary_rshift.h"
71 #include "nuitka/helper/operations_binary_sub.h"
72 #include "nuitka/helper/operations_binary_truediv.h"
73 
74 #include "nuitka/helper/operations_inplace_add.h"
75 #include "nuitka/helper/operations_inplace_bitand.h"
76 #include "nuitka/helper/operations_inplace_bitor.h"
77 #include "nuitka/helper/operations_inplace_bitxor.h"
78 #include "nuitka/helper/operations_inplace_floordiv.h"
79 #include "nuitka/helper/operations_inplace_lshift.h"
80 #include "nuitka/helper/operations_inplace_mod.h"
81 #include "nuitka/helper/operations_inplace_mult.h"
82 #include "nuitka/helper/operations_inplace_pow.h"
83 #include "nuitka/helper/operations_inplace_rshift.h"
84 #include "nuitka/helper/operations_inplace_sub.h"
85 #include "nuitka/helper/operations_inplace_truediv.h"
86 
87 #if PYTHON_VERSION < 0x300
88 // Classical division is Python2 only.
89 #include "nuitka/helper/operations_binary_olddiv.h"
90 #include "nuitka/helper/operations_inplace_olddiv.h"
91 #endif
92 #if PYTHON_VERSION >= 0x350
93 // Matrix multiplication is Python3.5 or higher only.
94 #include "nuitka/helper/operations_binary_matmult.h"
95 #include "nuitka/helper/operations_inplace_matmult.h"
96 #endif
97 
98 // TODO: Get rid of the need for these, we should inline the abstract
99 // algorithms, for now we have them for easier templating.
100 #define PyNumber_InPlaceSub PyNumber_InPlaceSubtract
101 #define PyNumber_InPlaceMult PyNumber_InPlaceMultiply
102 #define PyNumber_InPlaceOlddiv PyNumber_InPlaceDivide
103 #define PyNumber_InPlacePow(a, b) PyNumber_InPlacePower(a, b, Py_None)
104 #define PyNumber_InPlaceMod PyNumber_InPlaceRemainder
105 #define PyNumber_InPlaceBitor PyNumber_InPlaceOr
106 #define PyNumber_InPlaceBitxor PyNumber_InPlaceXor
107 #define PyNumber_InPlaceBitand PyNumber_InPlaceAnd
108 #define PyNumber_InPlaceTruediv PyNumber_InPlaceTrueDivide
109 #define PyNumber_InPlaceFloordiv PyNumber_InPlaceFloorDivide
110 #define PyNumber_InPlaceMatmult PyNumber_InPlaceMatrixMultiply
111 #endif
112