• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Written by Jim Hugunin and Chris Chase.
3 
4 This includes both the singular ellipsis object and slice objects.
5 
6 Guido, feel free to do whatever you want in the way of copyrights
7 for this file.
8 */
9 
10 /*
11 Py_Ellipsis encodes the '...' rubber index token. It is similar to
12 the Py_NoneStruct in that there is no way to create other objects of
13 this type and there is exactly one in existence.
14 */
15 
16 #include "Python.h"
17 #include "pycore_abstract.h"      // _PyIndex_Check()
18 #include "pycore_long.h"          // _PyLong_GetZero()
19 #include "pycore_modsupport.h"    // _PyArg_NoKeywords()
20 #include "pycore_object.h"        // _PyObject_GC_TRACK()
21 
22 
23 static PyObject *
ellipsis_new(PyTypeObject * type,PyObject * args,PyObject * kwargs)24 ellipsis_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
25 {
26     if (PyTuple_GET_SIZE(args) || (kwargs && PyDict_GET_SIZE(kwargs))) {
27         PyErr_SetString(PyExc_TypeError, "EllipsisType takes no arguments");
28         return NULL;
29     }
30     return Py_Ellipsis;
31 }
32 
33 static void
ellipsis_dealloc(PyObject * ellipsis)34 ellipsis_dealloc(PyObject *ellipsis)
35 {
36     /* This should never get called, but we also don't want to SEGV if
37      * we accidentally decref Ellipsis out of existence. Instead,
38      * since Ellipsis is an immortal object, re-set the reference count.
39      */
40     _Py_SetImmortal(ellipsis);
41 }
42 
43 static PyObject *
ellipsis_repr(PyObject * op)44 ellipsis_repr(PyObject *op)
45 {
46     return PyUnicode_FromString("Ellipsis");
47 }
48 
49 static PyObject *
ellipsis_reduce(PyObject * op,PyObject * Py_UNUSED (ignored))50 ellipsis_reduce(PyObject *op, PyObject *Py_UNUSED(ignored))
51 {
52     return PyUnicode_FromString("Ellipsis");
53 }
54 
55 static PyMethodDef ellipsis_methods[] = {
56     {"__reduce__", ellipsis_reduce, METH_NOARGS, NULL},
57     {NULL, NULL}
58 };
59 
60 PyDoc_STRVAR(ellipsis_doc,
61 "ellipsis()\n"
62 "--\n\n"
63 "The type of the Ellipsis singleton.");
64 
65 PyTypeObject PyEllipsis_Type = {
66     PyVarObject_HEAD_INIT(&PyType_Type, 0)
67     "ellipsis",                         /* tp_name */
68     0,                                  /* tp_basicsize */
69     0,                                  /* tp_itemsize */
70     ellipsis_dealloc,                   /* tp_dealloc */
71     0,                                  /* tp_vectorcall_offset */
72     0,                                  /* tp_getattr */
73     0,                                  /* tp_setattr */
74     0,                                  /* tp_as_async */
75     ellipsis_repr,                      /* tp_repr */
76     0,                                  /* tp_as_number */
77     0,                                  /* tp_as_sequence */
78     0,                                  /* tp_as_mapping */
79     0,                                  /* tp_hash */
80     0,                                  /* tp_call */
81     0,                                  /* tp_str */
82     PyObject_GenericGetAttr,            /* tp_getattro */
83     0,                                  /* tp_setattro */
84     0,                                  /* tp_as_buffer */
85     Py_TPFLAGS_DEFAULT,                 /* tp_flags */
86     ellipsis_doc,                       /* tp_doc */
87     0,                                  /* tp_traverse */
88     0,                                  /* tp_clear */
89     0,                                  /* tp_richcompare */
90     0,                                  /* tp_weaklistoffset */
91     0,                                  /* tp_iter */
92     0,                                  /* tp_iternext */
93     ellipsis_methods,                   /* tp_methods */
94     0,                                  /* tp_members */
95     0,                                  /* tp_getset */
96     0,                                  /* tp_base */
97     0,                                  /* tp_dict */
98     0,                                  /* tp_descr_get */
99     0,                                  /* tp_descr_set */
100     0,                                  /* tp_dictoffset */
101     0,                                  /* tp_init */
102     0,                                  /* tp_alloc */
103     ellipsis_new,                       /* tp_new */
104 };
105 
106 PyObject _Py_EllipsisObject = _PyObject_HEAD_INIT(&PyEllipsis_Type);
107 
108 
109 /* Slice object implementation */
110 
_PySlice_ClearFreeList(struct _Py_object_freelists * freelists,int is_finalization)111 void _PySlice_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization)
112 {
113     if (!is_finalization) {
114         return;
115     }
116 #ifdef WITH_FREELISTS
117     PySliceObject *obj = freelists->slices.slice_cache;
118     if (obj != NULL) {
119         freelists->slices.slice_cache = NULL;
120         PyObject_GC_Del(obj);
121     }
122 #endif
123 }
124 
125 /* start, stop, and step are python objects with None indicating no
126    index is present.
127 */
128 
129 static PySliceObject *
_PyBuildSlice_Consume2(PyObject * start,PyObject * stop,PyObject * step)130 _PyBuildSlice_Consume2(PyObject *start, PyObject *stop, PyObject *step)
131 {
132     assert(start != NULL && stop != NULL && step != NULL);
133     PySliceObject *obj;
134 #ifdef WITH_FREELISTS
135     struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
136     if (freelists->slices.slice_cache != NULL) {
137         obj = freelists->slices.slice_cache;
138         freelists->slices.slice_cache = NULL;
139         _Py_NewReference((PyObject *)obj);
140     }
141     else
142 #endif
143     {
144         obj = PyObject_GC_New(PySliceObject, &PySlice_Type);
145         if (obj == NULL) {
146             goto error;
147         }
148     }
149 
150     obj->start = start;
151     obj->stop = stop;
152     obj->step = Py_NewRef(step);
153 
154     _PyObject_GC_TRACK(obj);
155     return obj;
156 error:
157     Py_DECREF(start);
158     Py_DECREF(stop);
159     return NULL;
160 }
161 
162 PyObject *
PySlice_New(PyObject * start,PyObject * stop,PyObject * step)163 PySlice_New(PyObject *start, PyObject *stop, PyObject *step)
164 {
165     if (step == NULL) {
166         step = Py_None;
167     }
168     if (start == NULL) {
169         start = Py_None;
170     }
171     if (stop == NULL) {
172         stop = Py_None;
173     }
174     return (PyObject *)_PyBuildSlice_Consume2(Py_NewRef(start),
175                                               Py_NewRef(stop), step);
176 }
177 
178 PyObject *
_PyBuildSlice_ConsumeRefs(PyObject * start,PyObject * stop)179 _PyBuildSlice_ConsumeRefs(PyObject *start, PyObject *stop)
180 {
181     assert(start != NULL && stop != NULL);
182     return (PyObject *)_PyBuildSlice_Consume2(start, stop, Py_None);
183 }
184 
185 PyObject *
_PySlice_FromIndices(Py_ssize_t istart,Py_ssize_t istop)186 _PySlice_FromIndices(Py_ssize_t istart, Py_ssize_t istop)
187 {
188     PyObject *start, *end, *slice;
189     start = PyLong_FromSsize_t(istart);
190     if (!start)
191         return NULL;
192     end = PyLong_FromSsize_t(istop);
193     if (!end) {
194         Py_DECREF(start);
195         return NULL;
196     }
197 
198     slice = PySlice_New(start, end, NULL);
199     Py_DECREF(start);
200     Py_DECREF(end);
201     return slice;
202 }
203 
204 int
PySlice_GetIndices(PyObject * _r,Py_ssize_t length,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t * step)205 PySlice_GetIndices(PyObject *_r, Py_ssize_t length,
206                    Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
207 {
208     PySliceObject *r = (PySliceObject*)_r;
209     /* XXX support long ints */
210     if (r->step == Py_None) {
211         *step = 1;
212     } else {
213         if (!PyLong_Check(r->step)) return -1;
214         *step = PyLong_AsSsize_t(r->step);
215     }
216     if (r->start == Py_None) {
217         *start = *step < 0 ? length-1 : 0;
218     } else {
219         if (!PyLong_Check(r->start)) return -1;
220         *start = PyLong_AsSsize_t(r->start);
221         if (*start < 0) *start += length;
222     }
223     if (r->stop == Py_None) {
224         *stop = *step < 0 ? -1 : length;
225     } else {
226         if (!PyLong_Check(r->stop)) return -1;
227         *stop = PyLong_AsSsize_t(r->stop);
228         if (*stop < 0) *stop += length;
229     }
230     if (*stop > length) return -1;
231     if (*start >= length) return -1;
232     if (*step == 0) return -1;
233     return 0;
234 }
235 
236 int
PySlice_Unpack(PyObject * _r,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t * step)237 PySlice_Unpack(PyObject *_r,
238                Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
239 {
240     PySliceObject *r = (PySliceObject*)_r;
241     /* this is harder to get right than you might think */
242 
243     static_assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX,
244                   "-PY_SSIZE_T_MAX < PY_SSIZE_T_MIN + 1");
245 
246     if (r->step == Py_None) {
247         *step = 1;
248     }
249     else {
250         if (!_PyEval_SliceIndex(r->step, step)) return -1;
251         if (*step == 0) {
252             PyErr_SetString(PyExc_ValueError,
253                             "slice step cannot be zero");
254             return -1;
255         }
256         /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
257          * with -PY_SSIZE_T_MAX.  This doesn't affect the semantics, and it
258          * guards against later undefined behaviour resulting from code that
259          * does "step = -step" as part of a slice reversal.
260          */
261         if (*step < -PY_SSIZE_T_MAX)
262             *step = -PY_SSIZE_T_MAX;
263     }
264 
265     if (r->start == Py_None) {
266         *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
267     }
268     else {
269         if (!_PyEval_SliceIndex(r->start, start)) return -1;
270     }
271 
272     if (r->stop == Py_None) {
273         *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
274     }
275     else {
276         if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
277     }
278 
279     return 0;
280 }
281 
282 Py_ssize_t
PySlice_AdjustIndices(Py_ssize_t length,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t step)283 PySlice_AdjustIndices(Py_ssize_t length,
284                       Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t step)
285 {
286     /* this is harder to get right than you might think */
287 
288     assert(step != 0);
289     assert(step >= -PY_SSIZE_T_MAX);
290 
291     if (*start < 0) {
292         *start += length;
293         if (*start < 0) {
294             *start = (step < 0) ? -1 : 0;
295         }
296     }
297     else if (*start >= length) {
298         *start = (step < 0) ? length - 1 : length;
299     }
300 
301     if (*stop < 0) {
302         *stop += length;
303         if (*stop < 0) {
304             *stop = (step < 0) ? -1 : 0;
305         }
306     }
307     else if (*stop >= length) {
308         *stop = (step < 0) ? length - 1 : length;
309     }
310 
311     if (step < 0) {
312         if (*stop < *start) {
313             return (*start - *stop - 1) / (-step) + 1;
314         }
315     }
316     else {
317         if (*start < *stop) {
318             return (*stop - *start - 1) / step + 1;
319         }
320     }
321     return 0;
322 }
323 
324 #undef PySlice_GetIndicesEx
325 
326 int
PySlice_GetIndicesEx(PyObject * _r,Py_ssize_t length,Py_ssize_t * start,Py_ssize_t * stop,Py_ssize_t * step,Py_ssize_t * slicelength)327 PySlice_GetIndicesEx(PyObject *_r, Py_ssize_t length,
328                      Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step,
329                      Py_ssize_t *slicelength)
330 {
331     if (PySlice_Unpack(_r, start, stop, step) < 0)
332         return -1;
333     *slicelength = PySlice_AdjustIndices(length, start, stop, *step);
334     return 0;
335 }
336 
337 static PyObject *
slice_new(PyTypeObject * type,PyObject * args,PyObject * kw)338 slice_new(PyTypeObject *type, PyObject *args, PyObject *kw)
339 {
340     PyObject *start, *stop, *step;
341 
342     start = stop = step = NULL;
343 
344     if (!_PyArg_NoKeywords("slice", kw))
345         return NULL;
346 
347     if (!PyArg_UnpackTuple(args, "slice", 1, 3, &start, &stop, &step))
348         return NULL;
349 
350     /* This swapping of stop and start is to maintain similarity with
351        range(). */
352     if (stop == NULL) {
353         stop = start;
354         start = NULL;
355     }
356     return PySlice_New(start, stop, step);
357 }
358 
359 PyDoc_STRVAR(slice_doc,
360 "slice(stop)\n\
361 slice(start, stop[, step])\n\
362 \n\
363 Create a slice object.  This is used for extended slicing (e.g. a[0:10:2]).");
364 
365 static void
slice_dealloc(PySliceObject * r)366 slice_dealloc(PySliceObject *r)
367 {
368     _PyObject_GC_UNTRACK(r);
369     Py_DECREF(r->step);
370     Py_DECREF(r->start);
371     Py_DECREF(r->stop);
372 #ifdef WITH_FREELISTS
373     struct _Py_object_freelists *freelists = _Py_object_freelists_GET();
374     if (freelists->slices.slice_cache == NULL) {
375         freelists->slices.slice_cache = r;
376     }
377     else
378 #endif
379     {
380         PyObject_GC_Del(r);
381     }
382 }
383 
384 static PyObject *
slice_repr(PySliceObject * r)385 slice_repr(PySliceObject *r)
386 {
387     return PyUnicode_FromFormat("slice(%R, %R, %R)", r->start, r->stop, r->step);
388 }
389 
390 static PyMemberDef slice_members[] = {
391     {"start", _Py_T_OBJECT, offsetof(PySliceObject, start), Py_READONLY},
392     {"stop", _Py_T_OBJECT, offsetof(PySliceObject, stop), Py_READONLY},
393     {"step", _Py_T_OBJECT, offsetof(PySliceObject, step), Py_READONLY},
394     {0}
395 };
396 
397 /* Helper function to convert a slice argument to a PyLong, and raise TypeError
398    with a suitable message on failure. */
399 
400 static PyObject*
evaluate_slice_index(PyObject * v)401 evaluate_slice_index(PyObject *v)
402 {
403     if (_PyIndex_Check(v)) {
404         return PyNumber_Index(v);
405     }
406     else {
407         PyErr_SetString(PyExc_TypeError,
408                         "slice indices must be integers or "
409                         "None or have an __index__ method");
410         return NULL;
411     }
412 }
413 
414 /* Compute slice indices given a slice and length.  Return -1 on failure.  Used
415    by slice.indices and rangeobject slicing.  Assumes that `len` is a
416    nonnegative instance of PyLong. */
417 
418 int
_PySlice_GetLongIndices(PySliceObject * self,PyObject * length,PyObject ** start_ptr,PyObject ** stop_ptr,PyObject ** step_ptr)419 _PySlice_GetLongIndices(PySliceObject *self, PyObject *length,
420                         PyObject **start_ptr, PyObject **stop_ptr,
421                         PyObject **step_ptr)
422 {
423     PyObject *start=NULL, *stop=NULL, *step=NULL;
424     PyObject *upper=NULL, *lower=NULL;
425     int step_is_negative, cmp_result;
426 
427     /* Convert step to an integer; raise for zero step. */
428     if (self->step == Py_None) {
429         step = _PyLong_GetOne();
430         step_is_negative = 0;
431     }
432     else {
433         int step_sign;
434         step = evaluate_slice_index(self->step);
435         if (step == NULL)
436             goto error;
437         step_sign = _PyLong_Sign(step);
438         if (step_sign == 0) {
439             PyErr_SetString(PyExc_ValueError,
440                             "slice step cannot be zero");
441             goto error;
442         }
443         step_is_negative = step_sign < 0;
444     }
445 
446     /* Find lower and upper bounds for start and stop. */
447     if (step_is_negative) {
448         lower = PyLong_FromLong(-1L);
449         if (lower == NULL)
450             goto error;
451 
452         upper = PyNumber_Add(length, lower);
453         if (upper == NULL)
454             goto error;
455     }
456     else {
457         lower = _PyLong_GetZero();
458         upper = Py_NewRef(length);
459     }
460 
461     /* Compute start. */
462     if (self->start == Py_None) {
463         start = Py_NewRef(step_is_negative ? upper : lower);
464     }
465     else {
466         start = evaluate_slice_index(self->start);
467         if (start == NULL)
468             goto error;
469 
470         if (_PyLong_IsNegative((PyLongObject *)start)) {
471             /* start += length */
472             PyObject *tmp = PyNumber_Add(start, length);
473             Py_SETREF(start, tmp);
474             if (start == NULL)
475                 goto error;
476 
477             cmp_result = PyObject_RichCompareBool(start, lower, Py_LT);
478             if (cmp_result < 0)
479                 goto error;
480             if (cmp_result) {
481                 Py_SETREF(start, Py_NewRef(lower));
482             }
483         }
484         else {
485             cmp_result = PyObject_RichCompareBool(start, upper, Py_GT);
486             if (cmp_result < 0)
487                 goto error;
488             if (cmp_result) {
489                 Py_SETREF(start, Py_NewRef(upper));
490             }
491         }
492     }
493 
494     /* Compute stop. */
495     if (self->stop == Py_None) {
496         stop = Py_NewRef(step_is_negative ? lower : upper);
497     }
498     else {
499         stop = evaluate_slice_index(self->stop);
500         if (stop == NULL)
501             goto error;
502 
503         if (_PyLong_IsNegative((PyLongObject *)stop)) {
504             /* stop += length */
505             PyObject *tmp = PyNumber_Add(stop, length);
506             Py_SETREF(stop, tmp);
507             if (stop == NULL)
508                 goto error;
509 
510             cmp_result = PyObject_RichCompareBool(stop, lower, Py_LT);
511             if (cmp_result < 0)
512                 goto error;
513             if (cmp_result) {
514                 Py_SETREF(stop, Py_NewRef(lower));
515             }
516         }
517         else {
518             cmp_result = PyObject_RichCompareBool(stop, upper, Py_GT);
519             if (cmp_result < 0)
520                 goto error;
521             if (cmp_result) {
522                 Py_SETREF(stop, Py_NewRef(upper));
523             }
524         }
525     }
526 
527     *start_ptr = start;
528     *stop_ptr = stop;
529     *step_ptr = step;
530     Py_DECREF(upper);
531     Py_DECREF(lower);
532     return 0;
533 
534   error:
535     *start_ptr = *stop_ptr = *step_ptr = NULL;
536     Py_XDECREF(start);
537     Py_XDECREF(stop);
538     Py_XDECREF(step);
539     Py_XDECREF(upper);
540     Py_XDECREF(lower);
541     return -1;
542 }
543 
544 /* Implementation of slice.indices. */
545 
546 static PyObject*
slice_indices(PySliceObject * self,PyObject * len)547 slice_indices(PySliceObject* self, PyObject* len)
548 {
549     PyObject *start, *stop, *step;
550     PyObject *length;
551     int error;
552 
553     /* Convert length to an integer if necessary; raise for negative length. */
554     length = PyNumber_Index(len);
555     if (length == NULL)
556         return NULL;
557 
558     if (_PyLong_IsNegative((PyLongObject *)length)) {
559         PyErr_SetString(PyExc_ValueError,
560                         "length should not be negative");
561         Py_DECREF(length);
562         return NULL;
563     }
564 
565     error = _PySlice_GetLongIndices(self, length, &start, &stop, &step);
566     Py_DECREF(length);
567     if (error == -1)
568         return NULL;
569     else
570         return Py_BuildValue("(NNN)", start, stop, step);
571 }
572 
573 PyDoc_STRVAR(slice_indices_doc,
574 "S.indices(len) -> (start, stop, stride)\n\
575 \n\
576 Assuming a sequence of length len, calculate the start and stop\n\
577 indices, and the stride length of the extended slice described by\n\
578 S. Out of bounds indices are clipped in a manner consistent with the\n\
579 handling of normal slices.");
580 
581 static PyObject *
slice_reduce(PySliceObject * self,PyObject * Py_UNUSED (ignored))582 slice_reduce(PySliceObject* self, PyObject *Py_UNUSED(ignored))
583 {
584     return Py_BuildValue("O(OOO)", Py_TYPE(self), self->start, self->stop, self->step);
585 }
586 
587 PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
588 
589 static PyMethodDef slice_methods[] = {
590     {"indices",         (PyCFunction)slice_indices,
591      METH_O,            slice_indices_doc},
592     {"__reduce__",      (PyCFunction)slice_reduce,
593      METH_NOARGS,       reduce_doc},
594     {NULL, NULL}
595 };
596 
597 static PyObject *
slice_richcompare(PyObject * v,PyObject * w,int op)598 slice_richcompare(PyObject *v, PyObject *w, int op)
599 {
600     if (!PySlice_Check(v) || !PySlice_Check(w))
601         Py_RETURN_NOTIMPLEMENTED;
602 
603     if (v == w) {
604         PyObject *res;
605         /* XXX Do we really need this shortcut?
606            There's a unit test for it, but is that fair? */
607         switch (op) {
608         case Py_EQ:
609         case Py_LE:
610         case Py_GE:
611             res = Py_True;
612             break;
613         default:
614             res = Py_False;
615             break;
616         }
617         return Py_NewRef(res);
618     }
619 
620 
621     PyObject *t1 = PyTuple_Pack(3,
622                                 ((PySliceObject *)v)->start,
623                                 ((PySliceObject *)v)->stop,
624                                 ((PySliceObject *)v)->step);
625     if (t1 == NULL) {
626         return NULL;
627     }
628 
629     PyObject *t2 = PyTuple_Pack(3,
630                                 ((PySliceObject *)w)->start,
631                                 ((PySliceObject *)w)->stop,
632                                 ((PySliceObject *)w)->step);
633     if (t2 == NULL) {
634         Py_DECREF(t1);
635         return NULL;
636     }
637 
638     PyObject *res = PyObject_RichCompare(t1, t2, op);
639     Py_DECREF(t1);
640     Py_DECREF(t2);
641     return res;
642 }
643 
644 static int
slice_traverse(PySliceObject * v,visitproc visit,void * arg)645 slice_traverse(PySliceObject *v, visitproc visit, void *arg)
646 {
647     Py_VISIT(v->start);
648     Py_VISIT(v->stop);
649     Py_VISIT(v->step);
650     return 0;
651 }
652 
653 /* code based on tuplehash() of Objects/tupleobject.c */
654 #if SIZEOF_PY_UHASH_T > 4
655 #define _PyHASH_XXPRIME_1 ((Py_uhash_t)11400714785074694791ULL)
656 #define _PyHASH_XXPRIME_2 ((Py_uhash_t)14029467366897019727ULL)
657 #define _PyHASH_XXPRIME_5 ((Py_uhash_t)2870177450012600261ULL)
658 #define _PyHASH_XXROTATE(x) ((x << 31) | (x >> 33))  /* Rotate left 31 bits */
659 #else
660 #define _PyHASH_XXPRIME_1 ((Py_uhash_t)2654435761UL)
661 #define _PyHASH_XXPRIME_2 ((Py_uhash_t)2246822519UL)
662 #define _PyHASH_XXPRIME_5 ((Py_uhash_t)374761393UL)
663 #define _PyHASH_XXROTATE(x) ((x << 13) | (x >> 19))  /* Rotate left 13 bits */
664 #endif
665 
666 static Py_hash_t
slicehash(PySliceObject * v)667 slicehash(PySliceObject *v)
668 {
669     Py_uhash_t acc = _PyHASH_XXPRIME_5;
670 #define _PyHASH_SLICE_PART(com) { \
671     Py_uhash_t lane = PyObject_Hash(v->com); \
672     if(lane == (Py_uhash_t)-1) { \
673         return -1; \
674     } \
675     acc += lane * _PyHASH_XXPRIME_2; \
676     acc = _PyHASH_XXROTATE(acc); \
677     acc *= _PyHASH_XXPRIME_1; \
678 }
679     _PyHASH_SLICE_PART(start);
680     _PyHASH_SLICE_PART(stop);
681     _PyHASH_SLICE_PART(step);
682 #undef _PyHASH_SLICE_PART
683     if(acc == (Py_uhash_t)-1) {
684         return 1546275796;
685     }
686     return acc;
687 }
688 
689 PyTypeObject PySlice_Type = {
690     PyVarObject_HEAD_INIT(&PyType_Type, 0)
691     "slice",                    /* Name of this type */
692     sizeof(PySliceObject),      /* Basic object size */
693     0,                          /* Item size for varobject */
694     (destructor)slice_dealloc,                  /* tp_dealloc */
695     0,                                          /* tp_vectorcall_offset */
696     0,                                          /* tp_getattr */
697     0,                                          /* tp_setattr */
698     0,                                          /* tp_as_async */
699     (reprfunc)slice_repr,                       /* tp_repr */
700     0,                                          /* tp_as_number */
701     0,                                          /* tp_as_sequence */
702     0,                                          /* tp_as_mapping */
703     (hashfunc)slicehash,                        /* tp_hash */
704     0,                                          /* tp_call */
705     0,                                          /* tp_str */
706     PyObject_GenericGetAttr,                    /* tp_getattro */
707     0,                                          /* tp_setattro */
708     0,                                          /* tp_as_buffer */
709     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
710     slice_doc,                                  /* tp_doc */
711     (traverseproc)slice_traverse,               /* tp_traverse */
712     0,                                          /* tp_clear */
713     slice_richcompare,                          /* tp_richcompare */
714     0,                                          /* tp_weaklistoffset */
715     0,                                          /* tp_iter */
716     0,                                          /* tp_iternext */
717     slice_methods,                              /* tp_methods */
718     slice_members,                              /* tp_members */
719     0,                                          /* tp_getset */
720     0,                                          /* tp_base */
721     0,                                          /* tp_dict */
722     0,                                          /* tp_descr_get */
723     0,                                          /* tp_descr_set */
724     0,                                          /* tp_dictoffset */
725     0,                                          /* tp_init */
726     0,                                          /* tp_alloc */
727     slice_new,                                  /* tp_new */
728 };
729