3#ifndef __NUITKA_HELPER_SUBSCRIPTS_H__
4#define __NUITKA_HELPER_SUBSCRIPTS_H__
6extern PyObject *STRING_FROM_CHAR(
unsigned char c);
8#if PYTHON_VERSION >= 0x3b0
9static void formatNotSubscriptableTypeError(PyObject *type) {
10 SET_CURRENT_EXCEPTION_TYPE0_FORMAT1(PyExc_TypeError,
"type '%s' is not subscriptable",
11 ((PyTypeObject *)type)->tp_name);
15#if !defined(_NUITKA_EXPERIMENTAL_DISABLE_SUBSCRIPT_OPT)
16static void formatNotSubscriptableError(PyObject *source) {
17 SET_CURRENT_EXCEPTION_TYPE_COMPLAINT(
18#
if PYTHON_VERSION < 0x270
19 "'%s' object is unsubscriptable",
20#elif PYTHON_VERSION <= 0x272
21 "'%s' object is not subscriptable",
22#elif PYTHON_VERSION < 0x300
23 "'%s' object has no attribute '__getitem__'",
25 "'%s' object is not subscriptable",
31#if PYTHON_VERSION < 0x370
32#define HAS_SEQUENCE_ITEM_SLOT(type) (type->tp_as_sequence != NULL)
34#define HAS_SEQUENCE_ITEM_SLOT(type) (type->tp_as_sequence != NULL && type->tp_as_sequence->sq_item)
37#if !defined(_NUITKA_EXPERIMENTAL_DISABLE_SUBSCRIPT_OPT)
38static PyObject *SEQUENCE_GET_ITEM_CONST(PyObject *sequence, Py_ssize_t int_subscript) {
39 PySequenceMethods *tp_as_sequence = Py_TYPE(sequence)->tp_as_sequence;
40 assert(tp_as_sequence != NULL);
42#if PYTHON_VERSION < 0x370
43 if (unlikely(tp_as_sequence->sq_item == NULL)) {
44 PyErr_Format(PyExc_TypeError,
"'%s' object does not support indexing", Py_TYPE(sequence)->tp_name);
49 if (int_subscript < 0) {
50 if (tp_as_sequence->sq_length) {
51 Py_ssize_t length = (*tp_as_sequence->sq_length)(sequence);
56 int_subscript += length;
60 PyObject *res = tp_as_sequence->sq_item(sequence, int_subscript);
65NUITKA_MAY_BE_UNUSED
static PyObject *LOOKUP_SUBSCRIPT_CONST(PyThreadState *tstate, PyObject *source,
66 PyObject *const_subscript, Py_ssize_t int_subscript) {
68 CHECK_OBJECT(const_subscript);
70#if _NUITKA_EXPERIMENTAL_DISABLE_SUBSCRIPT_OPT
71 return PyObject_GetItem(source, const_subscript);
73 PyTypeObject *type = Py_TYPE(source);
74 PyMappingMethods *tp_as_mapping = type->tp_as_mapping;
78 if (tp_as_mapping && tp_as_mapping->mp_subscript) {
79 if (PyList_CheckExact(source)) {
80 Py_ssize_t list_size = PyList_GET_SIZE(source);
82 if (int_subscript < 0) {
83 if (-int_subscript > list_size) {
84 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_IndexError,
"list index out of range");
88 int_subscript += list_size;
90 if (int_subscript >= list_size) {
91 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_IndexError,
"list index out of range");
96 result = ((PyListObject *)source)->ob_item[int_subscript];
101#if PYTHON_VERSION < 0x300
102 else if (PyString_CheckExact(source)) {
103 Py_ssize_t string_size = PyString_GET_SIZE(source);
105 if (int_subscript < 0) {
106 if (-int_subscript > string_size) {
107 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_IndexError,
"string index out of range");
111 int_subscript += string_size;
113 if (int_subscript >= string_size) {
114 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_IndexError,
"string index out of range");
119 unsigned char c = ((PyStringObject *)source)->ob_sval[int_subscript];
120 return STRING_FROM_CHAR(c);
123 else if (PyUnicode_CheckExact(source)) {
124 if (int_subscript < 0) {
125 int_subscript += PyUnicode_GET_LENGTH(source);
128 result = type->tp_as_sequence->sq_item(source, int_subscript);
132 result = tp_as_mapping->mp_subscript(source, const_subscript);
134 }
else if (HAS_SEQUENCE_ITEM_SLOT(type)) {
135 result = SEQUENCE_GET_ITEM_CONST(source, int_subscript);
137#if PYTHON_VERSION >= 0x370
138 if (PyType_Check(source)) {
139#if PYTHON_VERSION >= 0x390
140 if (source == (PyObject *)&PyType_Type) {
141 PyObject *subscript = PyLong_FromSsize_t(int_subscript);
142 result = Py_GenericAlias(source, subscript);
143 Py_DECREF(subscript);
149 PyObject *meth = LOOKUP_ATTRIBUTE(tstate, source, const_str_plain___class_getitem__);
152 PyObject *subscript = PyLong_FromSsize_t(int_subscript);
153 result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, meth, subscript);
155 Py_DECREF(subscript);
161#if PYTHON_VERSION >= 0x3b0
162 formatNotSubscriptableTypeError(source);
168 formatNotSubscriptableError(source);
172 if (unlikely(result == NULL)) {
180NUITKA_MAY_BE_UNUSED
static PyObject *LOOKUP_SUBSCRIPT(PyThreadState *tstate, PyObject *source, PyObject *subscript) {
181 CHECK_OBJECT(source);
182 CHECK_OBJECT(subscript);
184#if _NUITKA_EXPERIMENTAL_DISABLE_SUBSCRIPT_OPT
185 return PyObject_GetItem(source, subscript);
187 PyTypeObject *type = Py_TYPE(source);
188 PyMappingMethods *tp_as_mapping = type->tp_as_mapping;
190 if (tp_as_mapping != NULL && tp_as_mapping->mp_subscript != NULL) {
191 return tp_as_mapping->mp_subscript(source, subscript);
192 }
else if (HAS_SEQUENCE_ITEM_SLOT(type)) {
193 if (Nuitka_Index_Check(subscript)) {
194 Py_ssize_t index = PyNumber_AsSsize_t(subscript, NULL);
196 if (index == -1 && HAS_ERROR_OCCURRED(tstate)) {
200 return SEQUENCE_GET_ITEM_CONST(source, index);
201 }
else if (type->tp_as_sequence->sq_item) {
202 PyErr_Format(PyExc_TypeError,
"sequence index must be integer, not '%s'", Py_TYPE(subscript)->tp_name);
204#if PYTHON_VERSION < 0x370
206 formatNotSubscriptableError(source);
212#if PYTHON_VERSION >= 0x370
213 if (PyType_Check(source)) {
214#if PYTHON_VERSION >= 0x390
215 if (source == (PyObject *)&PyType_Type) {
216 return Py_GenericAlias(source, subscript);
220 PyObject *meth = LOOKUP_ATTRIBUTE(tstate, source, const_str_plain___class_getitem__);
223 PyObject *result = CALL_FUNCTION_WITH_SINGLE_ARG(tstate, meth, subscript);
229#if PYTHON_VERSION >= 0x3b0
230 formatNotSubscriptableTypeError(source);
236 formatNotSubscriptableError(source);
241bool MATCH_MAPPING_KEY(PyThreadState *tstate, PyObject *map, PyObject *key);
243NUITKA_MAY_BE_UNUSED
static bool SET_SUBSCRIPT_CONST(PyThreadState *tstate, PyObject *target, PyObject *subscript,
244 Py_ssize_t int_subscript, PyObject *value) {
246 CHECK_OBJECT(target);
247 CHECK_OBJECT(subscript);
249#if _NUITKA_EXPERIMENTAL_DISABLE_SUBSCRIPT_OPT
250 int res = PyObject_SetItem(target, subscript, value);
253 PyMappingMethods *tp_as_mapping = Py_TYPE(target)->tp_as_mapping;
255 if (tp_as_mapping != NULL && tp_as_mapping->mp_ass_subscript) {
256 if (PyList_CheckExact(target)) {
257 Py_ssize_t list_size = PyList_GET_SIZE(target);
259 if (int_subscript < 0) {
260 if (-int_subscript > list_size) {
261 SET_CURRENT_EXCEPTION_TYPE0_STR(tstate, PyExc_IndexError,
"list assignment index out of range");
266 int_subscript += list_size;
269 PyListObject *target_list = (PyListObject *)target;
271 PyObject *old_value = target_list->ob_item[int_subscript];
273 target_list->ob_item[int_subscript] = value;
274 Py_DECREF(old_value);
278 int res = tp_as_mapping->mp_ass_subscript(target, subscript, value);
280 if (unlikely(res == -1)) {
286 }
else if (Py_TYPE(target)->tp_as_sequence) {
287 if (Nuitka_Index_Check(subscript)) {
288 Py_ssize_t key_value = PyNumber_AsSsize_t(subscript, PyExc_IndexError);
290 if (key_value == -1) {
291 if (HAS_ERROR_OCCURRED(tstate)) {
296 return SEQUENCE_SET_ITEM(target, key_value, value);
297 }
else if (Py_TYPE(target)->tp_as_sequence->sq_ass_item) {
298 PyErr_Format(PyExc_TypeError,
"sequence index must be integer, not '%s'", Py_TYPE(subscript)->tp_name);
302 PyErr_Format(PyExc_TypeError,
"'%s' object does not support item assignment", Py_TYPE(target)->tp_name);
307 PyErr_Format(PyExc_TypeError,
"'%s' object does not support item assignment", Py_TYPE(target)->tp_name);
314NUITKA_MAY_BE_UNUSED
static bool SET_SUBSCRIPT(PyThreadState *tstate, PyObject *target, PyObject *subscript,
317 CHECK_OBJECT(target);
318 CHECK_OBJECT(subscript);
320#if _NUITKA_EXPERIMENTAL_DISABLE_SUBSCRIPT_OPT
321 int res = PyObject_SetItem(target, subscript, value);
324 PyMappingMethods *tp_as_mapping = Py_TYPE(target)->tp_as_mapping;
326 if (tp_as_mapping != NULL && tp_as_mapping->mp_ass_subscript) {
327 int res = tp_as_mapping->mp_ass_subscript(target, subscript, value);
329 if (unlikely(res == -1)) {
332 }
else if (Py_TYPE(target)->tp_as_sequence) {
333 if (Nuitka_Index_Check(subscript)) {
334 Py_ssize_t key_value = PyNumber_AsSsize_t(subscript, PyExc_IndexError);
336 if (key_value == -1) {
337 if (HAS_ERROR_OCCURRED(tstate)) {
342 return SEQUENCE_SET_ITEM(target, key_value, value);
343 }
else if (Py_TYPE(target)->tp_as_sequence->sq_ass_item) {
344 PyErr_Format(PyExc_TypeError,
"sequence index must be integer, not '%s'", Py_TYPE(subscript)->tp_name);
348 PyErr_Format(PyExc_TypeError,
"'%s' object does not support item assignment", Py_TYPE(target)->tp_name);
353 PyErr_Format(PyExc_TypeError,
"'%s' object does not support item assignment", Py_TYPE(target)->tp_name);
362NUITKA_MAY_BE_UNUSED
static bool DEL_SUBSCRIPT(PyObject *target, PyObject *subscript) {
363 CHECK_OBJECT(target);
364 CHECK_OBJECT(subscript);
366 int status = PyObject_DelItem(target, subscript);
368 if (unlikely(status == -1)) {