diff Python/ceval.c @ 17597:32e7d0898eab legacy-trunk

Iterators phase 1. This comprises: new slot tp_iter in type object, plus new flag Py_TPFLAGS_HAVE_ITER new C API PyObject_GetIter(), calls tp_iter new builtin iter(), with two forms: iter(obj), and iter(function, sentinel) new internal object types iterobject and calliterobject new exception StopIteration new opcodes for "for" loops, GET_ITER and FOR_ITER (also supported by dis.py) new magic number for .pyc files new special method for instances: __iter__() returns an iterator iteration over dictionaries: "for x in dict" iterates over the keys iteration over files: "for x in file" iterates over lines TODO: documentation test suite decide whether to use a different way to spell iter(function, sentinal) decide whether "for key in dict" is a good idea use iterators in map/filter/reduce, min/max, and elsewhere (in/not in?) speed tuning (make next() a slot tp_next???)
author Guido van Rossum <guido@python.org>
date Fri, 20 Apr 2001 19:13:02 +0000
parents a34293ced63b
children 1fe8e50e6e1b
line wrap: on
line diff
--- a/Python/ceval.c	Fri Apr 20 19:04:55 2001 +0000
+++ b/Python/ceval.c	Fri Apr 20 19:13:02 2001 +0000
@@ -381,6 +381,7 @@
 	/* Make it easier to find out where we are with a debugger */
 	char *filename = PyString_AsString(co->co_filename);
 #endif
+	static PyObject *nextstr;
 
 /* Code access macros */
 
@@ -416,6 +417,11 @@
 				     GETLOCAL(i) = value; } while (0)
 
 /* Start of code */
+	if (nextstr == NULL) {
+		nextstr = PyString_InternFromString("next");
+		if (nextstr == NULL)
+			return NULL;
+	}
 
 #ifdef USE_STACKCHECK
 	if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) {
@@ -1875,6 +1881,41 @@
 			JUMPTO(oparg);
 			continue;
 
+		case GET_ITER:
+			/* before: [obj]; after [getiter(obj)] */
+			v = POP();
+			x = PyObject_GetIter(v);
+			Py_DECREF(v);
+			if (x != NULL) {
+				w = x;
+				x = PyObject_GetAttr(w, nextstr);
+				Py_DECREF(w);
+				if (x != NULL) {
+					PUSH(x);
+					continue;
+				}
+			}
+			break;
+
+		case FOR_ITER:
+			/* before: [iter]; after: [iter, iter()] *or* [] */
+			v = TOP();
+			x = PyObject_CallObject(v, NULL);
+			if (x == NULL) {
+				if (PyErr_ExceptionMatches(
+					PyExc_StopIteration))
+				{
+					PyErr_Clear();
+					x = v = POP();
+					Py_DECREF(v);
+					JUMPBY(oparg);
+					continue;
+				}
+				break;
+			}
+			PUSH(x);
+			continue;
+
 		case FOR_LOOP:
 			/* for v in s: ...
 			   On entry: stack contains s, i.