Kaydet (Commit) e289e0bd authored tarafından Thomas Wouters's avatar Thomas Wouters

Support for the in-place operations introduced by augmented assignment. Only

the list object supports this currently, but other candidates are
gladly accepted (like arraymodule and such.)
üst 12bba852
This diff is collapsed.
...@@ -1193,12 +1193,6 @@ generic_unary_op(PyInstanceObject *self, PyObject *methodname) ...@@ -1193,12 +1193,6 @@ generic_unary_op(PyInstanceObject *self, PyObject *methodname)
} }
/* Forward */
static int
halfbinop(PyObject *, PyObject *, char *, PyObject **,
PyObject * (*)(PyObject *, PyObject *), int);
/* Implement a binary operator involving at least one class instance. */ /* Implement a binary operator involving at least one class instance. */
PyObject * PyObject *
...@@ -1208,9 +1202,9 @@ PyInstance_DoBinOp(PyObject *v, PyObject *w, char *opname, char *ropname, ...@@ -1208,9 +1202,9 @@ PyInstance_DoBinOp(PyObject *v, PyObject *w, char *opname, char *ropname,
char buf[256]; char buf[256];
PyObject *result = NULL; PyObject *result = NULL;
if (halfbinop(v, w, opname, &result, thisfunc, 0) <= 0) if (PyInstance_HalfBinOp(v, w, opname, &result, thisfunc, 0) <= 0)
return result; return result;
if (halfbinop(w, v, ropname, &result, thisfunc, 1) <= 0) if (PyInstance_HalfBinOp(w, v, ropname, &result, thisfunc, 1) <= 0)
return result; return result;
/* Sigh -- special case for comparisons */ /* Sigh -- special case for comparisons */
if (strcmp(opname, "__cmp__") == 0) { if (strcmp(opname, "__cmp__") == 0) {
...@@ -1234,9 +1228,9 @@ PyInstance_DoBinOp(PyObject *v, PyObject *w, char *opname, char *ropname, ...@@ -1234,9 +1228,9 @@ PyInstance_DoBinOp(PyObject *v, PyObject *w, char *opname, char *ropname,
static PyObject *coerce_obj; static PyObject *coerce_obj;
static int int
halfbinop(PyObject *v, PyObject *w, char *opname, PyObject **r_result, PyInstance_HalfBinOp(PyObject *v, PyObject *w, char *opname, PyObject **r_result,
PyObject * (*thisfunc)(PyObject *, PyObject *), int swapped) PyObject * (*thisfunc)(PyObject *, PyObject *), int swapped)
{ {
PyObject *func; PyObject *func;
PyObject *args; PyObject *args;
...@@ -1451,6 +1445,35 @@ instance_pow(PyObject *v, PyObject *w, PyObject *z) ...@@ -1451,6 +1445,35 @@ instance_pow(PyObject *v, PyObject *w, PyObject *z)
return result; return result;
} }
static PyObject *
instance_inplace_pow(PyObject *v, PyObject *w, PyObject *z)
{
/* XXX Doesn't do coercions... */
PyObject *func;
PyObject *args;
PyObject *result;
static PyObject *ipowstr;
if (ipowstr == NULL)
ipowstr = PyString_InternFromString("__ipow__");
func = PyObject_GetAttr(v, ipowstr);
if (func == NULL) {
if (!PyErr_ExceptionMatches(PyExc_AttributeError))
return NULL;
return instance_pow(v, w, z);
}
args = Py_BuildValue("(OO)", w, z);
if (args == NULL) {
Py_DECREF(func);
return NULL;
}
result = PyEval_CallObject(func, args);
Py_DECREF(func);
Py_DECREF(args);
return result;
}
static PyNumberMethods instance_as_number = { static PyNumberMethods instance_as_number = {
0, /*nb_add*/ 0, /*nb_add*/
0, /*nb_subtract*/ 0, /*nb_subtract*/
...@@ -1475,6 +1498,17 @@ static PyNumberMethods instance_as_number = { ...@@ -1475,6 +1498,17 @@ static PyNumberMethods instance_as_number = {
(unaryfunc)instance_float, /*nb_float*/ (unaryfunc)instance_float, /*nb_float*/
(unaryfunc)instance_oct, /*nb_oct*/ (unaryfunc)instance_oct, /*nb_oct*/
(unaryfunc)instance_hex, /*nb_hex*/ (unaryfunc)instance_hex, /*nb_hex*/
0, /*nb_inplace_add*/
0, /*nb_inplace_subtract*/
0, /*nb_inplace_multiply*/
0, /*nb_inplace_divide*/
0, /*nb_inplace_remainder*/
(ternaryfunc)instance_inplace_pow, /*nb_inplace_power*/
0, /*nb_inplace_lshift*/
0, /*nb_inplace_rshift*/
0, /*nb_inplace_and*/
0, /*nb_inplace_xor*/
0, /*nb_inplace_or*/
}; };
PyTypeObject PyInstance_Type = { PyTypeObject PyInstance_Type = {
......
...@@ -496,6 +496,50 @@ PyList_SetSlice(PyObject *a, int ilow, int ihigh, PyObject *v) ...@@ -496,6 +496,50 @@ PyList_SetSlice(PyObject *a, int ilow, int ihigh, PyObject *v)
return list_ass_slice((PyListObject *)a, ilow, ihigh, v); return list_ass_slice((PyListObject *)a, ilow, ihigh, v);
} }
static PyObject *
list_inplace_repeat(PyListObject *self, int n)
{
PyObject **items;
int size, i, j;
size = PyList_GET_SIZE(self);
if (size == 0) {
Py_INCREF(self);
return (PyObject *)self;
}
items = self->ob_item;
if (n < 1) {
self->ob_item = NULL;
self->ob_size = 0;
for (i = 0; i < size; i++)
Py_XDECREF(items[i]);
PyMem_DEL(items);
Py_INCREF(self);
return (PyObject *)self;
}
NRESIZE(items, PyObject*, size*n);
if (items == NULL) {
PyErr_NoMemory();
goto finally;
}
self->ob_item = items;
for (i = 1; i < n; i++) { /* Start counting at 1, not 0 */
for (j = 0; j < size; j++) {
PyObject *o = PyList_GET_ITEM(self, j);
Py_INCREF(o);
PyList_SET_ITEM(self, self->ob_size++, o);
}
}
Py_INCREF(self);
return (PyObject *)self;
finally:
return NULL;
}
static int static int
list_ass_item(PyListObject *a, int i, PyObject *v) list_ass_item(PyListObject *a, int i, PyObject *v)
{ {
...@@ -556,25 +600,17 @@ listappend(PyListObject *self, PyObject *args) ...@@ -556,25 +600,17 @@ listappend(PyListObject *self, PyObject *args)
return ins(self, (int) self->ob_size, v); return ins(self, (int) self->ob_size, v);
} }
static PyObject * static int
listextend(PyListObject *self, PyObject *args) listextend_internal(PyListObject *self, PyObject *b)
{ {
PyObject *b = NULL, *res = NULL;
PyObject **items; PyObject **items;
int selflen = PyList_GET_SIZE(self); int selflen = PyList_GET_SIZE(self);
int blen; int blen;
register int i; register int i;
if (!PyArg_ParseTuple(args, "O:extend", &b))
return NULL;
b = PySequence_Fast(b, "list.extend() argument must be a sequence");
if (!b)
return NULL;
if (PyObject_Size(b) == 0) if (PyObject_Size(b) == 0)
/* short circuit when b is empty */ /* short circuit when b is empty */
goto ok; return 0;
if (self == (PyListObject*)b) { if (self == (PyListObject*)b) {
/* as in list_ass_slice() we must special case the /* as in list_ass_slice() we must special case the
...@@ -586,7 +622,7 @@ listextend(PyListObject *self, PyObject *args) ...@@ -586,7 +622,7 @@ listextend(PyListObject *self, PyObject *args)
Py_DECREF(b); Py_DECREF(b);
b = PyList_New(selflen); b = PyList_New(selflen);
if (!b) if (!b)
return NULL; return -1;
for (i = 0; i < selflen; i++) { for (i = 0; i < selflen; i++) {
PyObject *o = PyList_GET_ITEM(self, i); PyObject *o = PyList_GET_ITEM(self, i);
Py_INCREF(o); Py_INCREF(o);
...@@ -601,8 +637,10 @@ listextend(PyListObject *self, PyObject *args) ...@@ -601,8 +637,10 @@ listextend(PyListObject *self, PyObject *args)
NRESIZE(items, PyObject*, selflen + blen); NRESIZE(items, PyObject*, selflen + blen);
if (items == NULL) { if (items == NULL) {
PyErr_NoMemory(); PyErr_NoMemory();
goto failed; Py_DECREF(b);
return -1;
} }
self->ob_item = items; self->ob_item = items;
/* populate the end of self with b's items */ /* populate the end of self with b's items */
...@@ -611,14 +649,44 @@ listextend(PyListObject *self, PyObject *args) ...@@ -611,14 +649,44 @@ listextend(PyListObject *self, PyObject *args)
Py_INCREF(o); Py_INCREF(o);
PyList_SET_ITEM(self, self->ob_size++, o); PyList_SET_ITEM(self, self->ob_size++, o);
} }
ok:
res = Py_None;
Py_INCREF(res);
failed:
Py_DECREF(b); Py_DECREF(b);
return res; return 0;
}
static PyObject *
list_inplace_concat(PyListObject *self, PyObject *other)
{
other = PySequence_Fast(other, "argument to += must be a sequence");
if (!other)
return NULL;
if (listextend_internal(self, other) < 0)
return NULL;
Py_INCREF(self);
return (PyObject *)self;
} }
static PyObject *
listextend(PyListObject *self, PyObject *args)
{
PyObject *b;
if (!PyArg_ParseTuple(args, "O:extend", &b))
return NULL;
b = PySequence_Fast(b, "list.extend() argument must be a sequence");
if (!b)
return NULL;
if (listextend_internal(self, b) < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static PyObject * static PyObject *
listpop(PyListObject *self, PyObject *args) listpop(PyListObject *self, PyObject *args)
...@@ -1407,6 +1475,8 @@ static PySequenceMethods list_as_sequence = { ...@@ -1407,6 +1475,8 @@ static PySequenceMethods list_as_sequence = {
(intobjargproc)list_ass_item, /*sq_ass_item*/ (intobjargproc)list_ass_item, /*sq_ass_item*/
(intintobjargproc)list_ass_slice, /*sq_ass_slice*/ (intintobjargproc)list_ass_slice, /*sq_ass_slice*/
(objobjproc)list_contains, /*sq_contains*/ (objobjproc)list_contains, /*sq_contains*/
(binaryfunc)list_inplace_concat, /*sq_inplace_concat*/
(intargfunc)list_inplace_repeat, /*sq_inplace_repeat*/
}; };
PyTypeObject PyList_Type = { PyTypeObject PyList_Type = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment