// Tuple primitive operations // // These are registered in mypyc.primitives.tuple_ops. #include #include "CPy.h" PyObject *CPySequenceTuple_GetItem(PyObject *tuple, CPyTagged index) { if (CPyTagged_CheckShort(index)) { Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); Py_ssize_t size = PyTuple_GET_SIZE(tuple); if (n >= 0) { if (n >= size) { PyErr_SetString(PyExc_IndexError, "tuple index out of range"); return NULL; } } else { n += size; if (n < 0) { PyErr_SetString(PyExc_IndexError, "tuple index out of range"); return NULL; } } PyObject *result = PyTuple_GET_ITEM(tuple, n); Py_INCREF(result); return result; } else { PyErr_SetString(PyExc_OverflowError, CPYTHON_LARGE_INT_ERRMSG); return NULL; } } PyObject *CPySequenceTuple_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end) { if (likely(PyTuple_CheckExact(obj) && CPyTagged_CheckShort(start) && CPyTagged_CheckShort(end))) { Py_ssize_t startn = CPyTagged_ShortAsSsize_t(start); Py_ssize_t endn = CPyTagged_ShortAsSsize_t(end); if (startn < 0) { startn += PyTuple_GET_SIZE(obj); } if (endn < 0) { endn += PyTuple_GET_SIZE(obj); } return PyTuple_GetSlice(obj, startn, endn); } return CPyObject_GetSlice(obj, start, end); } // PyTuple_SET_ITEM does no error checking, // and should only be used to fill in brand new tuples. bool CPySequenceTuple_SetItemUnsafe(PyObject *tuple, CPyTagged index, PyObject *value) { if (CPyTagged_CheckShort(index)) { Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); PyTuple_SET_ITEM(tuple, n, value); return true; } else { PyErr_SetString(PyExc_OverflowError, CPYTHON_LARGE_INT_ERRMSG); return false; } }