diff options
| author | Benjamin Peterson <benjamin@python.org> | 2015-05-05 20:16:41 -0400 | 
|---|---|---|
| committer | Benjamin Peterson <benjamin@python.org> | 2015-05-05 20:16:41 -0400 | 
| commit | 025e9ebd0a0a19f50ca83af6ada0ac65be1fa2a1 (patch) | |
| tree | d769adcb6d4a557a00923f18ed2b0ca8b515a473 /Python/ceval.c | |
| parent | 4ccc1514d070cabe80e8cfa0469dc03c12d08be2 (diff) | |
| download | cpython-git-025e9ebd0a0a19f50ca83af6ada0ac65be1fa2a1.tar.gz | |
PEP 448: additional unpacking generalizations (closes #2292)
Patch by Neil Girdhar.
Diffstat (limited to 'Python/ceval.c')
| -rw-r--r-- | Python/ceval.c | 164 | 
1 files changed, 159 insertions, 5 deletions
| diff --git a/Python/ceval.c b/Python/ceval.c index 2f3d3ad8b8..5ee9077332 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -12,8 +12,10 @@  #include "Python.h"  #include "code.h" +#include "dictobject.h"  #include "frameobject.h"  #include "opcode.h" +#include "setobject.h"  #include "structmember.h"  #include <ctype.h> @@ -2379,6 +2381,43 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)              DISPATCH();          } +        TARGET_WITH_IMPL(BUILD_TUPLE_UNPACK, _build_list_unpack) +        TARGET(BUILD_LIST_UNPACK) +        _build_list_unpack: { +            int convert_to_tuple = opcode == BUILD_TUPLE_UNPACK; +            int i; +            PyObject *sum = PyList_New(0); +            PyObject *return_value; +            if (sum == NULL) +                goto error; + +            for (i = oparg; i > 0; i--) { +                PyObject *none_val; + +                none_val = _PyList_Extend((PyListObject *)sum, PEEK(i)); +                if (none_val == NULL) { +                    Py_DECREF(sum); +                    goto error; +                } +                Py_DECREF(none_val); +            } + +            if (convert_to_tuple) { +                return_value = PyList_AsTuple(sum); +                Py_DECREF(sum); +                if (return_value == NULL) +                    goto error; +            } +            else { +                return_value = sum; +            } + +            while (oparg--) +                Py_DECREF(POP()); +            PUSH(return_value); +            DISPATCH(); +        } +          TARGET(BUILD_SET) {              PyObject *set = PySet_New(NULL);              int err = 0; @@ -2398,14 +2437,127 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)              DISPATCH();          } +        TARGET(BUILD_SET_UNPACK) { +            int i; +            PyObject *sum = PySet_New(NULL); +            if (sum == NULL) +                goto error; + +            for (i = oparg; i > 0; i--) { +                if (_PySet_Update(sum, PEEK(i)) < 0) { +                    Py_DECREF(sum); +                    goto error; +                } +            } + +            while (oparg--) +                Py_DECREF(POP()); +            PUSH(sum); +            DISPATCH(); +        } +          TARGET(BUILD_MAP) {              PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg);              if (map == NULL)                  goto error; +            while (--oparg >= 0) { +                int err; +                PyObject *key = TOP(); +                PyObject *value = SECOND(); +                STACKADJ(-2); +                err = PyDict_SetItem(map, key, value); +                Py_DECREF(value); +                Py_DECREF(key); +                if (err != 0) { +                    Py_DECREF(map); +                    goto error; +                } +            }              PUSH(map);              DISPATCH();          } +        TARGET_WITH_IMPL(BUILD_MAP_UNPACK_WITH_CALL, _build_map_unpack) +        TARGET(BUILD_MAP_UNPACK) +        _build_map_unpack: { +            int with_call = opcode == BUILD_MAP_UNPACK_WITH_CALL; +            int num_maps; +            int function_location; +            int i; +            PyObject *sum = PyDict_New(); +            if (sum == NULL) +                goto error; +            if (with_call) { +                num_maps = oparg & 0xff; +                function_location = (oparg>>8) & 0xff; +            } +            else { +                num_maps = oparg; +            } + +            for (i = num_maps; i > 0; i--) { +                PyObject *arg = PEEK(i); +                if (with_call) { +                    PyObject *intersection = _PyDictView_Intersect(sum, arg); + +                    if (intersection == NULL) { +                        if (PyErr_ExceptionMatches(PyExc_AttributeError)) { +                            PyObject *func = ( +                                    PEEK(function_location + num_maps)); +                            PyErr_Format(PyExc_TypeError, +                                    "%.200s%.200s argument after ** " +                                    "must be a mapping, not %.200s", +                                    PyEval_GetFuncName(func), +                                    PyEval_GetFuncDesc(func), +                                    arg->ob_type->tp_name); +                        } +                        Py_DECREF(sum); +                        goto error; +                    } + +                    if (PySet_GET_SIZE(intersection)) { +                        Py_ssize_t idx = 0; +                        PyObject *key; +                        PyObject *func = PEEK(function_location + num_maps); +                        Py_hash_t hash; +                        _PySet_NextEntry(intersection, &idx, &key, &hash); +                        if (!PyUnicode_Check(key)) { +                            PyErr_Format(PyExc_TypeError, +                                    "%.200s%.200s keywords must be strings", +                                    PyEval_GetFuncName(func), +                                    PyEval_GetFuncDesc(func)); +                        } else { +                            PyErr_Format(PyExc_TypeError, +                                    "%.200s%.200s got multiple " +                                    "values for keyword argument '%U'", +                                    PyEval_GetFuncName(func), +                                    PyEval_GetFuncDesc(func), +                                    key); +                        } +                        Py_DECREF(intersection); +                        Py_DECREF(sum); +                        goto error; +                    } +                    Py_DECREF(intersection); +                } + +                if (PyDict_Update(sum, arg) < 0) { +                    if (PyErr_ExceptionMatches(PyExc_AttributeError)) { +                        PyErr_Format(PyExc_TypeError, +                                "'%.200s' object is not a mapping", +                                arg->ob_type->tp_name); +                    } +                    Py_DECREF(sum); +                    goto error; +                } +            } + +            while (num_maps--) +                Py_DECREF(POP()); +            PUSH(sum); +            DISPATCH(); +        } +          TARGET(STORE_MAP) {              PyObject *key = TOP();              PyObject *value = SECOND(); @@ -3050,6 +3202,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)              goto dispatch_opcode;          } +  #if USE_COMPUTED_GOTOS          _unknown_opcode:  #endif @@ -4557,6 +4710,12 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)              kwdict = d;          }      } +    if (nk > 0) { +        kwdict = update_keyword_args(kwdict, nk, pp_stack, func); +        if (kwdict == NULL) +            goto ext_call_fail; +    } +      if (flags & CALL_FLAG_VAR) {          stararg = EXT_POP(*pp_stack);          if (!PyTuple_Check(stararg)) { @@ -4578,11 +4737,6 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)          }          nstar = PyTuple_GET_SIZE(stararg);      } -    if (nk > 0) { -        kwdict = update_keyword_args(kwdict, nk, pp_stack, func); -        if (kwdict == NULL) -            goto ext_call_fail; -    }      callargs = update_star_args(na, nstar, stararg, pp_stack);      if (callargs == NULL)          goto ext_call_fail; | 
