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. */
79 Py_XINCREF(tstate
->frame
);
80 assert(f
->f_back
== NULL
);
81 f
->f_back
= tstate
->frame
;
84 result
= PyEval_EvalFrameEx(f
, exc
);
87 /* Don't keep the reference to f_back any longer than necessary. It
88 * may keep a chain of frames alive or it could create a reference
90 assert(f
->f_back
== tstate
->frame
);
93 /* If the generator just returned (as opposed to yielding), signal
94 * that the generator is exhausted. */
95 if (result
== Py_None
&& f
->f_stacktop
== NULL
) {
98 /* Set exception if not called by gen_iternext() */
100 PyErr_SetNone(PyExc_StopIteration
);
103 if (!result
|| f
->f_stacktop
== NULL
) {
104 /* generator can't be rerun, so release the frame */
106 gen
->gi_frame
= NULL
;
112 PyDoc_STRVAR(send_doc
,
113 "send(arg) -> send 'arg' into generator,\n\
114 return next yielded value or raise StopIteration.");
117 gen_send(PyGenObject
*gen
, PyObject
*arg
)
119 return gen_send_ex(gen
, arg
, 0);
122 PyDoc_STRVAR(close_doc
,
123 "close(arg) -> raise GeneratorExit inside generator.");
126 gen_close(PyGenObject
*gen
, PyObject
*args
)
129 PyErr_SetNone(PyExc_GeneratorExit
);
130 retval
= gen_send_ex(gen
, Py_None
, 1);
133 PyErr_SetString(PyExc_RuntimeError
,
134 "generator ignored GeneratorExit");
137 if (PyErr_ExceptionMatches(PyExc_StopIteration
)
138 || PyErr_ExceptionMatches(PyExc_GeneratorExit
))
140 PyErr_Clear(); /* ignore these errors */
148 gen_del(PyObject
*self
)
151 PyObject
*error_type
, *error_value
, *error_traceback
;
152 PyGenObject
*gen
= (PyGenObject
*)self
;
154 if (gen
->gi_frame
== NULL
|| gen
->gi_frame
->f_stacktop
== NULL
)
155 /* Generator isn't paused, so no need to close */
158 /* Temporarily resurrect the object. */
159 assert(self
->ob_refcnt
== 0);
162 /* Save the current exception, if any. */
163 PyErr_Fetch(&error_type
, &error_value
, &error_traceback
);
165 res
= gen_close(gen
, NULL
);
168 PyErr_WriteUnraisable(self
);
172 /* Restore the saved exception. */
173 PyErr_Restore(error_type
, error_value
, error_traceback
);
175 /* Undo the temporary resurrection; can't use DECREF here, it would
176 * cause a recursive call.
178 assert(self
->ob_refcnt
> 0);
179 if (--self
->ob_refcnt
== 0)
180 return; /* this is the normal path out */
182 /* close() resurrected it! Make it look like the original Py_DECREF
186 Py_ssize_t refcnt
= self
->ob_refcnt
;
187 _Py_NewReference(self
);
188 self
->ob_refcnt
= refcnt
;
190 assert(PyType_IS_GC(self
->ob_type
) &&
191 _Py_AS_GC(self
)->gc
.gc_refs
!= _PyGC_REFS_UNTRACKED
);
193 /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
194 * we need to undo that. */
196 /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
197 * chain, so no more to do there.
198 * If COUNT_ALLOCS, the original decref bumped tp_frees, and
199 * _Py_NewReference bumped tp_allocs: both of those need to be
203 --self
->ob_type
->tp_frees
;
204 --self
->ob_type
->tp_allocs
;
210 PyDoc_STRVAR(throw_doc
,
211 "throw(typ[,val[,tb]]) -> raise exception in generator,\n\
212 return next yielded value or raise StopIteration.");
215 gen_throw(PyGenObject
*gen
, PyObject
*args
)
219 PyObject
*val
= NULL
;
221 if (!PyArg_UnpackTuple(args
, "throw", 1, 3, &typ
, &val
, &tb
))
224 /* First, check the traceback argument, replacing None with
228 else if (tb
!= NULL
&& !PyTraceBack_Check(tb
)) {
229 PyErr_SetString(PyExc_TypeError
,
230 "throw() third argument must be a traceback object");
238 if (PyExceptionClass_Check(typ
)) {
239 PyErr_NormalizeException(&typ
, &val
, &tb
);
242 else if (PyExceptionInstance_Check(typ
)) {
243 /* Raising an instance. The value should be a dummy. */
244 if (val
&& val
!= Py_None
) {
245 PyErr_SetString(PyExc_TypeError
,
246 "instance exception may not have a separate value");
250 /* Normalize to raise <class>, <instance> */
253 typ
= PyExceptionInstance_Class(typ
);
258 /* Not something you can raise. throw() fails. */
259 PyErr_Format(PyExc_TypeError
,
260 "exceptions must be classes or instances "
261 "deriving from BaseException, 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);
286 gen_repr(PyGenObject
*gen
)
288 return PyUnicode_FromFormat("<generator object %S at %p>",
289 ((PyCodeObject
*)gen
->gi_code
)->co_name
,
295 gen_get_name(PyGenObject
*gen
)
297 PyObject
*name
= ((PyCodeObject
*)gen
->gi_code
)->co_name
;
303 PyDoc_STRVAR(gen__name__doc__
,
304 "Return the name of the generator's associated code object.");
306 static PyGetSetDef gen_getsetlist
[] = {
307 {"__name__", (getter
)gen_get_name
, NULL
, gen__name__doc__
},
312 static PyMemberDef gen_memberlist
[] = {
313 {"gi_frame", T_OBJECT
, offsetof(PyGenObject
, gi_frame
), READONLY
},
314 {"gi_running", T_INT
, offsetof(PyGenObject
, gi_running
), READONLY
},
315 {"gi_code", T_OBJECT
, offsetof(PyGenObject
, gi_code
), READONLY
},
316 {NULL
} /* Sentinel */
319 static PyMethodDef gen_methods
[] = {
320 {"send",(PyCFunction
)gen_send
, METH_O
, send_doc
},
321 {"throw",(PyCFunction
)gen_throw
, METH_VARARGS
, throw_doc
},
322 {"close",(PyCFunction
)gen_close
, METH_NOARGS
, close_doc
},
323 {NULL
, NULL
} /* Sentinel */
326 PyTypeObject PyGen_Type
= {
327 PyVarObject_HEAD_INIT(&PyType_Type
, 0)
328 "generator", /* tp_name */
329 sizeof(PyGenObject
), /* tp_basicsize */
332 (destructor
)gen_dealloc
, /* tp_dealloc */
337 (reprfunc
)gen_repr
, /* tp_repr */
338 0, /* tp_as_number */
339 0, /* tp_as_sequence */
340 0, /* tp_as_mapping */
344 PyObject_GenericGetAttr
, /* tp_getattro */
346 0, /* tp_as_buffer */
347 Py_TPFLAGS_DEFAULT
| Py_TPFLAGS_HAVE_GC
,/* tp_flags */
349 (traverseproc
)gen_traverse
, /* tp_traverse */
351 0, /* tp_richcompare */
352 offsetof(PyGenObject
, gi_weakreflist
), /* tp_weaklistoffset */
353 PyObject_SelfIter
, /* tp_iter */
354 (iternextfunc
)gen_iternext
, /* tp_iternext */
355 gen_methods
, /* tp_methods */
356 gen_memberlist
, /* tp_members */
357 gen_getsetlist
, /* tp_getset */
361 0, /* tp_descr_get */
362 0, /* tp_descr_set */
363 0, /* tp_dictoffset */
372 0, /* tp_subclasses */
374 gen_del
, /* tp_del */
378 PyGen_New(PyFrameObject
*f
)
380 PyGenObject
*gen
= PyObject_GC_New(PyGenObject
, &PyGen_Type
);
386 Py_INCREF(f
->f_code
);
387 gen
->gi_code
= (PyObject
*)(f
->f_code
);
389 gen
->gi_weakreflist
= NULL
;
390 _PyObject_GC_TRACK(gen
);
391 return (PyObject
*)gen
;
395 PyGen_NeedsFinalizing(PyGenObject
*gen
)
398 PyFrameObject
*f
= gen
->gi_frame
;
400 if (f
== NULL
|| f
->f_stacktop
== NULL
|| f
->f_iblock
<= 0)
401 return 0; /* no frame or empty blockstack == no finalization */
403 /* Any block type besides a loop requires cleanup. */
406 if (f
->f_blockstack
[i
].b_type
!= SETUP_LOOP
)
410 /* No blocks except loops, it's safe to skip finalization. */