summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorBarry Warsaw <barry@python.org>1997-08-25 22:13:04 (GMT)
committerBarry Warsaw <barry@python.org>1997-08-25 22:13:04 (GMT)
commite42b18f9d1fca06df34d9fcbd54a2a6045329197 (patch)
tree83a1d23ce04aadad0aae0aa35a59a62de9b15b0e /Python/ceval.c
parent1fb071cc648aa5e72f7c9aa6a230cb826bb8eed3 (diff)
downloadcpython-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.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c107
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)