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:
Barry Warsaw 1997-08-25 22:13:04 +00:00
parent 1fb071cc64
commit e42b18f9d1
1 changed files with 75 additions and 34 deletions

View File

@ -312,6 +312,7 @@ enum why_code {
};
static enum why_code do_raise Py_PROTO((PyObject *, PyObject *, PyObject *));
static int unpack_sequence Py_PROTO((PyObject *, int, PyObject **));
/* Backward compatible interface */
@ -1182,13 +1183,10 @@ eval_code2(co, globals, locals,
#endif
case UNPACK_TUPLE:
case UNPACK_LIST:
v = POP();
if (!PyTuple_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"unpack non-tuple");
why = WHY_EXCEPTION;
}
else if (PyTuple_Size(v) != oparg) {
if (PyTuple_Check(v)) {
if (PyTuple_Size(v) != oparg) {
PyErr_SetString(PyExc_ValueError,
"unpack tuple of wrong size");
why = WHY_EXCEPTION;
@ -1200,28 +1198,33 @@ eval_code2(co, globals, locals,
PUSH(w);
}
}
Py_DECREF(v);
break;
case UNPACK_LIST:
v = POP();
if (!PyList_Check(v)) {
PyErr_SetString(PyExc_TypeError,
"unpack non-list");
why = WHY_EXCEPTION;
}
else if (PyList_Size(v) != oparg) {
else if (PyList_Check(v)) {
if (PyList_Size(v) != oparg) {
PyErr_SetString(PyExc_ValueError,
"unpack list of wrong size");
why = WHY_EXCEPTION;
}
else {
for (; --oparg >= 0; ) {
w = PyList_GetItem(v, oparg);
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 {
PyErr_SetString(PyExc_TypeError,
"unpack non-sequence");
why = WHY_EXCEPTION;
}
Py_DECREF(v);
break;
@ -2042,6 +2045,44 @@ do_raise(type, value, tb)
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
static int
prtrace(v, str)