Commit 12919d05 authored by Guido van Rossum's avatar Guido van Rossum

Add and use coerce() routine for mixed mode arithmetic

parent dda95dd9
...@@ -82,7 +82,7 @@ builtin_dir(self, v) ...@@ -82,7 +82,7 @@ builtin_dir(self, v)
else { else {
if (!is_moduleobject(v)) { if (!is_moduleobject(v)) {
err_setstr(TypeError, err_setstr(TypeError,
"dir() argument, must be module or absent"); "dir() argument must be module or absent");
return NULL; return NULL;
} }
d = getmoduledict(v); d = getmoduledict(v);
...@@ -96,22 +96,28 @@ builtin_dir(self, v) ...@@ -96,22 +96,28 @@ builtin_dir(self, v)
} }
static object * static object *
builtin_divmod(self, v) builtin_divmod(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *x; object *v, *w, *x;
number_methods *nm; if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
err_setstr(TypeError, "divmod() requires 2 arguments"); err_setstr(TypeError, "divmod() requires 2 arguments");
return NULL; return NULL;
} }
x = gettupleitem(v, 0); v = gettupleitem(args, 0);
if ((nm = x->ob_type->tp_as_number) == NULL) { w = gettupleitem(args, 1);
if (v->ob_type->tp_as_number == NULL ||
w->ob_type->tp_as_number == NULL) {
err_setstr(TypeError, "divmod() requires numeric arguments"); err_setstr(TypeError, "divmod() requires numeric arguments");
return NULL; return NULL;
} }
return (*nm->nb_divmod)(x, gettupleitem(v, 1)); if (coerce(&v, &w) != 0)
return NULL;
x = (*v->ob_type->tp_as_number->nb_divmod)(v, w);
DECREF(v);
DECREF(w);
return x;
} }
static object * static object *
...@@ -362,22 +368,28 @@ builtin_ord(self, v) ...@@ -362,22 +368,28 @@ builtin_ord(self, v)
} }
static object * static object *
builtin_pow(self, v) builtin_pow(self, args)
object *self; object *self;
object *v; object *args;
{ {
object *x; object *v, *w, *x;
number_methods *nm; if (args == NULL || !is_tupleobject(args) || gettuplesize(args) != 2) {
if (v == NULL || !is_tupleobject(v) || gettuplesize(v) != 2) {
err_setstr(TypeError, "pow() requires 2 arguments"); err_setstr(TypeError, "pow() requires 2 arguments");
return NULL; return NULL;
} }
x = gettupleitem(v, 0); v = gettupleitem(args, 0);
if ((nm = x->ob_type->tp_as_number) == NULL) { w = gettupleitem(args, 1);
if (v->ob_type->tp_as_number == NULL ||
w->ob_type->tp_as_number == NULL) {
err_setstr(TypeError, "pow() requires numeric arguments"); err_setstr(TypeError, "pow() requires numeric arguments");
return NULL; return NULL;
} }
return (*nm->nb_power)(x, gettupleitem(v, 1)); if (coerce(&v, &w) != 0)
return NULL;
x = (*v->ob_type->tp_as_number->nb_power)(v, w);
DECREF(v);
DECREF(w);
return x;
} }
static object * static object *
...@@ -557,3 +569,50 @@ initbuiltin() ...@@ -557,3 +569,50 @@ initbuiltin()
initerrors(); initerrors();
(void) dictinsert(builtin_dict, "None", None); (void) dictinsert(builtin_dict, "None", None);
} }
/* Coerce two numeric types to the "larger" one.
Increment the reference count on each argument.
Return -1 and raise an exception if no coercion is possible
(and then no reference count is incremented).
XXX This should be distributed over the various numeric types,
XXX but for now I don't see how to implement that.
XXX So, for now, if you add a new numeric type,
XXX you must add to this function as well. */
int
coerce(pv, pw)
object **pv, **pw;
{
register object *v = *pv;
register object *w = *pw;
if (v->ob_type == w->ob_type) {
INCREF(v);
INCREF(w);
return 0;
}
if (v->ob_type->tp_as_number == NULL ||
w->ob_type->tp_as_number == NULL) {
err_setstr(TypeError, "mixing number and non-number");
return -1;
}
if (is_floatobject(v) || is_floatobject(w)) {
v = builtin_float((object *)0, v);
w = builtin_float((object *)0, w);
}
else if (is_longobject(v) || is_longobject(w)) {
v = builtin_long((object *)0, v);
w = builtin_long((object *)0, w);
}
else {
err_setstr(TypeError, "can't coerce numeric types?!?!?");
return -1;
}
if (v == NULL || w == NULL) {
XDECREF(v);
XDECREF(w);
return -1;
}
*pv = v;
*pw = w;
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment