diff options
author | Barry Warsaw <barry@python.org> | 1997-08-25 22:13:04 (GMT) |
---|---|---|
committer | Barry Warsaw <barry@python.org> | 1997-08-25 22:13:04 (GMT) |
commit | e42b18f9d1fca06df34d9fcbd54a2a6045329197 (patch) | |
tree | 83a1d23ce04aadad0aae0aa35a59a62de9b15b0e | |
parent | 1fb071cc648aa5e72f7c9aa6a230cb826bb8eed3 (diff) | |
download | cpython-e42b18f9d1fca06df34d9fcbd54a2a6045329197.zip cpython-e42b18f9d1fca06df34d9fcbd54a2a6045329197.tar.gz cpython-e42b18f9d1fca06df34d9fcbd54a2a6045329197.tar.bz2 |
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.
-rw-r--r-- | Python/ceval.c | 107 |
1 files changed, 74 insertions, 33 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index 4c7a958..e08e1c9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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,45 +1183,47 @@ 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) { - 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); + if (PyTuple_Check(v)) { + 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: - v = POP(); - if (!PyList_Check(v)) { - PyErr_SetString(PyExc_TypeError, - "unpack non-list"); - why = WHY_EXCEPTION; + 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_GET_ITEM(v, oparg); + Py_INCREF(w); + PUSH(w); + } + } } - else if (PyList_Size(v) != oparg) { - PyErr_SetString(PyExc_ValueError, - "unpack list of wrong size"); - why = WHY_EXCEPTION; + else if (PySequence_Check(v)) { + if (unpack_sequence(v, oparg, + stack_pointer + oparg)) + stack_pointer += oparg; + else + why = WHY_EXCEPTION; } else { - for (; --oparg >= 0; ) { - w = PyList_GetItem(v, oparg); - Py_INCREF(w); - PUSH(w); - } + 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) |