Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e42b18f

Browse files
committed
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.
1 parent 1fb071c commit e42b18f

1 file changed

Lines changed: 74 additions & 33 deletions

File tree

Python/ceval.c

Lines changed: 74 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ enum why_code {
312312
};
313313

314314
static enum why_code do_raise Py_PROTO((PyObject *, PyObject *, PyObject *));
315+
static int unpack_sequence Py_PROTO((PyObject *, int, PyObject **));
315316

316317

317318
/* Backward compatible interface */
@@ -1182,45 +1183,47 @@ eval_code2(co, globals, locals,
11821183
#endif
11831184

11841185
case UNPACK_TUPLE:
1186+
case UNPACK_LIST:
11851187
v = POP();
1186-
if (!PyTuple_Check(v)) {
1187-
PyErr_SetString(PyExc_TypeError,
1188-
"unpack non-tuple");
1189-
why = WHY_EXCEPTION;
1190-
}
1191-
else if (PyTuple_Size(v) != oparg) {
1192-
PyErr_SetString(PyExc_ValueError,
1193-
"unpack tuple of wrong size");
1194-
why = WHY_EXCEPTION;
1195-
}
1196-
else {
1197-
for (; --oparg >= 0; ) {
1198-
w = PyTuple_GET_ITEM(v, oparg);
1199-
Py_INCREF(w);
1200-
PUSH(w);
1188+
if (PyTuple_Check(v)) {
1189+
if (PyTuple_Size(v) != oparg) {
1190+
PyErr_SetString(PyExc_ValueError,
1191+
"unpack tuple of wrong size");
1192+
why = WHY_EXCEPTION;
1193+
}
1194+
else {
1195+
for (; --oparg >= 0; ) {
1196+
w = PyTuple_GET_ITEM(v, oparg);
1197+
Py_INCREF(w);
1198+
PUSH(w);
1199+
}
12011200
}
12021201
}
1203-
Py_DECREF(v);
1204-
break;
1205-
1206-
case UNPACK_LIST:
1207-
v = POP();
1208-
if (!PyList_Check(v)) {
1209-
PyErr_SetString(PyExc_TypeError,
1210-
"unpack non-list");
1211-
why = WHY_EXCEPTION;
1202+
else if (PyList_Check(v)) {
1203+
if (PyList_Size(v) != oparg) {
1204+
PyErr_SetString(PyExc_ValueError,
1205+
"unpack list of wrong size");
1206+
why = WHY_EXCEPTION;
1207+
}
1208+
else {
1209+
for (; --oparg >= 0; ) {
1210+
w = PyList_GET_ITEM(v, oparg);
1211+
Py_INCREF(w);
1212+
PUSH(w);
1213+
}
1214+
}
12121215
}
1213-
else if (PyList_Size(v) != oparg) {
1214-
PyErr_SetString(PyExc_ValueError,
1215-
"unpack list of wrong size");
1216-
why = WHY_EXCEPTION;
1216+
else if (PySequence_Check(v)) {
1217+
if (unpack_sequence(v, oparg,
1218+
stack_pointer + oparg))
1219+
stack_pointer += oparg;
1220+
else
1221+
why = WHY_EXCEPTION;
12171222
}
12181223
else {
1219-
for (; --oparg >= 0; ) {
1220-
w = PyList_GetItem(v, oparg);
1221-
Py_INCREF(w);
1222-
PUSH(w);
1223-
}
1224+
PyErr_SetString(PyExc_TypeError,
1225+
"unpack non-sequence");
1226+
why = WHY_EXCEPTION;
12241227
}
12251228
Py_DECREF(v);
12261229
break;
@@ -2042,6 +2045,44 @@ do_raise(type, value, tb)
20422045
return WHY_EXCEPTION;
20432046
}
20442047

2048+
static int
2049+
unpack_sequence(v, argcnt, sp)
2050+
PyObject *v;
2051+
int argcnt;
2052+
PyObject **sp;
2053+
{
2054+
int i;
2055+
PyObject *w;
2056+
2057+
for (i = 0; i < argcnt; i++) {
2058+
if (! (w = PySequence_GetItem(v, i))) {
2059+
if (PyErr_ExceptionMatches(PyExc_IndexError))
2060+
PyErr_SetString(PyExc_ValueError,
2061+
"unpack sequence of wrong size");
2062+
goto finally;
2063+
}
2064+
*--sp = w;
2065+
}
2066+
/* we better get an IndexError now */
2067+
if (PySequence_GetItem(v, i) == NULL) {
2068+
if (PyErr_ExceptionMatches(PyExc_IndexError)) {
2069+
PyErr_Clear();
2070+
return 1;
2071+
}
2072+
/* some other exception occurred. fall through to finally */
2073+
}
2074+
else
2075+
PyErr_SetString(PyExc_ValueError,
2076+
"unpack sequence of wrong size");
2077+
/* fall through */
2078+
finally:
2079+
for (; i > 0; i--)
2080+
Py_DECREF(*sp++);
2081+
2082+
return 0;
2083+
}
2084+
2085+
20452086
#ifdef LLTRACE
20462087
static int
20472088
prtrace(v, str)

0 commit comments

Comments
 (0)