diff -rc py_cvs/dist/src/Include/abstract.h py_coerce/Include/abstract.h
*** py_cvs/dist/src/Include/abstract.h	Sun Sep  3 19:44:09 2000
--- py_coerce/Include/abstract.h	Sat Dec  9 16:15:30 2000
***************
*** 470,475 ****
--- 470,486 ----
  
         */
  
+      DL_IMPORT(PyObject *) PyNumber_Compare(PyObject *o1, PyObject *o2);
+ 
+        /*
+ 	  Returns the result of comparing o1 and o2, or null on failure.
+ 	  This is the equivalent of the Python expression: cmp(o1,o2)
+ 
+ 	  XXX This should take a third argument as per the rich comparison
+ 	  proposal.
+ 
+        */
+ 
       DL_IMPORT(PyObject *) PyNumber_Add(PyObject *o1, PyObject *o2);
  
         /*
diff -rc py_cvs/dist/src/Include/classobject.h py_coerce/Include/classobject.h
*** py_cvs/dist/src/Include/classobject.h	Sun Sep  3 19:44:09 2000
--- py_coerce/Include/classobject.h	Sat Dec  9 16:15:30 2000
***************
*** 59,72 ****
  
  extern DL_IMPORT(int) PyClass_IsSubclass(PyObject *, PyObject *);
  
- extern DL_IMPORT(PyObject *) PyInstance_DoBinOp(PyObject *, PyObject *,
-                                                 char *, char *,
-                                                 PyObject * (*)(PyObject *,
-                                                                PyObject *));
- 
- extern DL_IMPORT(int)
- PyInstance_HalfBinOp(PyObject *, PyObject *, char *, PyObject **,
- 			PyObject * (*)(PyObject *, PyObject *), int);
  
  #ifdef __cplusplus
  }
--- 59,64 ----
diff -rc py_cvs/dist/src/Include/object.h py_coerce/Include/object.h
*** py_cvs/dist/src/Include/object.h	Mon Sep 25 21:41:10 2000
--- py_coerce/Include/object.h	Sat Dec  9 16:15:30 2000
***************
*** 119,124 ****
--- 119,129 ----
  typedef int (*traverseproc)(PyObject *, visitproc, void *);
  
  typedef struct {
+ 	/* For old style numbers all arguments are guaranteed to be of the
+ 	   object's type (modulo coercion hacks that is); new style numbers
+ 	   should check both arguments for proper type and implement the
+ 	   necessary conversions in the slots themselves. */
+ 
  	binaryfunc nb_add;
  	binaryfunc nb_subtract;
  	binaryfunc nb_multiply;
***************
*** 153,158 ****
--- 158,169 ----
  	binaryfunc nb_inplace_and;
  	binaryfunc nb_inplace_xor;
  	binaryfunc nb_inplace_or;
+ 
+ 	/* New style number slots; these are only used the
+ 	   Py_TPFLAGS_NEWSTYLENUMBER flag is set */
+ 
+ 	binaryfunc nb_cmp; /* XXX this should be richcmpfunc */
+ 
  } PyNumberMethods;
  
  typedef struct {
***************
*** 322,327 ****
--- 333,341 ----
  /* PySequenceMethods and PyNumberMethods contain in-place operators */
  #define Py_TPFLAGS_HAVE_INPLACEOPS (1L<<3)
  
+ /* PyNumberMethods do their own coercion */
+ #define Py_TPFLAGS_NEWSTYLENUMBER (1L<<4)
+ 
  #define Py_TPFLAGS_DEFAULT  (Py_TPFLAGS_HAVE_GETCHARBUFFER | \
                               Py_TPFLAGS_HAVE_SEQUENCE_IN | \
                               Py_TPFLAGS_HAVE_INPLACEOPS)
***************
*** 434,439 ****
--- 448,473 ----
  
  #define Py_None (&_Py_NoneStruct)
  
+ /*
+ Py_NotImplemented is a singleton used to signal that an operation is
+ not implemented for a given type combination.
+ */
+ 
+ extern DL_IMPORT(PyObject) _Py_NotImplementedStruct; /* Don't use this directly */
+ 
+ #define Py_NotImplemented (&_Py_NotImplementedStruct)
+ 
+ /* Coercion debugging printf */
+ /*#define COERCION_DEBUG*/
+ #ifdef COERCION_DEBUG
+ # ifndef DPRINTF    
+ #  define DPRINTF if (Py_DebugFlag) printf
+ # endif
+ #else
+ # ifndef DPRINTF    
+ #  define DPRINTF if (0) printf
+ # endif
+ #endif
  
  /*
  A common programming style in Python requires the forward declaration
diff -rc py_cvs/dist/src/Objects/abstract.c py_coerce/Objects/abstract.c
*** py_cvs/dist/src/Objects/abstract.c	Thu Oct  5 18:39:25 2000
--- py_coerce/Objects/abstract.c	Sun Dec 10 14:37:30 2000
***************
*** 1,7 ****
--- 1,12 ----
  /* Abstract Object Interface (many thanks to Jim Fulton) */
  
+ 
  #include "Python.h"
  #include <ctype.h>
+ #include "structmember.h" /* we need the offsetof() macro from there */
+ 
+ #define NEW_STYLE_NUMBER(o) PyType_HasFeature((o)->ob_type, \
+ 				Py_TPFLAGS_NEWSTYLENUMBER)
  
  /* Shorthands to return certain errors */
  
***************
*** 281,433 ****
  
  /* Binary operators */
  
! #define BINOP(v, w, opname, ropname, thisfunc) \
! 	if (PyInstance_Check(v) || PyInstance_Check(w)) \
! 		return PyInstance_DoBinOp(v, w, opname, ropname, thisfunc)
  
! PyObject *
! PyNumber_Or(PyObject *v, PyObject *w)
  {
! 	BINOP(v, w, "__or__", "__ror__", PyNumber_Or);
! 	if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_or) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
  	}
! 	return type_error("bad operand type(s) for |");
! }
  
! PyObject *
! PyNumber_Xor(PyObject *v, PyObject *w)
! {
! 	BINOP(v, w, "__xor__", "__rxor__", PyNumber_Xor);
! 	if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_xor) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
  	}
! 	return type_error("bad operand type(s) for ^");
! }
  
! PyObject *
! PyNumber_And(PyObject *v, PyObject *w)
! {
! 	BINOP(v, w, "__and__", "__rand__", PyNumber_And);
! 	if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_and) != NULL)
! 			x = (*f)(v, w);
  		Py_DECREF(v);
  		Py_DECREF(w);
- 		if (f != NULL)
- 			return x;
  	}
! 	return type_error("bad operand type(s) for &");
  }
  
! PyObject *
! PyNumber_Lshift(PyObject *v, PyObject *w)
! {
! 	BINOP(v, w, "__lshift__", "__rlshift__", PyNumber_Lshift);
! 	if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_lshift) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
  	}
! 	return type_error("bad operand type(s) for <<");
! }
  
! PyObject *
! PyNumber_Rshift(PyObject *v, PyObject *w)
! {
! 	BINOP(v, w, "__rshift__", "__rrshift__", PyNumber_Rshift);
! 	if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_rshift) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
  	}
! 	return type_error("bad operand type(s) for >>");
  }
  
  PyObject *
  PyNumber_Add(PyObject *v, PyObject *w)
  {
  	PySequenceMethods *m;
  
- 	BINOP(v, w, "__add__", "__radd__", PyNumber_Add);
  	m = v->ob_type->tp_as_sequence;
! 	if (m && m->sq_concat)
! 		return (*m->sq_concat)(v, w);
! 	else if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_add) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 	return type_error("bad operand type(s) for +");
! }
! 
! PyObject *
! PyNumber_Subtract(PyObject *v, PyObject *w)
! {
! 	BINOP(v, w, "__sub__", "__rsub__", PyNumber_Subtract);
! 	if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_subtract) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
  			return x;
  	}
! 	return type_error("bad operand type(s) for -");
  }
  
  PyObject *
--- 286,705 ----
  
  /* Binary operators */
  
! /* New style number protocol support */
  
! #define NB_SLOT(x) offsetof(PyNumberMethods,x)
! #define NB_BINOP(nb_methods,slot) \
! 		((binaryfunc*)(& ((char*)nb_methods)[slot] ))
! #define NB_TERNOP(nb_methods,slot) \
! 		((ternaryfunc*)(& ((char*)nb_methods)[slot] ))
! 
! /* Forward declarations for new slot emulators. */
! 
! static PyObject *old_compare(PyObject *v, PyObject *w);
! 
! /*
!   Calling scheme used for binary operations:
! 
!   v	w	Action
!   -------------------------------------------------------------------
!   new	new	v.op(v,w), w.op(v,w)
!   new	old	v.op(v,w), coerce(v,w), v.op(v,w)
!   old	new	w.op(v,w), coerce(v,w), v.op(v,w)
!   old	old	coerce(v,w), v.op(v,w)
! 
!   Legend:
!   -------
!   * new == new style number
!   * old == old style number
!   * Action indicates the order in which operations are tried until either
!     a valid result is produced or an error occurs.
! 
!  */
! 
! static PyObject *
! binary_op(PyObject *v, PyObject *w, const int op_slot, const char *operation)
  {
! 	PyNumberMethods *mv, *mw;
! 	register PyObject *x;
! 	register binaryfunc *slot;
! 	int c;
! 	
! 	DPRINTF("binary_op(%s at 0x%lx, %s at 0x%lx,"
! 		" %i,%s);\n",
! 		v->ob_type->tp_name,(long)v,
! 		w->ob_type->tp_name,(long)w,op_slot,operation);
! 
! 	/* First try: v.op(v,w) */
! 	mv = v->ob_type->tp_as_number;
! 	if (mv != NULL) {
! 		DPRINTF(" Trying first number\n");
! 		if (NEW_STYLE_NUMBER(v)) {
! 			DPRINTF("  is a new style number\n");
! 			slot = NB_BINOP(mv,op_slot);
! 			if (*slot) {
! 				x = (*slot)(v,w);
! 				if (x != Py_NotImplemented)
! 					return x;
! 				/* Can't do it... fall through */
! 				Py_DECREF(x);
! 				DPRINTF("  operation not implemented\n");
! 			}
! 			else
! 				DPRINTF("  slot not implemented\n");
! 		}
! 		else
! 			DPRINTF("  is an old style number\n");
  	}
! 	else
! 	    DPRINTF(" First argument is not a number\n");
  
! 	/* Then try: w.op(v,w) */
! 	mw = w->ob_type->tp_as_number;
! 	if (mw != NULL) {
! 		DPRINTF(" Trying second number\n"); 
! 		if (NEW_STYLE_NUMBER(w)) {
! 			DPRINTF("  is a new style number\n");
! 			slot = NB_BINOP(mw,op_slot);
! 			if (*slot) {
! 				x = (*slot)(v,w);
! 				if (x != Py_NotImplemented)
! 					return x;
! 				/* Can't do it... fall through */
! 				Py_DECREF(x);
! 				DPRINTF("  operation not implemented\n");
! 			}
! 			else
! 				DPRINTF("  slot not implemented\n");
! 			/* If both arguments are new style numbers and
! 			   don't implement the requested operation,
! 			   then we have bad operands. */
! 			if (NEW_STYLE_NUMBER(v))
! 				goto badOperands;
! 		}
! 		else
! 			DPRINTF("  is an old style number\n");
  	}
! 	else
! 	    DPRINTF(" Second argument is not a number\n");
  
! 	/* When using old coercion, make sure that the requested slot
! 	   is available on old style numbers or use an emulation. */
! 	if (op_slot > NB_SLOT(nb_hex)) {
! 
! 	    /* Emulation hooks: */
! 	    if (op_slot == NB_SLOT(nb_cmp))
! 		return old_compare(v,w);
! 
! 	    goto badOperands;
! 	}
! 	
! 	DPRINTF(" Reverting to old style coercion\n");
! 	
! 	c = PyNumber_CoerceEx(&v, &w);
! 	if (c < 0)
! 		return NULL;
! 	if (c == 0) {
! 		DPRINTF("  which gives: (%s at 0x%lx) "
! 			"%s (%s at 0x%lx)\n",
! 			v->ob_type->tp_name,(long)v,operation,
! 			w->ob_type->tp_name,(long)w);
! 		if (v->ob_type->tp_as_number != NULL) {
! 			slot = NB_BINOP(v->ob_type->tp_as_number,
! 					op_slot);
! 			if (*slot) {
! 				x = (*slot)(v, w);
! 				Py_DECREF(v);
! 				Py_DECREF(w);
! 				return x;
! 			}
! 		}
! 		/* PyNumber_CoerceEx has incremented the ref counts */
  		Py_DECREF(v);
  		Py_DECREF(w);
  	}
! 	/* if (c == 1), we fall through and report an error;
! 	   ref counts are not incremented by PyNumber_CoerceEx
! 	   in this case */
! 
!  badOperands:
! 	PyErr_Format(PyExc_TypeError, "bad operand type(s) for %s",operation);
! 	return NULL;
  }
  
! /*
!   Calling scheme used for ternary operations:
! 
!   v	w	z	Action
!   -------------------------------------------------------------------
!   new	new	new	v.op(v,w,z), w.op(v,w,z), z.op(v,w,z)
!   new	old	new	v.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
!   old	new	new	w.op(v,w,z), z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
!   old	old	new	z.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
!   new	new	old	v.op(v,w,z), w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
!   new	old	old	v.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
!   old	new	old	w.op(v,w,z), coerce(v,w,z), v.op(v,w,z)
!   old	old	old	coerce(v,w,z), v.op(v,w,z)
! 
!   Legend:
!   -------
!   * new == new style number
!   * old == old style number
!   * Action indicates the order in which operations are tried until either
!     a valid result is produced or an error occurs.
!   * coerce(v,w,z) actually does: coerce(v,w), coerce(v,z), coerce(w,z) and
!     only if z != Py_None; if z == Py_None, then it is treated as absent
!     variable and only coerce(v,w) is tried.
! 
!  */
! 
! static PyObject *
! ternary_op(PyObject *v,
! 	   PyObject *w,
! 	   PyObject *z,
! 	   const int op_slot,
! 	   const char *operation)
! {
! 	PyNumberMethods *mv, *mw, *mz;
! 	register PyObject *x = NULL;
! 	register ternaryfunc *slot;
! 	
! 	DPRINTF("ternary_op(%s at 0x%lx, "
! 		"%s at 0x%lx, %s at 0x%lx, %i,%s);\n",
! 		v->ob_type->tp_name,(long)v,
! 		w->ob_type->tp_name,(long)w,
! 		z->ob_type->tp_name,(long)z,
! 		op_slot,operation);
! 
! 	/* First try: v.op(v,w,z) */
! 	mv = v->ob_type->tp_as_number;
! 	if (mv != NULL) {
! 		DPRINTF(" Trying first number\n");
! 		if (NEW_STYLE_NUMBER(v)) {
! 			DPRINTF("  is a new style number\n");
! 			slot = NB_TERNOP(mv,op_slot);
! 			if (*slot) {
! 				x = (*slot)(v,w,z);
! 				if (x != Py_NotImplemented)
! 					return x;
! 				/* Can't do it... fall through */
! 				Py_DECREF(x);
! 				DPRINTF("  operation not implemented\n");
! 			}
! 			else
! 				DPRINTF("  slot not implemented\n");
! 		}
! 		else
! 			DPRINTF("  is an old style number\n");
  	}
! 	else
! 	    DPRINTF(" First argument is not a number\n");
  
! 	/* Next try: w.op(v,w,z) */
! 	mw = w->ob_type->tp_as_number;
! 	if (mw != NULL) {
! 		DPRINTF(" Trying second number\n"); 
! 		if (NEW_STYLE_NUMBER(w)) {
! 			DPRINTF("  is a new style number\n");
! 			slot = NB_TERNOP(mw,op_slot);
! 			if (*slot) {
! 				x = (*slot)(v,w,z);
! 				if (x != Py_NotImplemented)
! 					return x;
! 				/* Can't do it... fall through */
! 				Py_DECREF(x);
! 				DPRINTF("  operation not implemented\n");
! 			}
! 			else
! 				DPRINTF("  slot not implemented\n");
! 		}
! 		else
! 			DPRINTF("  is an old style number\n");
  	}
! 	else
! 	    DPRINTF(" Second argument is not a number\n");
! 
! 	/* Finally try: z.op(v,w,z) */
! 	mz = z->ob_type->tp_as_number;
! 	if (mz != NULL) {
! 		DPRINTF(" Trying third number\n"); 
! 		if (NEW_STYLE_NUMBER(z)) {
! 			DPRINTF("  is a new style number\n");
! 			slot = NB_TERNOP(mz,op_slot);
! 			if (*slot) {
! 				x = (*slot)(v,w,z);
! 				if (x != Py_NotImplemented)
! 					return x;
! 				/* Can't do it... fall through */
! 				Py_DECREF(x);
! 				DPRINTF("  operation not implemented\n");
! 			}
! 			else
! 				DPRINTF("  slot not implemented\n");
! 		}
! 		else
! 			DPRINTF("  is an old style number\n");
! 	}
! 	else
! 	    DPRINTF(" Third argument is not a number\n");
! 
! 	/* If all three arguments are new style numbers and
! 	   don't implement the requested operation,
! 	   then we have bad operands. */
! 	if (NEW_STYLE_NUMBER(v) && NEW_STYLE_NUMBER(w) &&
! 			(z == Py_None || NEW_STYLE_NUMBER(z))) {
! 		goto badOperands;
! 	}
! 	else {
! 		/* Revert to old style number coercion */
! 		PyObject *v1,*z1,*w2,*z2;
! 		int c;
! 		
! 		DPRINTF(" Reverting to old style coercion\n");
! 
! 		/* When using old coercion, make sure that the requested
! 		   slot is available on old style numbers. */
! 		if (op_slot > NB_SLOT(nb_hex))
! 			goto badOperands;
! 		
! 		c = PyNumber_Coerce(&v, &w);
! 		if (c != 0)
! 			goto error3;
! 
! 		/* Special case: if the third argument is None, it is
! 		   treated as absent argument and not coerced. */
! 		if (z == Py_None) {
! 			DPRINTF("  special case: third argument is None\n");
! 			if (v->ob_type->tp_as_number) {
! 				slot = NB_TERNOP(v->ob_type->tp_as_number,
! 						 op_slot);
! 				if (*slot)
! 					x = (*slot)(v, w, z);
! 				else
! 					c = -1;
! 			}
! 			else
! 				c = -1;
! 			goto error2;
! 		}
! 		v1 = v;
! 		z1 = z;
! 		c = PyNumber_Coerce(&v1, &z1);
! 		if (c != 0)
! 			goto error2;
! 		w2 = w;
! 		z2 = z1;
! 		c = PyNumber_Coerce(&w2, &z2);
! 		if (c != 0)
! 			goto error1;
! 
! 		if (v1->ob_type->tp_as_number != NULL) {
! 			slot = NB_TERNOP(v1->ob_type->tp_as_number,
! 					 op_slot);
! 			if (*slot)
! 				x = (*slot)(v1, w2, z2);
! 			else
! 				c = -1;
! 		}
! 		else
! 			c = -1;
! 
! 		Py_DECREF(w2);
! 		Py_DECREF(z2);
! 	error1:
! 		Py_DECREF(v1);
! 		Py_DECREF(z1);
! 	error2:
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 	error3:
! 		if (c >= 0)
! 			return x;
! 	}
! 	
!  badOperands:
! 	PyErr_Format(PyExc_TypeError, "bad operand type(s) for %s",operation);
! 	return NULL;
  }
  
+ /* XXX I should really wait for David Ascher to help on this one, but
+    to make the patch work *now*, I'll just use this for the time being: */
+ 
+ /* Emulate old method for comparing numeric types using coercion and
+    tp_compare. If coercion doesn't work, we use the type names as
+    comparison basis (like PyObject_Compare() does too). */
+ 
+ static PyObject *
+ old_compare(PyObject *v, PyObject *w)
+ {
+     int err;
+     char *vname, *wname;
+ 
+     DPRINTF("old_compare(%s at 0x%lx, %s at 0x%lx);\n",
+ 	    v->ob_type->tp_name,(long)v,
+ 	    w->ob_type->tp_name,(long)w);
+     err = PyNumber_CoerceEx(&v, &w);
+     if (err < 0)
+ 	    return NULL;
+     else if (err == 0 && v->ob_type->tp_compare) {
+ 	    int cmp;
+ 	    
+ 	    cmp = (*v->ob_type->tp_compare)(v, w);
+ 	    /* XXX Test for errors ? Looks like C types cannot raise
+ 	       exceptions in the compare slot... */
+ 	    Py_DECREF(v);
+ 	    Py_DECREF(w);
+ 	    DPRINTF(" compare slot returned: %i",cmp);
+ 	    return PyInt_FromLong(cmp);
+     }
+     DPRINTF(" using type names for comparison\n");
+     /* Numerical types compare smaller than all other types, XXX They don't
+      * really have to any more though.  Perhaps this should be removed. */
+     if (v->ob_type->tp_as_number) {
+           vname = "";
+     } else {
+           vname = v->ob_type->tp_name;
+     }
+     if (w->ob_type->tp_as_number) {
+           wname = "";
+     } else {
+           wname = w->ob_type->tp_name;
+     }
+     return PyInt_FromLong(strcmp(vname, wname));
+ }
+ 
+ #define BINOP(func, op, op_name) \
+     PyObject * \
+     func(PyObject *v, PyObject *w) \
+     { \
+             return binary_op(v, w, NB_SLOT(op), op_name); \
+     }
+ 
+ BINOP(PyNumber_Compare, nb_cmp, "cmp()")
+ BINOP(PyNumber_Or, nb_or, "|")
+ BINOP(PyNumber_Xor, nb_xor, "^")
+ BINOP(PyNumber_And, nb_and, "&")
+ BINOP(PyNumber_Lshift, nb_lshift, "<<")
+ BINOP(PyNumber_Rshift, nb_rshift, ">>")
+ BINOP(PyNumber_Subtract, nb_subtract, "-")
+ BINOP(PyNumber_Divide, nb_divide, "/")
+ BINOP(PyNumber_Divmod, nb_divmod, "divmod()")
+ 
  PyObject *
  PyNumber_Add(PyObject *v, PyObject *w)
  {
  	PySequenceMethods *m;
  
  	m = v->ob_type->tp_as_sequence;
! 	if (m && m->sq_concat) {
! 		PyObject *x;
! 		x = (*m->sq_concat)(v, w);
! 		if (x != NULL) 
  			return x;
+ 		/* Fall through and give the nb_add slot a chance... */
+ 		PyErr_Clear();
  	}
! 	return binary_op(v,w, NB_SLOT(nb_add), "+");
  }
  
  PyObject *
***************
*** 436,444 ****
  	PyTypeObject *tp = v->ob_type;
  	PySequenceMethods *m;
  
! 	BINOP(v, w, "__mul__", "__rmul__", PyNumber_Multiply);
! 	if (tp->tp_as_number != NULL &&
! 	    w->ob_type->tp_as_sequence != NULL) {
  		/* number*sequence -- swap v and w */
  		PyObject *tmp = v;
  		v = w;
--- 708,715 ----
  	PyTypeObject *tp = v->ob_type;
  	PySequenceMethods *m;
  
! 	if (tp->tp_as_number != NULL && w->ob_type->tp_as_sequence != NULL &&
! 			w->ob_type->tp_as_sequence->sq_repeat) {
  		/* number*sequence -- swap v and w */
  		PyObject *tmp = v;
  		v = w;
***************
*** 446,462 ****
  		tp = v->ob_type;
  	}
  	if (tp->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_multiply) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
  	}
  	m = tp->tp_as_sequence;
  	if (m && m->sq_repeat) {
--- 717,723 ----
  		tp = v->ob_type;
  	}
  	if (tp->tp_as_number != NULL) {
! 		return binary_op(v,w, NB_SLOT(nb_multiply), "*");
  	}
  	m = tp->tp_as_sequence;
  	if (m && m->sq_repeat) {
***************
*** 480,824 ****
  }
  
  PyObject *
- PyNumber_Divide(PyObject *v, PyObject *w)
- {
- 	BINOP(v, w, "__div__", "__rdiv__", PyNumber_Divide);
- 	if (v->ob_type->tp_as_number != NULL) {
- 		PyObject *x = NULL;
- 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
- 		if (PyNumber_Coerce(&v, &w) != 0)
- 			return NULL;
- 		if (v->ob_type->tp_as_number != NULL &&
- 		    (f = v->ob_type->tp_as_number->nb_divide) != NULL)
- 			x = (*f)(v, w);
- 		Py_DECREF(v);
- 		Py_DECREF(w);
- 		if (f != NULL)
- 			return x;
- 	}
- 	return type_error("bad operand type(s) for /");
- }
- 
- PyObject *
  PyNumber_Remainder(PyObject *v, PyObject *w)
  {
  	if (PyString_Check(v))
  		return PyString_Format(v, w);
  	else if (PyUnicode_Check(v))
  		return PyUnicode_Format(v, w);
! 	BINOP(v, w, "__mod__", "__rmod__", PyNumber_Remainder);
! 	if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_remainder) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 	return type_error("bad operand type(s) for %");
! }
! 
! PyObject *
! PyNumber_Divmod(PyObject *v, PyObject *w)
! {
! 	BINOP(v, w, "__divmod__", "__rdivmod__", PyNumber_Divmod);
! 	if (v->ob_type->tp_as_number != NULL) {
! 		PyObject *x = NULL;
! 		PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_divmod) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 	return type_error("bad operand type(s) for divmod()");
! }
! 
! /* Power (binary or ternary) */
! 
! static PyObject *
! do_pow(PyObject *v, PyObject *w)
! {
! 	PyObject *res;
! 	PyObject * (*f)(PyObject *, PyObject *, PyObject *);
! 	BINOP(v, w, "__pow__", "__rpow__", do_pow);
! 	if (v->ob_type->tp_as_number == NULL ||
! 	    w->ob_type->tp_as_number == NULL) {
! 		PyErr_SetString(PyExc_TypeError,
! 				"pow(x, y) requires numeric arguments");
! 		return NULL;
! 	}
! 	if (PyNumber_Coerce(&v, &w) != 0)
! 		return NULL;
! 	if (v->ob_type->tp_as_number != NULL &&
! 	    (f = v->ob_type->tp_as_number->nb_power) != NULL)
! 		res = (*f)(v, w, Py_None);
! 	else
! 		res = type_error("pow(x, y) not defined for these operands");
! 	Py_DECREF(v);
! 	Py_DECREF(w);
! 	return res;
  }
  
  PyObject *
  PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
  {
! 	PyObject *res;
! 	PyObject *v1, *z1, *w2, *z2;
! 	PyObject * (*f)(PyObject *, PyObject *, PyObject *);
! 
! 	if (z == Py_None)
! 		return do_pow(v, w);
! 	/* XXX The ternary version doesn't do class instance coercions */
! 	if (PyInstance_Check(v))
! 		return v->ob_type->tp_as_number->nb_power(v, w, z);
! 	if (v->ob_type->tp_as_number == NULL ||
! 	    z->ob_type->tp_as_number == NULL ||
! 	    w->ob_type->tp_as_number == NULL) {
! 		return type_error("pow(x, y, z) requires numeric arguments");
! 	}
! 	if (PyNumber_Coerce(&v, &w) != 0)
! 		return NULL;
! 	res = NULL;
! 	v1 = v;
! 	z1 = z;
! 	if (PyNumber_Coerce(&v1, &z1) != 0)
! 		goto error2;
! 	w2 = w;
! 	z2 = z1;
!  	if (PyNumber_Coerce(&w2, &z2) != 0)
! 		goto error1;
! 	if (v->ob_type->tp_as_number != NULL &&
! 	    (f = v1->ob_type->tp_as_number->nb_power) != NULL)
! 		res = (*f)(v1, w2, z2);
! 	else
! 		res = type_error(
! 			"pow(x, y, z) not defined for these operands");
! 	Py_DECREF(w2);
! 	Py_DECREF(z2);
!   error1:
! 	Py_DECREF(v1);
! 	Py_DECREF(z1);
!   error2:
! 	Py_DECREF(v);
! 	Py_DECREF(w);
! 	return res;
  }
  
  /* Binary in-place operators */
  
  /* The in-place operators are defined to fall back to the 'normal',
!    non in-place operations, if the in-place methods are not in place, and to
!    take class instances into account. This is how it is supposed to work:
  
!    - If the left-hand-side object (the first argument) is an
!      instance object, try to let PyInstance_HalfBinOp() handle it.  Pass the
!      non in-place variant of the function as callback, because it will only
!      be used if the left-hand object is changed by coercion.
! 
!    - Otherwise, if the left hand object is not an instance object, it has
!      the appropriate struct members, and they are filled, call the
!      appropriate function and return the result. No coercion is done on the
!      arguments; the left-hand object is the one the operation is performed
!      on, and it's up to the function to deal with the right-hand object.
       
     - Otherwise, in-place modification is not supported. Handle it exactly as
!      a non in-place operation of the same kind:
! 
!      - If either object is an instance, let PyInstance_DoBinOp() handle it.
!      
!      - Otherwise, both arguments are C types. If the left-hand object has
!        the appropriate struct members filled, coerce, call the
!        appropriate function, and return the result.
!   
!      - Otherwise, we are out of options: raise a type error specific to
!        augmented assignment.
  
     */
  
  #define HASINPLACE(t) PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)
  
! PyObject *
! PyNumber_InPlaceOr(PyObject *v, PyObject *w)
! {
! 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 	PyObject *x = NULL;
! 
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__ior__", &x,
! 					 PyNumber_Or, 0) <= 0)
! 			return x;
! 	}
! 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
! 		 (f = v->ob_type->tp_as_number->nb_inplace_or) != NULL)
! 		return (*f)(v, w);
! 
! 	BINOP(v, w, "__or__", "__ror__", PyNumber_Or);
! 
! 	if (v->ob_type->tp_as_number != NULL) {
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_or) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 
! 	return type_error("bad operand type(s) for |=");
! }
! 
! PyObject *
! PyNumber_InPlaceXor(PyObject *v, PyObject *w)
! {
! 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 	PyObject *x = NULL;
! 
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__ixor__", &x,
! 					 PyNumber_Xor, 0) <= 0)
! 			return x;
! 	}
! 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
! 		 (f = v->ob_type->tp_as_number->nb_inplace_xor) != NULL)
! 		return (*f)(v, w);
! 
! 	BINOP(v, w, "__xor__", "__rxor__", PyNumber_Xor);
! 
! 	if (v->ob_type->tp_as_number != NULL) {
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_xor) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 
! 	return type_error("bad operand type(s) for ^=");
! }
! 
! PyObject *
! PyNumber_InPlaceAnd(PyObject *v, PyObject *w)
! {
! 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 	PyObject *x = NULL;
! 
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__iand__", &x,
! 					 PyNumber_And, 0) <= 0)
! 			return x;
! 	}
! 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
! 		 (f = v->ob_type->tp_as_number->nb_inplace_and) != NULL)
! 		return (*f)(v, w);
! 
! 	BINOP(v, w, "__and__", "__rand__", PyNumber_And);
! 
! 	if (v->ob_type->tp_as_number != NULL) {
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_and) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 
! 	return type_error("bad operand type(s) for &=");
! }
! 
! PyObject *
! PyNumber_InPlaceLshift(PyObject *v, PyObject *w)
! {
! 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 	PyObject *x = NULL;
! 
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__ilshift__", &x,
! 					PyNumber_Lshift, 0) <= 0)
! 			return x;
! 	}
! 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
! 		 (f = v->ob_type->tp_as_number->nb_inplace_lshift) != NULL)
! 		return (*f)(v, w);
! 
! 	BINOP(v, w, "__lshift__", "__rlshift__", PyNumber_Lshift);
! 
! 	if (v->ob_type->tp_as_number != NULL) {
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_lshift) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 
! 	return type_error("bad operand type(s) for <<=");
! }
! 
! PyObject *
! PyNumber_InPlaceRshift(PyObject *v, PyObject *w)
! {
! 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 	PyObject *x = NULL;
! 
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__irshift__", &x,
! 					PyNumber_Rshift, 0) <= 0)
! 			return x;
! 	}
! 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
! 		 (f = v->ob_type->tp_as_number->nb_inplace_rshift) != NULL)
! 		return (*f)(v, w);
! 
! 	BINOP(v, w, "__rshift__", "__rrshift__", PyNumber_Rshift);
! 
! 	if (v->ob_type->tp_as_number != NULL) {
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_rshift) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 
! 	return type_error("bad operand type(s) for >>=");
! }
  
  PyObject *
  PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
  {
  	PyObject * (*f)(PyObject *, PyObject *) = NULL;
- 	PyObject *x = NULL;
  
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__iadd__", &x,
! 					 PyNumber_Add, 0) <= 0)
! 			return x;
! 	}
! 	else if (HASINPLACE(v)) {
  		if (v->ob_type->tp_as_sequence != NULL)
  			f = v->ob_type->tp_as_sequence->sq_inplace_concat;
  		if (f == NULL && v->ob_type->tp_as_number != NULL)
--- 741,805 ----
  }
  
  PyObject *
  PyNumber_Remainder(PyObject *v, PyObject *w)
  {
  	if (PyString_Check(v))
  		return PyString_Format(v, w);
  	else if (PyUnicode_Check(v))
  		return PyUnicode_Format(v, w);
! 	return binary_op(v,w, NB_SLOT(nb_remainder), "%");
  }
  
  PyObject *
  PyNumber_Power(PyObject *v, PyObject *w, PyObject *z)
  {
! 	return ternary_op(v,w,z, NB_SLOT(nb_power), "** or pow()");
  }
  
  /* Binary in-place operators */
  
  /* The in-place operators are defined to fall back to the 'normal',
!    non in-place operations, if the in-place methods are not in place.
  
!    - If the left hand object has the appropriate struct members, and
!      they are filled, call the appropriate function and return the
!      result.  No coercion is done on the arguments; the left-hand object
!      is the one the operation is performed on, and it's up to the
!      function to deal with the right-hand object.
       
     - Otherwise, in-place modification is not supported. Handle it exactly as
!      a non in-place operation of the same kind.
  
     */
  
  #define HASINPLACE(t) PyType_HasFeature((t)->ob_type, Py_TPFLAGS_HAVE_INPLACEOPS)
  
! #define INPLACE_BINOP(func, iop, op, op_name) \
!     PyObject * \
!     func(PyObject *v, PyObject *w) { \
!         PyNumberMethods *mv = v->ob_type->tp_as_number; \
!         if (mv != NULL && HASINPLACE(v)) { \
!             if (mv->iop != NULL) { \
!                 return (*mv->iop)(v, w); \
!             } \
!         } \
!         return binary_op(v, w, NB_SLOT(op), op_name); \
!     }
! 
! INPLACE_BINOP(PyNumber_InPlaceOr, nb_inplace_or, nb_or, "|=")
! INPLACE_BINOP(PyNumber_InPlaceXor, nb_inplace_xor, nb_xor, "^=")
! INPLACE_BINOP(PyNumber_InPlaceAnd, nb_inplace_and, nb_and, "&=")
! INPLACE_BINOP(PyNumber_InPlaceLshift, nb_inplace_lshift, nb_lshift, "<<=")
! INPLACE_BINOP(PyNumber_InPlaceRshift, nb_inplace_rshift, nb_rshift, ">>=")
! INPLACE_BINOP(PyNumber_InPlaceSubtract, nb_inplace_subtract, nb_subtract, "-=")
! INPLACE_BINOP(PyNumber_InPlaceDivide, nb_inplace_divide, nb_divide, "/=")
  
  PyObject *
  PyNumber_InPlaceAdd(PyObject *v, PyObject *w)
  {
  	PyObject * (*f)(PyObject *, PyObject *) = NULL;
  
! 	if (HASINPLACE(v)) {
  		if (v->ob_type->tp_as_sequence != NULL)
  			f = v->ob_type->tp_as_sequence->sq_inplace_concat;
  		if (f == NULL && v->ob_type->tp_as_number != NULL)
***************
*** 827,886 ****
  			return (*f)(v, w);
  	}
  
- 	BINOP(v, w, "__add__", "__radd__", PyNumber_Add);
- 
  	if (v->ob_type->tp_as_sequence != NULL) {
  		f = v->ob_type->tp_as_sequence->sq_concat;
  		if (f != NULL)
  			return (*f)(v, w);
  	}
- 	if (v->ob_type->tp_as_number != NULL) {
- 		if (PyNumber_Coerce(&v, &w) != 0)
- 			return NULL;
- 		if (v->ob_type->tp_as_number != NULL) {
- 			f = v->ob_type->tp_as_number->nb_add;
- 			if (f != NULL)
- 				x = (*f)(v, w);
- 		}
- 		Py_DECREF(v);
- 		Py_DECREF(w);
- 		if (f != NULL)
- 			return x;
- 	}
  
! 	return type_error("bad operand type(s) for +=");
! }
! 
! PyObject *
! PyNumber_InPlaceSubtract(PyObject *v, PyObject *w)
! {
! 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
! 	PyObject *x = NULL;
! 
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__isub__", &x,
! 					PyNumber_Subtract, 0) <= 0)
! 			return x;
! 	}
! 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
! 		 (f = v->ob_type->tp_as_number->nb_inplace_subtract) != NULL)
! 		return (*f)(v, w);
! 
! 	BINOP(v, w, "__sub__", "__rsub__", PyNumber_Subtract);
! 
! 	if (v->ob_type->tp_as_number != NULL) {
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_subtract) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 
! 	return type_error("bad operand type(s) for -=");
  }
  
  PyObject *
--- 808,820 ----
  			return (*f)(v, w);
  	}
  
  	if (v->ob_type->tp_as_sequence != NULL) {
  		f = v->ob_type->tp_as_sequence->sq_concat;
  		if (f != NULL)
  			return (*f)(v, w);
  	}
  
! 	return binary_op(v,w, NB_SLOT(nb_add), "+=");
  }
  
  PyObject *
***************
*** 888,901 ****
  {
  	PyObject * (*f)(PyObject *, PyObject *) = NULL;
  	PyObject * (*g)(PyObject *, int) = NULL;
- 	PyObject *x = NULL;
  
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__imul__", &x,
! 					PyNumber_Multiply, 0) <= 0)
! 			return x;
! 	}
! 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
  		 (f = v->ob_type->tp_as_number->nb_inplace_multiply) != NULL)
  		return (*f)(v, w);
  	else if (v->ob_type->tp_as_sequence != NULL && HASINPLACE(v) &&
--- 822,829 ----
  {
  	PyObject * (*f)(PyObject *, PyObject *) = NULL;
  	PyObject * (*g)(PyObject *, int) = NULL;
  
! 	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
  		 (f = v->ob_type->tp_as_number->nb_inplace_multiply) != NULL)
  		return (*f)(v, w);
  	else if (v->ob_type->tp_as_sequence != NULL && HASINPLACE(v) &&
***************
*** 917,934 ****
  		return (*g)(v, (int)mul_value);
  	}
  
- 	BINOP(v, w, "__mul__", "__rmul__", PyNumber_Multiply);
- 
  	if (v->ob_type->tp_as_number != NULL) {
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if (v->ob_type->tp_as_number != NULL &&
! 		    (f = v->ob_type->tp_as_number->nb_multiply) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
  	}
  	else if (v->ob_type->tp_as_sequence != NULL &&
  		 (g = v->ob_type->tp_as_sequence->sq_repeat) != NULL) {
--- 845,852 ----
  		return (*g)(v, (int)mul_value);
  	}
  
  	if (v->ob_type->tp_as_number != NULL) {
! 		return binary_op(v,w, NB_SLOT(nb_multiply), "*=");
  	}
  	else if (v->ob_type->tp_as_sequence != NULL &&
  		 (g = v->ob_type->tp_as_sequence->sq_repeat) != NULL) {
***************
*** 952,1000 ****
  }
  
  PyObject *
- PyNumber_InPlaceDivide(PyObject *v, PyObject *w)
- {
- 	PyObject * (*f)(PyObject *, PyObject *) = NULL;
- 	PyObject *x = NULL;
- 
- 	if (PyInstance_Check(v)) {
- 		if (PyInstance_HalfBinOp(v, w, "__idiv__", &x,
- 					PyNumber_Divide, 0) <= 0)
- 			return x;
- 	}
- 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
- 		 (f = v->ob_type->tp_as_number->nb_inplace_divide) != NULL)
- 		return (*f)(v, w);
- 
- 	BINOP(v, w, "__div__", "__rdiv__", PyNumber_Divide);
- 
- 	if (v->ob_type->tp_as_number != NULL) {
- 		if (PyNumber_Coerce(&v, &w) != 0)
- 			return NULL;
- 		if (v->ob_type->tp_as_number != NULL &&
- 		    (f = v->ob_type->tp_as_number->nb_divide) != NULL)
- 			x = (*f)(v, w);
- 		Py_DECREF(v);
- 		Py_DECREF(w);
- 		if (f != NULL)
- 			return x;
- 	}
- 
- 	return type_error("bad operand type(s) for /=");
- }
- 
- PyObject *
  PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)
  {
  	PyObject * (*f)(PyObject *, PyObject *) = NULL;
- 	PyObject *x = NULL;
  
! 	if (PyInstance_Check(v)) {
! 		if (PyInstance_HalfBinOp(v, w, "__imod__", &x,
! 					PyNumber_Remainder, 0) <= 0)
! 			return x;
! 	}
! 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
  		 (f = v->ob_type->tp_as_number->nb_inplace_remainder) != NULL)
  		return (*f)(v, w);
  
--- 870,880 ----
  }
  
  PyObject *
  PyNumber_InPlaceRemainder(PyObject *v, PyObject *w)
  {
  	PyObject * (*f)(PyObject *, PyObject *) = NULL;
  
! 	if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
  		 (f = v->ob_type->tp_as_number->nb_inplace_remainder) != NULL)
  		return (*f)(v, w);
  
***************
*** 1003,1110 ****
  	else if (PyUnicode_Check(v))
  		return PyUnicode_Format(v, w);
  
! 	BINOP(v, w, "__mod__", "__rmod__", PyNumber_Remainder);
! 
! 	if (v->ob_type->tp_as_number != NULL) {
! 		if (PyNumber_Coerce(&v, &w) != 0)
! 			return NULL;
! 		if ((f = v->ob_type->tp_as_number->nb_remainder) != NULL)
! 			x = (*f)(v, w);
! 		Py_DECREF(v);
! 		Py_DECREF(w);
! 		if (f != NULL)
! 			return x;
! 	}
! 
! 	return type_error("bad operand type(s) for %=");
  }
  
  
- /* In-place Power (binary or ternary, for API consistency) */
- 
- static PyObject *
- do_inplace_pow(PyObject *v, PyObject *w)
- {
- 	PyObject * (*f)(PyObject *, PyObject *, PyObject *) = NULL;
- 	PyObject *x = NULL;
- 
- 	if (PyInstance_Check(v)) {
- 		if (PyInstance_HalfBinOp(v, w, "__ipow__", &x, do_pow, 0) <= 0)
- 			return x;
- 	}
- 	else if (v->ob_type->tp_as_number != NULL && HASINPLACE(v) &&
- 		 (f = v->ob_type->tp_as_number->nb_inplace_power) != NULL)
- 		return (*f)(v, w, Py_None);
- 
- 	BINOP(v, w, "__pow__", "__rpow__", do_pow);
- 
- 	if (v->ob_type->tp_as_number == NULL ||
- 	    w->ob_type->tp_as_number == NULL) {
- 		return type_error("bad operand type(s) for **=");
- 	}
- 	if (PyNumber_Coerce(&v, &w) != 0)
- 		return NULL;
- 	if ((f = v->ob_type->tp_as_number->nb_power) != NULL)
- 		x = (*f)(v, w, Py_None);
- 	else
- 		x = type_error("bad operand type(s) for **=");
- 	Py_DECREF(v);
- 	Py_DECREF(w);
- 	return x;
- }
- 
  PyObject *
  PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
  {
! 	PyObject *res;
! 	PyObject *v1, *z1, *w2, *z2, *oldv;
! 	PyObject * (*f)(PyObject *, PyObject *, PyObject *);
! 
! 	if (z == Py_None)
! 		return do_inplace_pow(v, w);
! 	/* XXX The ternary version doesn't do class instance coercions */
! 	if (PyInstance_Check(v))
! 		return v->ob_type->tp_as_number->nb_inplace_power(v, w, z);
! 	if (v->ob_type->tp_as_number == NULL ||
! 	    z->ob_type->tp_as_number == NULL ||
! 	    w->ob_type->tp_as_number == NULL) {
! 		return type_error(
! 			"(inplace) pow(x, y, z) requires numeric arguments");
! 	}
! 	oldv = v;
! 	Py_INCREF(oldv);
! 	res = NULL;
! 	if (PyNumber_Coerce(&v, &w) != 0)
! 		goto error3;
! 	v1 = v;
! 	z1 = z;
! 	if (PyNumber_Coerce(&v1, &z1) != 0)
! 		goto error2;
! 	w2 = w;
! 	z2 = z1;
!  	if (PyNumber_Coerce(&w2, &z2) != 0)
! 		goto error1;
! 	if (oldv == v1 && HASINPLACE(v1) &&
! 	    v->ob_type->tp_as_number != NULL &&
! 	    (f = v1->ob_type->tp_as_number->nb_inplace_power) != NULL)
! 		res = (*f)(v1, w2, z2);
! 	else if (v1->ob_type->tp_as_number != NULL &&
! 		 (f = v1->ob_type->tp_as_number->nb_power) != NULL)
! 		res = (*f)(v1, w2, z2);
! 	else
! 		res = type_error(
! 		     "(inplace) pow(x, y, z) not defined for these operands");
! 	Py_DECREF(w2);
! 	Py_DECREF(z2);
!   error1:
! 	Py_DECREF(v1);
! 	Py_DECREF(z1);
!   error2:
! 	Py_DECREF(v);
! 	Py_DECREF(w);
!   error3:
! 	Py_DECREF(oldv);
! 	return res;
  }
  
  
--- 883,902 ----
  	else if (PyUnicode_Check(v))
  		return PyUnicode_Format(v, w);
  
! 	return binary_op(v,w, NB_SLOT(nb_remainder), "%=");
  }
  
  
  PyObject *
  PyNumber_InPlacePower(PyObject *v, PyObject *w, PyObject *z)
  {
! 	if (HASINPLACE(v) &&
! 	    v->ob_type->tp_as_number->nb_inplace_power != NULL) {
! 		return ternary_op(v,w,z, NB_SLOT(nb_inplace_power), "**=");
! 	}
! 	else {
! 		return ternary_op(v,w,z, NB_SLOT(nb_power), "**=");
! 	}
  }
  
  
diff -rc py_cvs/dist/src/Objects/classobject.c py_coerce/Objects/classobject.c
*** py_cvs/dist/src/Objects/classobject.c	Sat Nov 11 21:16:13 2000
--- py_coerce/Objects/classobject.c	Sun Dec 10 14:45:10 2000
***************
*** 4,9 ****
--- 4,10 ----
  #include "Python.h"
  #include "structmember.h"
  
+ 
  /* Forward */
  static PyObject *class_lookup(PyClassObject *, PyObject *,
  			      PyClassObject **);
***************
*** 755,790 ****
  	return res;
  }
  
- static PyObject *
- instance_compare1(PyObject *inst, PyObject *other)
- {
- 	return PyInstance_DoBinOp(inst, other, "__cmp__", "__rcmp__",
- 			     instance_compare1);
- }
- 
- static int
- instance_compare(PyObject *inst, PyObject *other)
- {
- 	PyObject *result;
- 	long outcome;
- 	result = instance_compare1(inst, other);
- 	if (result == NULL)
- 		return -1;
- 	if (!PyInt_Check(result)) {
- 		Py_DECREF(result);
- 		PyErr_SetString(PyExc_TypeError,
- 				"comparison did not return an int");
- 		return -1;
- 	}
- 	outcome = PyInt_AsLong(result);
- 	Py_DECREF(result);
- 	if (outcome < 0)
- 		return -1;
- 	else if (outcome > 0)
- 		return 1;
- 	return 0;
- }
- 
  static long
  instance_hash(PyInstanceObject *inst)
  {
--- 756,761 ----
***************
*** 1185,1216 ****
  	return res;
  }
  
! 
! /* Implement a binary operator involving at least one class instance. */
! 
! PyObject *
! PyInstance_DoBinOp(PyObject *v, PyObject *w, char *opname, char *ropname,
!                    PyObject * (*thisfunc)(PyObject *, PyObject *))
! {
! 	char buf[256];
! 	PyObject *result = NULL;
! 
! 	if (PyInstance_HalfBinOp(v, w, opname, &result, thisfunc, 0) <= 0)
! 		return result;
! 	if (PyInstance_HalfBinOp(w, v, ropname, &result, thisfunc, 1) <= 0)
! 		return result;
! 	/* Sigh -- special case for comparisons */
! 	if (strcmp(opname, "__cmp__") == 0) {
! 		Py_uintptr_t iv = (Py_uintptr_t)v;
! 		Py_uintptr_t iw = (Py_uintptr_t)w;
! 		long c = (iv < iw) ? -1 : (iv > iw) ? 1 : 0;
! 		return PyInt_FromLong(c);
! 	}
! 	sprintf(buf, "%s nor %s defined for these operands", opname, ropname);
! 	PyErr_SetString(PyExc_TypeError, buf);
! 	return NULL;
! }
! 
  
  /* Try one half of a binary operator involving a class instance.
     Return value:
--- 1156,1162 ----
  	return res;
  }
  
! static PyObject *coerce_obj;
  
  /* Try one half of a binary operator involving a class instance.
     Return value:
***************
*** 1218,1229 ****
     0  if we have a valid result
     1  if we could try another operation
  */
! 
! static PyObject *coerce_obj;
! 
! int
! PyInstance_HalfBinOp(PyObject *v, PyObject *w, char *opname, PyObject **r_result,
! 		     PyObject * (*thisfunc)(PyObject *, PyObject *), int swapped)
  {
  	PyObject *func;
  	PyObject *args;
--- 1164,1172 ----
     0  if we have a valid result
     1  if we could try another operation
  */
! static int
! half_binop(PyObject *v, PyObject *w, char *opname, PyObject **r_result,
! 		binaryfunc thisfunc, int swapped)
  {
  	PyObject *func;
  	PyObject *args;
***************
*** 1269,1277 ****
  			v = v1;
  			if (!PyInstance_Check(v) && !PyInstance_Check(w)) {
  				if (swapped)
! 					*r_result = (*thisfunc)(w, v);
  				else
! 					*r_result = (*thisfunc)(v, w);
  				Py_DECREF(coerced);
  				return *r_result == NULL ? -1 : 0;
  			}
--- 1212,1220 ----
  			v = v1;
  			if (!PyInstance_Check(v) && !PyInstance_Check(w)) {
  				if (swapped)
! 					*r_result = (thisfunc)(w, v);
  				else
! 					*r_result = (thisfunc)(v, w);
  				Py_DECREF(coerced);
  				return *r_result == NULL ? -1 : 0;
  			}
***************
*** 1298,1303 ****
--- 1241,1282 ----
  	return *r_result == NULL ? -1 : 0;
  }
  
+ /* Implement a binary operator involving at least one class instance. */
+ static PyObject *
+ do_binop(PyObject *v, PyObject *w, char *opname, char *ropname,
+                    binaryfunc thisfunc)
+ {
+ 	PyObject *result = NULL;
+ 
+ 	if (half_binop(v, w, opname, &result, thisfunc, 0) <= 0)
+ 		return result;
+ 	if (half_binop(w, v, ropname, &result, thisfunc, 1) <= 0)
+ 		return result;
+ 	if (!PyInstance_Check(w)) {
+ 		/* give other type a chance to perform the op */
+ 		Py_INCREF(Py_NotImplemented);
+ 		return Py_NotImplemented;
+ 	}
+ 	else {
+ 		/* give up */
+ 		char buf[256];
+ 		sprintf(buf, "%s nor %s defined for these operands",
+ 				opname, ropname);
+ 		PyErr_SetString(PyExc_TypeError, buf);
+ 		return NULL;
+ 	}
+ }
+ 
+ static PyObject *
+ do_binop_inplace(PyObject *v, PyObject *w, char *iopname, char *opname,
+ 			char *ropname, binaryfunc thisfunc)
+ {
+ 	PyObject *result = NULL;
+ 	if (half_binop(v, w, iopname, &result, thisfunc, 0) <= 0)
+ 		return result;
+ 	return do_binop(v, w, opname, ropname, thisfunc);
+ }
+ 
  static int
  instance_coerce(PyObject **pv, PyObject **pw)
  {
***************
*** 1314,1324 ****
  	}
  	coercefunc = PyObject_GetAttr(v, coerce_obj);
  	if (coercefunc == NULL) {
! 		/* No __coerce__ method: always OK */
  		PyErr_Clear();
  		Py_INCREF(v);
  		Py_INCREF(w);
! 		return 0;
  	}
  	/* Has __coerce__ method: call it */
  	args = Py_BuildValue("(O)", w);
--- 1293,1303 ----
  	}
  	coercefunc = PyObject_GetAttr(v, coerce_obj);
  	if (coercefunc == NULL) {
! 		/* No __coerce__ method */
  		PyErr_Clear();
  		Py_INCREF(v);
  		Py_INCREF(w);
! 		return 1;
  	}
  	/* Has __coerce__ method: call it */
  	args = Py_BuildValue("(O)", w);
***************
*** 1353,1359 ****
  	return 0;
  }
  
- 
  #define UNARY(funcname, methodname) \
  static PyObject *funcname(PyInstanceObject *self) { \
  	static PyObject *o; \
--- 1332,1337 ----
***************
*** 1361,1370 ****
--- 1339,1453 ----
  	return generic_unary_op(self, o); \
  }
  
+ #define BINARY(f, m, n) \
+ static PyObject *f(PyObject *v, PyObject *w) { \
+ 	return do_binop(v, w, "__" m "__", "__r" m "__", n); \
+ }
+ 
+ #define BINARY_INPLACE(f, m, n) \
+ static PyObject *f(PyObject *v, PyObject *w) { \
+ 	return do_binop_inplace(v, w, "__i" m "__", "__" m "__", \
+ 			"__r" m "__", n); \
+ }
+ 
  UNARY(instance_neg, "__neg__")
  UNARY(instance_pos, "__pos__")
  UNARY(instance_abs, "__abs__")
  
+ BINARY(instance_or, "or", PyNumber_Or)
+ BINARY(instance_and, "and", PyNumber_And)
+ BINARY(instance_xor, "xor", PyNumber_Xor)
+ BINARY(instance_lshift, "lshift", PyNumber_Lshift)
+ BINARY(instance_rshift, "rshift", PyNumber_Rshift)
+ BINARY(instance_add, "add", PyNumber_Add)
+ BINARY(instance_sub, "sub", PyNumber_Subtract)
+ BINARY(instance_mul, "mul", PyNumber_Multiply)
+ BINARY(instance_div, "div", PyNumber_Divide)
+ BINARY(instance_mod, "mod", PyNumber_Remainder)
+ BINARY(instance_divmod, "divmod", PyNumber_Divmod)
+ 
+ BINARY_INPLACE(instance_ior, "or", PyNumber_InPlaceOr)
+ BINARY_INPLACE(instance_ixor, "xor", PyNumber_InPlaceXor)
+ BINARY_INPLACE(instance_iand, "and", PyNumber_InPlaceAnd)
+ BINARY_INPLACE(instance_ilshift, "lshift", PyNumber_InPlaceLshift)
+ BINARY_INPLACE(instance_irshift, "rshift", PyNumber_InPlaceRshift)
+ BINARY_INPLACE(instance_iadd, "add", PyNumber_InPlaceAnd)
+ BINARY_INPLACE(instance_isub, "sub", PyNumber_InPlaceSubtract)
+ BINARY_INPLACE(instance_imul, "mul", PyNumber_InPlaceMultiply)
+ BINARY_INPLACE(instance_idiv, "div", PyNumber_InPlaceDivide)
+ BINARY_INPLACE(instance_imod, "mod", PyNumber_InPlaceRemainder)
+ 
+ static PyObject *
+ do_cmp(PyObject *v, PyObject *w)
+ {
+ 	int cmp = PyObject_Compare(v, w);
+ 	if (PyErr_Occurred()) {
+ 		return NULL;
+ 	}
+     	return PyInt_FromLong(cmp);
+ }
+ 
+ static PyObject *
+ instance_cmp(PyObject *v, PyObject *w) {
+ 	PyObject *result = NULL;
+ 
+ 	if (half_binop(v, w, "__cmp__", &result, do_cmp, 0) <= 0) {
+ 		return result;
+ 	}
+ 	/* instances rarely call __rcmp__, they automaticly reverse the
+ 	 * arguments and return the negative of __cmp__ if it exists */
+ 	if (half_binop(w, v, "__cmp__", &result, do_cmp, 1) <= 0) {
+ 		if (result != NULL) {
+ 			PyObject *r = PyNumber_Negative(result);
+ 			Py_DECREF(result);
+ 			return r;
+ 		}
+ 		else
+ 			return NULL;
+ 	}
+ 	if (half_binop(w, v, "__rcmp__", &result, do_cmp, 1) <= 0) {
+ 		return result;
+ 	}
+ 	if (!PyInstance_Check(w)) {
+ 		Py_INCREF(Py_NotImplemented);
+ 		return Py_NotImplemented;
+ 	}
+ 	else {
+ 		Py_uintptr_t iv = (Py_uintptr_t)v;
+ 		Py_uintptr_t iw = (Py_uintptr_t)w;
+ 		long c = (iv < iw) ? -1 : (iv > iw) ? 1 : 0;
+ 		return PyInt_FromLong(c);
+ 	}
+ }
+ 
+ static int
+ instance_compare(PyObject *inst, PyObject *other)
+ {
+ 	PyObject *result;
+ 	long outcome;
+ 	result = instance_cmp(inst, other);
+ 	if (result == NULL) {
+ 		return -1;
+ 	}
+ 	if (result == Py_NotImplemented) {
+ 		Py_DECREF(result);
+ 		return -1;
+ 	}
+ 	if (!PyInt_Check(result)) {
+ 		Py_DECREF(result);
+ 		PyErr_SetString(PyExc_TypeError,
+ 				"comparison did not return an int");
+ 		return -1;
+ 	}
+ 	outcome = PyInt_AsLong(result);
+ 	Py_DECREF(result);
+ 	if (outcome < 0)
+ 		return -1;
+ 	else if (outcome > 0)
+ 		return 1;
+ 	return 0;
+ }
+ 
  static int
  instance_nonzero(PyInstanceObject *self)
  {
***************
*** 1412,1508 ****
  UNARY(instance_oct, "__oct__")
  UNARY(instance_hex, "__hex__")
  
  /* This version is for ternary calls only (z != None) */
  static PyObject *
  instance_pow(PyObject *v, PyObject *w, PyObject *z)
! {
! 	/* XXX Doesn't do coercions... */
! 	PyObject *func;
! 	PyObject *args;
! 	PyObject *result;
! 	static PyObject *powstr;
  
! 	if (powstr == NULL)
! 		powstr = PyString_InternFromString("__pow__");
! 	func = PyObject_GetAttr(v, powstr);
! 	if (func == NULL)
! 		return NULL;
! 	args = Py_BuildValue("(OO)", w, z);
! 	if (args == NULL) {
  		Py_DECREF(func);
! 		return NULL;
  	}
- 	result = PyEval_CallObject(func, args);
- 	Py_DECREF(func);
- 	Py_DECREF(args);
- 	return result;
  }
  
  static PyObject *
! instance_inplace_pow(PyObject *v, PyObject *w, PyObject *z)
  {
! 	/* XXX Doesn't do coercions... */
! 	PyObject *func;
! 	PyObject *args;
! 	PyObject *result;
! 	static PyObject *ipowstr;
  
! 	if (ipowstr == NULL)
! 		ipowstr = PyString_InternFromString("__ipow__");
! 	func = PyObject_GetAttr(v, ipowstr);
! 	if (func == NULL) {
! 		if (!PyErr_ExceptionMatches(PyExc_AttributeError))
! 			return NULL;
! 		PyErr_Clear();
! 		return instance_pow(v, w, z);
  	}
! 	args = Py_BuildValue("(OO)", w, z);
! 	if (args == NULL) {
  		Py_DECREF(func);
! 		return NULL;
  	}
- 	result = PyEval_CallObject(func, args);
- 	Py_DECREF(func);
- 	Py_DECREF(args);
- 	return result;
  }
  
  
  static PyNumberMethods instance_as_number = {
! 	0, /*nb_add*/
! 	0, /*nb_subtract*/
! 	0, /*nb_multiply*/
! 	0, /*nb_divide*/
! 	0, /*nb_remainder*/
! 	0, /*nb_divmod*/
  	(ternaryfunc)instance_pow, /*nb_power*/
  	(unaryfunc)instance_neg, /*nb_negative*/
  	(unaryfunc)instance_pos, /*nb_positive*/
  	(unaryfunc)instance_abs, /*nb_absolute*/
  	(inquiry)instance_nonzero, /*nb_nonzero*/
  	(unaryfunc)instance_invert, /*nb_invert*/
! 	0, /*nb_lshift*/
! 	0, /*nb_rshift*/
! 	0, /*nb_and*/
! 	0, /*nb_xor*/
! 	0, /*nb_or*/
  	(coercion)instance_coerce, /*nb_coerce*/
  	(unaryfunc)instance_int, /*nb_int*/
  	(unaryfunc)instance_long, /*nb_long*/
  	(unaryfunc)instance_float, /*nb_float*/
  	(unaryfunc)instance_oct, /*nb_oct*/
  	(unaryfunc)instance_hex, /*nb_hex*/
! 	0, /*nb_inplace_add*/
! 	0, /*nb_inplace_subtract*/
! 	0, /*nb_inplace_multiply*/
! 	0, /*nb_inplace_divide*/
! 	0, /*nb_inplace_remainder*/
! 	(ternaryfunc)instance_inplace_pow, /*nb_inplace_power*/
! 	0, /*nb_inplace_lshift*/
! 	0, /*nb_inplace_rshift*/
! 	0, /*nb_inplace_and*/
! 	0, /*nb_inplace_xor*/
! 	0, /*nb_inplace_or*/
  };
  
  PyTypeObject PyInstance_Type = {
--- 1495,1611 ----
  UNARY(instance_oct, "__oct__")
  UNARY(instance_hex, "__hex__")
  
+ static PyObject *
+ bin_power(PyObject *v, PyObject *w)
+ {
+ 	return PyNumber_Power(v, w, NULL);
+ }
+ 
  /* This version is for ternary calls only (z != None) */
  static PyObject *
  instance_pow(PyObject *v, PyObject *w, PyObject *z)
! {	
! 	if (z == Py_None) {
! 		return do_binop(v, w, "__pow__", "__rpow__", bin_power);
! 	}
! 	else {
! 		PyObject *func;
! 		PyObject *args;
! 		PyObject *result;
  
! 		/* XXX Doesn't do coercions... */
! 		func = PyObject_GetAttrString(v, "__pow__");
! 		if (func == NULL)
! 			return NULL;
! 		args = Py_BuildValue("(OO)", w, z);
! 		if (args == NULL) {
! 			Py_DECREF(func);
! 			return NULL;
! 		}
! 		result = PyEval_CallObject(func, args);
  		Py_DECREF(func);
! 		Py_DECREF(args);
! 		return result;
  	}
  }
  
  static PyObject *
! bin_inplace_power(PyObject *v, PyObject *w)
  {
! 	return PyNumber_InPlacePower(v, w, NULL);
! }
  
! 
! static PyObject *
! instance_ipow(PyObject *v, PyObject *w, PyObject *z)
! {
! 	if (z == Py_None) {
! 		return do_binop_inplace(v, w, "__ipow__", "__pow__",
! 			"__rpow__", bin_inplace_power);
  	}
! 	else {
! 		/* XXX Doesn't do coercions... */
! 		PyObject *func;
! 		PyObject *args;
! 		PyObject *result;
! 
! 		func = PyObject_GetAttrString(v, "__ipow__");
! 		if (func == NULL) {
! 			if (!PyErr_ExceptionMatches(PyExc_AttributeError))
! 				return NULL;
! 			PyErr_Clear();
! 			return instance_pow(v, w, z);
! 		}
! 		args = Py_BuildValue("(OO)", w, z);
! 		if (args == NULL) {
! 			Py_DECREF(func);
! 			return NULL;
! 		}
! 		result = PyEval_CallObject(func, args);
  		Py_DECREF(func);
! 		Py_DECREF(args);
! 		return result;
  	}
  }
  
  
+ 
  static PyNumberMethods instance_as_number = {
! 	(binaryfunc)instance_add, /*nb_add*/
! 	(binaryfunc)instance_sub, /*nb_subtract*/
! 	(binaryfunc)instance_mul, /*nb_multiply*/
! 	(binaryfunc)instance_div, /*nb_divide*/
! 	(binaryfunc)instance_mod, /*nb_remainder*/
! 	(binaryfunc)instance_divmod, /*nb_divmod*/
  	(ternaryfunc)instance_pow, /*nb_power*/
  	(unaryfunc)instance_neg, /*nb_negative*/
  	(unaryfunc)instance_pos, /*nb_positive*/
  	(unaryfunc)instance_abs, /*nb_absolute*/
  	(inquiry)instance_nonzero, /*nb_nonzero*/
  	(unaryfunc)instance_invert, /*nb_invert*/
! 	(binaryfunc)instance_lshift, /*nb_lshift*/
! 	(binaryfunc)instance_rshift, /*nb_rshift*/
! 	(binaryfunc)instance_and, /*nb_and*/
! 	(binaryfunc)instance_xor, /*nb_xor*/
! 	(binaryfunc)instance_or, /*nb_or*/
  	(coercion)instance_coerce, /*nb_coerce*/
  	(unaryfunc)instance_int, /*nb_int*/
  	(unaryfunc)instance_long, /*nb_long*/
  	(unaryfunc)instance_float, /*nb_float*/
  	(unaryfunc)instance_oct, /*nb_oct*/
  	(unaryfunc)instance_hex, /*nb_hex*/
! 	(binaryfunc)instance_iadd, /*nb_inplace_add*/
! 	(binaryfunc)instance_isub, /*nb_inplace_subtract*/
! 	(binaryfunc)instance_imul, /*nb_inplace_multiply*/
! 	(binaryfunc)instance_idiv, /*nb_inplace_divide*/
! 	(binaryfunc)instance_imod, /*nb_inplace_remainder*/
! 	(ternaryfunc)instance_ipow, /*nb_inplace_power*/
! 	(binaryfunc)instance_ilshift, /*nb_inplace_lshift*/
! 	(binaryfunc)instance_irshift, /*nb_inplace_rshift*/
! 	(binaryfunc)instance_iand, /*nb_inplace_and*/
! 	(binaryfunc)instance_ixor, /*nb_inplace_xor*/
! 	(binaryfunc)instance_ior, /*nb_inplace_or*/
! 	(binaryfunc)instance_cmp, /*nb_cmp*/
  };
  
  PyTypeObject PyInstance_Type = {
***************
*** 1525,1532 ****
  	0,			/*tp_str*/
  	(getattrofunc)instance_getattr, /*tp_getattro*/
  	(setattrofunc)instance_setattr, /*tp_setattro*/
!         0, /* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC, /*tp_flags*/
  	0,		/* tp_doc */
  	(traverseproc)instance_traverse,	/* tp_traverse */
  };
--- 1628,1635 ----
  	0,			/*tp_str*/
  	(getattrofunc)instance_getattr, /*tp_getattro*/
  	(setattrofunc)instance_setattr, /*tp_setattro*/
! 	0, /* tp_as_buffer */
! 	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_GC | Py_TPFLAGS_NEWSTYLENUMBER, /*tp_flags*/
  	0,		/* tp_doc */
  	(traverseproc)instance_traverse,	/* tp_traverse */
  };
diff -rc py_cvs/dist/src/Objects/floatobject.c py_coerce/Objects/floatobject.c
*** py_cvs/dist/src/Objects/floatobject.c	Sat Nov 11 21:16:13 2000
--- py_coerce/Objects/floatobject.c	Sun Dec 10 14:02:32 2000
***************
*** 256,261 ****
--- 256,293 ----
  	}
  }
  
+ /* Macro and helper that convert PyObject obj to a C double and store
+    the value in dbl; this replaces the functionality of the coercion
+    slot function */
+ 
+ #define CONVERT_TO_DOUBLE(obj,dbl)			\
+ 	if (PyFloat_Check(obj))				\
+ 		dbl = PyFloat_AS_DOUBLE(obj);		\
+ 	else if (convert_to_double(&(obj),&(dbl)) < 0)	\
+ 		return obj;
+ 
+ static int
+ convert_to_double(PyObject **v,
+ 		  double *dbl)
+ {
+ 	register PyObject *obj = *v;
+ 	
+ 	if (PyInt_Check(obj)) {
+ 		*dbl = (double)PyInt_AS_LONG(obj);
+ 	}
+ 	else if (PyLong_Check(obj)) {
+ 		PyFPE_START_PROTECT("convert_to_double", {*v=NULL;return -1;})
+ 		*dbl = PyLong_AsDouble(obj);
+ 		PyFPE_END_PROTECT(result)
+ 	}
+ 	else {
+ 		Py_INCREF(Py_NotImplemented);
+ 		*v = Py_NotImplemented;
+ 		return -1;
+ 	}
+ 	return 0;
+ }
+ 
  /* Precisions used by repr() and str(), respectively.
  
     The repr() precision (17 significant decimal digits) is the minimal number
***************
*** 314,319 ****
--- 346,360 ----
  	return (i < j) ? -1 : (i > j) ? 1 : 0;
  }
  
+ /* Needed for the new style number compare slots */
+ static PyObject *
+ float_cmp(PyObject *v, PyObject *w)
+ {
+ 	double a,b;
+ 	CONVERT_TO_DOUBLE(v,a);
+ 	CONVERT_TO_DOUBLE(w,b);
+ 	return PyInt_FromLong((a < b) ? -1 : (a > b) ? 1 : 0);
+ }
  
  static long
  float_hash(PyFloatObject *v)
***************
*** 322,383 ****
  }
  
  static PyObject *
! float_add(PyFloatObject *v, PyFloatObject *w)
  {
! 	double result;
  	PyFPE_START_PROTECT("add", return 0)
! 	result = v->ob_fval + w->ob_fval;
! 	PyFPE_END_PROTECT(result)
! 	return PyFloat_FromDouble(result);
  }
  
  static PyObject *
! float_sub(PyFloatObject *v, PyFloatObject *w)
  {
! 	double result;
  	PyFPE_START_PROTECT("subtract", return 0)
! 	result = v->ob_fval - w->ob_fval;
! 	PyFPE_END_PROTECT(result)
! 	return PyFloat_FromDouble(result);
  }
  
  static PyObject *
! float_mul(PyFloatObject *v, PyFloatObject *w)
  {
! 	double result;
! 
  	PyFPE_START_PROTECT("multiply", return 0)
! 	result = v->ob_fval * w->ob_fval;
! 	PyFPE_END_PROTECT(result)
! 	return PyFloat_FromDouble(result);
  }
  
  static PyObject *
! float_div(PyFloatObject *v, PyFloatObject *w)
  {
! 	double result;
! 	if (w->ob_fval == 0) {
  		PyErr_SetString(PyExc_ZeroDivisionError, "float division");
  		return NULL;
  	}
  	PyFPE_START_PROTECT("divide", return 0)
! 	result = v->ob_fval / w->ob_fval;
! 	PyFPE_END_PROTECT(result)
! 	return PyFloat_FromDouble(result);
  }
  
  static PyObject *
! float_rem(PyFloatObject *v, PyFloatObject *w)
  {
  	double vx, wx;
  	double mod;
! 	wx = w->ob_fval;
  	if (wx == 0.0) {
  		PyErr_SetString(PyExc_ZeroDivisionError, "float modulo");
  		return NULL;
  	}
  	PyFPE_START_PROTECT("modulo", return 0)
- 	vx = v->ob_fval;
  	mod = fmod(vx, wx);
  	/* note: checking mod*wx < 0 is incorrect -- underflows to
  	   0 if wx < sqrt(smallest nonzero double) */
--- 363,431 ----
  }
  
  static PyObject *
! float_add(PyObject *v, PyObject *w)
  {
! 	double a,b;
! 	CONVERT_TO_DOUBLE(v,a);
! 	CONVERT_TO_DOUBLE(w,b);
  	PyFPE_START_PROTECT("add", return 0)
! 	a = a + b;
! 	PyFPE_END_PROTECT(a)
! 	return PyFloat_FromDouble(a);
  }
  
  static PyObject *
! float_sub(PyObject *v, PyObject *w)
  {
! 	double a,b;
! 	CONVERT_TO_DOUBLE(v,a);
! 	CONVERT_TO_DOUBLE(w,b);
  	PyFPE_START_PROTECT("subtract", return 0)
! 	a = a - b;
! 	PyFPE_END_PROTECT(a)
! 	return PyFloat_FromDouble(a);
  }
  
  static PyObject *
! float_mul(PyObject *v, PyObject *w)
  {
! 	double a,b;
! 	CONVERT_TO_DOUBLE(v,a);
! 	CONVERT_TO_DOUBLE(w,b);
  	PyFPE_START_PROTECT("multiply", return 0)
! 	a = a * b;
! 	PyFPE_END_PROTECT(a)
! 	return PyFloat_FromDouble(a);
  }
  
  static PyObject *
! float_div(PyObject *v, PyObject *w)
  {
! 	double a,b;
! 	CONVERT_TO_DOUBLE(v,a);
! 	CONVERT_TO_DOUBLE(w,b);
! 	if (b == 0.0) {
  		PyErr_SetString(PyExc_ZeroDivisionError, "float division");
  		return NULL;
  	}
  	PyFPE_START_PROTECT("divide", return 0)
! 	a = a / b;
! 	PyFPE_END_PROTECT(a)
! 	return PyFloat_FromDouble(a);
  }
  
  static PyObject *
! float_rem(PyObject *v, PyObject *w)
  {
  	double vx, wx;
  	double mod;
!  	CONVERT_TO_DOUBLE(v,vx);
!  	CONVERT_TO_DOUBLE(w,wx);
  	if (wx == 0.0) {
  		PyErr_SetString(PyExc_ZeroDivisionError, "float modulo");
  		return NULL;
  	}
  	PyFPE_START_PROTECT("modulo", return 0)
  	mod = fmod(vx, wx);
  	/* note: checking mod*wx < 0 is incorrect -- underflows to
  	   0 if wx < sqrt(smallest nonzero double) */
***************
*** 389,405 ****
  }
  
  static PyObject *
! float_divmod(PyFloatObject *v, PyFloatObject *w)
  {
  	double vx, wx;
  	double div, mod, floordiv;
! 	wx = w->ob_fval;
  	if (wx == 0.0) {
  		PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
  		return NULL;
  	}
  	PyFPE_START_PROTECT("divmod", return 0)
- 	vx = v->ob_fval;
  	mod = fmod(vx, wx);
  	/* fmod is typically exact, so vx-mod is *mathematically* an
  	   exact multiple of wx.  But this is fp arithmetic, and fp
--- 437,453 ----
  }
  
  static PyObject *
! float_divmod(PyObject *v, PyObject *w)
  {
  	double vx, wx;
  	double div, mod, floordiv;
!  	CONVERT_TO_DOUBLE(v,vx);
!  	CONVERT_TO_DOUBLE(w,wx);
  	if (wx == 0.0) {
  		PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
  		return NULL;
  	}
  	PyFPE_START_PROTECT("divmod", return 0)
  	mod = fmod(vx, wx);
  	/* fmod is typically exact, so vx-mod is *mathematically* an
  	   exact multiple of wx.  But this is fp arithmetic, and fp
***************
*** 437,443 ****
  }
  
  static PyObject *
! float_pow(PyFloatObject *v, PyObject *w, PyFloatObject *z)
  {
  	double iv, iw, ix;
  	long intw;
--- 485,491 ----
  }
  
  static PyObject *
! float_pow(PyObject *v, PyObject *w, PyObject *z)
  {
  	double iv, iw, ix;
  	long intw;
***************
*** 446,462 ****
    * long integers.  Maybe something clever with logarithms could be done.
    * [AMK]
    */
! 	iv = v->ob_fval;
! 	iw = ((PyFloatObject *)w)->ob_fval;
  	intw = (long)iw;
  
  	/* Sort out special cases here instead of relying on pow() */
  	if (iw == 0) { 		/* x**0 is 1, even 0**0 */
  		PyFPE_START_PROTECT("pow", return NULL)
  		if ((PyObject *)z != Py_None) {
! 			ix = fmod(1.0, z->ob_fval);
! 			if (ix != 0 && z->ob_fval < 0)
! 				ix += z->ob_fval;
  		}
  		else
  			ix = 1.0;
--- 494,511 ----
    * long integers.  Maybe something clever with logarithms could be done.
    * [AMK]
    */
! 	CONVERT_TO_DOUBLE(v,iv);
! 	CONVERT_TO_DOUBLE(w,iw);
  	intw = (long)iw;
  
  	/* Sort out special cases here instead of relying on pow() */
  	if (iw == 0) { 		/* x**0 is 1, even 0**0 */
  		PyFPE_START_PROTECT("pow", return NULL)
  		if ((PyObject *)z != Py_None) {
! 			double iz;
! 			CONVERT_TO_DOUBLE(w,iz);
! 			ix=fmod(1.0, iz);
! 			if (ix!=0 && iz<0) ix+=iz;
  		}
  		else
  			ix = 1.0;
***************
*** 501,515 ****
  		return NULL;
  	}
  	if ((PyObject *)z != Py_None) {
! 		PyFPE_START_PROTECT("pow", return NULL)
! 		ix = fmod(ix, z->ob_fval);	/* XXX To Be Rewritten */
! 		if (ix != 0 &&
! 		    ((iv < 0 && z->ob_fval > 0) ||
! 		     (iv > 0 && z->ob_fval < 0)
! 		    )) {
! 		     ix += z->ob_fval;
  		}
! 		PyFPE_END_PROTECT(ix)
  	}
  	return PyFloat_FromDouble(ix);
  }
--- 550,563 ----
  		return NULL;
  	}
  	if ((PyObject *)z != Py_None) {
! 		double iz;
! 		CONVERT_TO_DOUBLE(z,iz);
! 		PyFPE_START_PROTECT("pow", return 0)
! 	 	ix=fmod(ix, iz);	/* XXX To Be Rewritten */
! 	 	if (ix!=0 && ((iv<0 && iz>0) || (iv>0 && iz<0) )) {
! 		     ix+=iz;
  		}
!   		PyFPE_END_PROTECT(ix)
  	}
  	return PyFloat_FromDouble(ix);
  }
***************
*** 611,616 ****
--- 659,678 ----
  	(unaryfunc)float_float, /*nb_float*/
  	0,		/*nb_oct*/
  	0,		/*nb_hex*/
+ 	0,		/*nb_inplace_add*/
+ 	0,		/*nb_inplace_subtract*/
+ 	0,		/*nb_inplace_multiply*/
+ 	0,		/*nb_inplace_divide*/
+ 	0,		/*nb_inplace_remainder*/
+ 	0, 		/*nb_inplace_power*/
+ 	0,		/*nb_inplace_lshift*/
+ 	0,		/*nb_inplace_rshift*/
+ 	0,		/*nb_inplace_and*/
+ 	0,		/*nb_inplace_xor*/
+ 	0,		/*nb_inplace_or*/
+ 
+ 	/* New style slots: */
+ 	(binaryfunc)float_cmp, /*nb_cmp*/
  };
  
  PyTypeObject PyFloat_Type = {
***************
*** 631,636 ****
--- 693,702 ----
  	(hashfunc)float_hash,	/*tp_hash*/
          0,			/*tp_call*/
          (reprfunc)float_str,	/*tp_str*/
+ 	0,			/*tp_getattro*/
+ 	0,			/*tp_setattro*/
+ 	0,			/*tp_as_buffer*/
+ 	Py_TPFLAGS_NEWSTYLENUMBER /*tp_flags*/
  };
  
  void
diff -rc py_cvs/dist/src/Objects/intobject.c py_coerce/Objects/intobject.c
*** py_cvs/dist/src/Objects/intobject.c	Sat Nov 11 21:16:13 2000
--- py_coerce/Objects/intobject.c	Sun Dec 10 14:02:15 2000
***************
*** 219,224 ****
--- 219,237 ----
  
  /* Methods */
  
+ /* Integers are seen as the "smallest" of all numeric types and thus
+    don't have any knowledge about conversion of other types to
+    integers. */
+ 
+ #define CONVERT_TO_LONG(obj,lng)		\
+ 	if (PyInt_Check(obj)) {			\
+ 		lng = PyInt_AS_LONG(obj);	\
+ 	}					\
+ 	else {					\
+ 		Py_INCREF(Py_NotImplemented);	\
+ 		return Py_NotImplemented;	\
+ 	}
+ 
  /* ARGSUSED */
  static int
  int_print(PyIntObject *v, FILE *fp, int flags)
***************
*** 244,249 ****
--- 257,272 ----
  	return (i < j) ? -1 : (i > j) ? 1 : 0;
  }
  
+ /* Needed for the new style number compare slots */
+ static PyObject *
+ int_cmp(PyObject *v, PyObject *w)
+ {
+ 	register long a, b;
+ 	CONVERT_TO_LONG(v,a);
+ 	CONVERT_TO_LONG(w,b);
+ 	return PyInt_FromLong((a < b) ? -1 : (a > b) ? 1 : 0);
+ }
+ 
  static long
  int_hash(PyIntObject *v)
  {
***************
*** 259,266 ****
  int_add(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b, x;
! 	a = v->ob_ival;
! 	b = w->ob_ival;
  	x = a + b;
  	if ((x^a) < 0 && (x^b) < 0)
  		return err_ovf("integer addition");
--- 282,289 ----
  int_add(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b, x;
! 	CONVERT_TO_LONG(v,a);
! 	CONVERT_TO_LONG(w,b);
  	x = a + b;
  	if ((x^a) < 0 && (x^b) < 0)
  		return err_ovf("integer addition");
***************
*** 271,278 ****
  int_sub(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b, x;
! 	a = v->ob_ival;
! 	b = w->ob_ival;
  	x = a - b;
  	if ((x^a) < 0 && (x^~b) < 0)
  		return err_ovf("integer subtraction");
--- 294,301 ----
  int_sub(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b, x;
! 	CONVERT_TO_LONG(v,a);
! 	CONVERT_TO_LONG(w,b);
  	x = a - b;
  	if ((x^a) < 0 && (x^~b) < 0)
  		return err_ovf("integer subtraction");
***************
*** 314,321 ****
  	long a, b, ah, bh, x, y;
  	int s = 1;
  
! 	a = v->ob_ival;
! 	b = w->ob_ival;
  	ah = a >> (LONG_BIT/2);
  	bh = b >> (LONG_BIT/2);
  
--- 337,344 ----
  	long a, b, ah, bh, x, y;
  	int s = 1;
  
! 	CONVERT_TO_LONG(v,a);
! 	CONVERT_TO_LONG(w,b);
  	ah = a >> (LONG_BIT/2);
  	bh = b >> (LONG_BIT/2);
  
***************
*** 408,418 ****
  }
  
  static int
! i_divmod(register PyIntObject *x, register PyIntObject *y,
           long *p_xdivy, long *p_xmody)
  {
- 	long xi = x->ob_ival;
- 	long yi = y->ob_ival;
  	long xdivy, xmody;
  	
  	if (yi == 0) {
--- 431,439 ----
  }
  
  static int
! i_divmod(register long xi, register long yi,
           long *p_xdivy, long *p_xmody)
  {
  	long xdivy, xmody;
  	
  	if (yi == 0) {
***************
*** 451,458 ****
  static PyObject *
  int_div(PyIntObject *x, PyIntObject *y)
  {
  	long d, m;
! 	if (i_divmod(x, y, &d, &m) < 0)
  		return NULL;
  	return PyInt_FromLong(d);
  }
--- 472,482 ----
  static PyObject *
  int_div(PyIntObject *x, PyIntObject *y)
  {
+ 	long xi, yi;
  	long d, m;
! 	CONVERT_TO_LONG(x,xi);
! 	CONVERT_TO_LONG(y,yi);
! 	if (i_divmod(xi, yi, &d, &m) < 0)
  		return NULL;
  	return PyInt_FromLong(d);
  }
***************
*** 460,467 ****
  static PyObject *
  int_mod(PyIntObject *x, PyIntObject *y)
  {
  	long d, m;
! 	if (i_divmod(x, y, &d, &m) < 0)
  		return NULL;
  	return PyInt_FromLong(m);
  }
--- 484,494 ----
  static PyObject *
  int_mod(PyIntObject *x, PyIntObject *y)
  {
+ 	long xi, yi;
  	long d, m;
! 	CONVERT_TO_LONG(x,xi);
! 	CONVERT_TO_LONG(y,yi);
! 	if (i_divmod(xi, yi, &d, &m) < 0)
  		return NULL;
  	return PyInt_FromLong(m);
  }
***************
*** 469,476 ****
  static PyObject *
  int_divmod(PyIntObject *x, PyIntObject *y)
  {
  	long d, m;
! 	if (i_divmod(x, y, &d, &m) < 0)
  		return NULL;
  	return Py_BuildValue("(ll)", d, m);
  }
--- 496,506 ----
  static PyObject *
  int_divmod(PyIntObject *x, PyIntObject *y)
  {
+ 	long xi, yi;
  	long d, m;
! 	CONVERT_TO_LONG(x,xi);
! 	CONVERT_TO_LONG(y,yi);
! 	if (i_divmod(xi, yi, &d, &m) < 0)
  		return NULL;
  	return Py_BuildValue("(ll)", d, m);
  }
***************
*** 480,487 ****
  {
  #if 1
  	register long iv, iw, iz=0, ix, temp, prev;
! 	iv = v->ob_ival;
! 	iw = w->ob_ival;
  	if (iw < 0) {
  		if (iv)
  			PyErr_SetString(PyExc_ValueError,
--- 510,517 ----
  {
  #if 1
  	register long iv, iw, iz=0, ix, temp, prev;
! 	CONVERT_TO_LONG(v,iv);
! 	CONVERT_TO_LONG(w,iw);
  	if (iw < 0) {
  		if (iv)
  			PyErr_SetString(PyExc_ValueError,
***************
*** 492,498 ****
  		return NULL;
  	}
   	if ((PyObject *)z != Py_None) {
! 		iz = z->ob_ival;
  		if (iz == 0) {
  			PyErr_SetString(PyExc_ValueError,
  					"pow() arg 3 cannot be 0");
--- 522,528 ----
  		return NULL;
  	}
   	if ((PyObject *)z != Py_None) {
! 		CONVERT_TO_LONG(z,iz);
  		if (iz == 0) {
  			PyErr_SetString(PyExc_ValueError,
  					"pow() arg 3 cannot be 0");
***************
*** 531,557 ****
  		}
  	}
  	if (iz) {
! 	 	PyObject *t1, *t2;
! 	 	long int div, mod;
! 	 	t1=PyInt_FromLong(ix); 
! 		t2=PyInt_FromLong(iz);
! 	 	if (t1==NULL || t2==NULL ||
! 	 		i_divmod((PyIntObject *)t1,
! 				 (PyIntObject *)t2, &div, &mod)<0)
! 		{
! 		 	Py_XDECREF(t1);
! 		 	Py_XDECREF(t2);
  			return(NULL);
- 		}
- 		Py_DECREF(t1);
- 		Py_DECREF(t2);
  	 	ix=mod;
  	}
  	return PyInt_FromLong(ix);
  #else
  	register long iv, iw, ix;
! 	iv = v->ob_ival;
! 	iw = w->ob_ival;
  	if (iw < 0) {
  		PyErr_SetString(PyExc_ValueError,
  				"integer to the negative power");
--- 561,576 ----
  		}
  	}
  	if (iz) {
! 	 	long div, mod;
! 	 	if (i_divmod(ix, iz, &div, &mod) < 0)
  			return(NULL);
  	 	ix=mod;
  	}
  	return PyInt_FromLong(ix);
  #else
  	register long iv, iw, ix;
! 	CONVERT_TO_LONG(v,iv);
! 	CONVERT_TO_LONG(w,iw);
  	if (iw < 0) {
  		PyErr_SetString(PyExc_ValueError,
  				"integer to the negative power");
***************
*** 618,625 ****
  int_lshift(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	a = v->ob_ival;
! 	b = w->ob_ival;
  	if (b < 0) {
  		PyErr_SetString(PyExc_ValueError, "negative shift count");
  		return NULL;
--- 637,644 ----
  int_lshift(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	CONVERT_TO_LONG(v,a);
! 	CONVERT_TO_LONG(w,b);
  	if (b < 0) {
  		PyErr_SetString(PyExc_ValueError, "negative shift count");
  		return NULL;
***************
*** 639,646 ****
  int_rshift(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	a = v->ob_ival;
! 	b = w->ob_ival;
  	if (b < 0) {
  		PyErr_SetString(PyExc_ValueError, "negative shift count");
  		return NULL;
--- 658,665 ----
  int_rshift(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	CONVERT_TO_LONG(v,a);
! 	CONVERT_TO_LONG(w,b);
  	if (b < 0) {
  		PyErr_SetString(PyExc_ValueError, "negative shift count");
  		return NULL;
***************
*** 665,672 ****
  int_and(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	a = v->ob_ival;
! 	b = w->ob_ival;
  	return PyInt_FromLong(a & b);
  }
  
--- 684,691 ----
  int_and(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	CONVERT_TO_LONG(v,a);
! 	CONVERT_TO_LONG(w,b);
  	return PyInt_FromLong(a & b);
  }
  
***************
*** 674,681 ****
  int_xor(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	a = v->ob_ival;
! 	b = w->ob_ival;
  	return PyInt_FromLong(a ^ b);
  }
  
--- 693,700 ----
  int_xor(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	CONVERT_TO_LONG(v,a);
! 	CONVERT_TO_LONG(w,b);
  	return PyInt_FromLong(a ^ b);
  }
  
***************
*** 683,690 ****
  int_or(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	a = v->ob_ival;
! 	b = w->ob_ival;
  	return PyInt_FromLong(a | b);
  }
  
--- 702,709 ----
  int_or(PyIntObject *v, PyIntObject *w)
  {
  	register long a, b;
! 	CONVERT_TO_LONG(v,a);
! 	CONVERT_TO_LONG(w,b);
  	return PyInt_FromLong(a | b);
  }
  
***************
*** 746,757 ****
  	(binaryfunc)int_and, /*nb_and*/
  	(binaryfunc)int_xor, /*nb_xor*/
  	(binaryfunc)int_or, /*nb_or*/
! 	0,		/*nb_coerce*/
  	(unaryfunc)int_int, /*nb_int*/
  	(unaryfunc)int_long, /*nb_long*/
  	(unaryfunc)int_float, /*nb_float*/
  	(unaryfunc)int_oct, /*nb_oct*/
  	(unaryfunc)int_hex, /*nb_hex*/
  };
  
  PyTypeObject PyInt_Type = {
--- 765,779 ----
  	(binaryfunc)int_and, /*nb_and*/
  	(binaryfunc)int_xor, /*nb_xor*/
  	(binaryfunc)int_or, /*nb_or*/
! 	0, 		/*nb_coerce*/
  	(unaryfunc)int_int, /*nb_int*/
  	(unaryfunc)int_long, /*nb_long*/
  	(unaryfunc)int_float, /*nb_float*/
  	(unaryfunc)int_oct, /*nb_oct*/
  	(unaryfunc)int_hex, /*nb_hex*/
+ 
+ 	/* New style slots: */
+ 	(binaryfunc)int_cmp, /*nb_cmp*/
  };
  
  PyTypeObject PyInt_Type = {
***************
*** 770,775 ****
--- 792,803 ----
  	0,		/*tp_as_sequence*/
  	0,		/*tp_as_mapping*/
  	(hashfunc)int_hash, /*tp_hash*/
+         0,			/*tp_call*/
+         0,			/*tp_str*/
+ 	0,			/*tp_getattro*/
+ 	0,			/*tp_setattro*/
+ 	0,			/*tp_as_buffer*/
+ 	Py_TPFLAGS_NEWSTYLENUMBER /*tp_flags*/
  };
  
  void
diff -rc py_cvs/dist/src/Objects/object.c py_coerce/Objects/object.c
*** py_cvs/dist/src/Objects/object.c	Sat Nov 11 21:16:13 2000
--- py_coerce/Objects/object.c	Sat Dec  9 17:14:48 2000
***************
*** 308,327 ****
  	return res;
  }
  
! 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);
  }
  
  PyObject *_PyCompareState_Key;
--- 308,365 ----
  	return res;
  }
  
! static int
  do_cmp(PyObject *v, PyObject *w)
  {
! 	int result;
! 	PyTypeObject *vtp, *wtp;
! 	if ((vtp = v->ob_type) == (wtp = w->ob_type)) {
! 		if (vtp->tp_compare != NULL) {
! 			return (*vtp->tp_compare)(v, w);
! 		}
! 		else if (vtp->tp_as_number == NULL) {
! 			Py_uintptr_t iv = (Py_uintptr_t)v;
! 			Py_uintptr_t iw = (Py_uintptr_t)w;
! 			return (iv < iw) ? -1 : 1;
! 		}
! 		/* numeric types without ob_compare fall through here, they
! 		 * may only implement nb_cmp */
! 	}
! 	if (vtp->tp_as_number || wtp->tp_as_number) {
! 		/* numeric, different types or no ob_compare */
! 		int c;
! 		PyObject *res = PyNumber_Compare(v, w);
! 		if (res == NULL)
! 			return -1;
! 		if (!PyInt_Check(res)) {
! 		    PyErr_SetString(PyExc_TypeError,
! 				"comparison did not return an int");
! 		    return -1;
! 		}
! 		c = PyInt_AS_LONG(res);
! 		Py_DECREF(res);
! 		result = (c < 0) ? -1 : (c > 0) ? 1 : 0;	
! 	}
! 	else {
! 		/* not numeric, different types */
! 		if (PyUnicode_Check(v) || PyUnicode_Check(w)) {
! 		    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;
!                 }
!                 result = strcmp(vtp->tp_name, wtp->tp_name);
! 	}
! 	return result;
  }
  
  PyObject *_PyCompareState_Key;
***************
*** 401,528 ****
  	}
  	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);
  		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;
  		}
! 		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;
  }
--- 439,480 ----
  	}
  	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);
  		if (PyDict_GetItem(inprogress, pair)) {
  			/* already comparing these objects.  assume
  			   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;
  }
***************
*** 825,830 ****
--- 777,785 ----
  	register PyObject *w = *pw;
  	int res;
  
+ 	DPRINTF("PyNumber_CoerceEx(%s at 0x%lx, %s at 0x%lx);\n",
+ 		v->ob_type->tp_name,(long)v,
+ 		w->ob_type->tp_name,(long)w);
  	if (v->ob_type == w->ob_type && !PyInstance_Check(v)) {
  		Py_INCREF(v);
  		Py_INCREF(w);
***************
*** 915,920 ****
--- 870,906 ----
  
  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)
  };
  
  
diff -rc py_cvs/dist/src/Python/bltinmodule.c py_coerce/Python/bltinmodule.c
*** py_cvs/dist/src/Python/bltinmodule.c	Mon Dec  4 21:25:33 2000
--- py_coerce/Python/bltinmodule.c	Sat Dec  9 16:15:30 2000
***************
*** 2258,2263 ****
--- 2258,2266 ----
  		return NULL;
  	if (PyDict_SetItemString(dict, "Ellipsis", Py_Ellipsis) < 0)
  		return NULL;
+ 	if (PyDict_SetItemString(dict, "NotImplemented", 
+ 				 Py_NotImplemented) < 0)
+ 		return NULL;
  	debug = PyInt_FromLong(Py_OptimizeFlag == 0);
  	if (PyDict_SetItemString(dict, "__debug__", debug) < 0) {
  		Py_XDECREF(debug);
