mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
eval_code2(): collapsed the implementations of UNPACK_TUPLE and
UNPACK_LIST byte codes and added a third code path that allows generalized sequence unpacking. Now both syntaxes: a, b, c = seq [a, b, c] = seq can be used to unpack any sequence with the exact right number of items. unpack_sequence(): out-lined implementation of generalized sequence unpacking. tuple and list unpacking are still inlined.
This commit is contained in:
parent
1fb071cc64
commit
e42b18f9d1
1 changed files with 75 additions and 34 deletions
109
Python/ceval.c
109
Python/ceval.c
|
@ -312,6 +312,7 @@ enum why_code {
|
||||||
};
|
};
|
||||||
|
|
||||||
static enum why_code do_raise Py_PROTO((PyObject *, PyObject *, PyObject *));
|
static enum why_code do_raise Py_PROTO((PyObject *, PyObject *, PyObject *));
|
||||||
|
static int unpack_sequence Py_PROTO((PyObject *, int, PyObject **));
|
||||||
|
|
||||||
|
|
||||||
/* Backward compatible interface */
|
/* Backward compatible interface */
|
||||||
|
@ -1182,45 +1183,47 @@ eval_code2(co, globals, locals,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case UNPACK_TUPLE:
|
case UNPACK_TUPLE:
|
||||||
v = POP();
|
|
||||||
if (!PyTuple_Check(v)) {
|
|
||||||
PyErr_SetString(PyExc_TypeError,
|
|
||||||
"unpack non-tuple");
|
|
||||||
why = WHY_EXCEPTION;
|
|
||||||
}
|
|
||||||
else if (PyTuple_Size(v) != oparg) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"unpack tuple of wrong size");
|
|
||||||
why = WHY_EXCEPTION;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
for (; --oparg >= 0; ) {
|
|
||||||
w = PyTuple_GET_ITEM(v, oparg);
|
|
||||||
Py_INCREF(w);
|
|
||||||
PUSH(w);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Py_DECREF(v);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case UNPACK_LIST:
|
case UNPACK_LIST:
|
||||||
v = POP();
|
v = POP();
|
||||||
if (!PyList_Check(v)) {
|
if (PyTuple_Check(v)) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
if (PyTuple_Size(v) != oparg) {
|
||||||
"unpack non-list");
|
PyErr_SetString(PyExc_ValueError,
|
||||||
why = WHY_EXCEPTION;
|
"unpack tuple of wrong size");
|
||||||
|
why = WHY_EXCEPTION;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (; --oparg >= 0; ) {
|
||||||
|
w = PyTuple_GET_ITEM(v, oparg);
|
||||||
|
Py_INCREF(w);
|
||||||
|
PUSH(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (PyList_Size(v) != oparg) {
|
else if (PyList_Check(v)) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
if (PyList_Size(v) != oparg) {
|
||||||
"unpack list of wrong size");
|
PyErr_SetString(PyExc_ValueError,
|
||||||
why = WHY_EXCEPTION;
|
"unpack list of wrong size");
|
||||||
|
why = WHY_EXCEPTION;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (; --oparg >= 0; ) {
|
||||||
|
w = PyList_GET_ITEM(v, oparg);
|
||||||
|
Py_INCREF(w);
|
||||||
|
PUSH(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (PySequence_Check(v)) {
|
||||||
|
if (unpack_sequence(v, oparg,
|
||||||
|
stack_pointer + oparg))
|
||||||
|
stack_pointer += oparg;
|
||||||
|
else
|
||||||
|
why = WHY_EXCEPTION;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (; --oparg >= 0; ) {
|
PyErr_SetString(PyExc_TypeError,
|
||||||
w = PyList_GetItem(v, oparg);
|
"unpack non-sequence");
|
||||||
Py_INCREF(w);
|
why = WHY_EXCEPTION;
|
||||||
PUSH(w);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Py_DECREF(v);
|
Py_DECREF(v);
|
||||||
break;
|
break;
|
||||||
|
@ -2042,6 +2045,44 @@ do_raise(type, value, tb)
|
||||||
return WHY_EXCEPTION;
|
return WHY_EXCEPTION;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
unpack_sequence(v, argcnt, sp)
|
||||||
|
PyObject *v;
|
||||||
|
int argcnt;
|
||||||
|
PyObject **sp;
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
PyObject *w;
|
||||||
|
|
||||||
|
for (i = 0; i < argcnt; i++) {
|
||||||
|
if (! (w = PySequence_GetItem(v, i))) {
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_IndexError))
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"unpack sequence of wrong size");
|
||||||
|
goto finally;
|
||||||
|
}
|
||||||
|
*--sp = w;
|
||||||
|
}
|
||||||
|
/* we better get an IndexError now */
|
||||||
|
if (PySequence_GetItem(v, i) == NULL) {
|
||||||
|
if (PyErr_ExceptionMatches(PyExc_IndexError)) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* some other exception occurred. fall through to finally */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
PyErr_SetString(PyExc_ValueError,
|
||||||
|
"unpack sequence of wrong size");
|
||||||
|
/* fall through */
|
||||||
|
finally:
|
||||||
|
for (; i > 0; i--)
|
||||||
|
Py_DECREF(*sp++);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef LLTRACE
|
#ifdef LLTRACE
|
||||||
static int
|
static int
|
||||||
prtrace(v, str)
|
prtrace(v, str)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue