[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.8,2.16.8.9
Guido van Rossum
gvanrossum@users.sourceforge.net
Fri, 04 May 2001 10:09:40 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv31686
Modified Files:
Tag: descr-branch
typeobject.c
Log Message:
Basic support for single inheritance at the C level.
NOTE: This only works for base classes that support subtyping. This
requires a tp_construct slot that takes an already-allocated object as
first argument. I'll check in experimental support for subclassing
list and dict next.
Instructions:
Define and initialize a static type struct like normal, but leave most
slots empty. Put the address of the base class in your tp_base slot.
Call PyType_InitDict() for your type *before creating the first
instance*. This will copy all the slots from the base class into your
derived class. It will also initialize your tp_dict.
To create an instance, use PyObject_CallObject() to call your type
object. I'll check in an example module soon.
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.8
retrieving revision 2.16.8.9
diff -C2 -r2.16.8.8 -r2.16.8.9
*** typeobject.c 2001/05/01 21:04:21 2.16.8.8
--- typeobject.c 2001/05/04 17:09:38 2.16.8.9
***************
*** 14,18 ****
type_bases(PyTypeObject *type, void *context)
{
! return PyTuple_New(0);
}
--- 14,21 ----
type_bases(PyTypeObject *type, void *context)
{
! if (type->tp_base == NULL)
! return PyTuple_New(0);
! else
! return Py_BuildValue("(O)", type->tp_base);
}
***************
*** 49,52 ****
--- 52,84 ----
static PyObject *
+ type_call(PyTypeObject *type, PyObject *args, PyObject *kwds)
+ {
+ char *dummy = NULL;
+ PyObject *obj, *res;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "", &dummy))
+ return NULL;
+
+ if (type->tp_construct == NULL) {
+ PyErr_Format(PyExc_TypeError,
+ "cannot construct '%.100s' instances",
+ type->tp_name);
+ return NULL;
+ }
+ obj = PyObject_New(PyObject, type);
+ if (obj == NULL)
+ return NULL;
+ res = (type->tp_construct)(obj);
+ if (res != obj) {
+ Py_DECREF(obj);
+ if (res == NULL)
+ return NULL;
+ }
+ if (PyType_IS_GC(type))
+ PyObject_GC_Init(res);
+ return res;
+ }
+
+ static PyObject *
type_getattro(PyTypeObject *type, PyObject *name)
{
***************
*** 108,112 ****
0, /* tp_as_mapping */
0, /* tp_hash */
! 0, /* tp_call */
0, /* tp_str */
(getattrofunc)type_getattro, /* tp_getattro */
--- 140,144 ----
0, /* tp_as_mapping */
0, /* tp_hash */
! (ternaryfunc)type_call, /* tp_call */
0, /* tp_str */
(getattrofunc)type_getattro, /* tp_getattro */
***************
*** 211,222 ****
staticforward int add_operators(PyTypeObject *);
int
PyType_InitDict(PyTypeObject *type)
{
PyObject *dict;
if (type->tp_dict != NULL)
return 0;
! dict = PyDict_New();
if (dict == NULL)
return -1;
--- 243,409 ----
staticforward int add_operators(PyTypeObject *);
+ static int
+ inherit_slots(PyTypeObject *type, PyTypeObject *base)
+ {
+ #undef COPYSLOT
+ #undef COPYNUM
+ #undef COPYSEQ
+ #undef COPYMAP
+ #define COPYSLOT(SLOT) \
+ if (!type->SLOT) type->SLOT = base->SLOT
+
+ #define COPYNUM(SLOT) COPYSLOT(tp_as_number->SLOT)
+ #define COPYSEQ(SLOT) COPYSLOT(tp_as_sequence->SLOT)
+ #define COPYMAP(SLOT) COPYSLOT(tp_as_mapping->SLOT)
+
+ if (type->tp_as_number == NULL)
+ type->tp_as_number = base->tp_as_number;
+ else if (base->tp_as_number) {
+ COPYNUM(nb_add);
+ COPYNUM(nb_subtract);
+ COPYNUM(nb_multiply);
+ COPYNUM(nb_divide);
+ COPYNUM(nb_remainder);
+ COPYNUM(nb_divmod);
+ COPYNUM(nb_power);
+ COPYNUM(nb_negative);
+ COPYNUM(nb_positive);
+ COPYNUM(nb_absolute);
+ COPYNUM(nb_nonzero);
+ COPYNUM(nb_invert);
+ COPYNUM(nb_lshift);
+ COPYNUM(nb_rshift);
+ COPYNUM(nb_and);
+ COPYNUM(nb_xor);
+ COPYNUM(nb_or);
+ COPYNUM(nb_coerce);
+ COPYNUM(nb_int);
+ COPYNUM(nb_long);
+ COPYNUM(nb_float);
+ COPYNUM(nb_oct);
+ COPYNUM(nb_hex);
+ COPYNUM(nb_inplace_add);
+ COPYNUM(nb_inplace_subtract);
+ COPYNUM(nb_inplace_multiply);
+ COPYNUM(nb_inplace_divide);
+ COPYNUM(nb_inplace_remainder);
+ COPYNUM(nb_inplace_power);
+ COPYNUM(nb_inplace_lshift);
+ COPYNUM(nb_inplace_rshift);
+ COPYNUM(nb_inplace_and);
+ COPYNUM(nb_inplace_xor);
+ COPYNUM(nb_inplace_or);
+ }
+
+ if (type->tp_as_sequence == NULL)
+ type->tp_as_sequence = base->tp_as_sequence;
+ else if (base->tp_as_sequence) {
+ COPYSEQ(sq_length);
+ COPYSEQ(sq_concat);
+ COPYSEQ(sq_repeat);
+ COPYSEQ(sq_item);
+ COPYSEQ(sq_slice);
+ COPYSEQ(sq_ass_item);
+ COPYSEQ(sq_ass_slice);
+ COPYSEQ(sq_contains);
+ COPYSEQ(sq_inplace_concat);
+ COPYSEQ(sq_inplace_repeat);
+ }
+
+ if (type->tp_as_mapping == NULL)
+ type->tp_as_mapping = base->tp_as_mapping;
+ else if (base->tp_as_mapping) {
+ COPYMAP(mp_length);
+ COPYMAP(mp_subscript);
+ COPYMAP(mp_ass_subscript);
+ }
+
+ /* Special flag magic */
+ if (!type->tp_as_buffer && base->tp_as_buffer) {
+ type->tp_flags &= ~Py_TPFLAGS_HAVE_GETCHARBUFFER;
+ type->tp_flags |=
+ base->tp_flags & Py_TPFLAGS_HAVE_GETCHARBUFFER;
+ }
+ if (!type->tp_as_sequence && base->tp_as_sequence) {
+ type->tp_flags &= ~Py_TPFLAGS_HAVE_SEQUENCE_IN;
+ type->tp_flags |= base->tp_flags & Py_TPFLAGS_HAVE_SEQUENCE_IN;
+ }
+ if (!(type->tp_flags & Py_TPFLAGS_GC) &&
+ (base->tp_flags & Py_TPFLAGS_GC) &&
+ (type->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE/*GC slots exist*/) &&
+ (!type->tp_traverse && !type->tp_clear)) {
+ type->tp_flags |= Py_TPFLAGS_GC;
+ type->tp_basicsize += PyGC_HEAD_SIZE;
+ COPYSLOT(tp_traverse);
+ COPYSLOT(tp_clear);
+ }
+ if ((type->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS) !=
+ (base->tp_flags & Py_TPFLAGS_HAVE_INPLACEOPS)) {
+ if ((!type->tp_as_number && base->tp_as_number) ||
+ (!type->tp_as_sequence && base->tp_as_sequence)) {
+ type->tp_flags &= ~Py_TPFLAGS_HAVE_INPLACEOPS;
+ if (!type->tp_as_number && !type->tp_as_sequence) {
+ type->tp_flags |= base->tp_flags &
+ Py_TPFLAGS_HAVE_INPLACEOPS;
+ }
+ }
+ /* Wow */
+ }
+ if (!type->tp_as_number && base->tp_as_number) {
+ type->tp_flags &= ~Py_TPFLAGS_CHECKTYPES;
+ type->tp_flags |= base->tp_flags & Py_TPFLAGS_CHECKTYPES;
+ }
+
+ COPYSLOT(tp_name);
+ COPYSLOT(tp_basicsize);
+ COPYSLOT(tp_itemsize);
+ COPYSLOT(tp_dealloc);
+ COPYSLOT(tp_print);
+ COPYSLOT(tp_getattr);
+ COPYSLOT(tp_setattr);
+ COPYSLOT(tp_compare);
+ COPYSLOT(tp_repr);
+ COPYSLOT(tp_hash);
+ COPYSLOT(tp_call);
+ COPYSLOT(tp_str);
+ COPYSLOT(tp_getattro);
+ COPYSLOT(tp_setattro);
+ COPYSLOT(tp_as_buffer);
+ COPYSLOT(tp_flags);
+ COPYSLOT(tp_doc);
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_RICHCOMPARE) {
+ COPYSLOT(tp_richcompare);
+ }
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_WEAKREFS) {
+ COPYSLOT(tp_weaklistoffset);
+ }
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_ITER) {
+ COPYSLOT(tp_iter);
+ COPYSLOT(tp_iternext);
+ }
+ if (type->tp_flags & base->tp_flags & Py_TPFLAGS_HAVE_CLASS) {
+ COPYSLOT(tp_descr_get);
+ COPYSLOT(tp_descr_set);
+ COPYSLOT(tp_construct);
+ }
+
+ return 0;
+ }
+
int
PyType_InitDict(PyTypeObject *type)
{
PyObject *dict;
+ PyTypeObject *base = type->tp_base;
if (type->tp_dict != NULL)
return 0;
! if (base) {
! if (PyType_InitDict(base) < 0)
! return -1;
! dict = PyDict_Copy(base->tp_dict);
! }
! else
! dict = PyDict_New();
if (dict == NULL)
return -1;
***************
*** 246,249 ****
--- 433,443 ----
return -1;
}
+
+ /* Inherit base class slots and methods */
+ if (base) {
+ if (inherit_slots(type, base) < 0)
+ return -1;
+ }
+
return 0;
}