[Python-checkins] CVS: python/dist/src/Objects typeobject.c,2.98,2.99

Guido van Rossum gvanrossum@users.sourceforge.net
Thu, 11 Oct 2001 11:33:55 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv25854/Objects

Modified Files:
	typeobject.c 
Log Message:
Another step in the right direction: when a new class's attribute
corresponding to a dispatch slot (e.g. __getitem__ or __add__) is set,
calculate the proper dispatch slot and propagate the change to all
subclasses.  Because of multiple inheritance, there's no easy way to
avoid always recursing down the tree of subclasses.  Who cares?

(There's more to do, but this works.  There's also a test for this now.)



Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.98
retrieving revision 2.99
diff -C2 -d -r2.98 -r2.99
*** typeobject.c	2001/10/09 20:17:57	2.98
--- typeobject.c	2001/10/11 18:33:53	2.99
***************
*** 677,681 ****
  staticforward void object_dealloc(PyObject *);
  staticforward int object_init(PyObject *, PyObject *, PyObject *);
! staticforward int update_slot(PyTypeObject *, PyObject *, PyObject *);
  staticforward void fixup_slot_dispatchers(PyTypeObject *);
  
--- 677,681 ----
  staticforward void object_dealloc(PyObject *);
  staticforward int object_init(PyObject *, PyObject *, PyObject *);
! staticforward int update_slot(PyTypeObject *, PyObject *);
  staticforward void fixup_slot_dispatchers(PyTypeObject *);
  
***************
*** 1108,1112 ****
  		if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
  			return -1;
! 		return update_slot(type, name, value);
  	}
  	PyErr_SetString(PyExc_TypeError, "can't set static type attributes");
--- 1108,1112 ----
  		if (PyObject_GenericSetAttr((PyObject *)type, name, value) < 0)
  			return -1;
! 		return update_slot(type, name);
  	}
  	PyErr_SetString(PyExc_TypeError, "can't set static type attributes");
***************
*** 3680,3683 ****
--- 3680,3684 ----
  	void *function;
  	wrapperfunc wrapper;
+ 	PyObject *name_strobj;
  } slotdef;
  
***************
*** 3798,3804 ****
  
  	TPSLOT("__str__", tp_str, slot_tp_str, wrap_unaryfunc),
- 	TPSLOT("__str__", tp_print, NULL, NULL),
  	TPSLOT("__repr__", tp_repr, slot_tp_repr, wrap_unaryfunc),
- 	TPSLOT("__repr__", tp_print, NULL, NULL),
  	TPSLOT("__cmp__", tp_compare, _PyObject_SlotCompare, wrap_cmpfunc),
  	TPSLOT("__hash__", tp_hash, slot_tp_hash, wrap_hashfunc),
--- 3799,3803 ----
***************
*** 3828,3860 ****
  };
  
- static int
- update_slot(PyTypeObject *type, PyObject *name, PyObject *value)
- {
- 	char *s;
- 	int n;
- 	slotdef *p;
- 	void **ptr;
- 
- 	assert(type->tp_flags & Py_TPFLAGS_HEAPTYPE);
- 	if (value == NULL)
- 		return 0; /* Can't unset a slot */
- 	s = PyString_AsString(name);
- 	n = PyString_Size(name);
- 	if (s == NULL || n < 0) {
- 		/* Shouldn't happen, but can't be bothered */
- 		PyErr_Clear();
- 		return 0;
- 	}
- 	if (!(s[0] == '_' && s[1] == '_' && s[n-1] == '_' && s[n-2] == '_'))
- 		return 0;
- 	for (p = slotdefs; p->name; p++) {
- 		if (!strcmp(p->name, s)) {
- 			ptr = (void **) ((char *)type + p->offset);
- 			*ptr = p->function;
- 		}
- 	}
- 	return 0;
- }
- 
  static void **
  slotptr(PyTypeObject *type, int offset)
--- 3827,3830 ----
***************
*** 3882,3885 ****
--- 3852,3968 ----
  		ptr += offset;
  	return (void **)ptr;
+ }
+ 
+ staticforward int recurse_down_subclasses(PyTypeObject *type, int offset);
+ 
+ static int
+ update_one_slot(PyTypeObject *type, int offset)
+ {
+ 	slotdef *p;
+ 	PyObject *descr;
+ 	PyWrapperDescrObject *d;
+ 	void *generic = NULL, *specific = NULL;
+ 	int use_generic = 0;
+ 	void **ptr;
+ 
+ 	for (p = slotdefs; p->name; p++) {
+ 		if (p->offset != offset)
+ 			continue;
+ 		descr = _PyType_Lookup(type, p->name_strobj);
+ 		if (descr == NULL)
+ 			continue;
+ 		ptr = slotptr(type, p->offset);
+ 		if (ptr == NULL)
+ 			continue;
+ 		generic = p->function;
+ 		if (descr->ob_type == &PyWrapperDescr_Type) {
+ 			d = (PyWrapperDescrObject *)descr;
+ 			if (d->d_base->wrapper == p->wrapper &&
+ 			    PyType_IsSubtype(type, d->d_type)) {
+ 				if (specific == NULL ||
+ 				    specific == d->d_wrapped)
+ 					specific = d->d_wrapped;
+ 				else
+ 					use_generic = 1;
+ 			}
+ 		}
+ 		else
+ 			use_generic = 1;
+ 		if (specific && !use_generic)
+ 			*ptr = specific;
+ 		else
+ 			*ptr = generic;
+ 	}
+ 	if (recurse_down_subclasses(type, offset) < 0)
+ 		return -1;
+ 	return 0;
+ }
+ 
+ static int
+ recurse_down_subclasses(PyTypeObject *type, int offset)
+ {
+ 	PyTypeObject *subclass;
+ 	PyObject *ref, *subclasses;
+ 	int i, n;
+ 
+ 	subclasses = type->tp_subclasses;
+ 	if (subclasses == NULL)
+ 		return 0;
+ 	assert(PyList_Check(subclasses));
+ 	n = PyList_GET_SIZE(subclasses);
+ 	for (i = 0; i < n; i++) {
+ 		ref = PyList_GET_ITEM(subclasses, i);
+ 		assert(PyWeakref_CheckRef(ref));
+ 		subclass = (PyTypeObject *)PyWeakref_GET_OBJECT(ref);
+ 		if (subclass == NULL)
+ 			continue;
+ 		assert(PyType_Check(subclass));
+ 		if (update_one_slot(subclass, offset) < 0)
+ 			return -1;
+ 	}
+ 	return 0;
+ }
+ 
+ static void
+ init_name_strobj(void)
+ {
+ 	slotdef *p;
+ 	static int initialized = 0;
+ 
+ 	if (initialized)
+ 		return;
+ 	for (p = slotdefs; p->name; p++) {
+ 		p->name_strobj = PyString_InternFromString(p->name);
+ 		if (!p->name_strobj)
+ 			Py_FatalError("XXX ouch");
+ 	}
+ 	initialized = 1;
+ }
+ 
+ static void
+ collect_offsets(PyObject *name, int offsets[])
+ {
+ 	slotdef *p;
+ 
+ 	init_name_strobj();
+ 	for (p = slotdefs; p->name; p++) {
+ 		if (name == p->name_strobj)
+ 			*offsets++ = p->offset;
+ 	}
+ 	*offsets = 0;
+ }
+ 
+ static int
+ update_slot(PyTypeObject *type, PyObject *name)
+ {
+ 	int offsets[10];
+ 	int *ip;
+ 
+ 	collect_offsets(name, offsets);
+ 	for (ip = offsets; *ip; ip++) {
+ 		if (update_one_slot(type, *ip) < 0)
+ 			return -1;
+ 	}
+ 	return 0;
  }