mirror of
https://github.com/python/cpython.git
synced 2025-09-18 14:40:43 +00:00
Add and use coerce() routine for mixed mode arithmetic
This commit is contained in:
parent
22825e86f6
commit
c6bb8f7ab2
1 changed files with 76 additions and 17 deletions
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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()
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue