diff options
author | Guido van Rossum <guido@python.org> | 1994-09-29 09:45:57 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1994-09-29 09:45:57 (GMT) |
commit | 180d7b4d5588737601b3242d8ce9cab59a75286f (patch) | |
tree | b5ac47852aa67c7bf2b1a82eaf0b0117b314e348 | |
parent | fe3f1a256bc4f0c359ab843d5de517946916218f (diff) | |
download | cpython-180d7b4d5588737601b3242d8ce9cab59a75286f.zip cpython-180d7b4d5588737601b3242d8ce9cab59a75286f.tar.gz cpython-180d7b4d5588737601b3242d8ce9cab59a75286f.tar.bz2 |
* Python/ceval.c, Include/ceval.h: promote MakePendingCalls to
global: Py_MakePendingCalls. Also guard against recursive calls
* Include/classobject.h, Objects/classobject.c,
Python/{ceval.c,bltinmodule.c}: entirely redone operator
overloading. The rules for class instances are now much more
relaxed than for other built-in types
(whose coerce must still return two objects of the same type)
-rw-r--r-- | Python/bltinmodule.c | 21 | ||||
-rw-r--r-- | Python/ceval.c | 37 |
2 files changed, 48 insertions, 10 deletions
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index b38ed5b..3acf187 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -243,6 +243,8 @@ builtin_coerce(self, args) if (!getargs(args, "(OO)", &v, &w)) return NULL; + if (is_instanceobject(v) || is_instanceobject(w)) + return instancebinop(v, w, "__coerce__", "__rcoerce__"); if (coerce(&v, &w) < 0) return NULL; res = mkvalue("(OO)", v, w); @@ -314,9 +316,11 @@ builtin_divmod(self, args) object *v, *w, *x; if (!getargs(args, "(OO)", &v, &w)) return NULL; + if (is_instanceobject(v) || is_instanceobject(w)) + return instancebinop(v, w, "__divmod__", "__rdivmod__"); 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 or class instance arguments"); return NULL; } if (coerce(&v, &w) != 0) @@ -876,11 +880,16 @@ builtin_pow(self, args) { object *v, *w, *z, *x; z = None; - if (!getargs(args, "(OO)", &v, &w)) { - err_clear(); - if (!getargs(args, "(OOO)", &v, &w, &z)) { - return NULL; - } + if (!newgetargs(args, "OO|O", &v, &w, &z)) + return NULL; + if (z == None) { + if (is_instanceobject(v) || is_instanceobject(w)) + return instancebinop(v, w, "__pow__", "__rpow__"); + } + else { + /* XXX The ternary version doesn't do coercions */ + if (is_instanceobject(v)) + return v->ob_type->tp_as_number->nb_power(v, w, z); } if (v->ob_type->tp_as_number == NULL || (z!=None && z->ob_type->tp_as_number == NULL) || diff --git a/Python/ceval.c b/Python/ceval.c index 2cc5f97..d567c9d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -196,10 +196,14 @@ Py_AddPendingCall(func, arg) int (*func) PROTO((ANY *)); ANY *arg; { + static int busy = 0; int i, j; /* XXX Begin critical section */ /* XXX If you want this to be safe against nested XXX asynchronous calls, you'll have to work harder! */ + if (busy) + return -1; + busy = 1; i = pendinglast; j = (i + 1) % NPENDINGCALLS; if (j == pendingfirst) @@ -207,17 +211,22 @@ Py_AddPendingCall(func, arg) pendingcalls[i].func = func; pendingcalls[i].arg = arg; pendinglast = j; + busy = 0; /* XXX End critical section */ return 0; } -static int -MakePendingCalls() +int +Py_MakePendingCalls() { + static int busy = 0; #ifdef WITH_THREAD if (get_thread_ident() != main_thread) return 0; #endif + if (busy) + return 0; + busy = 1; for (;;) { int i; int (*func) PROTO((ANY *)); @@ -228,9 +237,12 @@ MakePendingCalls() func = pendingcalls[i].func; arg = pendingcalls[i].arg; pendingfirst = (i + 1) % NPENDINGCALLS; - if (func(arg) < 0) + if (func(arg) < 0) { + busy = 0; return -1; + } } + busy = 0; return 0; } @@ -398,7 +410,7 @@ eval_code(co, globals, locals, owner, arg) So we do it only every Nth instruction. */ if (pendingfirst != pendinglast) { - if (MakePendingCalls() < 0) { + if (Py_MakePendingCalls() < 0) { why = WHY_EXCEPTION; goto on_error; } @@ -1736,10 +1748,18 @@ flushline() } +#define BINOP(opname, ropname) \ + do { \ + if (is_instanceobject(v) || is_instanceobject(w)) \ + return instancebinop(v, w, opname, ropname); \ + } while (0) + + static object * or(v, w) object *v, *w; { + BINOP("__or__", "__ror__"); if (v->ob_type->tp_as_number != NULL) { object *x; object * (*f) FPROTO((object *, object *)); @@ -1760,6 +1780,7 @@ static object * xor(v, w) object *v, *w; { + BINOP("__xor__", "__rxor__"); if (v->ob_type->tp_as_number != NULL) { object *x; object * (*f) FPROTO((object *, object *)); @@ -1780,6 +1801,7 @@ static object * and(v, w) object *v, *w; { + BINOP("__and__", "__rand__"); if (v->ob_type->tp_as_number != NULL) { object *x; object * (*f) FPROTO((object *, object *)); @@ -1800,6 +1822,7 @@ static object * lshift(v, w) object *v, *w; { + BINOP("__lshift__", "__rshift__"); if (v->ob_type->tp_as_number != NULL) { object *x; object * (*f) FPROTO((object *, object *)); @@ -1820,6 +1843,7 @@ static object * rshift(v, w) object *v, *w; { + BINOP("__rshift__", "__rrshift__"); if (v->ob_type->tp_as_number != NULL) { object *x; object * (*f) FPROTO((object *, object *)); @@ -1840,6 +1864,7 @@ static object * add(v, w) object *v, *w; { + BINOP("__add__", "__radd__"); if (v->ob_type->tp_as_sequence != NULL) return (*v->ob_type->tp_as_sequence->sq_concat)(v, w); else if (v->ob_type->tp_as_number != NULL) { @@ -1859,6 +1884,7 @@ static object * sub(v, w) object *v, *w; { + BINOP("__sub__", "__rsub__"); if (v->ob_type->tp_as_number != NULL) { object *x; if (coerce(&v, &w) != 0) @@ -1878,6 +1904,7 @@ mul(v, w) { typeobject *tp; tp = v->ob_type; + BINOP("__mul__", "__rmul__"); if (tp->tp_as_number != NULL && w->ob_type->tp_as_sequence != NULL && !is_instanceobject(v)) { @@ -1921,6 +1948,7 @@ static object * divide(v, w) object *v, *w; { + BINOP("__div__", "__rdiv__"); if (v->ob_type->tp_as_number != NULL) { object *x; if (coerce(&v, &w) != 0) @@ -1938,6 +1966,7 @@ static object * rem(v, w) object *v, *w; { + BINOP("__mod__", "__rmod__"); if (v->ob_type->tp_as_number != NULL) { object *x; if (coerce(&v, &w) != 0) |