diff options
author | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-03-28 23:49:17 (GMT) |
---|---|---|
committer | Jeremy Hylton <jeremy@alum.mit.edu> | 2000-03-28 23:49:17 (GMT) |
commit | 7690151c7e95f38b91a9c572ce29b4d8a4ca671d (patch) | |
tree | fb8eb51104f6aaa895c37c4c144072be016674f5 /Python/ceval.c | |
parent | 93a7c0fe6b2186448ebe35a5af0ac3880d8f16fc (diff) | |
download | cpython-7690151c7e95f38b91a9c572ce29b4d8a4ca671d.zip cpython-7690151c7e95f38b91a9c572ce29b4d8a4ca671d.tar.gz cpython-7690151c7e95f38b91a9c572ce29b4d8a4ca671d.tar.bz2 |
slightly modified version of Greg Ewing's extended call syntax patch
executive summary:
Instead of typing 'apply(f, args, kwargs)' you can type 'f(*arg, **kwargs)'.
Some file-by-file details follow.
Grammar/Grammar:
simplify varargslist, replacing '*' '*' with '**'
add * & ** options to arglist
Include/opcode.h & Lib/dis.py:
define three new opcodes
CALL_FUNCTION_VAR
CALL_FUNCTION_KW
CALL_FUNCTION_VAR_KW
Python/ceval.c:
extend TypeError "keyword parameter redefined" message to include
the name of the offending keyword
reindent CALL_FUNCTION using four spaces
add handling of sequences and dictionaries using extend calls
fix function import_from to use PyErr_Format
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 279 |
1 files changed, 160 insertions, 119 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 46a60f1..7a97771 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -499,15 +499,16 @@ eval_code2(co, globals, locals, if (kwdict == NULL) { PyErr_Format(PyExc_TypeError, "unexpected keyword argument: %.400s", - PyString_AsString(keyword)); + PyString_AsString(keyword)); goto fail; } PyDict_SetItem(kwdict, keyword, value); } else { if (GETLOCAL(j) != NULL) { - PyErr_SetString(PyExc_TypeError, - "keyword parameter redefined"); + PyErr_Format(PyExc_TypeError, + "keyword parameter redefined: %.400s", + PyString_AsString(keyword)); goto fail; } Py_INCREF(value); @@ -1548,125 +1549,166 @@ eval_code2(co, globals, locals, break; case CALL_FUNCTION: + case CALL_FUNCTION_VAR: + case CALL_FUNCTION_KW: + case CALL_FUNCTION_VAR_KW: { - int na = oparg & 0xff; - int nk = (oparg>>8) & 0xff; - int n = na + 2*nk; - PyObject **pfunc = stack_pointer - n - 1; - PyObject *func = *pfunc; - PyObject *self = NULL; - PyObject *class = NULL; - f->f_lasti = INSTR_OFFSET() - 3; /* For tracing */ - if (PyMethod_Check(func)) { - self = PyMethod_Self(func); - class = PyMethod_Class(func); - func = PyMethod_Function(func); - Py_INCREF(func); - if (self != NULL) { - Py_INCREF(self); - Py_DECREF(*pfunc); - *pfunc = self; - na++; - n++; - } - else { - /* Unbound methods must be - called with an instance of - the class (or a derived - class) as first argument */ - if (na > 0 && - (self = stack_pointer[-n]) - != NULL && - PyInstance_Check(self) && - PyClass_IsSubclass( - (PyObject *) - (((PyInstanceObject *)self) - ->in_class), - class)) - /* Handy-dandy */ ; - else { - PyErr_SetString( - PyExc_TypeError, - "unbound method must be called with class instance 1st argument"); - x = NULL; - break; - } - } + int na = oparg & 0xff; + int nk = (oparg>>8) & 0xff; + int flags = (opcode - CALL_FUNCTION) & 3; + int n = na + 2*nk + (flags & 1) + ((flags >> 1) & 1); + PyObject **pfunc = stack_pointer - n - 1; + PyObject *func = *pfunc; + PyObject *self = NULL; + PyObject *class = NULL; + f->f_lasti = INSTR_OFFSET() - 3; /* For tracing */ + if (PyMethod_Check(func)) { + self = PyMethod_Self(func); + class = PyMethod_Class(func); + func = PyMethod_Function(func); + Py_INCREF(func); + if (self != NULL) { + Py_INCREF(self); + Py_DECREF(*pfunc); + *pfunc = self; + na++; + n++; } - else - Py_INCREF(func); - if (PyFunction_Check(func)) { - PyObject *co = PyFunction_GetCode(func); - PyObject *globals = - PyFunction_GetGlobals(func); - PyObject *argdefs = - PyFunction_GetDefaults(func); - PyObject **d; - int nd; - if (argdefs != NULL) { - d = &PyTuple_GET_ITEM(argdefs, 0); - nd = ((PyTupleObject *)argdefs) -> - ob_size; - } - else { - d = NULL; - nd = 0; - } - x = eval_code2( - (PyCodeObject *)co, - globals, (PyObject *)NULL, - stack_pointer-n, na, - stack_pointer-2*nk, nk, - d, nd, - class); + else { + /* Unbound methods must be called with an + instance of the class (or a derived + class) as first argument */ + if (na > 0 && (self = stack_pointer[-n]) != NULL + && PyInstance_Check(self) + && PyClass_IsSubclass((PyObject *) + (((PyInstanceObject *)self)->in_class), + class)) + /* Handy-dandy */ ; + else { + PyErr_SetString(PyExc_TypeError, + "unbound method must be called with class instance 1st argument"); + x = NULL; + break; + } + } + } + else + Py_INCREF(func); + if (PyFunction_Check(func) && flags == 0) { + PyObject *co = PyFunction_GetCode(func); + PyObject *globals = PyFunction_GetGlobals(func); + PyObject *argdefs = PyFunction_GetDefaults(func); + PyObject **d; + int nd; + if (argdefs != NULL) { + d = &PyTuple_GET_ITEM(argdefs, 0); + nd = ((PyTupleObject *)argdefs)->ob_size; } else { - PyObject *args = PyTuple_New(na); - PyObject *kwdict = NULL; - if (args == NULL) { - x = NULL; - break; - } - if (nk > 0) { - kwdict = PyDict_New(); - if (kwdict == NULL) { - x = NULL; - break; - } - err = 0; - while (--nk >= 0) { - PyObject *value = POP(); - PyObject *key = POP(); - err = PyDict_SetItem( - kwdict, key, value); - Py_DECREF(key); - Py_DECREF(value); - if (err) - break; - } - if (err) { - Py_DECREF(args); - Py_DECREF(kwdict); - break; - } + d = NULL; + nd = 0; + } + x = eval_code2((PyCodeObject *)co, globals, + (PyObject *)NULL, stack_pointer-n, na, + stack_pointer-2*nk, nk, d, nd, + class); + } + else { + int nstar = 0; + PyObject *args; + PyObject *stararg = 0; + PyObject *kwdict = NULL; + if (flags & 2) { + kwdict = POP(); + if (!PyDict_Check(kwdict)) { + PyErr_SetString(PyExc_TypeError, + "** argument must be a dictionary"); + x = NULL; + break; + } + } + if (flags & 1) { + stararg = POP(); + if (!PySequence_Check(stararg)) { + PyErr_SetString(PyExc_TypeError, + "* argument must be a sequence"); + x = NULL; + break; + } + nstar = PySequence_Length(stararg); + } + if (nk > 0) { + if (kwdict == NULL) { + kwdict = PyDict_New(); + if (kwdict == NULL) { + x = NULL; + break; } - while (--na >= 0) { - w = POP(); - PyTuple_SET_ITEM(args, na, w); + } + err = 0; + while (--nk >= 0) { + PyObject *value = POP(); + PyObject *key = POP(); + if (PyDict_GetItem(kwdict, key) != NULL) { + err = 1; + PyErr_Format(PyExc_TypeError, + "keyword parameter redefined: %.400s", + PyString_AsString(key)); + break; } - x = PyEval_CallObjectWithKeywords( - func, args, kwdict); + err = PyDict_SetItem(kwdict, key, value); + Py_DECREF(key); + Py_DECREF(value); + if (err) + break; + } + if (err) { Py_DECREF(args); - Py_XDECREF(kwdict); - } - Py_DECREF(func); - while (stack_pointer > pfunc) { - w = POP(); - Py_DECREF(w); - } - PUSH(x); - if (x != NULL) continue; - break; + Py_DECREF(kwdict); + break; + } + } + args = PyTuple_New(na + nstar); + if (args == NULL) { + x = NULL; + break; + } + if (stararg) { + PyObject *t = NULL; + int i; + if (!PyTuple_Check(stararg)) { + /* must be sequence to pass earlier test */ + t = PySequence_Tuple(stararg); + if (t == NULL) { + x = NULL; + break; + } + Py_DECREF(stararg); + stararg = t; + } + for (i = 0; i < nstar; i++) { + PyObject *a = PyTuple_GET_ITEM(stararg, i); + Py_INCREF(a); + PyTuple_SET_ITEM(args, na + i, a); + } + Py_DECREF(stararg); + } + while (--na >= 0) { + w = POP(); + PyTuple_SET_ITEM(args, na, w); + } + x = PyEval_CallObjectWithKeywords(func, args, kwdict); + Py_DECREF(args); + Py_XDECREF(kwdict); + } + Py_DECREF(func); + while (stack_pointer > pfunc) { + w = POP(); + Py_DECREF(w); + } + PUSH(x); + if (x != NULL) continue; + break; } case MAKE_FUNCTION: @@ -2687,10 +2729,9 @@ import_from(locals, v, name) else { x = PyDict_GetItem(w, name); if (x == NULL) { - char buf[250]; - sprintf(buf, "cannot import name %.230s", - PyString_AsString(name)); - PyErr_SetString(PyExc_ImportError, buf); + PyErr_Format(PyExc_ImportError, + "cannot import name %.230s", + PyString_AsString(name)); return -1; } else |