[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.12,2.16.8.13
Guido van Rossum
gvanrossum@users.sourceforge.net
Mon, 07 May 2001 16:19:26 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv18783
Modified Files:
Tag: descr-branch
typeobject.c
Log Message:
Implement overriding of special operations slots by __foo__ methods.
I had to create a *lot* of little wrapper functions for this; haven't
had the time to test them all yet.
Next step (maybe tomorrow): Python subclass instances should have a
__dict__ (unless they specify something else).
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.12
retrieving revision 2.16.8.13
diff -C2 -r2.16.8.12 -r2.16.8.13
*** typeobject.c 2001/05/06 02:52:04 2.16.8.12
--- typeobject.c 2001/05/07 23:19:24 2.16.8.13
***************
*** 149,157 ****
}
/* TypeType's constructor is called when a type is subclassed */
static PyObject *
type_construct(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! PyObject *name, *bases, *dict, *x;
PyTypeObject *base;
char *dummy = NULL;
--- 149,169 ----
}
+ staticforward void override_slots(PyTypeObject *type, PyObject *dict);
+
+ typedef struct {
+ PyTypeObject type;
+ PyNumberMethods as_number;
+ PySequenceMethods as_sequence;
+ PyMappingMethods as_mapping;
+ PyBufferProcs as_buffer;
+ char name[1];
+ } etype;
+
/* TypeType's constructor is called when a type is subclassed */
static PyObject *
type_construct(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
! char *name;
! PyObject *bases, *dict, *x;
PyTypeObject *base;
char *dummy = NULL;
***************
*** 162,166 ****
return NULL;
}
! if (!PyArg_ParseTupleAndKeywords(args, kwds, "SOO", &dummy,
&name, &bases, &dict))
return NULL;
--- 174,178 ----
return NULL;
}
! if (!PyArg_ParseTupleAndKeywords(args, kwds, "sOO", &dummy,
&name, &bases, &dict))
return NULL;
***************
*** 186,195 ****
return NULL;
}
! type = PyObject_New(PyTypeObject, &PyType_Type);
if (type == NULL)
return NULL;
! memset(((char *)type) + offsetof(PyTypeObject, tp_name), '\0',
! sizeof(PyTypeObject) - offsetof(PyTypeObject, tp_name));
! type->tp_name = PyString_AS_STRING(name);
type->tp_flags = Py_TPFLAGS_DEFAULT;
Py_INCREF(base);
--- 198,211 ----
return NULL;
}
! type = PyObject_MALLOC(sizeof(etype) + strlen(name));
if (type == NULL)
return NULL;
! memset(type, '\0', sizeof(etype));
! PyObject_INIT(type, &PyType_Type);
! type->tp_as_number = & (((etype *)type)->as_number);
! type->tp_as_sequence = & (((etype *)type)->as_sequence);
! type->tp_as_mapping = & (((etype *)type)->as_mapping);
! type->tp_as_buffer = & (((etype *)type)->as_buffer);
! type->tp_name = strcpy(((etype *)type)->name, name);
type->tp_flags = Py_TPFLAGS_DEFAULT;
Py_INCREF(base);
***************
*** 209,213 ****
}
Py_DECREF(x); /* throw away None */
! PyDict_SetItemString(type->tp_dict, "__name__", name);
return (PyObject *)type;
}
--- 225,229 ----
}
Py_DECREF(x); /* throw away None */
! override_slots(type, dict);
return (PyObject *)type;
}
***************
*** 1117,1119 ****
--- 1133,1443 ----
return 0;
+ }
+
+ /* Slot wrappers that call the corresponding __foo__ slot */
+
+ #define SLOT0(SLOTNAME, OPNAME) \
+ static PyObject * \
+ slot_##SLOTNAME(PyObject *self) \
+ { \
+ return PyObject_CallMethod(self, "__" #OPNAME "__", ""); \
+ }
+
+ #define SLOT1(SLOTNAME, OPNAME, ARG1TYPE, ARGCODES) \
+ static PyObject * \
+ slot_##SLOTNAME(PyObject *self, ARG1TYPE arg1) \
+ { \
+ return PyObject_CallMethod(self, "__" #OPNAME "__", #ARGCODES, arg1); \
+ }
+
+ #define SLOT2(SLOTNAME, OPNAME, ARG1TYPE, ARG2TYPE, ARGCODES) \
+ static PyObject * \
+ slot_##SLOTNAME(PyObject *self, ARG1TYPE arg1, ARG2TYPE arg2) \
+ { \
+ return PyObject_CallMethod(self, "__" #OPNAME "__", \
+ #ARGCODES, arg1, arg2); \
+ }
+
+ static int
+ slot_sq_length(PyObject *self)
+ {
+ PyObject *res = PyObject_CallMethod(self, "__len__", "");
+
+ if (res == NULL)
+ return -1;
+ return (int)PyInt_AsLong(res);
+ }
+
+ SLOT1(sq_concat, add, PyObject *, O);
+ SLOT1(sq_repeat, mul, int, i);
+ SLOT1(sq_item, getitem, int, i);
+ SLOT2(sq_slice, getslice, int, int, ii);
+
+ static int
+ slot_sq_ass_item(PyObject *self, int index, PyObject *value)
+ {
+ PyObject *res = PyObject_CallMethod(self, "__setitem__",
+ "iO", index, value);
+ if (res == NULL)
+ return -1;
+ Py_DECREF(res);
+ return 0;
+ }
+
+ static int
+ slot_sq_ass_slice(PyObject *self, int i, int j, PyObject *value)
+ {
+ PyObject *res = PyObject_CallMethod(self, "__setitem__",
+ "iiO", i, j, value);
+ if (res == NULL)
+ return -1;
+ Py_DECREF(res);
+ return 0;
+ }
+
+ static int
+ slot_sq_contains(PyObject *self, PyObject *value)
+ {
+ PyObject *res = PyObject_CallMethod(self, "__contains__", "O", value);
+ int r;
+
+ if (res == NULL)
+ return -1;
+ r = PyInt_AsLong(res);
+ Py_DECREF(res);
+ return r;
+ }
+
+ SLOT1(sq_inplace_concat, iadd, PyObject *, O);
+ SLOT1(sq_inplace_repeat, imul, int, i);
+
+ #define slot_mp_length slot_sq_length
+
+ SLOT1(mp_subscript, getitem, PyObject *, O);
+
+ static int
+ slot_mp_ass_subscript(PyObject *self, PyObject *key, PyObject *value)
+ {
+ PyObject *res = PyObject_CallMethod(self, "__setitem__",
+ "OO", key, value);
+ if (res == NULL)
+ return -1;
+ Py_DECREF(res);
+ return 0;
+ }
+
+ SLOT1(nb_add, add, PyObject *, O);
+ SLOT1(nb_subtract, sub, PyObject *, O);
+ SLOT1(nb_multiply, mul, PyObject *, O);
+ SLOT1(nb_divide, div, PyObject *, O);
+ SLOT1(nb_remainder, mod, PyObject *, O);
+ SLOT1(nb_divmod, divmod, PyObject *, O);
+ SLOT2(nb_power, pow, PyObject *, PyObject *, OO);
+ SLOT0(nb_negative, neg);
+ SLOT0(nb_positive, pos);
+ SLOT0(nb_absolute, abs);
+
+ static int
+ slot_nb_nonzero(PyObject *self)
+ {
+ PyObject *res = PyObject_CallMethod(self, "__nonzero__", "");
+
+ if (res == NULL)
+ return -1;
+ return (int)PyInt_AsLong(res);
+ }
+
+ SLOT0(nb_invert, invert);
+ SLOT1(nb_lshift, lshift, PyObject *, O);
+ SLOT1(nb_rshift, rshift, PyObject *, O);
+ SLOT1(nb_and, and, PyObject *, O);
+ SLOT1(nb_xor, xor, PyObject *, O);
+ SLOT1(nb_or, or, PyObject *, O);
+ /* Not coerce() */
+ SLOT0(nb_int, int);
+ SLOT0(nb_long, long);
+ SLOT0(nb_float, float);
+ SLOT0(nb_oct, oct);
+ SLOT0(nb_hex, hex);
+ SLOT1(nb_inplace_add, iadd, PyObject *, O);
+ SLOT1(nb_inplace_subtract, isub, PyObject *, O);
+ SLOT1(nb_inplace_multiply, imul, PyObject *, O);
+ SLOT1(nb_inplace_divide, idiv, PyObject *, O);
+ SLOT1(nb_inplace_remainder, imod, PyObject *, O);
+ SLOT2(nb_inplace_power, ipow, PyObject *, PyObject *, OO);
+ SLOT1(nb_inplace_lshift, ilshift, PyObject *, O);
+ SLOT1(nb_inplace_rshift, irshift, PyObject *, O);
+ SLOT1(nb_inplace_and, iand, PyObject *, O);
+ SLOT1(nb_inplace_xor, ixor, PyObject *, O);
+ SLOT1(nb_inplace_or, ior, PyObject *, O);
+
+ static int
+ slot_tp_compare(PyObject *self, PyObject *other)
+ {
+ PyObject *res = PyObject_CallMethod(self, "__cmp__", "O", other);
+ long r;
+
+ if (res == NULL)
+ return -1;
+ r = PyInt_AsLong(res);
+ Py_DECREF(res);
+ return (int)r;
+ }
+
+ SLOT0(tp_repr, repr);
+
+ static long
+ slot_tp_hash(PyObject *self)
+ {
+ PyObject *res = PyObject_CallMethod(self, "__hash__", "");
+ long h;
+
+ if (res == NULL)
+ return -1;
+ h = PyInt_AsLong(res);
+ if (h == -1 && !PyErr_Occurred())
+ h = -2;
+ return h;
+ }
+
+ static PyObject *
+ slot_tp_call(PyObject *self, PyObject *args, PyObject *kwds)
+ {
+ PyObject *meth = PyObject_GetAttrString(self, "__call__");
+ PyObject *res;
+
+ if (meth == NULL)
+ return NULL;
+ res = PyObject_Call(meth, args, kwds);
+ Py_DECREF(meth);
+ return res;
+ }
+
+ SLOT0(tp_str, str);
+
+ /* Map rich comparison operators to their __xx__ namesakes */
+ static char *name_op[] = {
+ "__lt__",
+ "__le__",
+ "__eq__",
+ "__ne__",
+ "__gt__",
+ "__ge__",
+ };
+
+ static PyObject *
+ slot_tp_richcompare(PyObject *self, PyObject *other, int op)
+ {
+ PyObject *meth = PyObject_GetAttrString(self, name_op[op]);
+ PyObject *res;
+
+ if (meth == NULL)
+ return NULL;
+ res = PyObject_CallFunction(meth, "O", other);
+ Py_DECREF(meth);
+ return res;
+ }
+
+ SLOT0(tp_iter, iter);
+
+ static PyObject *
+ slot_tp_iternext(PyObject *self)
+ {
+ return PyObject_CallMethod(self, "next", "");
+ }
+
+ static void
+ override_slots(PyTypeObject *type, PyObject *dict)
+ {
+ PySequenceMethods *sq = type->tp_as_sequence;
+ PyMappingMethods *mp = type->tp_as_mapping;
+ PyNumberMethods *nb = type->tp_as_number;
+
+ #define SQSLOT(OPNAME, SLOTNAME) \
+ if (PyDict_GetItemString(dict, "__" #OPNAME "__")) { \
+ sq->SLOTNAME = slot_##SLOTNAME; \
+ }
+
+ #define MPSLOT(OPNAME, SLOTNAME) \
+ if (PyDict_GetItemString(dict, "__" #OPNAME "__")) { \
+ mp->SLOTNAME = slot_##SLOTNAME; \
+ }
+
+ #define NBSLOT(OPNAME, SLOTNAME) \
+ if (PyDict_GetItemString(dict, "__" #OPNAME "__")) { \
+ nb->SLOTNAME = slot_##SLOTNAME; \
+ }
+
+ #define TPSLOT(OPNAME, SLOTNAME) \
+ if (PyDict_GetItemString(dict, "__" #OPNAME "__")) { \
+ type->SLOTNAME = slot_##SLOTNAME; \
+ }
+
+ SQSLOT(len, sq_length);
+ SQSLOT(add, sq_concat);
+ SQSLOT(mul, sq_repeat);
+ SQSLOT(getitem, sq_item);
+ SQSLOT(getslice, sq_slice);
+ SQSLOT(setitem, sq_ass_item);
+ SQSLOT(setslice, sq_ass_slice);
+ SQSLOT(contains, sq_contains);
+ SQSLOT(iadd, sq_inplace_concat);
+ SQSLOT(imul, sq_inplace_repeat);
+
+ MPSLOT(len, mp_length);
+ MPSLOT(getitem, mp_subscript);
+ MPSLOT(setitem, mp_ass_subscript);
+
+ NBSLOT(add, nb_add);
+ NBSLOT(sub, nb_subtract);
+ NBSLOT(mul, nb_multiply);
+ NBSLOT(div, nb_divide);
+ NBSLOT(mod, nb_remainder);
+ NBSLOT(divmod, nb_divmod);
+ NBSLOT(pow, nb_power);
+ NBSLOT(neg, nb_negative);
+ NBSLOT(pos, nb_positive);
+ NBSLOT(abs, nb_absolute);
+ NBSLOT(nonzero, nb_nonzero);
+ NBSLOT(invert, nb_invert);
+ NBSLOT(lshift, nb_lshift);
+ NBSLOT(rshift, nb_rshift);
+ NBSLOT(and, nb_and);
+ NBSLOT(xor, nb_xor);
+ NBSLOT(or, nb_or);
+ /* Not coerce() */
+ NBSLOT(int, nb_int);
+ NBSLOT(long, nb_long);
+ NBSLOT(float, nb_float);
+ NBSLOT(oct, nb_oct);
+ NBSLOT(hex, nb_hex);
+ NBSLOT(iadd, nb_inplace_add);
+ NBSLOT(isub, nb_inplace_subtract);
+ NBSLOT(imul, nb_inplace_multiply);
+ NBSLOT(idiv, nb_inplace_divide);
+ NBSLOT(imod, nb_inplace_remainder);
+ NBSLOT(ipow, nb_inplace_power);
+ NBSLOT(ilshift, nb_inplace_lshift);
+ NBSLOT(irshift, nb_inplace_rshift);
+ NBSLOT(iand, nb_inplace_and);
+ NBSLOT(ixor, nb_inplace_xor);
+ NBSLOT(ior, nb_inplace_or);
+
+ if (PyDict_GetItemString(dict, "__str__") ||
+ PyDict_GetItemString(dict, "__repr__"))
+ type->tp_print = NULL;
+
+ TPSLOT(cmp, tp_compare);
+ TPSLOT(repr, tp_repr);
+ TPSLOT(hash, tp_hash);
+ TPSLOT(call, tp_call);
+ TPSLOT(str, tp_str);
+ TPSLOT(lt, tp_richcompare);
+ TPSLOT(le, tp_richcompare);
+ TPSLOT(eq, tp_richcompare);
+ TPSLOT(ne, tp_richcompare);
+ TPSLOT(gt, tp_richcompare);
+ TPSLOT(ge, tp_richcompare);
+ TPSLOT(iter, tp_iter);
+ TPSLOT(next, tp_iternext);
}