summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorTim Peters <tim.peters@gmail.com>2001-06-21 02:49:55 (GMT)
committerTim Peters <tim.peters@gmail.com>2001-06-21 02:49:55 (GMT)
commitd6d010b874a82df889037bdb1cc71032d2155034 (patch)
tree643bda2ce2915c0142dfd240afb36bd5b1141403 /Python
parent2b13ce831795f6f0304c157a31909ac2ce5d5ccb (diff)
downloadcpython-d6d010b874a82df889037bdb1cc71032d2155034.zip
cpython-d6d010b874a82df889037bdb1cc71032d2155034.tar.gz
cpython-d6d010b874a82df889037bdb1cc71032d2155034.tar.bz2
Teach the UNPACK_SEQUENCE opcode how to tease an iterable object into
giving up the goods. NEEDS DOC CHANGES
Diffstat (limited to 'Python')
-rw-r--r--Python/ceval.c70
1 files changed, 38 insertions, 32 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index a71d48f..fcb8fc3 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -476,7 +476,7 @@ enum why_code {
};
static enum why_code do_raise(PyObject *, PyObject *, PyObject *);
-static int unpack_sequence(PyObject *, int, PyObject **);
+static int unpack_iterable(PyObject *, int, PyObject **);
PyObject *
@@ -1488,18 +1488,11 @@ eval_frame(PyFrameObject *f)
}
}
}
- 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");
+ else if (unpack_iterable(v, oparg,
+ stack_pointer + oparg))
+ stack_pointer += oparg;
+ else
why = WHY_EXCEPTION;
- }
Py_DECREF(v);
break;
@@ -2694,37 +2687,50 @@ do_raise(PyObject *type, PyObject *value, PyObject *tb)
return WHY_EXCEPTION;
}
+/* Iterate v argcnt times and store the results on the stack (via decreasing
+ sp). Return 1 for success, 0 if error. */
+
static int
-unpack_sequence(PyObject *v, int argcnt, PyObject **sp)
+unpack_iterable(PyObject *v, int argcnt, PyObject **sp)
{
- int i;
+ int i = 0;
+ PyObject *it; /* iter(v) */
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;
+ assert(v != NULL);
+
+ it = PyObject_GetIter(v);
+ if (it == NULL)
+ goto Error;
+
+ for (; i < argcnt; i++) {
+ w = PyIter_Next(it);
+ if (w == NULL) {
+ /* Iterator done, via error or exhaustion. */
+ if (!PyErr_Occurred()) {
+ PyErr_Format(PyExc_ValueError,
+ "need more than %d value%s to unpack",
+ i, i == 1 ? "" : "s");
+ }
+ goto Error;
}
*--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 */
+
+ /* We better have exhausted the iterator now. */
+ w = PyIter_Next(it);
+ if (w == NULL) {
+ if (PyErr_Occurred())
+ goto Error;
+ Py_DECREF(it);
+ return 1;
}
- else
- PyErr_SetString(PyExc_ValueError,
- "unpack sequence of wrong size");
+ PyErr_SetString(PyExc_ValueError, "too many values to unpack");
/* fall through */
-finally:
+Error:
for (; i > 0; i--, sp++)
Py_DECREF(*sp);
-
+ Py_XDECREF(it);
return 0;
}