[Python-checkins] CVS: python/dist/src/Objects object.c,2.103,2.104

Neil Schemenauer python-dev@python.org
Wed, 03 Jan 2001 17:48:12 -0800


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

Modified Files:
	object.c 
Log Message:
Changes for PEP 208.  PyObject_Compare has been rewritten.  Instances no
longer get special treatment.  The Py_NotImplemented type is here as well.


Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.103
retrieving revision 2.104
diff -C2 -r2.103 -r2.104
*** object.c	2000/10/24 19:57:45	2.103
--- object.c	2001/01/04 01:48:10	2.104
***************
*** 309,326 ****
  }
  
! static PyObject *
  do_cmp(PyObject *v, PyObject *w)
  {
! 	long c;
! 	/* __rcmp__ actually won't be called unless __cmp__ isn't defined,
! 	   because the check in cmpobject() reverses the objects first.
! 	   This is intentional -- it makes no sense to define cmp(x,y)
! 	   different than -cmp(y,x). */
! 	if (PyInstance_Check(v) || PyInstance_Check(w))
! 		return PyInstance_DoBinOp(v, w, "__cmp__", "__rcmp__", do_cmp);
! 	c = PyObject_Compare(v, w);
! 	if (c && PyErr_Occurred())
! 		return NULL;
! 	return PyInt_FromLong(c);
  }
  
--- 309,402 ----
  }
  
! #define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
! 				Py_TPFLAGS_NEWSTYLENUMBER)
! 
! static int
! cmp_to_int(PyObject *result)
! {
! 	int c;
! 	if (result == NULL)
! 		return -1;
! 	if (!PyInt_Check(result)) {
! 	    PyErr_SetString(PyExc_TypeError,
! 			"comparison did not return an int");
! 	    return -1;
! 	}
! 	c = PyInt_AS_LONG(result);
! 	Py_DECREF(result);
! 	return (c < 0) ? -1 : (c > 0) ? 1 : 0;	
! }
! 
! static int
  do_cmp(PyObject *v, PyObject *w)
  {
! 	PyNumberMethods *mv, *mw;
! 	PyObject *x;
! 	int c;
! 
! 	/* new style nb_cmp gets priority */
! 	mv = v->ob_type->tp_as_number;
! 	if (mv != NULL && NEW_STYLE_NUMBER(v) && mv->nb_cmp) {
! 		x = (*mv->nb_cmp)(v, w);
! 		if (x != Py_NotImplemented)
! 			return cmp_to_int(x);
! 		Py_DECREF(x);
! 	}
! 	mw = w->ob_type->tp_as_number;
! 	if (mw != NULL && NEW_STYLE_NUMBER(w) && mw->nb_cmp) {
! 		x = (*mw->nb_cmp)(v, w);
! 		if (x != Py_NotImplemented)
! 			return cmp_to_int(x);
! 		Py_DECREF(x);
! 	}
! 	/* fall back to tp_compare */
! 	if (v->ob_type == w->ob_type) {
! 		if (v->ob_type->tp_compare != NULL) {
! 			return (*v->ob_type->tp_compare)(v, w);
! 		}
! 		else {
! 			Py_uintptr_t iv = (Py_uintptr_t)v;
! 			Py_uintptr_t iw = (Py_uintptr_t)w;
! 			return (iv < iw) ? -1 : (iv > iw) ? 1 : 0;
! 		}
! 	}
! 	if (PyUnicode_Check(v) || PyUnicode_Check(w)) {
! 	    c = PyUnicode_Compare(v, w);
! 	    if (c == -1 &&
! 		PyErr_Occurred() &&
! 		PyErr_ExceptionMatches(PyExc_TypeError))
! 		/* TypeErrors are ignored: if Unicode coercion
! 		fails due to one of the arguments not having
! 		the right type, we continue as defined by the
! 		coercion protocol (see above). Luckily,
! 		decoding errors are reported as ValueErrors and
! 		are not masked by this technique. */
! 		PyErr_Clear();
! 	    else
! 		return c;
! 	}
! 	/* fall back to coercion */
! 	if (mv && mw && (!NEW_STYLE_NUMBER(v) || !NEW_STYLE_NUMBER(w))) {
! 		/* old style operand, both operations numeric, coerce  */
! 		int err = PyNumber_CoerceEx(&v, &w);
! 		if (err < 0)
! 			return -1;
! 		if (err == 0) {
! 			if (v->ob_type->tp_compare) {
! 				c = (*v->ob_type->tp_compare)(v, w);
! 			}
! 			else {
! 				Py_uintptr_t iv = (Py_uintptr_t)v;
! 				Py_uintptr_t iw = (Py_uintptr_t)w;
! 				c = (iv < iw) ? -1 : (iv > iw) ? 1 : 0;
! 			}
! 			Py_DECREF(v);
! 			Py_DECREF(w);
! 			return c;
! 		}
! 	}
! 	/* last resort, use type names */
! 	c = strcmp(v->ob_type->tp_name, w->ob_type->tp_name);
! 	return (c < 0) ? -1: (c > 0) ? 1 : 0;
  }
  
***************
*** 402,508 ****
  	if (v == w)
  		return 0;
! 	if (PyInstance_Check(v) || PyInstance_Check(w)) {
! 		PyObject *res;
! 		int c;
! 		if (!PyInstance_Check(v))
! 			return -PyObject_Compare(w, v);
! 		_PyCompareState_nesting++;
! 		if (_PyCompareState_nesting > NESTING_LIMIT) {
! 			PyObject *inprogress, *pair;
! 
! 			inprogress = get_inprogress_dict();
! 			if (inprogress == NULL) {
! 				_PyCompareState_nesting--;
! 				return -1;
! 			}
! 			pair = make_pair(v, w);
! 			if (PyDict_GetItem(inprogress, pair)) {
! 				/* already comparing these objects.  assume
! 				   they're equal until shown otherwise */
! 				Py_DECREF(pair);
! 				_PyCompareState_nesting--;
! 				return 0;
! 			}
! 			if (PyDict_SetItem(inprogress, pair, pair) == -1) {
! 				_PyCompareState_nesting--;
! 				return -1;
! 			}
! 			res = do_cmp(v, w);
! 			/* XXX DelItem shouldn't fail */
! 			PyDict_DelItem(inprogress, pair);
! 			Py_DECREF(pair);
! 		} else {
! 			res = do_cmp(v, w);
! 		}
! 		_PyCompareState_nesting--;
! 		if (res == NULL)
! 			return -1;
! 		if (!PyInt_Check(res)) {
! 			Py_DECREF(res);
! 			PyErr_SetString(PyExc_TypeError,
! 					"comparison did not return an int");
! 			return -1;
! 		}
! 		c = PyInt_AsLong(res);
! 		Py_DECREF(res);
! 		return (c < 0) ? -1 : (c > 0) ? 1 : 0;	
! 	}
! 	if ((vtp = v->ob_type) != (wtp = w->ob_type)) {
! 		char *vname = vtp->tp_name;
! 		char *wname = wtp->tp_name;
! 		if (vtp->tp_as_number != NULL && wtp->tp_as_number != NULL) {
! 			int err;
! 			err = PyNumber_CoerceEx(&v, &w);
! 			if (err < 0)
! 				return -1;
! 			else if (err == 0) {
! 				int cmp;
! 				vtp = v->ob_type;
! 				if (vtp->tp_compare == NULL)
! 					cmp = (v < w) ? -1 : 1;
! 				else
! 					cmp = (*vtp->tp_compare)(v, w);
! 				Py_DECREF(v);
! 				Py_DECREF(w);
! 				return cmp;
! 			}
! 		}
! 		else if (PyUnicode_Check(v) || PyUnicode_Check(w)) {
! 			int result = PyUnicode_Compare(v, w);
! 			if (result == -1 && PyErr_Occurred() && 
! 			    PyErr_ExceptionMatches(PyExc_TypeError))
! 				/* TypeErrors are ignored: if Unicode coercion
! 				fails due to one of the arguments not
! 			 	having the right type, we continue as
! 				defined by the coercion protocol (see
! 				above). Luckily, decoding errors are
! 				reported as ValueErrors and are not masked
! 				by this technique. */
! 				PyErr_Clear();
! 			else
! 				return result;
! 		}
! 		else if (vtp->tp_as_number != NULL)
! 			vname = "";
! 		else if (wtp->tp_as_number != NULL)
! 			wname = "";
! 		/* Numerical types compare smaller than all other types */
! 		return strcmp(vname, wname);
! 	}
! 	if (vtp->tp_compare == NULL) {
! 		Py_uintptr_t iv = (Py_uintptr_t)v;
! 		Py_uintptr_t iw = (Py_uintptr_t)w;
! 		return (iv < iw) ? -1 : 1;
! 	}
  	_PyCompareState_nesting++;
! 	if (_PyCompareState_nesting > NESTING_LIMIT
! 	    && (vtp->tp_as_mapping 
! 		|| (vtp->tp_as_sequence && !PyString_Check(v)))) {
  		PyObject *inprogress, *pair;
  
  		inprogress = get_inprogress_dict();
  		if (inprogress == NULL) {
! 			_PyCompareState_nesting--;
! 			return -1;
  		}
  		pair = make_pair(v, w);
--- 478,495 ----
  	if (v == w)
  		return 0;
! 	vtp = v->ob_type;
! 	wtp = w->ob_type;
  	_PyCompareState_nesting++;
! 	if (_PyCompareState_nesting > NESTING_LIMIT &&
! 		(vtp->tp_as_mapping
! 		 || PyInstance_Check(v)
! 		 || (vtp->tp_as_sequence && !PyString_Check(v)))) {
! 		/* try to detect circular data structures */
  		PyObject *inprogress, *pair;
  
  		inprogress = get_inprogress_dict();
  		if (inprogress == NULL) {
!                         result = -1;
!                         goto exit_cmp;
  		}
  		pair = make_pair(v, w);
***************
*** 511,527 ****
  			   they're equal until shown otherwise */
  			Py_DECREF(pair);
! 			_PyCompareState_nesting--;
! 			return 0;
  		}
  		if (PyDict_SetItem(inprogress, pair, pair) == -1) {
! 			_PyCompareState_nesting--;
! 			return -1;
  		}
! 		result = (*vtp->tp_compare)(v, w);
! 		PyDict_DelItem(inprogress, pair); /* XXX shouldn't fail */
  		Py_DECREF(pair);
- 	} else {
- 		result = (*vtp->tp_compare)(v, w);
  	}
  	_PyCompareState_nesting--;
  	return result;
--- 498,517 ----
  			   they're equal until shown otherwise */
  			Py_DECREF(pair);
!                         result = 0;
!                         goto exit_cmp;
  		}
  		if (PyDict_SetItem(inprogress, pair, pair) == -1) {
!                         result = -1;
!                         goto exit_cmp;
  		}
! 		result = do_cmp(v, w);
! 		/* XXX DelItem shouldn't fail */
! 		PyDict_DelItem(inprogress, pair);
  		Py_DECREF(pair);
  	}
+ 	else {
+ 		result = do_cmp(v, w);
+ 	}
+ exit_cmp:
  	_PyCompareState_nesting--;
  	return result;
***************
*** 916,919 ****
--- 906,940 ----
  PyObject _Py_NoneStruct = {
  	PyObject_HEAD_INIT(&PyNothing_Type)
+ };
+ 
+ /* NotImplemented is an object that can be used to signal that an
+    operation is not implemented for the given type combination. */
+ 
+ static PyObject *
+ NotImplemented_repr(PyObject *op)
+ {
+ 	return PyString_FromString("NotImplemented");
+ }
+ 
+ static PyTypeObject PyNotImplemented_Type = {
+ 	PyObject_HEAD_INIT(&PyType_Type)
+ 	0,
+ 	"NotImplemented",
+ 	0,
+ 	0,
+ 	0,		/*tp_dealloc*/ /*never called*/
+ 	0,		/*tp_print*/
+ 	0,		/*tp_getattr*/
+ 	0,		/*tp_setattr*/
+ 	0,		/*tp_compare*/
+ 	(reprfunc)NotImplemented_repr, /*tp_repr*/
+ 	0,		/*tp_as_number*/
+ 	0,		/*tp_as_sequence*/
+ 	0,		/*tp_as_mapping*/
+ 	0,		/*tp_hash */
+ };
+ 
+ PyObject _Py_NotImplementedStruct = {
+ 	PyObject_HEAD_INIT(&PyNotImplemented_Type)
  };