mp.c: Use implicit-conversion rules in `coerce'.
[catacomb-python] / mp.c
diff --git a/mp.c b/mp.c
index e299a7d..163e690 100644 (file)
--- a/mp.c
+++ b/mp.c
@@ -287,7 +287,7 @@ int convgf(PyObject *o, void *p)
   return (1);
 }
 
-static mp *implicitmp(PyObject *o)
+mp *implicitmp(PyObject *o)
 {
   if (!o ||
       GF_PYCHECK(o) ||
@@ -298,7 +298,7 @@ static mp *implicitmp(PyObject *o)
   return (tomp(o));
 }
 
-static mp *implicitgf(PyObject *o)
+mp *implicitgf(PyObject *o)
 {
   if (!o ||
       MP_PYCHECK(o) ||
@@ -393,25 +393,24 @@ UNOP(mp, not2c)
 static PyObject *mp_pyid(PyObject *x) { RETURN_OBJ(x); }
 
 #define gf_lsr mp_lsr
-#define SHIFTOP(pre, name, rname)                                      \
+#define SHIFTOP(pre, PRE, name, rname)                                 \
   static PyObject *pre##_py##name(PyObject *x, PyObject *y) {          \
-    mp *xx, *yy;                                                       \
+    PyObject *yix = 0;                                                 \
     PyObject *z = 0;                                                   \
     long n;                                                            \
-    if (pre##binop(x, y, &xx, &yy)) RETURN_NOTIMPL;                    \
-    if (mp_tolong_checked(yy, &n, 1)) goto end;                                \
-    if (n < 0)                                                         \
-      z = pre##_pywrap(mp_##rname(MP_NEW, xx, -n));                    \
-    else                                                               \
-      z = pre##_pywrap(mp_##name(MP_NEW, xx, n));                      \
-  end:                                                                 \
-    MP_DROP(xx); MP_DROP(yy);                                          \
+    if (!PRE##_PYCHECK(x)) RETURN_NOTIMPL;                             \
+    if (GF_PYCHECK(y) || FE_PYCHECK(y)) RETURN_NOTIMPL;                        \
+    yix = PyNumber_Index(y); if (!yix) { PyErr_Clear(); RETURN_NOTIMPL; } \
+    n = PyInt_AsLong(yix); Py_DECREF(yix);                             \
+    if (n == -1 && PyErr_Occurred())  { PyErr_Clear(); RETURN_NOTIMPL; } \
+    if (n < 0) z = pre##_pywrap(mp_##rname(MP_NEW, MP_X(x), -n));      \
+    else z = pre##_pywrap(mp_##name(MP_NEW, MP_X(x), n));              \
     return (z);                                                                \
   }
-SHIFTOP(mp, lsl2c, lsr2c)
-SHIFTOP(mp, lsr2c, lsl2c)
-SHIFTOP(gf, lsl, lsr)
-SHIFTOP(gf, lsr, lsl)
+SHIFTOP(mp, MP, lsl2c, lsr2c)
+SHIFTOP(mp, MP, lsr2c, lsl2c)
+SHIFTOP(gf, GF, lsl, lsr)
+SHIFTOP(gf, GF, lsr, lsl)
 #undef SHIFTOP
 
 #define DIVOP(pre, name, qq, rr, gather)                               \
@@ -465,7 +464,7 @@ static PyObject *mp_pyexp(PyObject *x, PyObject *y, PyObject *z)
   PyObject *rc = 0;
 
   if ((xx = implicitmp(x)) == 0 || (yy = implicitmp(y)) == 0 ||
-      (z && z != Py_None && (zz = tomp(z)) == 0)) {
+      (z && z != Py_None && (zz = implicitmp(z)) == 0)) {
     mp_drop(xx); mp_drop(yy); mp_drop(zz);
     RETURN_NOTIMPL;
   }
@@ -547,7 +546,7 @@ static PyObject *mp_pyfloat(PyObject *x)
       Py_INCREF(*x); Py_INCREF(*y);                                    \
       return (0);                                                      \
     }                                                                  \
-    if ((z = tomp(*y)) != 0) {                                         \
+    if ((z = implicit##pre(*y)) != 0) {                                        \
       Py_INCREF(*x);                                                   \
       *y = pre##_pywrap(z);                                            \
       return (0);                                                      \
@@ -1993,8 +1992,8 @@ static PyObject *gf_pyexp(PyObject *x, PyObject *y, PyObject *z)
   mp *r = 0;
   PyObject *rc = 0;
 
-  if ((xx = tomp(x)) == 0 || (yy = tomp(y)) == 0 ||
-      (z && z != Py_None && (zz = tomp(z)) == 0)) {
+  if ((xx = implicitgf(x)) == 0 || (yy = implicitmp(y)) == 0 ||
+      (z && z != Py_None && (zz = implicitgf(z)) == 0)) {
     mp_drop(xx); mp_drop(yy); mp_drop(zz);
     RETURN_NOTIMPL;
   }