1 /* Generator object implementation */
4 #include "frameobject.h"
7 #include "structmember.h"
11 gen_traverse(PyGenObject
*gen
, visitproc visit
, void *arg
)
13 Py_VISIT((PyObject
*)gen
->gi_frame
);
18 gen_dealloc(PyGenObject
*gen
)
20 PyObject
*self
= (PyObject
*) gen
;
22 _PyObject_GC_UNTRACK(gen
);
24 if (gen
->gi_weakreflist
!= NULL
)
25 PyObject_ClearWeakRefs(self
);
27 _PyObject_GC_TRACK(self
);
29 if (gen
->gi_frame
!= NULL
&& gen
->gi_frame
->f_stacktop
!= NULL
) {
30 /* Generator is paused, so we need to close */
31 gen
->ob_type
->tp_del(self
);
32 if (self
->ob_refcnt
> 0)
33 return; /* resurrected. :( */
36 _PyObject_GC_UNTRACK(self
);
37 Py_CLEAR(gen
->gi_frame
);
43 gen_send_ex(PyGenObject
*gen
, PyObject
*arg
, int exc
)
45 PyThreadState
*tstate
= PyThreadState_GET();
46 PyFrameObject
*f
= gen
->gi_frame
;
49 if (gen
->gi_running
) {
50 PyErr_SetString(PyExc_ValueError
,
51 "generator already executing");
54 if (f
==NULL
|| f
->f_stacktop
== NULL
) {
55 /* Only set exception if called from send() */
57 PyErr_SetNone(PyExc_StopIteration
);
61 if (f
->f_lasti
== -1) {
62 if (arg
&& arg
!= Py_None
) {
63 PyErr_SetString(PyExc_TypeError
,
64 "can't send non-None value to a "
65 "just-started generator");
69 /* Push arg onto the frame's value stack */
70 result
= arg
? arg
: Py_None
;
72 *(f
->f_stacktop
++) = result
;
75 /* Generators always return to their most recent caller, not
76 * necessarily their creator. */
77 Py_XINCREF(tstate
->frame
);
78 assert(f
->f_back
== NULL
);
79 f
->f_back
= tstate
->frame
;
82 result
= PyEval_EvalFrameEx(f
, exc
);
85 /* Don't keep the reference to f_back any longer than necessary. It
86 * may keep a chain of frames alive or it could create a reference
88 assert(f
->f_back
== tstate
->frame
);
91 /* If the generator just returned (as opposed to yielding), signal
92 * that the generator is exhausted. */
93 if (result
== Py_None
&& f
->f_stacktop
== NULL
) {
96 /* Set exception if not called by gen_iternext() */
98 PyErr_SetNone(PyExc_StopIteration
);
101 if (!result
|| f
->f_stacktop
== NULL
) {
102 /* generator can't be rerun, so release the frame */
104 gen
->gi_frame
= NULL
;
110 PyDoc_STRVAR(send_doc
,
111 "send(arg) -> send 'arg' into generator,\n\
112 return next yielded value or raise StopIteration.");
115 gen_send(PyGenObject
*gen
, PyObject
*arg
)
117 return gen_send_ex(gen
, arg
, 0);
120 PyDoc_STRVAR(close_doc
,
121 "close(arg) -> raise GeneratorExit inside generator.");
124 gen_close(PyGenObject
*gen
, PyObject
*args
)
127 PyErr_SetNone(PyExc_GeneratorExit
);
128 retval
= gen_send_ex(gen
, Py_None
, 1);
131 PyErr_SetString(PyExc_RuntimeError
,
132 "generator ignored GeneratorExit");
135 if (PyErr_ExceptionMatches(PyExc_StopIteration
)
136 || PyErr_ExceptionMatches(PyExc_GeneratorExit
))
138 PyErr_Clear(); /* ignore these errors */
146 gen_del(PyObject
*self
)
149 PyObject
*error_type
, *error_value
, *error_traceback
;
150 PyGenObject
*gen
= (PyGenObject
*)self
;
152 if (gen
->gi_frame
== NULL
|| gen
->gi_frame
->f_stacktop
== NULL
)
153 /* Generator isn't paused, so no need to close */
156 /* Temporarily resurrect the object. */
157 assert(self
->ob_refcnt
== 0);
160 /* Save the current exception, if any. */
161 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
163 res
= gen_close(gen
, NULL
);
166 PyErr_WriteUnraisable(self
);
170 /* Restore the saved exception. */
171 PyErr_Restore(error_type
, error_value
, error_traceback
);
173 /* Undo the temporary resurrection; can't use DECREF here, it would
174 * cause a recursive call.
176 assert(self
->ob_refcnt
> 0);
177 if (--self
->ob_refcnt
== 0)
178 return; /* this is the normal path out */
180 /* close() resurrected it! Make it look like the original Py_DECREF
184 Py_ssize_t refcnt
= self
->ob_refcnt
;
185 _Py_NewReference(self
);
186 self
->ob_refcnt
= refcnt
;
188 assert(PyType_IS_GC(self
->ob_type
) &&
189 _Py_AS_GC(self
)->gc
.gc_refs
!= _PyGC_REFS_UNTRACKED
);
191 /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
192 * we need to undo that. */
194 /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
195 * chain, so no more to do there.
196 * If COUNT_ALLOCS, the original decref bumped tp_frees, and
197 * _Py_NewReference bumped tp_allocs: both of those need to be
201 --self
->ob_type
->tp_frees
;
202 --self
->ob_type
->tp_allocs
;
208 PyDoc_STRVAR(throw_doc
,
209 "throw(typ[,val[,tb]]) -> raise exception in generator,\n\
210 return next yielded value or raise StopIteration.");
213 gen_throw(PyGenObject
*gen
, PyObject
*args
)
217 PyObject
*val
= NULL
;
219 if (!PyArg_UnpackTuple(args
, "throw", 1, 3, &typ
, &val
, &tb
))
222 /* First, check the traceback argument, replacing None with
226 else if (tb
!= NULL
&& !PyTraceBack_Check(tb
)) {
227 PyErr_SetString(PyExc_TypeError
,
228 "throw() third argument must be a traceback object");
236 if (PyExceptionClass_Check(typ
)) {
237 PyErr_NormalizeException(&typ
, &val
, &tb
);
240 else if (PyExceptionInstance_Check(typ
)) {
241 /* Raising an instance. The value should be a dummy. */
242 if (val
&& val
!= Py_None
) {
243 PyErr_SetString(PyExc_TypeError
,
244 "instance exception may not have a separate value");
248 /* Normalize to raise <class>, <instance> */
251 typ
= PyExceptionInstance_Class(typ
);
256 /* Allow raising builtin string exceptions */
258 else if (!PyString_CheckExact(typ
)) {
259 /* Not something you can raise. throw() fails. */
260 PyErr_Format(PyExc_TypeError
,
261 "exceptions must be classes, or instances, not %s",
262 typ
->ob_type
->tp_name
);
266 PyErr_Restore(typ
, val
, tb
);
267 return gen_send_ex(gen
, Py_None
, 1);
270 /* Didn't use our arguments, so restore their original refcounts */
279 gen_iternext(PyGenObject
*gen
)
281 return gen_send_ex(gen
, NULL
, 0);
285 static PyMemberDef gen_memberlist
[] = {
286 {"gi_frame", T_OBJECT
, offsetof(PyGenObject
, gi_frame
), RO
},
287 {"gi_running", T_INT
, offsetof(PyGenObject
, gi_running
), RO
},
288 {NULL
} /* Sentinel */
291 static PyMethodDef gen_methods
[] = {
292 {"send",(PyCFunction
)gen_send
, METH_O
, send_doc
},
293 {"throw",(PyCFunction
)gen_throw
, METH_VARARGS
, throw_doc
},
294 {"close",(PyCFunction
)gen_close
, METH_NOARGS
, close_doc
},
295 {NULL
, NULL
} /* Sentinel */
298 PyTypeObject PyGen_Type
= {
299 PyObject_HEAD_INIT(&PyType_Type
)
301 "generator", /* tp_name */
302 sizeof(PyGenObject
), /* tp_basicsize */
305 (destructor
)gen_dealloc
, /* tp_dealloc */
311 0, /* tp_as_number */
312 0, /* tp_as_sequence */
313 0, /* tp_as_mapping */
317 PyObject_GenericGetAttr
, /* tp_getattro */
319 0, /* tp_as_buffer */
320 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
,/* tp_flags */
322 (traverseproc
)gen_traverse
, /* tp_traverse */
324 0, /* tp_richcompare */
325 offsetof(PyGenObject
, gi_weakreflist
), /* tp_weaklistoffset */
326 PyObject_SelfIter
, /* tp_iter */
327 (iternextfunc
)gen_iternext
, /* tp_iternext */
328 gen_methods
, /* tp_methods */
329 gen_memberlist
, /* tp_members */
334 0, /* tp_descr_get */
335 0, /* tp_descr_set */
336 0, /* tp_dictoffset */
345 0, /* tp_subclasses */
347 gen_del
, /* tp_del */
351 PyGen_New(PyFrameObject
*f
)
353 PyGenObject
*gen
= PyObject_GC_New(PyGenObject
, &PyGen_Type
);
360 gen
->gi_weakreflist
= NULL
;
361 _PyObject_GC_TRACK(gen
);
362 return (PyObject
*)gen
;
366 PyGen_NeedsFinalizing(PyGenObject
*gen
)
369 PyFrameObject
*f
= gen
->gi_frame
;
371 if (f
== NULL
|| f
->f_stacktop
== NULL
|| f
->f_iblock
<= 0)
372 return 0; /* no frame or empty blockstack == no finalization */
374 /* Any block type besides a loop requires cleanup. */
377 if (f
->f_blockstack
[i
].b_type
!= SETUP_LOOP
)
381 /* No blocks except loops, it's safe to skip finalization. */