diff -r 9a98ff4a2290 Objects/listobject.c --- a/Objects/listobject.c Wed Jan 22 05:49:11 2014 -0800 +++ b/Objects/listobject.c Thu Jan 23 11:20:50 2014 +0800 @@ -9,6 +9,21 @@ #include /* For size_t */ #endif +/*[clinic input] +class list +[clinic start generated code]*/ +/*[clinic end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ + +/*[python input] +class PyListObject_converter(self_converter): + type = "PyListObject *" + +class slice_index_converter(CConverter): + type = "Py_ssize_t" + converter = "_PyEval_SliceIndex" +[python start generated code]*/ +/*[python end generated code: checksum=da39a3ee5e6b4b0d3255bfef95601890afd80709]*/ + /* Ensure ob_item has room for at least newsize elements, and set * ob_size to newsize. If newsize > ob_size on entry, the content * of the new slots at exit is undefined heap trash; it's the caller's @@ -745,14 +760,49 @@ return 0; } +/*[clinic input] +list.insert + + self: PyListObject + index: Py_ssize_t + object: object + / + +L.insert(index, object) -- insert object before index +[clinic start generated code]*/ + +PyDoc_STRVAR(list_insert__doc__, +"insert(index, object)\n" +"L.insert(index, object) -- insert object before index"); + +#define LIST_INSERT_METHODDEF \ + {"insert", (PyCFunction)list_insert, METH_VARARGS, list_insert__doc__}, + static PyObject * -listinsert(PyListObject *self, PyObject *args) +list_insert_impl(PyListObject *self, Py_ssize_t index, PyObject *object); + +static PyObject * +list_insert(PyObject *self, PyObject *args) { - Py_ssize_t i; - PyObject *v; - if (!PyArg_ParseTuple(args, "nO:insert", &i, &v)) - return NULL; - if (ins1(self, i, v) == 0) + PyObject *return_value = NULL; + Py_ssize_t index; + PyObject *object; + + if (!PyArg_ParseTuple(args, + "nO:insert", + &index, &object)) + goto exit; + return_value = list_insert_impl((PyListObject *)self, index, object); + +exit: + return return_value; +} + +static PyObject * +list_insert_impl(PyListObject *self, Py_ssize_t index, PyObject *object) +/*[clinic end generated code: checksum=120463c2cb49d724c8ad15fbec61d0a0bbbdf174]*/ +{ + if (ins1(self, index, object) == 0) Py_RETURN_NONE; return NULL; } @@ -908,29 +958,66 @@ return (PyObject *)self; } +/*[clinic input] +list.pop + + self: PyListObject + index: Py_ssize_t = -1 + / + +L.pop([index]) -> item -- remove and return item at index (default last). + +Raises IndexError if list is empty or index is out of range. +[clinic start generated code]*/ + +PyDoc_STRVAR(list_pop__doc__, +"pop(index=-1)\n" +"L.pop([index]) -> item -- remove and return item at index (default last).\n" +"\n" +"Raises IndexError if list is empty or index is out of range."); + +#define LIST_POP_METHODDEF \ + {"pop", (PyCFunction)list_pop, METH_VARARGS, list_pop__doc__}, + static PyObject * -listpop(PyListObject *self, PyObject *args) +list_pop_impl(PyListObject *self, Py_ssize_t index); + +static PyObject * +list_pop(PyObject *self, PyObject *args) { - Py_ssize_t i = -1; + PyObject *return_value = NULL; + Py_ssize_t index = -1; + + if (!PyArg_ParseTuple(args, + "|n:pop", + &index)) + goto exit; + return_value = list_pop_impl((PyListObject *)self, index); + +exit: + return return_value; +} + +static PyObject * +list_pop_impl(PyListObject *self, Py_ssize_t index) +/*[clinic end generated code: checksum=2c36b44386b677c854154408c8694f788299f835]*/ +{ PyObject *v; int status; - if (!PyArg_ParseTuple(args, "|n:pop", &i)) - return NULL; - if (Py_SIZE(self) == 0) { /* Special-case most common failure cause */ PyErr_SetString(PyExc_IndexError, "pop from empty list"); return NULL; } - if (i < 0) - i += Py_SIZE(self); - if (i < 0 || i >= Py_SIZE(self)) { + if (index < 0) + index += Py_SIZE(self); + if (index < 0 || index >= Py_SIZE(self)) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } - v = self->ob_item[i]; - if (i == Py_SIZE(self) - 1) { + v = self->ob_item[index]; + if (index == Py_SIZE(self) - 1) { status = list_resize(self, Py_SIZE(self) - 1); if (status >= 0) return v; /* and v now owns the reference the list had */ @@ -938,7 +1025,7 @@ return NULL; } Py_INCREF(v); - status = list_ass_slice(self, i, i+1, (PyObject *)NULL); + status = list_ass_slice(self, index, index+1, (PyObject *)NULL); if (status < 0) { Py_DECREF(v); return NULL; @@ -1905,8 +1992,47 @@ * list will be some permutation of its input state (nothing is lost or * duplicated). */ +/*[clinic input] +list.sort + + self: PyListObject + key: object(c_default="NULL") = None + reverse: int(c_default="0") = False + +L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE* +[clinic start generated code]*/ + +PyDoc_STRVAR(list_sort__doc__, +"sort(key=None, reverse=False)\n" +"L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*"); + +#define LIST_SORT_METHODDEF \ + {"sort", (PyCFunction)list_sort, METH_VARARGS|METH_KEYWORDS, list_sort__doc__}, + static PyObject * -listsort(PyListObject *self, PyObject *args, PyObject *kwds) +list_sort_impl(PyListObject *self, PyObject *key, int reverse); + +static PyObject * +list_sort(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *return_value = NULL; + static char *_keywords[] = {"key", "reverse", NULL}; + PyObject *key = NULL; + int reverse = 0; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|Oi:sort", _keywords, + &key, &reverse)) + goto exit; + return_value = list_sort_impl((PyListObject *)self, key, reverse); + +exit: + return return_value; +} + +static PyObject * +list_sort_impl(PyListObject *self, PyObject *key, int reverse) +/*[clinic end generated code: checksum=61252635ad9cc76db317ea34c218d11e580dfbab]*/ { MergeState ms; Py_ssize_t nremaining; @@ -1916,26 +2042,13 @@ PyObject **saved_ob_item; PyObject **final_ob_item; PyObject *result = NULL; /* guilty until proved innocent */ - int reverse = 0; - PyObject *keyfunc = NULL; Py_ssize_t i; - static char *kwlist[] = {"key", "reverse", 0}; PyObject **keys; assert(self != NULL); - assert (PyList_Check(self)); - if (args != NULL) { - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|Oi:sort", - kwlist, &keyfunc, &reverse)) - return NULL; - if (Py_SIZE(args) > 0) { - PyErr_SetString(PyExc_TypeError, - "must use keyword argument for key function"); - return NULL; - } - } - if (keyfunc == Py_None) - keyfunc = NULL; + assert(PyList_Check(self)); + if (key == Py_None) + key = NULL; /* The list is temporarily made empty, so that mutations performed * by comparison functions can't affect the slice of memory we're @@ -1949,7 +2062,7 @@ self->ob_item = NULL; self->allocated = -1; /* any operation will reset it to >= 0 */ - if (keyfunc == NULL) { + if (key == NULL) { keys = NULL; lo.keys = saved_ob_item; lo.values = NULL; @@ -1965,7 +2078,7 @@ } for (i = 0; i < saved_ob_size ; i++) { - keys[i] = PyObject_CallFunctionObjArgs(keyfunc, saved_ob_item[i], + keys[i] = PyObject_CallFunctionObjArgs(key, saved_ob_item[i], NULL); if (keys[i] == NULL) { for (i=i-1 ; i>=0 ; i--) @@ -2087,7 +2200,7 @@ PyErr_BadInternalCall(); return -1; } - v = listsort((PyListObject *)v, (PyObject *)NULL, (PyObject *)NULL); + v = list_sort_impl((PyListObject *)v, (PyObject *)NULL, 0); if (v == NULL) return -1; Py_DECREF(v); @@ -2141,16 +2254,78 @@ return w; } +/*[clinic input] +list.index + + self: PyListObject + value: object + [ + start: slice_index = 0 + [ + stop: slice_index(c_default="Py_SIZE(self)") = unspecified + ] + ] + / + +L.index(value, [start, [stop]]) -> integer -- return first index of value. + +Raises ValueError if the value is not present. +[clinic start generated code]*/ + +PyDoc_STRVAR(list_index__doc__, +"index(value, [start=0, [stop=unspecified]])\n" +"L.index(value, [start, [stop]]) -> integer -- return first index of value.\n" +"\n" +"Raises ValueError if the value is not present."); + +#define LIST_INDEX_METHODDEF \ + {"index", (PyCFunction)list_index, METH_VARARGS, list_index__doc__}, + static PyObject * -listindex(PyListObject *self, PyObject *args) +list_index_impl(PyListObject *self, PyObject *value, int group_right_1, Py_ssize_t start, int group_right_2, Py_ssize_t stop); + +static PyObject * +list_index(PyObject *self, PyObject *args) { - Py_ssize_t i, start=0, stop=Py_SIZE(self); - PyObject *v; - - if (!PyArg_ParseTuple(args, "O|O&O&:index", &v, - _PyEval_SliceIndex, &start, - _PyEval_SliceIndex, &stop)) - return NULL; + PyObject *return_value = NULL; + PyObject *value; + int group_right_1 = 0; + Py_ssize_t start = 0; + int group_right_2 = 0; + Py_ssize_t stop = Py_SIZE(self); + + switch (PyTuple_GET_SIZE(args)) { + case 1: + if (!PyArg_ParseTuple(args, "O:index", &value)) + goto exit; + break; + case 2: + if (!PyArg_ParseTuple(args, "OO&:index", &value, _PyEval_SliceIndex, &start)) + goto exit; + group_right_1 = 1; + break; + case 3: + if (!PyArg_ParseTuple(args, "OO&O&:index", &value, _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &stop)) + goto exit; + group_right_1 = 1; + group_right_2 = 1; + break; + default: + PyErr_SetString(PyExc_TypeError, "list.index requires 1 to 3 arguments"); + goto exit; + } + return_value = list_index_impl((PyListObject *)self, value, group_right_1, start, group_right_2, stop); + +exit: + return return_value; +} + +static PyObject * +list_index_impl(PyListObject *self, PyObject *value, int group_right_1, Py_ssize_t start, int group_right_2, Py_ssize_t stop) +/*[clinic end generated code: checksum=3525bf4d4ca14f240d95da00c7778beba5b9d0b4]*/ +{ + Py_ssize_t i; + if (start < 0) { start += Py_SIZE(self); if (start < 0) @@ -2162,13 +2337,13 @@ stop = 0; } for (i = start; i < stop && i < Py_SIZE(self); i++) { - int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ); + int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ); if (cmp > 0) return PyLong_FromSsize_t(i); else if (cmp < 0) return NULL; } - PyErr_Format(PyExc_ValueError, "%R is not in list", v); + PyErr_Format(PyExc_ValueError, "%R is not in list", value); return NULL; } @@ -2288,15 +2463,47 @@ return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op); } +/*[clinic input] +list.__init__ + + self: PyListObject + sequence: object(c_default="NULL") = unspecified + +list() -> new empty list + +list(iterable) -> new list initialized from iterable's items +[clinic start generated code]*/ + +PyDoc_STRVAR(list___init____doc__, +"list(sequence=unspecified)\n" +"list() -> new empty list\n" +"\n" +"list(iterable) -> new list initialized from iterable\'s items"); + static int -list_init(PyListObject *self, PyObject *args, PyObject *kw) +list___init___impl(PyListObject *self, PyObject *sequence); + +static int +list___init__(PyObject *self, PyObject *args, PyObject *kwargs) { - PyObject *arg = NULL; - static char *kwlist[] = {"sequence", 0}; - - if (!PyArg_ParseTupleAndKeywords(args, kw, "|O:list", kwlist, &arg)) - return -1; - + int return_value = -1; + static char *_keywords[] = {"sequence", NULL}; + PyObject *sequence = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "|O:__init__", _keywords, + &sequence)) + goto exit; + return_value = list___init___impl((PyListObject *)self, sequence); + +exit: + return return_value; +} + +static int +list___init___impl(PyListObject *self, PyObject *sequence) +/*[clinic end generated code: checksum=bc85a7dc3e13cc3a3adf172b066fcb05bba6fe78]*/ +{ /* Verify list invariants established by PyType_GenericAlloc() */ assert(0 <= Py_SIZE(self)); assert(Py_SIZE(self) <= self->allocated || self->allocated == -1); @@ -2307,8 +2514,8 @@ if (self->ob_item != NULL) { (void)list_clear(self); } - if (arg != NULL) { - PyObject *rv = listextend(self, arg); + if (sequence != NULL) { + PyObject *rv = listextend(self, sequence); if (rv == NULL) return -1; Py_DECREF(rv); @@ -2342,23 +2549,13 @@ "L.append(object) -> None -- append object to end"); PyDoc_STRVAR(extend_doc, "L.extend(iterable) -> None -- extend list by appending elements from the iterable"); -PyDoc_STRVAR(insert_doc, -"L.insert(index, object) -- insert object before index"); -PyDoc_STRVAR(pop_doc, -"L.pop([index]) -> item -- remove and return item at index (default last).\n" -"Raises IndexError if list is empty or index is out of range."); PyDoc_STRVAR(remove_doc, "L.remove(value) -> None -- remove first occurrence of value.\n" "Raises ValueError if the value is not present."); -PyDoc_STRVAR(index_doc, -"L.index(value, [start, [stop]]) -> integer -- return first index of value.\n" -"Raises ValueError if the value is not present."); PyDoc_STRVAR(count_doc, "L.count(value) -> integer -- return number of occurrences of value"); PyDoc_STRVAR(reverse_doc, "L.reverse() -- reverse *IN PLACE*"); -PyDoc_STRVAR(sort_doc, -"L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*"); static PyObject *list_subscript(PyListObject*, PyObject*); @@ -2369,14 +2566,14 @@ {"clear", (PyCFunction)listclear, METH_NOARGS, clear_doc}, {"copy", (PyCFunction)listcopy, METH_NOARGS, copy_doc}, {"append", (PyCFunction)listappend, METH_O, append_doc}, - {"insert", (PyCFunction)listinsert, METH_VARARGS, insert_doc}, + LIST_INSERT_METHODDEF {"extend", (PyCFunction)listextend, METH_O, extend_doc}, - {"pop", (PyCFunction)listpop, METH_VARARGS, pop_doc}, + LIST_POP_METHODDEF {"remove", (PyCFunction)listremove, METH_O, remove_doc}, - {"index", (PyCFunction)listindex, METH_VARARGS, index_doc}, + LIST_INDEX_METHODDEF {"count", (PyCFunction)listcount, METH_O, count_doc}, {"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc}, - {"sort", (PyCFunction)listsort, METH_VARARGS | METH_KEYWORDS, sort_doc}, + LIST_SORT_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2393,10 +2590,6 @@ (ssizeargfunc)list_inplace_repeat, /* sq_inplace_repeat */ }; -PyDoc_STRVAR(list_doc, -"list() -> new empty list\n" -"list(iterable) -> new list initialized from iterable's items"); - static PyObject * list_subscript(PyListObject* self, PyObject* item) { @@ -2642,7 +2835,7 @@ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS, /* tp_flags */ - list_doc, /* tp_doc */ + list___init____doc__, /* tp_doc */ (traverseproc)list_traverse, /* tp_traverse */ (inquiry)list_clear, /* tp_clear */ list_richcompare, /* tp_richcompare */ @@ -2657,7 +2850,7 @@ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)list_init, /* tp_init */ + (initproc)list___init__, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ PyObject_GC_Del, /* tp_free */