mirror of
https://github.com/python/cpython.git
synced 2025-10-21 06:02:21 +00:00
PEP 448: additional unpacking generalizations (closes #2292)
Patch by Neil Girdhar.
This commit is contained in:
parent
4ccc1514d0
commit
025e9ebd0a
26 changed files with 2664 additions and 2118 deletions
164
Python/ceval.c
164
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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue