blob: 34ecf2cb5feb94e7d233db7c4e052315aab67fe5 [file] [log] [blame]
Martin v. Löwise440e472004-06-01 15:22:42 +00001/* Generator object implementation */
2
3#include "Python.h"
4#include "frameobject.h"
Martin v. Löwise440e472004-06-01 15:22:42 +00005#include "structmember.h"
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00006#include "opcode.h"
Martin v. Löwise440e472004-06-01 15:22:42 +00007
Nick Coghlan1f7ce622012-01-13 21:43:40 +10008static PyObject *gen_close(PyGenObject *gen, PyObject *args);
Nick Coghlan1f7ce622012-01-13 21:43:40 +10009
Martin v. Löwise440e472004-06-01 15:22:42 +000010static int
11gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
12{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000013 Py_VISIT((PyObject *)gen->gi_frame);
14 Py_VISIT(gen->gi_code);
15 return 0;
Martin v. Löwise440e472004-06-01 15:22:42 +000016}
17
18static void
19gen_dealloc(PyGenObject *gen)
20{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000021 PyObject *self = (PyObject *) gen;
Antoine Pitrou04e70d12013-05-08 18:12:35 +020022 PyFrameObject *f = gen->gi_frame;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000023
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000024 _PyObject_GC_UNTRACK(gen);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000025
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000026 if (gen->gi_weakreflist != NULL)
27 PyObject_ClearWeakRefs(self);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000028
Antoine Pitrou04e70d12013-05-08 18:12:35 +020029 gen->gi_frame = NULL;
30 if (f) {
31 /* Close the generator by finalizing the frame */
32 PyObject *retval, *t, *v, *tb;
33 PyErr_Fetch(&t, &v, &tb);
34 f->f_gen = NULL;
35 retval = _PyFrame_Finalize(f);
36 if (retval)
37 Py_DECREF(retval);
38 else if (PyErr_Occurred())
39 PyErr_WriteUnraisable((PyObject *) gen);
40 Py_DECREF(f);
41 PyErr_Restore(t, v, tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000042 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000043 Py_CLEAR(gen->gi_code);
44 PyObject_GC_Del(gen);
Martin v. Löwise440e472004-06-01 15:22:42 +000045}
46
47static PyObject *
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000048gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
Martin v. Löwise440e472004-06-01 15:22:42 +000049{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000050 PyFrameObject *f = gen->gi_frame;
Martin v. Löwise440e472004-06-01 15:22:42 +000051
Antoine Pitrou04e70d12013-05-08 18:12:35 +020052 /* For compatibility, we check gi_running before f == NULL */
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050053 if (gen->gi_running) {
54 PyErr_SetString(PyExc_ValueError,
55 "generator already executing");
56 return NULL;
57 }
Antoine Pitrou04e70d12013-05-08 18:12:35 +020058 if (f == NULL) {
59 /* Only set exception if send() called, not throw() or next() */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000060 if (arg && !exc)
61 PyErr_SetNone(PyExc_StopIteration);
62 return NULL;
63 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000064
Antoine Pitrou04e70d12013-05-08 18:12:35 +020065 return _PyFrame_GeneratorSend(f, arg, exc);
Martin v. Löwise440e472004-06-01 15:22:42 +000066}
67
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000068PyDoc_STRVAR(send_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000069"send(arg) -> send 'arg' into generator,\n\
70return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000071
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050072PyObject *
73_PyGen_Send(PyGenObject *gen, PyObject *arg)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000074{
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050075 return gen_send_ex(gen, arg, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000076}
77
78PyDoc_STRVAR(close_doc,
Benjamin Petersonab3da292012-05-03 18:44:09 -040079"close() -> raise GeneratorExit inside generator.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000080
Nick Coghlan1f7ce622012-01-13 21:43:40 +100081/*
82 * This helper function is used by gen_close and gen_throw to
83 * close a subiterator being delegated to by yield-from.
84 */
85
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050086static PyObject *
87gen_yf(PyGenObject *gen)
88{
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050089 PyFrameObject *f = gen->gi_frame;
Antoine Pitrou04e70d12013-05-08 18:12:35 +020090 if (f)
91 return _PyFrame_YieldingFrom(f);
92 else
93 return NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050094}
Nick Coghlan1f7ce622012-01-13 21:43:40 +100095
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000096static PyObject *
97gen_close(PyGenObject *gen, PyObject *args)
98{
Antoine Pitrou04e70d12013-05-08 18:12:35 +020099 PyFrameObject *f = gen->gi_frame;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000100
Antoine Pitrou04e70d12013-05-08 18:12:35 +0200101 /* For compatibility, we check gi_running before f == NULL */
102 if (gen->gi_running) {
103 PyErr_SetString(PyExc_ValueError,
104 "generator already executing");
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000105 return NULL;
106 }
Antoine Pitrou04e70d12013-05-08 18:12:35 +0200107 if (f == NULL)
108 Py_RETURN_NONE;
109
110 return _PyFrame_Finalize(f);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000111}
112
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000113PyDoc_STRVAR(throw_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000114"throw(typ[,val[,tb]]) -> raise exception in generator,\n\
115return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000116
117static PyObject *
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000118gen_throw(PyGenObject *gen, PyObject *args)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000119{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000120 PyObject *typ;
121 PyObject *tb = NULL;
122 PyObject *val = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500123 PyObject *yf = gen_yf(gen);
Nick Coghlan5b0dac12012-06-17 15:45:11 +1000124 _Py_IDENTIFIER(throw);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000125
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000126 if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
127 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000128
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000129 if (yf) {
130 PyObject *ret;
131 int err;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000132 if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500133 gen->gi_running = 1;
Antoine Pitrou04e70d12013-05-08 18:12:35 +0200134 err = _PyFrame_CloseIterator(yf);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500135 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000136 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000137 if (err < 0)
138 return gen_send_ex(gen, Py_None, 1);
139 goto throw_here;
140 }
141 if (PyGen_CheckExact(yf)) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500142 gen->gi_running = 1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000143 ret = gen_throw((PyGenObject *)yf, args);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500144 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000145 } else {
Nick Coghlan5b0dac12012-06-17 15:45:11 +1000146 PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000147 if (meth == NULL) {
148 if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
149 Py_DECREF(yf);
150 return NULL;
151 }
152 PyErr_Clear();
153 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000154 goto throw_here;
155 }
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500156 gen->gi_running = 1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000157 ret = PyObject_CallObject(meth, args);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500158 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000159 Py_DECREF(meth);
160 }
161 Py_DECREF(yf);
162 if (!ret) {
163 PyObject *val;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500164 /* Pop subiterator from stack */
165 ret = *(--gen->gi_frame->f_stacktop);
166 assert(ret == yf);
167 Py_DECREF(ret);
168 /* Termination repetition of YIELD_FROM */
169 gen->gi_frame->f_lasti++;
Nick Coghlanc40bc092012-06-17 15:15:49 +1000170 if (_PyGen_FetchStopIterationValue(&val) == 0) {
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000171 ret = gen_send_ex(gen, val, 0);
172 Py_DECREF(val);
173 } else {
174 ret = gen_send_ex(gen, Py_None, 1);
175 }
176 }
177 return ret;
178 }
179
180throw_here:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 /* First, check the traceback argument, replacing None with
182 NULL. */
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400183 if (tb == Py_None) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000184 tb = NULL;
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400185 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000186 else if (tb != NULL && !PyTraceBack_Check(tb)) {
187 PyErr_SetString(PyExc_TypeError,
188 "throw() third argument must be a traceback object");
189 return NULL;
190 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000191
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000192 Py_INCREF(typ);
193 Py_XINCREF(val);
194 Py_XINCREF(tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000195
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400196 if (PyExceptionClass_Check(typ))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 PyErr_NormalizeException(&typ, &val, &tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000198
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000199 else if (PyExceptionInstance_Check(typ)) {
200 /* Raising an instance. The value should be a dummy. */
201 if (val && val != Py_None) {
202 PyErr_SetString(PyExc_TypeError,
203 "instance exception may not have a separate value");
204 goto failed_throw;
205 }
206 else {
207 /* Normalize to raise <class>, <instance> */
208 Py_XDECREF(val);
209 val = typ;
210 typ = PyExceptionInstance_Class(typ);
211 Py_INCREF(typ);
Antoine Pitrou551ba202011-10-18 16:40:50 +0200212
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400213 if (tb == NULL)
Antoine Pitrou551ba202011-10-18 16:40:50 +0200214 /* Returns NULL if there's no traceback */
215 tb = PyException_GetTraceback(val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000216 }
217 }
218 else {
219 /* Not something you can raise. throw() fails. */
220 PyErr_Format(PyExc_TypeError,
221 "exceptions must be classes or instances "
222 "deriving from BaseException, not %s",
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000223 Py_TYPE(typ)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000224 goto failed_throw;
225 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000226
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000227 PyErr_Restore(typ, val, tb);
228 return gen_send_ex(gen, Py_None, 1);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000229
230failed_throw:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000231 /* Didn't use our arguments, so restore their original refcounts */
232 Py_DECREF(typ);
233 Py_XDECREF(val);
234 Py_XDECREF(tb);
235 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000236}
237
238
239static PyObject *
240gen_iternext(PyGenObject *gen)
241{
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000242 PyObject *val = NULL;
243 PyObject *ret;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500244 ret = gen_send_ex(gen, val, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000245 Py_XDECREF(val);
246 return ret;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000247}
248
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000249/*
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000250 * If StopIteration exception is set, fetches its 'value'
251 * attribute if any, otherwise sets pvalue to None.
252 *
253 * Returns 0 if no exception or StopIteration is set.
254 * If any other exception is set, returns -1 and leaves
255 * pvalue unchanged.
256 */
257
258int
Nick Coghlanc40bc092012-06-17 15:15:49 +1000259_PyGen_FetchStopIterationValue(PyObject **pvalue) {
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000260 PyObject *et, *ev, *tb;
261 PyObject *value = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500262
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000263 if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
264 PyErr_Fetch(&et, &ev, &tb);
265 Py_XDECREF(et);
266 Py_XDECREF(tb);
267 if (ev) {
268 value = ((PyStopIterationObject *)ev)->value;
Amaury Forgeot d'Arce557da82012-01-13 21:06:12 +0100269 Py_INCREF(value);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000270 Py_DECREF(ev);
271 }
272 } else if (PyErr_Occurred()) {
273 return -1;
274 }
275 if (value == NULL) {
276 value = Py_None;
Amaury Forgeot d'Arce557da82012-01-13 21:06:12 +0100277 Py_INCREF(value);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000278 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000279 *pvalue = value;
280 return 0;
281}
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000282
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000283static PyObject *
284gen_repr(PyGenObject *gen)
285{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000286 return PyUnicode_FromFormat("<generator object %S at %p>",
287 ((PyCodeObject *)gen->gi_code)->co_name,
288 gen);
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000289}
290
291
292static PyObject *
293gen_get_name(PyGenObject *gen)
294{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000295 PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name;
296 Py_INCREF(name);
297 return name;
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000298}
299
300
301PyDoc_STRVAR(gen__name__doc__,
302"Return the name of the generator's associated code object.");
303
304static PyGetSetDef gen_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000305 {"__name__", (getter)gen_get_name, NULL, gen__name__doc__},
306 {NULL}
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000307};
308
309
Martin v. Löwise440e472004-06-01 15:22:42 +0000310static PyMemberDef gen_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000311 {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY},
Benjamin Peterson657e9eb2012-03-07 18:17:03 -0600312 {"gi_running", T_BOOL, offsetof(PyGenObject, gi_running), READONLY},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000313 {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY},
314 {NULL} /* Sentinel */
Martin v. Löwise440e472004-06-01 15:22:42 +0000315};
316
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000317static PyMethodDef gen_methods[] = {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500318 {"send",(PyCFunction)_PyGen_Send, METH_O, send_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000319 {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
320 {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
321 {NULL, NULL} /* Sentinel */
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000322};
323
Martin v. Löwise440e472004-06-01 15:22:42 +0000324PyTypeObject PyGen_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000325 PyVarObject_HEAD_INIT(&PyType_Type, 0)
326 "generator", /* tp_name */
327 sizeof(PyGenObject), /* tp_basicsize */
328 0, /* tp_itemsize */
329 /* methods */
330 (destructor)gen_dealloc, /* tp_dealloc */
331 0, /* tp_print */
332 0, /* tp_getattr */
333 0, /* tp_setattr */
334 0, /* tp_reserved */
335 (reprfunc)gen_repr, /* tp_repr */
336 0, /* tp_as_number */
337 0, /* tp_as_sequence */
338 0, /* tp_as_mapping */
339 0, /* tp_hash */
340 0, /* tp_call */
341 0, /* tp_str */
342 PyObject_GenericGetAttr, /* tp_getattro */
343 0, /* tp_setattro */
344 0, /* tp_as_buffer */
345 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
346 0, /* tp_doc */
347 (traverseproc)gen_traverse, /* tp_traverse */
348 0, /* tp_clear */
349 0, /* tp_richcompare */
350 offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
351 PyObject_SelfIter, /* tp_iter */
352 (iternextfunc)gen_iternext, /* tp_iternext */
353 gen_methods, /* tp_methods */
354 gen_memberlist, /* tp_members */
355 gen_getsetlist, /* tp_getset */
356 0, /* tp_base */
357 0, /* tp_dict */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000358
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000359 0, /* tp_descr_get */
360 0, /* tp_descr_set */
361 0, /* tp_dictoffset */
362 0, /* tp_init */
363 0, /* tp_alloc */
364 0, /* tp_new */
365 0, /* tp_free */
366 0, /* tp_is_gc */
367 0, /* tp_bases */
368 0, /* tp_mro */
369 0, /* tp_cache */
370 0, /* tp_subclasses */
371 0, /* tp_weaklist */
Martin v. Löwise440e472004-06-01 15:22:42 +0000372};
373
374PyObject *
375PyGen_New(PyFrameObject *f)
376{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000377 PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
378 if (gen == NULL) {
379 Py_DECREF(f);
380 return NULL;
381 }
382 gen->gi_frame = f;
Antoine Pitrou04e70d12013-05-08 18:12:35 +0200383 f->f_gen = (PyObject *) gen;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000384 Py_INCREF(f->f_code);
385 gen->gi_code = (PyObject *)(f->f_code);
386 gen->gi_running = 0;
387 gen->gi_weakreflist = NULL;
388 _PyObject_GC_TRACK(gen);
389 return (PyObject *)gen;
Martin v. Löwise440e472004-06-01 15:22:42 +0000390}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000391
392int
393PyGen_NeedsFinalizing(PyGenObject *gen)
394{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000395 return 0;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000396}