summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-08-16 21:40:29 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-08-16 21:40:29 (GMT)
commitc70200165c4199e50201148d5971798342a86b5a (patch)
treee51dd4a1d5b50948d3696b9ab3a3392e7b4881b7 /Python
parente3f1e8a9d3e8892730d28fa24cdc9359e07d63f6 (diff)
downloadcpython-c70200165c4199e50201148d5971798342a86b5a.zip
cpython-c70200165c4199e50201148d5971798342a86b5a.tar.gz
cpython-c70200165c4199e50201148d5971798342a86b5a.tar.bz2
Issue #27128: Cleanup _PyEval_EvalCodeWithName()
* Add comments * Add empty lines for readability * PEP 7 style for if block * Remove useless assert(globals != NULL); (globals is tested a few lines before)
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c54
1 files changed, 43 insertions, 11 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 7ca3ad2..6e4c6aa 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -3793,12 +3793,13 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyFrameObject *f;
PyObject *retval = NULL;
PyObject **fastlocals, **freevars;
- PyThreadState *tstate = PyThreadState_GET();
+ PyThreadState *tstate;
PyObject *x, *u;
int total_args = co->co_argcount + co->co_kwonlyargcount;
- int i;
- int n = argcount;
- PyObject *kwdict = NULL;
+ int i, n;
+ PyObject *kwdict;
+
+ assert((kwcount == 0) || (kws != NULL));
if (globals == NULL) {
PyErr_SetString(PyExc_SystemError,
@@ -3806,36 +3807,50 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
return NULL;
}
+ /* Create the frame */
+ tstate = PyThreadState_GET();
assert(tstate != NULL);
- assert(globals != NULL);
f = PyFrame_New(tstate, co, globals, locals);
- if (f == NULL)
+ if (f == NULL) {
return NULL;
-
+ }
fastlocals = f->f_localsplus;
freevars = f->f_localsplus + co->co_nlocals;
- /* Parse arguments. */
+ /* Create a dictionary for keyword parameters (**kwags) */
if (co->co_flags & CO_VARKEYWORDS) {
kwdict = PyDict_New();
if (kwdict == NULL)
goto fail;
i = total_args;
- if (co->co_flags & CO_VARARGS)
+ if (co->co_flags & CO_VARARGS) {
i++;
+ }
SETLOCAL(i, kwdict);
}
- if (argcount > co->co_argcount)
+ else {
+ kwdict = NULL;
+ }
+
+ /* Copy positional arguments into local variables */
+ if (argcount > co->co_argcount) {
n = co->co_argcount;
+ }
+ else {
+ n = argcount;
+ }
for (i = 0; i < n; i++) {
x = args[i];
Py_INCREF(x);
SETLOCAL(i, x);
}
+
+ /* Pack other positional arguments into the *args argument */
if (co->co_flags & CO_VARARGS) {
u = PyTuple_New(argcount - n);
- if (u == NULL)
+ if (u == NULL) {
goto fail;
+ }
SETLOCAL(total_args, u);
for (i = n; i < argcount; i++) {
x = args[i];
@@ -3843,17 +3858,21 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
PyTuple_SET_ITEM(u, i-n, x);
}
}
+
+ /* Handle keyword arguments (passed as an array of (key, value)) */
for (i = 0; i < kwcount; i++) {
PyObject **co_varnames;
PyObject *keyword = kws[2*i];
PyObject *value = kws[2*i + 1];
int j;
+
if (keyword == NULL || !PyUnicode_Check(keyword)) {
PyErr_Format(PyExc_TypeError,
"%U() keywords must be strings",
co->co_name);
goto fail;
}
+
/* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
@@ -3862,6 +3881,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
if (nm == keyword)
goto kw_found;
}
+
/* Slow fallback, just in case */
for (j = 0; j < total_args; j++) {
PyObject *nm = co_varnames[j];
@@ -3872,6 +3892,7 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
else if (cmp < 0)
goto fail;
}
+
if (j >= total_args && kwdict == NULL) {
PyErr_Format(PyExc_TypeError,
"%U() got an unexpected "
@@ -3880,10 +3901,12 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
keyword);
goto fail;
}
+
if (PyDict_SetItem(kwdict, keyword, value) == -1) {
goto fail;
}
continue;
+
kw_found:
if (GETLOCAL(j) != NULL) {
PyErr_Format(PyExc_TypeError,
@@ -3896,10 +3919,14 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
Py_INCREF(value);
SETLOCAL(j, value);
}
+
+ /* Check the number of positional arguments */
if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) {
too_many_positional(co, argcount, defcount, fastlocals);
goto fail;
}
+
+ /* Add missing positional arguments (copy default values from defs) */
if (argcount < co->co_argcount) {
int m = co->co_argcount - defcount;
int missing = 0;
@@ -3922,6 +3949,8 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
}
}
}
+
+ /* Add missing keyword arguments (copy default values from kwdefs) */
if (co->co_kwonlyargcount > 0) {
int missing = 0;
for (i = co->co_argcount; i < total_args; i++) {
@@ -3964,12 +3993,15 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
goto fail;
SETLOCAL(co->co_nlocals + i, c);
}
+
+ /* Copy closure variables to free variables */
for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
PyObject *o = PyTuple_GET_ITEM(closure, i);
Py_INCREF(o);
freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
}
+ /* Handle generator/coroutine */
if (co->co_flags & (CO_GENERATOR | CO_COROUTINE)) {
PyObject *gen;
PyObject *coro_wrapper = tstate->coroutine_wrapper;