Index: Doc/api/concrete.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/api/concrete.tex,v retrieving revision 1.39 diff -u -r1.39 concrete.tex --- Doc/api/concrete.tex 25 Mar 2004 08:51:22 -0000 1.39 +++ Doc/api/concrete.tex 20 May 2004 14:56:41 -0000 @@ -2603,3 +2603,34 @@ reference counts are adjusted, and no checks are made for safety; \var{cell} must be non-\NULL{} and must be a cell object. \end{cfuncdesc} + + +\subsection{Generator Objects \label{gen-objects}} + +Generator objects are what Python uses to implement generator iterators. +They are normally created by iterating over a function that yields values, +rather than explicitly calling \cfunction{PyGen_New}. + +\begin{ctypedesc}{PyGenObject} + The C structure used for generator objects. +\end{ctypedesc} + +\begin{cvardesc}{PyTypeObject}{PyGen_Type} + The type object corresponding to generator objects +\end{cvardesc} + +\begin{cfuncdesc}{int}{PyGen_Check}{ob} + Return true if \var{ob} is a generator object; \var{ob} must not be + \NULL. +\end{cfuncdesc} + +\begin{cfuncdesc}{int}{PyGen_CheckExact}{ob} + Return true if \var{ob}'s type is \var{PyGen_Type} + is a generator object; \var{ob} must not be + \NULL. +\end{cfuncdesc} + +\begin{cfuncdesc}{PyObject*}{PyGen_New}{PyFrameObject *frame} + Create and return a new generator object based on the \var{frame} object. + The parameter must not be \NULL. +\end{cfuncdesc} Index: Python/ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.396 diff -u -r2.396 ceval.c --- Python/ceval.c 11 Apr 2004 14:59:33 -0000 2.396 +++ Python/ceval.c 20 May 2004 14:56:42 -0000 @@ -10,6 +10,7 @@ #include "compile.h" #include "frameobject.h" +#include "genobject.h" #include "eval.h" #include "opcode.h" #include "structmember.h" @@ -139,143 +140,6 @@ } #endif -static PyTypeObject gentype; - -typedef struct { - PyObject_HEAD - /* The gi_ prefix is intended to remind of generator-iterator. */ - - PyFrameObject *gi_frame; - - /* True if generator is being executed. */ - int gi_running; - - /* List of weak reference. */ - PyObject *gi_weakreflist; -} genobject; - -static PyObject * -gen_new(PyFrameObject *f) -{ - genobject *gen = PyObject_GC_New(genobject, &gentype); - if (gen == NULL) { - Py_DECREF(f); - return NULL; - } - gen->gi_frame = f; - gen->gi_running = 0; - gen->gi_weakreflist = NULL; - _PyObject_GC_TRACK(gen); - return (PyObject *)gen; -} - -static int -gen_traverse(genobject *gen, visitproc visit, void *arg) -{ - return visit((PyObject *)gen->gi_frame, arg); -} - -static void -gen_dealloc(genobject *gen) -{ - _PyObject_GC_UNTRACK(gen); - if (gen->gi_weakreflist != NULL) - PyObject_ClearWeakRefs((PyObject *) gen); - Py_DECREF(gen->gi_frame); - PyObject_GC_Del(gen); -} - -static PyObject * -gen_iternext(genobject *gen) -{ - PyThreadState *tstate = PyThreadState_GET(); - PyFrameObject *f = gen->gi_frame; - PyObject *result; - - if (gen->gi_running) { - PyErr_SetString(PyExc_ValueError, - "generator already executing"); - return NULL; - } - if (f->f_stacktop == NULL) - return NULL; - - /* Generators always return to their most recent caller, not - * necessarily their creator. */ - Py_XINCREF(tstate->frame); - assert(f->f_back == NULL); - f->f_back = tstate->frame; - - gen->gi_running = 1; - result = eval_frame(f); - gen->gi_running = 0; - - /* Don't keep the reference to f_back any longer than necessary. It - * may keep a chain of frames alive or it could create a reference - * cycle. */ - Py_XDECREF(f->f_back); - f->f_back = NULL; - - /* If the generator just returned (as opposed to yielding), signal - * that the generator is exhausted. */ - if (result == Py_None && f->f_stacktop == NULL) { - Py_DECREF(result); - result = NULL; - } - - return result; -} - -static PyObject * -gen_getiter(PyObject *gen) -{ - Py_INCREF(gen); - return gen; -} - -static PyMemberDef gen_memberlist[] = { - {"gi_frame", T_OBJECT, offsetof(genobject, gi_frame), RO}, - {"gi_running", T_INT, offsetof(genobject, gi_running), RO}, - {NULL} /* Sentinel */ -}; - -static PyTypeObject gentype = { - PyObject_HEAD_INIT(&PyType_Type) - 0, /* ob_size */ - "generator", /* tp_name */ - sizeof(genobject), /* tp_basicsize */ - 0, /* tp_itemsize */ - /* methods */ - (destructor)gen_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_compare */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ - 0, /* tp_doc */ - (traverseproc)gen_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - offsetof(genobject, gi_weakreflist), /* tp_weaklistoffset */ - (getiterfunc)gen_getiter, /* tp_iter */ - (iternextfunc)gen_iternext, /* tp_iternext */ - 0, /* tp_methods */ - gen_memberlist, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ -}; - #ifdef WITH_THREAD @@ -2673,7 +2537,7 @@ /* Create a new generator that owns the ready to run frame * and return that as the value. */ - return gen_new(f); + return PyGen_New(f); } retval = eval_frame(f); @@ -3407,6 +3271,12 @@ } } +PyObject * +PyEval_EvaluateFrame(PyObject *fo) +{ + return eval_frame((PyFrameObject *)fo); +} + #define EXT_POP(STACK_POINTER) (*--(STACK_POINTER)) static void Index: Include/ceval.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/ceval.h,v retrieving revision 2.50 diff -u -r2.50 ceval.h --- Include/ceval.h 28 Oct 2003 12:05:46 -0000 2.50 +++ Include/ceval.h 20 May 2004 14:56:42 -0000 @@ -64,6 +64,7 @@ PyAPI_FUNC(char *) PyEval_GetFuncDesc(PyObject *); PyAPI_FUNC(PyObject *) PyEval_GetCallStats(PyObject *); +PyAPI_FUNC(PyObject *) PyEval_EvaluateFrame(PyObject *); /* this used to be handled on a per-thread basis - now just two globals */ PyAPI_DATA(volatile int) _Py_Ticker; Index: Makefile.pre.in =================================================================== RCS file: /cvsroot/python/python/dist/src/Makefile.pre.in,v retrieving revision 1.142 diff -u -r1.142 Makefile.pre.in --- Makefile.pre.in 18 Mar 2004 07:51:27 -0000 1.142 +++ Makefile.pre.in 20 May 2004 14:56:43 -0000 @@ -261,6 +261,7 @@ Objects/complexobject.o \ Objects/descrobject.o \ Objects/enumobject.o \ + Objects/genobject.o \ Objects/fileobject.o \ Objects/floatobject.o \ Objects/frameobject.o \ @@ -478,6 +479,7 @@ Include/descrobject.h \ Include/dictobject.h \ Include/enumobject.h \ + Include/genobject.h \ Include/fileobject.h \ Include/floatobject.h \ Include/funcobject.h \