[Python-checkins] CVS: python/dist/src/Python bltinmodule.c,2.197,2.198 ceval.c,2.238,2.239 compile.c,2.196,2.197 exceptions.c,1.23,1.24 import.c,2.175,2.176

Guido van Rossum gvanrossum@users.sourceforge.net
Fri, 20 Apr 2001 12:13:04 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv31661/Python

Modified Files:
	bltinmodule.c ceval.c compile.c exceptions.c import.c 
Log Message:
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???)



Index: bltinmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/bltinmodule.c,v
retrieving revision 2.197
retrieving revision 2.198
diff -C2 -r2.197 -r2.198
*** bltinmodule.c	2001/04/07 20:34:48	2.197
--- bltinmodule.c	2001/04/20 19:13:02	2.198
***************
*** 1313,1316 ****
--- 1313,1342 ----
  
  static PyObject *
+ builtin_iter(PyObject *self, PyObject *args)
+ {
+ 	PyObject *v, *w = NULL;
+ 
+ 	if (!PyArg_ParseTuple(args, "O|O:iter", &v, &w))
+ 		return NULL;
+ 	if (w == NULL)
+ 		return PyObject_GetIter(v);
+ 	if (!PyCallable_Check(v)) {
+ 		PyErr_SetString(PyExc_TypeError,
+ 				"iter(v, w): v must be callable");
+ 		return NULL;
+ 	}
+ 	return PyCallIter_New(v, w);
+ }
+ 
+ static char iter_doc[] =
+ "iter(collection) -> iterator\n\
+ iter(callable, sentinel) -> iterator\n\
+ \n\
+ Get an iterator from an object.  In the first form, the argument must\n\
+ supply its own iterator, or be a sequence.\n\
+ In the second form, the callable is called until it returns the sentinel.";
+ 
+ 
+ static PyObject *
  builtin_len(PyObject *self, PyObject *args)
  {
***************
*** 2149,2152 ****
--- 2175,2179 ----
  	{"isinstance",  builtin_isinstance, 1, isinstance_doc},
  	{"issubclass",  builtin_issubclass, 1, issubclass_doc},
+ 	{"iter",	builtin_iter, 1, iter_doc},
  	{"len",		builtin_len, 1, len_doc},
  	{"list",	builtin_list, 1, list_doc},

Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.238
retrieving revision 2.239
diff -C2 -r2.238 -r2.239
*** ceval.c	2001/04/13 16:51:46	2.238
--- ceval.c	2001/04/20 19:13:02	2.239
***************
*** 382,385 ****
--- 382,386 ----
  	char *filename = PyString_AsString(co->co_filename);
  #endif
+ 	static PyObject *nextstr;
  
  /* Code access macros */
***************
*** 417,420 ****
--- 418,426 ----
  
  /* Start of code */
+ 	if (nextstr == NULL) {
+ 		nextstr = PyString_InternFromString("next");
+ 		if (nextstr == NULL)
+ 			return NULL;
+ 	}
  
  #ifdef USE_STACKCHECK
***************
*** 1874,1877 ****
--- 1880,1918 ----
  		case JUMP_ABSOLUTE:
  			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;
  

Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.196
retrieving revision 2.197
diff -C2 -r2.196 -r2.197
*** compile.c	2001/04/14 17:51:48	2.196
--- compile.c	2001/04/20 19:13:02	2.197
***************
*** 1233,1237 ****
  com_list_for(struct compiling *c, node *n, node *e, char *t)
  {
- 	PyObject *v;
  	int anchor = 0;
  	int save_begin = c->c_begin;
--- 1233,1236 ----
***************
*** 1239,1251 ****
  	/* list_iter: for v in expr [list_iter] */
  	com_node(c, CHILD(n, 3)); /* expr */
! 	v = PyInt_FromLong(0L);
! 	if (v == NULL)
! 		c->c_errors++;
! 	com_addoparg(c, LOAD_CONST, com_addconst(c, v));
! 	com_push(c, 1);
! 	Py_XDECREF(v);
  	c->c_begin = c->c_nexti;
  	com_addoparg(c, SET_LINENO, n->n_lineno);
! 	com_addfwref(c, FOR_LOOP, &anchor);
  	com_push(c, 1);
  	com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
--- 1238,1245 ----
  	/* list_iter: for v in expr [list_iter] */
  	com_node(c, CHILD(n, 3)); /* expr */
! 	com_addbyte(c, GET_ITER);
  	c->c_begin = c->c_nexti;
  	com_addoparg(c, SET_LINENO, n->n_lineno);
! 	com_addfwref(c, FOR_ITER, &anchor);
  	com_push(c, 1);
  	com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
***************
*** 1256,1260 ****
  	c->c_begin = save_begin;
  	com_backpatch(c, anchor);
! 	com_pop(c, 2); /* FOR_LOOP has popped these */
  }  
  
--- 1250,1254 ----
  	c->c_begin = save_begin;
  	com_backpatch(c, anchor);
! 	com_pop(c, 1); /* FOR_ITER has popped this */
  }  
  
***************
*** 2874,2878 ****
  com_for_stmt(struct compiling *c, node *n)
  {
- 	PyObject *v;
  	int break_anchor = 0;
  	int anchor = 0;
--- 2868,2871 ----
***************
*** 2883,2895 ****
  	block_push(c, SETUP_LOOP);
  	com_node(c, CHILD(n, 3));
! 	v = PyInt_FromLong(0L);
! 	if (v == NULL)
! 		c->c_errors++;
! 	com_addoparg(c, LOAD_CONST, com_addconst(c, v));
! 	com_push(c, 1);
! 	Py_XDECREF(v);
  	c->c_begin = c->c_nexti;
  	com_addoparg(c, SET_LINENO, n->n_lineno);
! 	com_addfwref(c, FOR_LOOP, &anchor);
  	com_push(c, 1);
  	com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
--- 2876,2883 ----
  	block_push(c, SETUP_LOOP);
  	com_node(c, CHILD(n, 3));
! 	com_addbyte(c, GET_ITER);
  	c->c_begin = c->c_nexti;
  	com_addoparg(c, SET_LINENO, n->n_lineno);
! 	com_addfwref(c, FOR_ITER, &anchor);
  	com_push(c, 1);
  	com_assign(c, CHILD(n, 1), OP_ASSIGN, NULL);
***************
*** 2900,2904 ****
  	c->c_begin = save_begin;
  	com_backpatch(c, anchor);
! 	com_pop(c, 2); /* FOR_LOOP has popped these */
  	com_addbyte(c, POP_BLOCK);
  	block_pop(c, SETUP_LOOP);
--- 2888,2892 ----
  	c->c_begin = save_begin;
  	com_backpatch(c, anchor);
! 	com_pop(c, 1); /* FOR_ITER has popped this */
  	com_addbyte(c, POP_BLOCK);
  	block_pop(c, SETUP_LOOP);

Index: exceptions.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/exceptions.c,v
retrieving revision 1.23
retrieving revision 1.24
diff -C2 -r1.23 -r1.24
*** exceptions.c	2001/04/14 17:51:48	1.23
--- exceptions.c	2001/04/20 19:13:02	1.24
***************
*** 53,56 ****
--- 53,57 ----
   |\n\
   +-- SystemExit\n\
+  +-- StopIteration\n\
   +-- StandardError\n\
   |    |\n\
***************
*** 370,373 ****
--- 371,377 ----
  TypeError__doc__[] = "Inappropriate argument type.";
  
+ static char
+ StopIteration__doc__[] = "Signal the end from iterator.next().";
+ 
  
  
***************
*** 925,928 ****
--- 929,933 ----
  
  PyObject *PyExc_Exception;
+ PyObject *PyExc_StopIteration;
  PyObject *PyExc_StandardError;
  PyObject *PyExc_ArithmeticError;
***************
*** 986,989 ****
--- 991,996 ----
    */
   {"Exception", &PyExc_Exception},
+  {"StopIteration", &PyExc_StopIteration, &PyExc_Exception,
+   StopIteration__doc__},
   {"StandardError", &PyExc_StandardError, &PyExc_Exception,
    StandardError__doc__},

Index: import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.175
retrieving revision 2.176
diff -C2 -r2.175 -r2.176
*** import.c	2001/04/13 17:50:20	2.175
--- import.c	2001/04/20 19:13:02	2.176
***************
*** 44,48 ****
     added to the .pyc file header? */
  /* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */
! #define MAGIC (60202 | ((long)'\r'<<16) | ((long)'\n'<<24))
  
  /* Magic word as global; note that _PyImport_Init() can change the
--- 44,48 ----
     added to the .pyc file header? */
  /* New way to come up with the magic number: (YEAR-1995), MONTH, DAY */
! #define MAGIC (60420 | ((long)'\r'<<16) | ((long)'\n'<<24))
  
  /* Magic word as global; note that _PyImport_Init() can change the