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
);
14 Py_VISIT(gen
->gi_code
);
19 gen_dealloc(PyGenObject
*gen
)
21 PyObject
*self
= (PyObject
*) gen
;
23 _PyObject_GC_UNTRACK(gen
);
25 if (gen
->gi_weakreflist
!= NULL
)
26 PyObject_ClearWeakRefs(self
);
28 _PyObject_GC_TRACK(self
);
30 if (gen
->gi_frame
!= NULL
&& gen
->gi_frame
->f_stacktop
!= NULL
) {
31 /* Generator is paused, so we need to close */
32 Py_TYPE(gen
)->tp_del(self
);
33 if (self
->ob_refcnt
> 0)
34 return; /* resurrected. :( */
37 _PyObject_GC_UNTRACK(self
);
38 Py_CLEAR(gen
->gi_frame
);
39 Py_CLEAR(gen
->gi_code
);
45 gen_send_ex(PyGenObject
*gen
, PyObject
*arg
, int exc
)
47 PyThreadState
*tstate
= PyThreadState_GET();
48 PyFrameObject
*f
= gen
->gi_frame
;
51 if (gen
->gi_running
) {
52 PyErr_SetString(PyExc_ValueError
,
53 "generator already executing");
56 if (f
==NULL
|| f
->f_stacktop
== NULL
) {
57 /* Only set exception if called from send() */
59 PyErr_SetNone(PyExc_StopIteration
);
63 if (f
->f_lasti
== -1) {
64 if (arg
&& arg
!= Py_None
) {
65 PyErr_SetString(PyExc_TypeError
,
66 "can't send non-None value to a "
67 "just-started generator");
71 /* Push arg onto the frame's value stack */
72 result
= arg
? arg
: Py_None
;
74 *(f
->f_stacktop
++) = result
;
77 /* Generators always return to their most recent caller, not
78 * necessarily their creator. */
80 Py_XINCREF(tstate
->frame
);
81 assert(f
->f_back
== NULL
);
82 f
->f_back
= tstate
->frame
;
85 result
= PyEval_EvalFrameEx(f
, exc
);
88 /* Don't keep the reference to f_back any longer than necessary. It
89 * may keep a chain of frames alive or it could create a reference
91 assert(f
->f_back
== tstate
->frame
);
93 /* Clear the borrowed reference to the thread state */
96 /* If the generator just returned (as opposed to yielding), signal
97 * that the generator is exhausted. */
98 if (result
== Py_None
&& f
->f_stacktop
== NULL
) {
101 /* Set exception if not called by gen_iternext() */
103 PyErr_SetNone(PyExc_StopIteration
);
106 if (!result
|| f
->f_stacktop
== NULL
) {
107 /* generator can't be rerun, so release the frame */
109 gen
->gi_frame
= NULL
;
115 PyDoc_STRVAR(send_doc
,
116 "send(arg) -> send 'arg' into generator,\n\
117 return next yielded value or raise StopIteration.");
120 gen_send(PyGenObject
*gen
, PyObject
*arg
)
122 return gen_send_ex(gen
, arg
, 0);
125 PyDoc_STRVAR(close_doc
,
126 "close() -> raise GeneratorExit inside generator.");
129 gen_close(PyGenObject
*gen
, PyObject
*args
)
132 PyErr_SetNone(PyExc_GeneratorExit
);
133 retval
= gen_send_ex(gen
, Py_None
, 1);
136 PyErr_SetString(PyExc_RuntimeError
,
137 "generator ignored GeneratorExit");
140 if (PyErr_ExceptionMatches(PyExc_StopIteration
)
141 || PyErr_ExceptionMatches(PyExc_GeneratorExit
))
143 PyErr_Clear(); /* ignore these errors */
151 gen_del(PyObject
*self
)
154 PyObject
*error_type
, *error_value
, *error_traceback
;
155 PyGenObject
*gen
= (PyGenObject
*)self
;
157 if (gen
->gi_frame
== NULL
|| gen
->gi_frame
->f_stacktop
== NULL
)
158 /* Generator isn't paused, so no need to close */
161 /* Temporarily resurrect the object. */
162 assert(self
->ob_refcnt
== 0);
165 /* Save the current exception, if any. */
166 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
168 res
= gen_close(gen
, NULL
);
171 PyErr_WriteUnraisable(self
);
175 /* Restore the saved exception. */
176 PyErr_Restore(error_type
, error_value
, error_traceback
);
178 /* Undo the temporary resurrection; can't use DECREF here, it would
179 * cause a recursive call.
181 assert(self
->ob_refcnt
> 0);
182 if (--self
->ob_refcnt
== 0)
183 return; /* this is the normal path out */
185 /* close() resurrected it! Make it look like the original Py_DECREF
189 Py_ssize_t refcnt
= self
->ob_refcnt
;
190 _Py_NewReference(self
);
191 self
->ob_refcnt
= refcnt
;
193 assert(PyType_IS_GC(self
->ob_type
) &&
194 _Py_AS_GC(self
)->gc
.gc_refs
!= _PyGC_REFS_UNTRACKED
);
196 /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
197 * we need to undo that. */
199 /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
200 * chain, so no more to do there.
201 * If COUNT_ALLOCS, the original decref bumped tp_frees, and
202 * _Py_NewReference bumped tp_allocs: both of those need to be
206 --self
->ob_type
->tp_frees
;
207 --self
->ob_type
->tp_allocs
;
213 PyDoc_STRVAR(throw_doc
,
214 "throw(typ[,val[,tb]]) -> raise exception in generator,\n\
215 return next yielded value or raise StopIteration.");
218 gen_throw(PyGenObject
*gen
, PyObject
*args
)
222 PyObject
*val
= NULL
;
224 if (!PyArg_UnpackTuple(args
, "throw", 1, 3, &typ
, &val
, &tb
))
227 /* First, check the traceback argument, replacing None with
231 else if (tb
!= NULL
&& !PyTraceBack_Check(tb
)) {
232 PyErr_SetString(PyExc_TypeError
,
233 "throw() third argument must be a traceback object");
241 if (PyExceptionClass_Check(typ
)) {
242 PyErr_NormalizeException(&typ
, &val
, &tb
);
245 else if (PyExceptionInstance_Check(typ
)) {
246 /* Raising an instance. The value should be a dummy. */
247 if (val
&& val
!= Py_None
) {
248 PyErr_SetString(PyExc_TypeError
,
249 "instance exception may not have a separate value");
253 /* Normalize to raise <class>, <instance> */
256 typ
= PyExceptionInstance_Class(typ
);
261 /* Not something you can raise. throw() fails. */
262 PyErr_Format(PyExc_TypeError
,
263 "exceptions must be classes, or instances, not %s",
264 typ
->ob_type
->tp_name
);
268 PyErr_Restore(typ
, val
, tb
);
269 return gen_send_ex(gen
, Py_None
, 1);
272 /* Didn't use our arguments, so restore their original refcounts */
281 gen_iternext(PyGenObject
*gen
)
283 return gen_send_ex(gen
, NULL
, 0);
288 gen_repr(PyGenObject
*gen
)
291 code_name
= PyString_AsString(((PyCodeObject
*)gen
->gi_code
)->co_name
);
292 if (code_name
== NULL
)
294 return PyString_FromFormat("<generator object %.200s at %p>",
300 gen_get_name(PyGenObject
*gen
)
302 PyObject
*name
= ((PyCodeObject
*)gen
->gi_code
)->co_name
;
308 PyDoc_STRVAR(gen__name__doc__
,
309 "Return the name of the generator's associated code object.");
311 static PyGetSetDef gen_getsetlist
[] = {
312 {"__name__", (getter
)gen_get_name
, NULL
, gen__name__doc__
},
317 static PyMemberDef gen_memberlist
[] = {
318 {"gi_frame", T_OBJECT
, offsetof(PyGenObject
, gi_frame
), RO
},
319 {"gi_running", T_INT
, offsetof(PyGenObject
, gi_running
), RO
},
320 {"gi_code", T_OBJECT
, offsetof(PyGenObject
, gi_code
), RO
},
321 {NULL
} /* Sentinel */
324 static PyMethodDef gen_methods
[] = {
325 {"send",(PyCFunction
)gen_send
, METH_O
, send_doc
},
326 {"throw",(PyCFunction
)gen_throw
, METH_VARARGS
, throw_doc
},
327 {"close",(PyCFunction
)gen_close
, METH_NOARGS
, close_doc
},
328 {NULL
, NULL
} /* Sentinel */
331 PyTypeObject PyGen_Type
= {
332 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
333 "generator", /* tp_name */
334 sizeof(PyGenObject
), /* tp_basicsize */
337 (destructor
)gen_dealloc
, /* tp_dealloc */
342 (reprfunc
)gen_repr
, /* tp_repr */
343 0, /* tp_as_number */
344 0, /* tp_as_sequence */
345 0, /* tp_as_mapping */
349 PyObject_GenericGetAttr
, /* tp_getattro */
351 0, /* tp_as_buffer */
352 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
,/* tp_flags */
354 (traverseproc
)gen_traverse
, /* tp_traverse */
356 0, /* tp_richcompare */
357 offsetof(PyGenObject
, gi_weakreflist
), /* tp_weaklistoffset */
358 PyObject_SelfIter
, /* tp_iter */
359 (iternextfunc
)gen_iternext
, /* tp_iternext */
360 gen_methods
, /* tp_methods */
361 gen_memberlist
, /* tp_members */
362 gen_getsetlist
, /* tp_getset */
366 0, /* tp_descr_get */
367 0, /* tp_descr_set */
368 0, /* tp_dictoffset */
377 0, /* tp_subclasses */
379 gen_del
, /* tp_del */
383 PyGen_New(PyFrameObject
*f
)
385 PyGenObject
*gen
= PyObject_GC_New(PyGenObject
, &PyGen_Type
);
391 Py_INCREF(f
->f_code
);
392 gen
->gi_code
= (PyObject
*)(f
->f_code
);
394 gen
->gi_weakreflist
= NULL
;
395 _PyObject_GC_TRACK(gen
);
396 return (PyObject
*)gen
;
400 PyGen_NeedsFinalizing(PyGenObject
*gen
)
403 PyFrameObject
*f
= gen
->gi_frame
;
405 if (f
== NULL
|| f
->f_stacktop
== NULL
|| f
->f_iblock
<= 0)
406 return 0; /* no frame or empty blockstack == no finalization */
408 /* Any block type besides a loop requires cleanup. */
411 if (f
->f_blockstack
[i
].b_type
!= SETUP_LOOP
)
415 /* No blocks except loops, it's safe to skip finalization. */