diff options
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 2f3d3ad..5ee9077 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; |