blob: 0fc14db89e7fd4a23a0fc5051467314e563c64c4 [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;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000022
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000023 _PyObject_GC_UNTRACK(gen);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000024
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000025 if (gen->gi_weakreflist != NULL)
26 PyObject_ClearWeakRefs(self);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000027
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000028 _PyObject_GC_TRACK(self);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000029
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000030 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. :( */
35 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000036
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000037 _PyObject_GC_UNTRACK(self);
38 Py_CLEAR(gen->gi_frame);
39 Py_CLEAR(gen->gi_code);
40 PyObject_GC_Del(gen);
Martin v. Löwise440e472004-06-01 15:22:42 +000041}
42
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000043
Martin v. Löwise440e472004-06-01 15:22:42 +000044static PyObject *
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000045gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
Martin v. Löwise440e472004-06-01 15:22:42 +000046{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000047 PyThreadState *tstate = PyThreadState_GET();
48 PyFrameObject *f = gen->gi_frame;
49 PyObject *result;
Martin v. Löwise440e472004-06-01 15:22:42 +000050
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -050051 if (gen->gi_running) {
52 PyErr_SetString(PyExc_ValueError,
53 "generator already executing");
54 return NULL;
55 }
Benjamin Petersonf50af112012-03-15 15:37:54 -050056 if (f == NULL || f->f_stacktop == NULL) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000057 /* Only set exception if called from send() */
58 if (arg && !exc)
59 PyErr_SetNone(PyExc_StopIteration);
60 return NULL;
61 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000062
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 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");
68 return NULL;
69 }
70 } else {
71 /* Push arg onto the frame's value stack */
72 result = arg ? arg : Py_None;
73 Py_INCREF(result);
74 *(f->f_stacktop++) = result;
75 }
Martin v. Löwise440e472004-06-01 15:22:42 +000076
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000077 /* 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;
Martin v. Löwise440e472004-06-01 15:22:42 +000082
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000083 gen->gi_running = 1;
84 result = PyEval_EvalFrameEx(f, exc);
85 gen->gi_running = 0;
Martin v. Löwise440e472004-06-01 15:22:42 +000086
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000087 /* 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
89 * cycle. */
90 assert(f->f_back == tstate->frame);
91 Py_CLEAR(f->f_back);
Martin v. Löwise440e472004-06-01 15:22:42 +000092
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000093 /* If the generator just returned (as opposed to yielding), signal
94 * that the generator is exhausted. */
Nick Coghlan1f7ce622012-01-13 21:43:40 +100095 if (result && f->f_stacktop == NULL) {
96 if (result == Py_None) {
97 /* Delay exception instantiation if we can */
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000098 PyErr_SetNone(PyExc_StopIteration);
Nick Coghlan1f7ce622012-01-13 21:43:40 +100099 } else {
100 PyObject *e = PyStopIteration_Create(result);
101 if (e != NULL) {
102 PyErr_SetObject(PyExc_StopIteration, e);
103 Py_DECREF(e);
104 }
105 }
106 Py_CLEAR(result);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000107 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000108
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000109 if (!result || f->f_stacktop == NULL) {
110 /* generator can't be rerun, so release the frame */
Antoine Pitroua370fcf2011-08-20 14:15:03 +0200111 /* first clean reference cycle through stored exception traceback */
112 PyObject *t, *v, *tb;
113 t = f->f_exc_type;
114 v = f->f_exc_value;
115 tb = f->f_exc_traceback;
116 f->f_exc_type = NULL;
117 f->f_exc_value = NULL;
118 f->f_exc_traceback = NULL;
119 Py_XDECREF(t);
120 Py_XDECREF(v);
121 Py_XDECREF(tb);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000122 gen->gi_frame = NULL;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000123 Py_DECREF(f);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000124 }
Martin v. Löwise440e472004-06-01 15:22:42 +0000125
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000126 return result;
Martin v. Löwise440e472004-06-01 15:22:42 +0000127}
128
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000129PyDoc_STRVAR(send_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000130"send(arg) -> send 'arg' into generator,\n\
131return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000132
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500133PyObject *
134_PyGen_Send(PyGenObject *gen, PyObject *arg)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000135{
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500136 return gen_send_ex(gen, arg, 0);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000137}
138
139PyDoc_STRVAR(close_doc,
140"close(arg) -> raise GeneratorExit inside generator.");
141
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000142/*
143 * This helper function is used by gen_close and gen_throw to
144 * close a subiterator being delegated to by yield-from.
145 */
146
147static int
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500148gen_close_iter(PyObject *yf)
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000149{
150 PyObject *retval = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500151
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000152 if (PyGen_CheckExact(yf)) {
153 retval = gen_close((PyGenObject *)yf, NULL);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500154 if (retval == NULL)
155 return -1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000156 } else {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500157 PyObject *meth = PyObject_GetAttrString(yf, "close");
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000158 if (meth == NULL) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500159 if (!PyErr_ExceptionMatches(PyExc_AttributeError))
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000160 PyErr_WriteUnraisable(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000161 PyErr_Clear();
162 } else {
163 retval = PyObject_CallFunction(meth, "");
164 Py_DECREF(meth);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500165 if (retval == NULL)
166 return -1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000167 }
168 }
169 Py_XDECREF(retval);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500170 return 0;
171}
172
173static PyObject *
174gen_yf(PyGenObject *gen)
175{
176 PyObject *yf = NULL;
177 PyFrameObject *f = gen->gi_frame;
178
179 if (f) {
180 PyObject *bytecode = f->f_code->co_code;
181 unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
182
183 if (code[f->f_lasti + 1] != YIELD_FROM)
184 return NULL;
185 yf = f->f_stacktop[-1];
186 Py_INCREF(yf);
187 }
188
189 return yf;
190}
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000191
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000192static PyObject *
193gen_close(PyGenObject *gen, PyObject *args)
194{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000195 PyObject *retval;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500196 PyObject *yf = gen_yf(gen);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000197 int err = 0;
198
199 if (yf) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500200 gen->gi_running = 1;
201 err = gen_close_iter(yf);
202 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000203 Py_DECREF(yf);
204 }
205 if (err == 0)
206 PyErr_SetNone(PyExc_GeneratorExit);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000207 retval = gen_send_ex(gen, Py_None, 1);
208 if (retval) {
209 Py_DECREF(retval);
210 PyErr_SetString(PyExc_RuntimeError,
211 "generator ignored GeneratorExit");
212 return NULL;
213 }
214 if (PyErr_ExceptionMatches(PyExc_StopIteration)
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500215 || PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000216 PyErr_Clear(); /* ignore these errors */
217 Py_INCREF(Py_None);
218 return Py_None;
219 }
220 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000221}
222
223static void
224gen_del(PyObject *self)
225{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 PyObject *res;
227 PyObject *error_type, *error_value, *error_traceback;
228 PyGenObject *gen = (PyGenObject *)self;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000229
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000230 if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
231 /* Generator isn't paused, so no need to close */
232 return;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000233
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000234 /* Temporarily resurrect the object. */
235 assert(self->ob_refcnt == 0);
236 self->ob_refcnt = 1;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000237
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000238 /* Save the current exception, if any. */
239 PyErr_Fetch(&error_type, &error_value, &error_traceback);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000240
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000241 res = gen_close(gen, NULL);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000242
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000243 if (res == NULL)
244 PyErr_WriteUnraisable(self);
245 else
246 Py_DECREF(res);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000247
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000248 /* Restore the saved exception. */
249 PyErr_Restore(error_type, error_value, error_traceback);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000250
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000251 /* Undo the temporary resurrection; can't use DECREF here, it would
252 * cause a recursive call.
253 */
254 assert(self->ob_refcnt > 0);
255 if (--self->ob_refcnt == 0)
256 return; /* this is the normal path out */
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000257
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000258 /* close() resurrected it! Make it look like the original Py_DECREF
259 * never happened.
260 */
261 {
262 Py_ssize_t refcnt = self->ob_refcnt;
263 _Py_NewReference(self);
264 self->ob_refcnt = refcnt;
265 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000266 assert(PyType_IS_GC(Py_TYPE(self)) &&
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000267 _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000268
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000269 /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
270 * we need to undo that. */
271 _Py_DEC_REFTOTAL;
272 /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
273 * chain, so no more to do there.
274 * If COUNT_ALLOCS, the original decref bumped tp_frees, and
275 * _Py_NewReference bumped tp_allocs: both of those need to be
276 * undone.
277 */
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000278#ifdef COUNT_ALLOCS
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000279 --(Py_TYPE(self)->tp_frees);
280 --(Py_TYPE(self)->tp_allocs);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000281#endif
282}
283
284
285
286PyDoc_STRVAR(throw_doc,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000287"throw(typ[,val[,tb]]) -> raise exception in generator,\n\
288return next yielded value or raise StopIteration.");
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000289
290static PyObject *
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000291gen_throw(PyGenObject *gen, PyObject *args)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000292{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000293 PyObject *typ;
294 PyObject *tb = NULL;
295 PyObject *val = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500296 PyObject *yf = gen_yf(gen);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000297
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000298 if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
299 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000300
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000301 if (yf) {
302 PyObject *ret;
303 int err;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000304 if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500305 gen->gi_running = 1;
306 err = gen_close_iter(yf);
307 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000308 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000309 if (err < 0)
310 return gen_send_ex(gen, Py_None, 1);
311 goto throw_here;
312 }
313 if (PyGen_CheckExact(yf)) {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500314 gen->gi_running = 1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000315 ret = gen_throw((PyGenObject *)yf, args);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500316 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000317 } else {
318 PyObject *meth = PyObject_GetAttrString(yf, "throw");
319 if (meth == NULL) {
320 if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
321 Py_DECREF(yf);
322 return NULL;
323 }
324 PyErr_Clear();
325 Py_DECREF(yf);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000326 goto throw_here;
327 }
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500328 gen->gi_running = 1;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000329 ret = PyObject_CallObject(meth, args);
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500330 gen->gi_running = 0;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000331 Py_DECREF(meth);
332 }
333 Py_DECREF(yf);
334 if (!ret) {
335 PyObject *val;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500336 /* Pop subiterator from stack */
337 ret = *(--gen->gi_frame->f_stacktop);
338 assert(ret == yf);
339 Py_DECREF(ret);
340 /* Termination repetition of YIELD_FROM */
341 gen->gi_frame->f_lasti++;
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000342 if (PyGen_FetchStopIterationValue(&val) == 0) {
343 ret = gen_send_ex(gen, val, 0);
344 Py_DECREF(val);
345 } else {
346 ret = gen_send_ex(gen, Py_None, 1);
347 }
348 }
349 return ret;
350 }
351
352throw_here:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 /* First, check the traceback argument, replacing None with
354 NULL. */
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400355 if (tb == Py_None) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000356 tb = NULL;
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400357 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000358 else if (tb != NULL && !PyTraceBack_Check(tb)) {
359 PyErr_SetString(PyExc_TypeError,
360 "throw() third argument must be a traceback object");
361 return NULL;
362 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000363
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000364 Py_INCREF(typ);
365 Py_XINCREF(val);
366 Py_XINCREF(tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000367
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400368 if (PyExceptionClass_Check(typ))
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000369 PyErr_NormalizeException(&typ, &val, &tb);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000370
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000371 else if (PyExceptionInstance_Check(typ)) {
372 /* Raising an instance. The value should be a dummy. */
373 if (val && val != Py_None) {
374 PyErr_SetString(PyExc_TypeError,
375 "instance exception may not have a separate value");
376 goto failed_throw;
377 }
378 else {
379 /* Normalize to raise <class>, <instance> */
380 Py_XDECREF(val);
381 val = typ;
382 typ = PyExceptionInstance_Class(typ);
383 Py_INCREF(typ);
Antoine Pitrou551ba202011-10-18 16:40:50 +0200384
Benjamin Peterson9d9141f2011-10-19 16:57:40 -0400385 if (tb == NULL)
Antoine Pitrou551ba202011-10-18 16:40:50 +0200386 /* Returns NULL if there's no traceback */
387 tb = PyException_GetTraceback(val);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000388 }
389 }
390 else {
391 /* Not something you can raise. throw() fails. */
392 PyErr_Format(PyExc_TypeError,
393 "exceptions must be classes or instances "
394 "deriving from BaseException, not %s",
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000395 Py_TYPE(typ)->tp_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000396 goto failed_throw;
397 }
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000398
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000399 PyErr_Restore(typ, val, tb);
400 return gen_send_ex(gen, Py_None, 1);
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000401
402failed_throw:
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 /* Didn't use our arguments, so restore their original refcounts */
404 Py_DECREF(typ);
405 Py_XDECREF(val);
406 Py_XDECREF(tb);
407 return NULL;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000408}
409
410
411static PyObject *
412gen_iternext(PyGenObject *gen)
413{
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000414 PyObject *val = NULL;
415 PyObject *ret;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500416 ret = gen_send_ex(gen, val, 0);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000417 Py_XDECREF(val);
418 return ret;
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000419}
420
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000421/*
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000422 * If StopIteration exception is set, fetches its 'value'
423 * attribute if any, otherwise sets pvalue to None.
424 *
425 * Returns 0 if no exception or StopIteration is set.
426 * If any other exception is set, returns -1 and leaves
427 * pvalue unchanged.
428 */
429
430int
431PyGen_FetchStopIterationValue(PyObject **pvalue) {
432 PyObject *et, *ev, *tb;
433 PyObject *value = NULL;
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500434
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000435 if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
436 PyErr_Fetch(&et, &ev, &tb);
437 Py_XDECREF(et);
438 Py_XDECREF(tb);
439 if (ev) {
440 value = ((PyStopIterationObject *)ev)->value;
Amaury Forgeot d'Arce557da82012-01-13 21:06:12 +0100441 Py_INCREF(value);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000442 Py_DECREF(ev);
443 }
444 } else if (PyErr_Occurred()) {
445 return -1;
446 }
447 if (value == NULL) {
448 value = Py_None;
Amaury Forgeot d'Arce557da82012-01-13 21:06:12 +0100449 Py_INCREF(value);
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000450 }
Nick Coghlan1f7ce622012-01-13 21:43:40 +1000451 *pvalue = value;
452 return 0;
453}
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000454
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000455static PyObject *
456gen_repr(PyGenObject *gen)
457{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000458 return PyUnicode_FromFormat("<generator object %S at %p>",
459 ((PyCodeObject *)gen->gi_code)->co_name,
460 gen);
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000461}
462
463
464static PyObject *
465gen_get_name(PyGenObject *gen)
466{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000467 PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name;
468 Py_INCREF(name);
469 return name;
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000470}
471
472
473PyDoc_STRVAR(gen__name__doc__,
474"Return the name of the generator's associated code object.");
475
476static PyGetSetDef gen_getsetlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000477 {"__name__", (getter)gen_get_name, NULL, gen__name__doc__},
478 {NULL}
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +0000479};
480
481
Martin v. Löwise440e472004-06-01 15:22:42 +0000482static PyMemberDef gen_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000483 {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY},
Benjamin Peterson657e9eb2012-03-07 18:17:03 -0600484 {"gi_running", T_BOOL, offsetof(PyGenObject, gi_running), READONLY},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000485 {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY},
486 {NULL} /* Sentinel */
Martin v. Löwise440e472004-06-01 15:22:42 +0000487};
488
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000489static PyMethodDef gen_methods[] = {
Benjamin Peterson2afe6ae2012-03-15 15:37:39 -0500490 {"send",(PyCFunction)_PyGen_Send, METH_O, send_doc},
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000491 {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
492 {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
493 {NULL, NULL} /* Sentinel */
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000494};
495
Martin v. Löwise440e472004-06-01 15:22:42 +0000496PyTypeObject PyGen_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000497 PyVarObject_HEAD_INIT(&PyType_Type, 0)
498 "generator", /* tp_name */
499 sizeof(PyGenObject), /* tp_basicsize */
500 0, /* tp_itemsize */
501 /* methods */
502 (destructor)gen_dealloc, /* tp_dealloc */
503 0, /* tp_print */
504 0, /* tp_getattr */
505 0, /* tp_setattr */
506 0, /* tp_reserved */
507 (reprfunc)gen_repr, /* tp_repr */
508 0, /* tp_as_number */
509 0, /* tp_as_sequence */
510 0, /* tp_as_mapping */
511 0, /* tp_hash */
512 0, /* tp_call */
513 0, /* tp_str */
514 PyObject_GenericGetAttr, /* tp_getattro */
515 0, /* tp_setattro */
516 0, /* tp_as_buffer */
517 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
518 0, /* tp_doc */
519 (traverseproc)gen_traverse, /* tp_traverse */
520 0, /* tp_clear */
521 0, /* tp_richcompare */
522 offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
523 PyObject_SelfIter, /* tp_iter */
524 (iternextfunc)gen_iternext, /* tp_iternext */
525 gen_methods, /* tp_methods */
526 gen_memberlist, /* tp_members */
527 gen_getsetlist, /* tp_getset */
528 0, /* tp_base */
529 0, /* tp_dict */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000530
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000531 0, /* tp_descr_get */
532 0, /* tp_descr_set */
533 0, /* tp_dictoffset */
534 0, /* tp_init */
535 0, /* tp_alloc */
536 0, /* tp_new */
537 0, /* tp_free */
538 0, /* tp_is_gc */
539 0, /* tp_bases */
540 0, /* tp_mro */
541 0, /* tp_cache */
542 0, /* tp_subclasses */
543 0, /* tp_weaklist */
544 gen_del, /* tp_del */
Martin v. Löwise440e472004-06-01 15:22:42 +0000545};
546
547PyObject *
548PyGen_New(PyFrameObject *f)
549{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000550 PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
551 if (gen == NULL) {
552 Py_DECREF(f);
553 return NULL;
554 }
555 gen->gi_frame = f;
556 Py_INCREF(f->f_code);
557 gen->gi_code = (PyObject *)(f->f_code);
558 gen->gi_running = 0;
559 gen->gi_weakreflist = NULL;
560 _PyObject_GC_TRACK(gen);
561 return (PyObject *)gen;
Martin v. Löwise440e472004-06-01 15:22:42 +0000562}
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000563
564int
565PyGen_NeedsFinalizing(PyGenObject *gen)
566{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000567 int i;
568 PyFrameObject *f = gen->gi_frame;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000569
Benjamin Petersonf07c9a12011-07-03 17:23:22 -0500570 if (f == NULL || f->f_stacktop == NULL)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000571 return 0; /* no frame or empty blockstack == no finalization */
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000572
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000573 /* Any block type besides a loop requires cleanup. */
Benjamin Petersonf07c9a12011-07-03 17:23:22 -0500574 for (i = 0; i < f->f_iblock; i++)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000575 if (f->f_blockstack[i].b_type != SETUP_LOOP)
576 return 1;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000577
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000578 /* No blocks except loops, it's safe to skip finalization. */
579 return 0;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000580}