diff -urN py_cvs/dist/src/Generator.py py_gen/Generator.py
--- py_cvs/dist/src/Generator.py	Wed Dec 31 19:00:00 1969
+++ py_gen/Generator.py	Sat Mar 17 20:15:22 2001
@@ -0,0 +1,16 @@
+import sys
+
+class Generator:
+    def __init__(self):
+        self.frame = sys._getframe(1)
+        self.frame.suspend(self)
+        
+    def suspend(self, value):
+        self.frame.suspend(value)
+
+    def end(self):
+        raise IndexError
+
+    def __getitem__(self, i):
+        # fake indices suck, need iterators
+        return self.frame.resume()
diff -urN py_cvs/dist/src/Include/ceval.h py_gen/Include/ceval.h
--- py_cvs/dist/src/Include/ceval.h	Mon Sep 25 21:41:10 2000
+++ py_gen/Include/ceval.h	Sat Mar 17 19:24:01 2001
@@ -10,6 +10,10 @@
 DL_IMPORT(PyObject *) PyEval_CallObjectWithKeywords
 	(PyObject *, PyObject *, PyObject *);
 
+struct _frame;
+
+DL_IMPORT(PyObject *) PyEval_EvalFrame(struct _frame *);
+
 /* DLL-level Backwards compatibility: */
 #undef PyEval_CallObject
 DL_IMPORT(PyObject *) PyEval_CallObject(PyObject *, PyObject *);
diff -urN py_cvs/dist/src/Include/frameobject.h py_gen/Include/frameobject.h
--- py_cvs/dist/src/Include/frameobject.h	Wed Mar 14 22:39:33 2001
+++ py_gen/Include/frameobject.h	Sat Mar 17 19:24:01 2001
@@ -21,6 +21,11 @@
     PyObject *f_globals;	/* global symbol table (PyDictObject) */
     PyObject *f_locals;		/* local symbol table (PyDictObject) */
     PyObject **f_valuestack;	/* points after the last local */
+    PyObject **f_stackbottom;	/* points to the last item on the stack if
+				   frame has been suspended. */
+    PyObject *f_suspendvalue;	/* set to v when f.suspend(v) is called.  ceval
+				   will then suspend execution of the frame and
+				   return v. */
     PyObject *f_trace;		/* Trace function */
     PyObject *f_exc_type, *f_exc_value, *f_exc_traceback;
     PyThreadState *f_tstate;
diff -urN py_cvs/dist/src/Objects/frameobject.c py_gen/Objects/frameobject.c
--- py_cvs/dist/src/Objects/frameobject.c	Wed Mar 14 22:39:59 2001
+++ py_gen/Objects/frameobject.c	Sat Mar 17 19:24:22 2001
@@ -27,11 +27,59 @@
 };
 
 static PyObject *
+frame_suspend(PyFrameObject *f, PyObject *args)
+{
+	PyObject *v;
+	if (!PyArg_ParseTuple(args, "O|:suspend", &v))
+		return NULL;
+	if (f->f_stackbottom == NULL) {
+		PyErr_SetString(PyExc_ValueError, "frame not suspendable");
+		return NULL;
+	}
+	Py_INCREF(v);
+	f->f_suspendvalue = v;
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
+static PyObject *
+frame_resume(PyFrameObject *f, PyObject *args)
+{
+	PyThreadState *tstate = PyThreadState_GET();
+	if (!PyArg_ParseTuple(args, ":resume"))
+		return NULL;
+	if (f->f_stackbottom == NULL) {
+		PyErr_SetString(PyExc_ValueError, "frame not resumable");
+		return NULL;
+	}
+	f->f_back = tstate->frame;
+	/* don't run off the end of the code */
+	if (f->f_lasti >= PySequence_Size(f->f_code->co_code)) {
+		Py_INCREF(Py_None);
+		return Py_None;
+	}
+	Py_INCREF(f);
+	return PyEval_EvalFrame(f);
+}
+
+
+static struct PyMethodDef frame_methods[] = {
+	{"suspend",	(PyCFunction)frame_suspend, METH_VARARGS},
+	{"resume",	(PyCFunction)frame_resume, METH_VARARGS},
+	{NULL, 		NULL}	/* Sentinel */
+};
+
+static PyObject *
 frame_getattr(PyFrameObject *f, char *name)
 {
+	PyObject *res;
 	if (strcmp(name, "f_locals") == 0)
 		PyFrame_FastToLocals(f);
-	return PyMember_Get((char *)f, frame_memberlist, name);
+	res = PyMember_Get((char *)f, frame_memberlist, name);
+	if (res != NULL)
+		return res;
+	PyErr_Clear();
+	return Py_FindMethod(frame_methods, (PyObject *)f, name);
 }
 
 static int
@@ -67,6 +115,7 @@
 {
 	int i, slots;
 	PyObject **fastlocals;
+	PyObject **p;
 
 	Py_TRASHCAN_SAFE_BEGIN(f)
 	/* Kill all local variables */
@@ -75,7 +124,10 @@
 	for (i = slots; --i >= 0; ++fastlocals) {
 		Py_XDECREF(*fastlocals);
 	}
-
+	/* Free stack */
+	for (p = f->f_valuestack; p < f->f_stackbottom; p++) {
+		Py_XDECREF(*p);
+	}
 	Py_XDECREF(f->f_back);
 	Py_XDECREF(f->f_code);
 	Py_XDECREF(f->f_builtins);
@@ -85,6 +137,7 @@
 	Py_XDECREF(f->f_exc_type);
 	Py_XDECREF(f->f_exc_value);
 	Py_XDECREF(f->f_exc_traceback);
+	Py_XDECREF(f->f_suspendvalue);
 	f->f_back = free_list;
 	free_list = f;
 	Py_TRASHCAN_SAFE_END(f)
@@ -221,6 +274,8 @@
 		f->f_localsplus[extras] = NULL;
 
 	f->f_valuestack = f->f_localsplus + (f->f_nlocals + ncells + nfrees);
+	f->f_stackbottom = f->f_valuestack;
+	f->f_suspendvalue = NULL;
 
 	return f;
 }
diff -urN py_cvs/dist/src/Python/ceval.c py_gen/Python/ceval.c
--- py_cvs/dist/src/Python/ceval.c	Wed Mar 14 22:39:59 2001
+++ py_gen/Python/ceval.c	Sat Mar 17 19:24:01 2001
@@ -322,6 +322,7 @@
 		WHY_EXCEPTION,	/* Exception occurred */
 		WHY_RERAISE,	/* Exception re-raised by 'finally' */
 		WHY_RETURN,	/* 'return' statement */
+		WHY_SUSPEND,	/* 'suspend' statement */
 		WHY_BREAK,	/* 'break' statement */
 		WHY_CONTINUE	/* 'continue' statement */
 };
@@ -341,13 +342,8 @@
 			  NULL);
 }
 
-
-/* Interpreter main loop */
-
-static PyObject *
-eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
-	   PyObject **args, int argcount, PyObject **kws, int kwcount,
-	   PyObject **defs, int defcount, PyObject *closure)
+PyObject *
+PyEval_EvalFrame(PyFrameObject *f)
 {
 #ifdef DXPAIRS
 	int lastopcode = 0;
@@ -364,10 +360,10 @@
 	register PyObject *u;
 	register PyObject *t;
 	register PyObject *stream = NULL;    /* for PRINT opcodes */
-	register PyFrameObject *f; /* Current frame */
 	register PyObject **fastlocals, **freevars;
 	PyObject *retval = NULL;	/* Return value */
-	PyThreadState *tstate = PyThreadState_GET();
+	PyThreadState *tstate = f->f_tstate;
+	PyCodeObject *co = f->f_code;
 	unsigned char *first_instr;
 #ifdef LLTRACE
 	int lltrace;
@@ -410,225 +406,17 @@
 #define SETLOCAL(i, value)	do { Py_XDECREF(GETLOCAL(i)); \
 				     GETLOCAL(i) = value; } while (0)
 
-/* Start of code */
-
-#ifdef USE_STACKCHECK
-	if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) {
-		PyErr_SetString(PyExc_MemoryError, "Stack overflow");
-		return NULL;
-	}
-#endif
-
-	if (globals == NULL) {
-		PyErr_SetString(PyExc_SystemError, "eval_code2: NULL globals");
-		return NULL;
-	}
-
 #ifdef LLTRACE
-	lltrace = PyDict_GetItemString(globals, "__lltrace__") != NULL;
+	lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL;
 #endif
 
-	f = PyFrame_New(tstate,			/*back*/
-			co,			/*code*/
-			globals, locals);
-	if (f == NULL)
-		return NULL;
-
+	_PyCode_GETCODEPTR(co, &first_instr);
+	next_instr = first_instr + f->f_lasti;
+	stack_pointer = f->f_stackbottom;
 	tstate->frame = f;
 	fastlocals = f->f_localsplus;
 	freevars = f->f_localsplus + f->f_nlocals;
 
-	if (co->co_argcount > 0 ||
-	    co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
-		int i;
-		int n = argcount;
-		PyObject *kwdict = NULL;
-		if (co->co_flags & CO_VARKEYWORDS) {
-			kwdict = PyDict_New();
-			if (kwdict == NULL)
-				goto fail;
-			i = co->co_argcount;
-			if (co->co_flags & CO_VARARGS)
-				i++;
-			SETLOCAL(i, kwdict);
-		}
-		if (argcount > co->co_argcount) {
-			if (!(co->co_flags & CO_VARARGS)) {
-				PyErr_Format(PyExc_TypeError,
-				    "%.200s() takes %s %d "
-				    "%sargument%s (%d given)",
-				    PyString_AsString(co->co_name),
-				    defcount ? "at most" : "exactly",
-				    co->co_argcount,
-				    kwcount ? "non-keyword " : "",
-				    co->co_argcount == 1 ? "" : "s",
-				    argcount);
-				goto fail;
-			}
-			n = co->co_argcount;
-		}
-		for (i = 0; i < n; i++) {
-			x = args[i];
-			Py_INCREF(x);
-			SETLOCAL(i, x);
-		}
-		if (co->co_flags & CO_VARARGS) {
-			u = PyTuple_New(argcount - n);
-			if (u == NULL)
-				goto fail;
-			SETLOCAL(co->co_argcount, u);
-			for (i = n; i < argcount; i++) {
-				x = args[i];
-				Py_INCREF(x);
-				PyTuple_SET_ITEM(u, i-n, x);
-			}
-		}
-		for (i = 0; i < kwcount; i++) {
-			PyObject *keyword = kws[2*i];
-			PyObject *value = kws[2*i + 1];
-			int j;
-			if (keyword == NULL || !PyString_Check(keyword)) {
-				PyErr_Format(PyExc_TypeError,
-				    "%.200s() keywords must be strings",
-				    PyString_AsString(co->co_name));
-				goto fail;
-			}
-			/* XXX slow -- speed up using dictionary? */
-			for (j = 0; j < co->co_argcount; j++) {
-				PyObject *nm = PyTuple_GET_ITEM(
-					co->co_varnames, j);
-				int cmp = PyObject_RichCompareBool(
-					keyword, nm, Py_EQ);
-				if (cmp > 0)
-					break;
-				else if (cmp < 0)
-					goto fail;
-			}
-			/* Check errors from Compare */
-			if (PyErr_Occurred())
-				goto fail;
-			if (j >= co->co_argcount) {
-				if (kwdict == NULL) {
-					PyErr_Format(PyExc_TypeError,
-					    "%.200s() got an unexpected "
-					    "keyword argument '%.400s'",
-					    PyString_AsString(co->co_name),
-					    PyString_AsString(keyword));
-					goto fail;
-				}
-				PyDict_SetItem(kwdict, keyword, value);
-			}
-			else {
-				if (GETLOCAL(j) != NULL) {
-					PyErr_Format(PyExc_TypeError,
-					     "%.200s() got multiple "
-					     "values for keyword "
-					     "argument '%.400s'",
-					     PyString_AsString(co->co_name),
-					     PyString_AsString(keyword));
-					goto fail;
-				}
-				Py_INCREF(value);
-				SETLOCAL(j, value);
-			}
-		}
-		if (argcount < co->co_argcount) {
-			int m = co->co_argcount - defcount;
-			for (i = argcount; i < m; i++) {
-				if (GETLOCAL(i) == NULL) {
-					PyErr_Format(PyExc_TypeError,
-					    "%.200s() takes %s %d "
-					    "%sargument%s (%d given)",
-					    PyString_AsString(co->co_name),
-					    ((co->co_flags & CO_VARARGS) ||
-					     defcount) ? "at least"
-						       : "exactly",
-					    m, kwcount ? "non-keyword " : "",
-					    m == 1 ? "" : "s", i);
-					goto fail;
-				}
-			}
-			if (n > m)
-				i = n - m;
-			else
-				i = 0;
-			for (; i < defcount; i++) {
-				if (GETLOCAL(m+i) == NULL) {
-					PyObject *def = defs[i];
-					Py_INCREF(def);
-					SETLOCAL(m+i, def);
-				}
-			}
-		}
-	}
-	else {
-		if (argcount > 0 || kwcount > 0) {
-			PyErr_Format(PyExc_TypeError,
-				     "%.200s() takes no arguments (%d given)",
-				     PyString_AsString(co->co_name),
-				     argcount + kwcount);
-			goto fail;
-		}
-	}
-	/* Allocate storage for cell vars and copy free vars into frame */ 
-	if (f->f_ncells) {
-		int i;
-		for (i = 0; i < f->f_ncells; ++i)
-			freevars[i] = PyCell_New(NULL);
-	}
-	if (f->f_nfreevars) {
-		int i;
-		for (i = 0; i < f->f_nfreevars; ++i) {
-			PyObject *o = PyTuple_GET_ITEM(closure, i);
-			Py_INCREF(o);
-			freevars[f->f_ncells + i] = o;
-		}
-	}
-
-	if (tstate->sys_tracefunc != NULL) {
-		/* tstate->sys_tracefunc, if defined, is a function that
-		   will be called  on *every* entry to a code block.
-		   Its return value, if not None, is a function that
-		   will be called at the start of each executed line
-		   of code.  (Actually, the function must return
-		   itself in order to continue tracing.)
-		   The trace functions are called with three arguments:
-		   a pointer to the current frame, a string indicating
-		   why the function is called, and an argument which
-		   depends on the situation.  The global trace function
-		   (sys.trace) is also called whenever an exception
-		   is detected. */
-		if (call_trace(&tstate->sys_tracefunc,
-			       &f->f_trace, f, "call",
-			       Py_None/*XXX how to compute arguments now?*/)) {
-			/* Trace function raised an error */
-			goto fail;
-		}
-	}
-
-	if (tstate->sys_profilefunc != NULL) {
-		/* Similar for sys_profilefunc, except it needn't return
-		   itself and isn't called for "line" events */
-		if (call_trace(&tstate->sys_profilefunc,
-			       (PyObject**)0, f, "call",
-			       Py_None/*XXX*/)) {
-			goto fail;
-		}
-	}
-
-	if (++tstate->recursion_depth > recursion_limit) {
-		--tstate->recursion_depth;
-		PyErr_SetString(PyExc_RuntimeError,
-				"maximum recursion depth exceeded");
-		tstate->frame = f->f_back;
-		Py_DECREF(f);
-		return NULL;
-	}
-
-	_PyCode_GETCODEPTR(co, &first_instr);
-	next_instr = first_instr;
-	stack_pointer = f->f_valuestack;
-
 	why = WHY_NOT;
 	err = 0;
 	x = Py_None;	/* Not a reference, just anything non-NULL */
@@ -679,6 +467,13 @@
 #endif
 		}
 
+                if (f->f_suspendvalue != NULL) {
+			why = WHY_SUSPEND;
+			retval = f->f_suspendvalue;
+			f->f_suspendvalue = NULL;
+			goto on_error;
+		}
+
 		/* Extract opcode and argument */
 
 #if defined(Py_DEBUG) || defined(LLTRACE)
@@ -2134,7 +1929,7 @@
 
 		/* Unwind stacks if a (pseudo) exception occurred */
 
-		while (why != WHY_NOT && f->f_iblock > 0) {
+		while (why != WHY_NOT && why != WHY_SUSPEND && f->f_iblock > 0) {
 			PyTryBlock *b = PyFrame_BlockPop(f);
 
 			if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) {
@@ -2148,9 +1943,11 @@
 				break;
 			}
 
-			while (STACK_LEVEL() > b->b_level) {
-				v = POP();
-				Py_XDECREF(v);
+			if (why != WHY_RETURN) {
+				while (STACK_LEVEL() > b->b_level) {
+					v = POP();
+					Py_XDECREF(v);
+				}
 			}
 			if (b->b_type == SETUP_LOOP && why == WHY_BREAK) {
 				why = WHY_NOT;
@@ -2204,12 +2001,14 @@
 
 	/* Pop remaining stack entries */
 
+	/*
 	while (!EMPTY()) {
 		v = POP();
 		Py_XDECREF(v);
 	}
+	*/
 
-	if (why != WHY_RETURN)
+	if (why != WHY_RETURN && why != WHY_SUSPEND)
 		retval = NULL;
 
 	if (f->f_trace) {
@@ -2236,6 +2035,245 @@
 
 	--tstate->recursion_depth;
 
+	/* Restore previous frame and release the current one */
+
+	f->f_lasti = INSTR_OFFSET();
+	if (why == WHY_SUSPEND) {
+		/* make frame resumable */
+		f->f_stackbottom = stack_pointer;
+	} else {
+		f->f_stackbottom = NULL; 
+	}
+	tstate->frame = f->f_back;
+	Py_DECREF(f);
+
+	return retval;
+}
+
+/* Interpreter main loop */
+
+static PyObject *
+eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
+	   PyObject **args, int argcount, PyObject **kws, int kwcount,
+	   PyObject **defs, int defcount, PyObject *closure)
+{
+	register PyFrameObject *f; /* Current frame */
+	register PyObject **fastlocals, **freevars;
+	PyThreadState *tstate = PyThreadState_GET();
+	PyObject *x, *u;
+
+
+/* Start of code */
+
+#ifdef USE_STACKCHECK
+	if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) {
+		PyErr_SetString(PyExc_MemoryError, "Stack overflow");
+		return NULL;
+	}
+#endif
+
+	if (globals == NULL) {
+		PyErr_SetString(PyExc_SystemError, "eval_code2: NULL globals");
+		return NULL;
+	}
+
+	f = PyFrame_New(tstate,			/*back*/
+			co,			/*code*/
+			globals, locals);
+	if (f == NULL)
+		return NULL;
+
+	fastlocals = f->f_localsplus;
+	freevars = f->f_localsplus + f->f_nlocals;
+
+	if (co->co_argcount > 0 ||
+	    co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
+		int i;
+		int n = argcount;
+		PyObject *kwdict = NULL;
+		if (co->co_flags & CO_VARKEYWORDS) {
+			kwdict = PyDict_New();
+			if (kwdict == NULL) {
+				goto fail;
+			}
+			i = co->co_argcount;
+			if (co->co_flags & CO_VARARGS)
+				i++;
+			SETLOCAL(i, kwdict);
+		}
+		if (argcount > co->co_argcount) {
+			if (!(co->co_flags & CO_VARARGS)) {
+				PyErr_Format(PyExc_TypeError,
+				    "%.200s() takes %s %d "
+				    "%sargument%s (%d given)",
+				    PyString_AsString(co->co_name),
+				    defcount ? "at most" : "exactly",
+				    co->co_argcount,
+				    kwcount ? "non-keyword " : "",
+				    co->co_argcount == 1 ? "" : "s",
+				    argcount);
+				goto fail;
+			}
+			n = co->co_argcount;
+		}
+		for (i = 0; i < n; i++) {
+			x = args[i];
+			Py_INCREF(x);
+			SETLOCAL(i, x);
+		}
+		if (co->co_flags & CO_VARARGS) {
+			u = PyTuple_New(argcount - n);
+			if (u == NULL)
+				goto fail;
+			SETLOCAL(co->co_argcount, u);
+			for (i = n; i < argcount; i++) {
+				x = args[i];
+				Py_INCREF(x);
+				PyTuple_SET_ITEM(u, i-n, x);
+			}
+		}
+		for (i = 0; i < kwcount; i++) {
+			PyObject *keyword = kws[2*i];
+			PyObject *value = kws[2*i + 1];
+			int j;
+			if (keyword == NULL || !PyString_Check(keyword)) {
+				PyErr_Format(PyExc_TypeError,
+				    "%.200s() keywords must be strings",
+				    PyString_AsString(co->co_name));
+				goto fail;
+			}
+			/* XXX slow -- speed up using dictionary? */
+			for (j = 0; j < co->co_argcount; j++) {
+				PyObject *nm = PyTuple_GET_ITEM(
+					co->co_varnames, j);
+				int cmp = PyObject_RichCompareBool(
+					keyword, nm, Py_EQ);
+				if (cmp > 0)
+					break;
+				else if (cmp < 0)
+					goto fail;
+			}
+			/* Check errors from Compare */
+			if (PyErr_Occurred())
+				goto fail;
+			if (j >= co->co_argcount) {
+				if (kwdict == NULL) {
+					PyErr_Format(PyExc_TypeError,
+					    "%.200s() got an unexpected "
+					    "keyword argument '%.400s'",
+					    PyString_AsString(co->co_name),
+					    PyString_AsString(keyword));
+					goto fail;
+				}
+				PyDict_SetItem(kwdict, keyword, value);
+			}
+			else {
+				if (GETLOCAL(j) != NULL) {
+					PyErr_Format(PyExc_TypeError,
+					     "%.200s() got multiple "
+					     "values for keyword "
+					     "argument '%.400s'",
+					     PyString_AsString(co->co_name),
+					     PyString_AsString(keyword));
+					goto fail;
+				}
+				Py_INCREF(value);
+				SETLOCAL(j, value);
+			}
+		}
+		if (argcount < co->co_argcount) {
+			int m = co->co_argcount - defcount;
+			for (i = argcount; i < m; i++) {
+				if (GETLOCAL(i) == NULL) {
+					PyErr_Format(PyExc_TypeError,
+					    "%.200s() takes %s %d "
+					    "%sargument%s (%d given)",
+					    PyString_AsString(co->co_name),
+					    ((co->co_flags & CO_VARARGS) ||
+					     defcount) ? "at least"
+						       : "exactly",
+					    m, kwcount ? "non-keyword " : "",
+					    m == 1 ? "" : "s", i);
+					goto fail;
+				}
+			}
+			if (n > m)
+				i = n - m;
+			else
+				i = 0;
+			for (; i < defcount; i++) {
+				if (GETLOCAL(m+i) == NULL) {
+					PyObject *def = defs[i];
+					Py_INCREF(def);
+					SETLOCAL(m+i, def);
+				}
+			}
+		}
+	}
+	else {
+		if (argcount > 0 || kwcount > 0) {
+			PyErr_Format(PyExc_TypeError,
+				     "%.200s() takes no arguments (%d given)",
+				     PyString_AsString(co->co_name),
+				     argcount + kwcount);
+			goto fail;
+		}
+	}
+	/* Allocate storage for cell vars and copy free vars into frame */ 
+	if (f->f_ncells) {
+		int i;
+		for (i = 0; i < f->f_ncells; ++i)
+			freevars[i] = PyCell_New(NULL);
+	}
+	if (f->f_nfreevars) {
+		int i;
+		for (i = 0; i < f->f_nfreevars; ++i) {
+			PyObject *o = PyTuple_GET_ITEM(closure, i);
+			Py_INCREF(o);
+			freevars[f->f_ncells + i] = o;
+		}
+	}
+
+	if (tstate->sys_tracefunc != NULL) {
+		/* tstate->sys_tracefunc, if defined, is a function that
+		   will be called  on *every* entry to a code block.
+		   Its return value, if not None, is a function that
+		   will be called at the start of each executed line
+		   of code.  (Actually, the function must return
+		   itself in order to continue tracing.)
+		   The trace functions are called with three arguments:
+		   a pointer to the current frame, a string indicating
+		   why the function is called, and an argument which
+		   depends on the situation.  The global trace function
+		   (sys.trace) is also called whenever an exception
+		   is detected. */
+		if (call_trace(&tstate->sys_tracefunc,
+			       &f->f_trace, f, "call",
+			       Py_None/*XXX how to compute arguments now?*/)) {
+			/* Trace function raised an error */
+			goto fail;
+		}
+	}
+
+	if (tstate->sys_profilefunc != NULL) {
+		/* Similar for sys_profilefunc, except it needn't return
+		   itself and isn't called for "line" events */
+		if (call_trace(&tstate->sys_profilefunc,
+			       (PyObject**)0, f, "call",
+			       Py_None/*XXX*/)) {
+			goto fail;
+		}
+	}
+
+	if (++tstate->recursion_depth > recursion_limit) {
+		--tstate->recursion_depth;
+		PyErr_SetString(PyExc_RuntimeError,
+				"maximum recursion depth exceeded");
+		goto fail;
+	}
+
+	return PyEval_EvalFrame(f);
+
   fail: /* Jump here from prelude on failure */
 
 	/* Restore previous frame and release the current one */
@@ -2243,7 +2281,7 @@
 	tstate->frame = f->f_back;
 	Py_DECREF(f);
 
-	return retval;
+	return NULL;
 }
 
 static void
diff -urN py_cvs/dist/src/pi.py py_gen/pi.py
--- py_cvs/dist/src/pi.py	Wed Dec 31 19:00:00 1969
+++ py_gen/pi.py	Sat Mar 17 20:16:50 2001
@@ -0,0 +1,23 @@
+from Generator import Generator
+
+def pi():
+    g = Generator()
+    k, a, b, a1, b1 = 2L, 4L, 1L, 12L, 4L
+    while 1:
+        # Next approximation
+        p, q, k = k*k, 2L*k+1L, k+1L
+        a, b, a1, b1 = a1, b1, p*a+q*a1, p*b+q*b1
+        # Print common digits
+        d, d1 = a/b, a1/b1
+        while d == d1:
+            g.suspend(int(d))
+            a, a1 = 10L*(a%b), 10L*(a1%b1)
+            d, d1 = a/b, a1/b1
+
+def test():
+    pi_digits = pi()
+    for i in range(100):
+        print pi_digits[i],
+
+if __name__ == "__main__":
+    test()
diff -urN py_cvs/dist/src/t.py py_gen/t.py
--- py_cvs/dist/src/t.py	Wed Dec 31 19:00:00 1969
+++ py_gen/t.py	Sat Mar 17 19:24:01 2001
@@ -0,0 +1,5 @@
+import sys
+
+def foo():
+    sys._getframe().suspend(10)
+print foo()
diff -urN py_cvs/dist/src/t2.py py_gen/t2.py
--- py_cvs/dist/src/t2.py	Wed Dec 31 19:00:00 1969
+++ py_gen/t2.py	Sat Mar 17 19:24:01 2001
@@ -0,0 +1,15 @@
+import sys
+
+def g():
+    for n in range(1000):
+        f = sys._getframe()
+        f.suspend((n, f))
+    return None, None
+
+
+if __name__ == "__main__":
+    n, frame = g()
+    while frame:
+        print n
+        n, frame = frame.resume()
+
diff -urN py_cvs/dist/src/t3.py py_gen/t3.py
--- py_cvs/dist/src/t3.py	Wed Dec 31 19:00:00 1969
+++ py_gen/t3.py	Sat Mar 17 19:24:01 2001
@@ -0,0 +1,13 @@
+import sys
+
+def g():
+    while 1:
+        f = sys._getframe()
+        f.suspend(f)
+
+
+if __name__ == "__main__":
+    f = g()
+    while 1:
+        f.resume()
+
diff -urN py_cvs/dist/src/tree.py py_gen/tree.py
--- py_cvs/dist/src/tree.py	Wed Dec 31 19:00:00 1969
+++ py_gen/tree.py	Sat Mar 17 20:14:38 2001
@@ -0,0 +1,68 @@
+from types import TupleType
+from Generator import Generator
+
+# (A - B) + C * (E/F)
+expr = ("+", 
+         ("-", "A", "B"),
+         ("*", "C",
+              ("/", "E", "F")))
+           
+
+def preorder(node):
+    g = Generator()
+    if isinstance(node, TupleType):
+        g.suspend("(")
+        value, left, right = node
+        g.suspend(value)
+        for child in preorder(left):
+            g.suspend(child)
+        for child in preorder(right):
+            g.suspend(child)
+        g.suspend(")")
+    else:
+        g.suspend(node)
+    g.end()
+
+def postorder(node):
+    g = Generator()
+    if isinstance(node, TupleType):
+        value, left, right = node
+        for child in postorder(left):
+            g.suspend(child)
+        for child in postorder(right):
+            g.suspend(child)
+        g.suspend(value)
+    else:
+        g.suspend(node)
+    g.end()
+
+def inorder(node):
+    g = Generator()
+    if isinstance(node, TupleType):
+        g.suspend("(")
+        value, left, right = node
+        for child in inorder(left):
+            g.suspend(child)
+        g.suspend(value)
+        for child in inorder(right):
+            g.suspend(child)
+        g.suspend(")")
+    else:
+        g.suspend(node)
+    g.end()
+
+
+print "preorder:",
+for node in preorder(expr):
+    print node,
+print
+
+print "postorder:",
+for node in postorder(expr):
+    print node,
+print
+
+print "inorder:",
+for node in inorder(expr):
+    print node,
+print
