[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.16.8.30,2.16.8.31
Guido van Rossum
gvanrossum@users.sourceforge.net
Tue, 05 Jun 2001 18:02:23 -0700
Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv29594/Objects
Modified Files:
Tag: descr-branch
typeobject.c
Log Message:
A VERY preliminary of multiple inheritance. Lots of stuff doesn't
work (hey, __bases__ doesn't even reflect the auxiliary base classes!)
but it allows me to write and test some simple mix-in classes.
Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.16.8.30
retrieving revision 2.16.8.31
diff -C2 -r2.16.8.30 -r2.16.8.31
*** typeobject.c 2001/06/05 19:31:56 2.16.8.30
--- typeobject.c 2001/06/06 01:02:20 2.16.8.31
***************
*** 139,142 ****
--- 139,143 ----
staticforward void override_slots(PyTypeObject *type, PyObject *dict);
+ staticforward PyTypeObject *solid_base(PyTypeObject *type);
typedef struct {
***************
*** 150,153 ****
--- 151,167 ----
} etype;
+ static int
+ issubtype(PyTypeObject *a, PyTypeObject *b)
+ {
+ if (b == &PyBaseObject_Type)
+ return 1; /* Every type is an implicit subtype of this */
+ while (a != NULL) {
+ if (a == b)
+ return 1;
+ a = a->tp_base;
+ }
+ return 0;
+ }
+
/* TypeType's initializer; called when a type is subclassed */
static int
***************
*** 159,163 ****
etype *et;
struct memberlist *mp;
! int i, nslots, slotoffset, allocsize;
assert(PyType_Check(self));
--- 173,177 ----
etype *et;
struct memberlist *mp;
! int i, n, nslots, slotoffset, allocsize;
assert(PyType_Check(self));
***************
*** 172,196 ****
"usage: TypeType(name, bases, dict) ");
return -1;
- }
- if (PyTuple_GET_SIZE(bases) > 1) {
- PyErr_SetString(PyExc_TypeError,
- "can't multiple-inherit from types (yet)");
- return -1;
}
! if (PyTuple_GET_SIZE(bases) < 1)
! base = &PyBaseObject_Type;
! else {
base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0);
! if (!PyType_Check((PyObject *)base)) {
! PyErr_SetString(PyExc_TypeError,
! "base type must be a type");
! return -1;
! }
! if (base->tp_new == NULL) {
! PyErr_SetString(PyExc_TypeError,
! "base type must have a tp_new slot");
! return -1;
}
}
/* Check for a __slots__ sequence variable in dict, and count it */
--- 186,226 ----
"usage: TypeType(name, bases, dict) ");
return -1;
}
! n = PyTuple_GET_SIZE(bases);
! if (n > 0) {
! PyTypeObject *winner, *candidate, *base_i;
base = (PyTypeObject *)PyTuple_GET_ITEM(bases, 0);
! winner = &PyBaseObject_Type;
! for (i = 0; i < n; i++) {
! base_i = (PyTypeObject *)PyTuple_GET_ITEM(bases, i);
! if (!PyType_Check((PyObject *)base_i)) {
! PyErr_SetString(
! PyExc_TypeError,
! "bases must be types");
! return -1;
! }
! candidate = solid_base(base_i);
! if (issubtype(winner, candidate))
! ;
! else if (issubtype(candidate, winner)) {
! winner = candidate;
! base = base_i;
! }
! else {
! PyErr_SetString(
! PyExc_TypeError,
! "multiple bases have "
! "instance lay-out conflict");
! return -1;
! }
}
}
+ else
+ base = &PyBaseObject_Type;
+ if (base->tp_new == NULL) {
+ PyErr_SetString(PyExc_TypeError,
+ "base type must have a tp_new slot");
+ return -1;
+ }
/* Check for a __slots__ sequence variable in dict, and count it */
***************
*** 286,289 ****
--- 316,333 ----
add_members(type, et->members);
+ /* XXX This is close, but not quite right! */
+ if (n > 1) {
+ PyTypeObject *t;
+ for (i = n; --i >= 0; ) {
+ t = (PyTypeObject *) PyTuple_GET_ITEM(bases, i);
+ x = PyObject_CallMethod(type->tp_dict,
+ "update", "O", t->tp_dict);
+ if (x == NULL) {
+ Py_DECREF(type);
+ return -1;
+ }
+ }
+ }
+
x = PyObject_CallMethod(type->tp_dict, "update", "O", dict);
if (x == NULL) {
***************
*** 297,311 ****
static int
! issubtype(PyTypeObject *a, PyTypeObject *b)
{
! while (a != b) {
! a = a->tp_base;
! if (a == NULL)
! return 0;
! }
return 1;
}
! #define ISSUBTYPE(a, b) issubtype(a, b)
static PyObject *
--- 341,380 ----
static int
! extra_ivars(PyTypeObject *type, PyTypeObject *base)
{
! int t_size = type->tp_basicsize;
! int b_size = base->tp_basicsize;
!
! /* XXX what about tp_itemsize? */
! assert((type->tp_flags & Py_TPFLAGS_GC) >=
! (base->tp_flags & Py_TPFLAGS_GC)); /* base has GC, type not! */
! if (type->tp_flags & Py_TPFLAGS_GC)
! t_size -= PyGC_HEAD_SIZE;
! if (base->tp_flags & Py_TPFLAGS_GC)
! b_size -= PyGC_HEAD_SIZE;
! assert(t_size >= b_size); /* type smaller than base! */
! if (t_size == b_size)
! return 0;
! if (type->tp_dictoffset != 0 && base->tp_dictoffset == 0 &&
! type->tp_dictoffset == b_size &&
! t_size == b_size + sizeof(PyObject *))
! return 0; /* "Forgive" adding a __dict__ only */
return 1;
}
! static PyTypeObject *
! solid_base(PyTypeObject *type)
! {
! PyTypeObject *base;
!
! if (type->tp_base)
! base = solid_base(type->tp_base);
! else
! base = &PyBaseObject_Type;
! if (extra_ivars(type, base))
! return type;
! else
! return base;
! }
static PyObject *
***************
*** 326,332 ****
PyObject *base_i = PyTuple_GET_ITEM(bases, i);
PyTypeObject *type_i = base_i->ob_type;
! if (ISSUBTYPE(metatype, type_i))
continue;
! if (ISSUBTYPE(type_i, metatype)) {
metatype = type_i;
continue;
--- 395,401 ----
PyObject *base_i = PyTuple_GET_ITEM(bases, i);
PyTypeObject *type_i = base_i->ob_type;
! if (issubtype(metatype, type_i))
continue;
! if (issubtype(type_i, metatype)) {
metatype = type_i;
continue;