New argument passing mechanism.

This commit is contained in:
Guido van Rossum 1991-12-16 13:04:47 +00:00
parent c02e15c45e
commit 9c7b861a00
1 changed files with 109 additions and 35 deletions

View File

@ -59,6 +59,7 @@ static object *xor();
static object *or(); static object *or();
static object *call_builtin(); static object *call_builtin();
static object *call_function(); static object *call_function();
object *call_object();
static object *apply_subscript(); static object *apply_subscript();
static object *loop_subscript(); static object *loop_subscript();
static object *apply_slice(); static object *apply_slice();
@ -272,10 +273,7 @@ eval_code(co, globals, locals, arg)
case UNARY_CALL: case UNARY_CALL:
v = POP(); v = POP();
if (is_instancemethodobject(v) || is_funcobject(v)) x = call_object(v, (object *)NULL);
x = call_function(v, (object *)NULL);
else
x = call_builtin(v, (object *)NULL);
DECREF(v); DECREF(v);
PUSH(x); PUSH(x);
break; break;
@ -344,10 +342,7 @@ eval_code(co, globals, locals, arg)
case BINARY_CALL: case BINARY_CALL:
w = POP(); w = POP();
v = POP(); v = POP();
if (is_instancemethodobject(v) || is_funcobject(v)) x = call_object(v, w);
x = call_function(v, w);
else
x = call_builtin(v, w);
DECREF(v); DECREF(v);
DECREF(w); DECREF(w);
PUSH(x); PUSH(x);
@ -550,22 +545,6 @@ eval_code(co, globals, locals, arg)
why = WHY_RETURN; why = WHY_RETURN;
break; break;
case REQUIRE_ARGS:
if (EMPTY()) {
err_setstr(TypeError,
"function expects argument(s)");
why = WHY_EXCEPTION;
}
break;
case REFUSE_ARGS:
if (!EMPTY()) {
err_setstr(TypeError,
"function expects no argument(s)");
why = WHY_EXCEPTION;
}
break;
case BUILD_FUNCTION: case BUILD_FUNCTION:
v = POP(); v = POP();
x = newfuncobject(v, f->f_globals); x = newfuncobject(v, f->f_globals);
@ -629,6 +608,79 @@ eval_code(co, globals, locals, arg)
err_setstr(NameError, getstringvalue(w)); err_setstr(NameError, getstringvalue(w));
break; break;
case UNPACK_ARG:
/* Implement various compatibility hacks:
(a) f(a,b,...) should accept f((1,2,...))
(b) f((a,b,...)) should accept f(1,2,...)
(c) f(self,(a,b,...)) should accept f(x,1,2,...)
*/
{
int n;
if (EMPTY()) {
err_setstr(TypeError,
"no argument list");
why = WHY_EXCEPTION;
break;
}
v = POP();
if (!is_tupleobject(v)) {
err_setstr(TypeError,
"bad argument list");
why = WHY_EXCEPTION;
break;
}
n = gettuplesize(v);
if (n == 1 && oparg != 1) {
/* Rule (a) */
w = gettupleitem(v, 0);
if (is_tupleobject(w)) {
INCREF(w);
DECREF(v);
v = w;
n = gettuplesize(v);
}
}
else if (n != 1 && oparg == 1) {
/* Rule (b) */
PUSH(v);
break;
/* Don't fall through */
}
else if (n > 2 && oparg == 2) {
/* Rule (c) */
int i;
w = newtupleobject(n-1);
u = newtupleobject(2);
if (u == NULL || w == NULL) {
XDECREF(w);
XDECREF(u);
DECREF(v);
why = WHY_EXCEPTION;
break;
}
t = gettupleitem(v, 0);
INCREF(t);
settupleitem(u, 0, t);
for (i = 1; i < n; i++) {
t = gettupleitem(v, i);
INCREF(t);
settupleitem(w, i-1, t);
}
settupleitem(u, 1, w);
DECREF(v);
v = u;
n = 2;
}
if (n != oparg) {
err_setstr(TypeError,
"arg count mismatch");
why = WHY_EXCEPTION;
DECREF(v);
break;
}
PUSH(v);
}
/* Fall through */
case UNPACK_TUPLE: case UNPACK_TUPLE:
v = POP(); v = POP();
if (!is_tupleobject(v)) { if (!is_tupleobject(v)) {
@ -1346,10 +1398,19 @@ call_builtin(func, arg)
if (is_methodobject(func)) { if (is_methodobject(func)) {
method meth = getmethod(func); method meth = getmethod(func);
object *self = getself(func); object *self = getself(func);
if (!getvarargs(func) && arg != NULL && is_tupleobject(arg)) {
int size = gettuplesize(arg);
if (size == 1)
arg = gettupleitem(arg, 0);
else if (size == 0)
arg = NULL;
}
return (*meth)(self, arg); return (*meth)(self, arg);
} }
if (is_classobject(func)) { if (is_classobject(func)) {
if (arg != NULL) { if (arg != NULL &&
!(is_tupleobject(arg) &&
gettuplesize(arg) == 0)) {
err_setstr(TypeError, err_setstr(TypeError,
"classobject() allows no arguments"); "classobject() allows no arguments");
return NULL; return NULL;
@ -1370,21 +1431,34 @@ call_function(func, arg)
object *co, *v; object *co, *v;
if (is_instancemethodobject(func)) { if (is_instancemethodobject(func)) {
int argcount;
object *self = instancemethodgetself(func); object *self = instancemethodgetself(func);
func = instancemethodgetfunc(func); func = instancemethodgetfunc(func);
if (arg == NULL) { if (arg == NULL)
arg = self; argcount = 0;
} else if (is_tupleobject(arg))
else { argcount = gettuplesize(arg);
newarg = newtupleobject(2); else
argcount = 1;
newarg = newtupleobject(argcount + 1);
if (newarg == NULL) if (newarg == NULL)
return NULL; return NULL;
INCREF(self); INCREF(self);
INCREF(arg);
settupleitem(newarg, 0, self); settupleitem(newarg, 0, self);
if (arg != NULL && !is_tupleobject(arg)) {
INCREF(arg);
settupleitem(newarg, 1, arg); settupleitem(newarg, 1, arg);
arg = newarg;
} }
else {
int i;
object *v;
for (i = 0; i < argcount; i++) {
v = gettupleitem(arg, i);
XINCREF(v);
settupleitem(newarg, i+1, v);
}
}
arg = newarg;
} }
else { else {
if (!is_funcobject(func)) { if (!is_funcobject(func)) {