diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2016-08-16 21:40:29 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2016-08-16 21:40:29 (GMT) |
commit | c70200165c4199e50201148d5971798342a86b5a (patch) | |
tree | e51dd4a1d5b50948d3696b9ab3a3392e7b4881b7 /Python | |
parent | e3f1e8a9d3e8892730d28fa24cdc9359e07d63f6 (diff) | |
download | cpython-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.c | 54 |
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; |