Line data Source code
1 : /* Generator object implementation */
2 :
3 : #include "Python.h"
4 : #include "frameobject.h"
5 : #include "structmember.h"
6 : #include "opcode.h"
7 :
8 : static PyObject *gen_close(PyGenObject *gen, PyObject *args);
9 :
10 : static int
11 0 : gen_traverse(PyGenObject *gen, visitproc visit, void *arg)
12 : {
13 0 : Py_VISIT((PyObject *)gen->gi_frame);
14 0 : Py_VISIT(gen->gi_code);
15 0 : return 0;
16 : }
17 :
18 : static void
19 254 : gen_dealloc(PyGenObject *gen)
20 : {
21 254 : PyObject *self = (PyObject *) gen;
22 :
23 254 : _PyObject_GC_UNTRACK(gen);
24 :
25 254 : if (gen->gi_weakreflist != NULL)
26 0 : PyObject_ClearWeakRefs(self);
27 :
28 254 : _PyObject_GC_TRACK(self);
29 :
30 254 : if (gen->gi_frame != NULL && gen->gi_frame->f_stacktop != NULL) {
31 : /* Generator is paused, so we need to close */
32 24 : Py_TYPE(gen)->tp_del(self);
33 24 : if (self->ob_refcnt > 0)
34 254 : return; /* resurrected. :( */
35 : }
36 :
37 254 : _PyObject_GC_UNTRACK(self);
38 254 : Py_CLEAR(gen->gi_frame);
39 254 : Py_CLEAR(gen->gi_code);
40 254 : PyObject_GC_Del(gen);
41 : }
42 :
43 :
44 : static PyObject *
45 757 : gen_send_ex(PyGenObject *gen, PyObject *arg, int exc)
46 : {
47 757 : PyThreadState *tstate = PyThreadState_GET();
48 757 : PyFrameObject *f = gen->gi_frame;
49 : PyObject *result;
50 :
51 757 : if (gen->gi_running) {
52 0 : PyErr_SetString(PyExc_ValueError,
53 : "generator already executing");
54 0 : return NULL;
55 : }
56 757 : if (f == NULL || f->f_stacktop == NULL) {
57 : /* Only set exception if called from send() */
58 0 : if (arg && !exc)
59 0 : PyErr_SetNone(PyExc_StopIteration);
60 0 : return NULL;
61 : }
62 :
63 757 : if (f->f_lasti == -1) {
64 254 : if (arg && arg != Py_None) {
65 0 : PyErr_SetString(PyExc_TypeError,
66 : "can't send non-None value to a "
67 : "just-started generator");
68 0 : return NULL;
69 : }
70 : } else {
71 : /* Push arg onto the frame's value stack */
72 503 : result = arg ? arg : Py_None;
73 503 : Py_INCREF(result);
74 503 : *(f->f_stacktop++) = result;
75 : }
76 :
77 : /* Generators always return to their most recent caller, not
78 : * necessarily their creator. */
79 757 : Py_XINCREF(tstate->frame);
80 : assert(f->f_back == NULL);
81 757 : f->f_back = tstate->frame;
82 :
83 757 : gen->gi_running = 1;
84 757 : result = PyEval_EvalFrameEx(f, exc);
85 757 : gen->gi_running = 0;
86 :
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
89 : * cycle. */
90 : assert(f->f_back == tstate->frame);
91 757 : Py_CLEAR(f->f_back);
92 :
93 : /* If the generator just returned (as opposed to yielding), signal
94 : * that the generator is exhausted. */
95 757 : if (result && f->f_stacktop == NULL) {
96 230 : if (result == Py_None) {
97 : /* Delay exception instantiation if we can */
98 230 : PyErr_SetNone(PyExc_StopIteration);
99 : } else {
100 0 : PyObject *e = PyObject_CallFunctionObjArgs(
101 : PyExc_StopIteration, result, NULL);
102 0 : if (e != NULL) {
103 0 : PyErr_SetObject(PyExc_StopIteration, e);
104 0 : Py_DECREF(e);
105 : }
106 : }
107 230 : Py_CLEAR(result);
108 : }
109 :
110 757 : if (!result || f->f_stacktop == NULL) {
111 : /* generator can't be rerun, so release the frame */
112 : /* first clean reference cycle through stored exception traceback */
113 : PyObject *t, *v, *tb;
114 254 : t = f->f_exc_type;
115 254 : v = f->f_exc_value;
116 254 : tb = f->f_exc_traceback;
117 254 : f->f_exc_type = NULL;
118 254 : f->f_exc_value = NULL;
119 254 : f->f_exc_traceback = NULL;
120 254 : Py_XDECREF(t);
121 254 : Py_XDECREF(v);
122 254 : Py_XDECREF(tb);
123 254 : gen->gi_frame = NULL;
124 254 : Py_DECREF(f);
125 : }
126 :
127 757 : return result;
128 : }
129 :
130 : PyDoc_STRVAR(send_doc,
131 : "send(arg) -> send 'arg' into generator,\n\
132 : return next yielded value or raise StopIteration.");
133 :
134 : PyObject *
135 0 : _PyGen_Send(PyGenObject *gen, PyObject *arg)
136 : {
137 0 : return gen_send_ex(gen, arg, 0);
138 : }
139 :
140 : PyDoc_STRVAR(close_doc,
141 : "close() -> raise GeneratorExit inside generator.");
142 :
143 : /*
144 : * This helper function is used by gen_close and gen_throw to
145 : * close a subiterator being delegated to by yield-from.
146 : */
147 :
148 : static int
149 0 : gen_close_iter(PyObject *yf)
150 : {
151 0 : PyObject *retval = NULL;
152 : _Py_IDENTIFIER(close);
153 :
154 0 : if (PyGen_CheckExact(yf)) {
155 0 : retval = gen_close((PyGenObject *)yf, NULL);
156 0 : if (retval == NULL)
157 0 : return -1;
158 : } else {
159 0 : PyObject *meth = _PyObject_GetAttrId(yf, &PyId_close);
160 0 : if (meth == NULL) {
161 0 : if (!PyErr_ExceptionMatches(PyExc_AttributeError))
162 0 : PyErr_WriteUnraisable(yf);
163 0 : PyErr_Clear();
164 : } else {
165 0 : retval = PyObject_CallFunction(meth, "");
166 0 : Py_DECREF(meth);
167 0 : if (retval == NULL)
168 0 : return -1;
169 : }
170 : }
171 0 : Py_XDECREF(retval);
172 0 : return 0;
173 : }
174 :
175 : static PyObject *
176 24 : gen_yf(PyGenObject *gen)
177 : {
178 24 : PyObject *yf = NULL;
179 24 : PyFrameObject *f = gen->gi_frame;
180 :
181 24 : if (f) {
182 24 : PyObject *bytecode = f->f_code->co_code;
183 24 : unsigned char *code = (unsigned char *)PyBytes_AS_STRING(bytecode);
184 :
185 24 : if (code[f->f_lasti + 1] != YIELD_FROM)
186 24 : return NULL;
187 0 : yf = f->f_stacktop[-1];
188 0 : Py_INCREF(yf);
189 : }
190 :
191 0 : return yf;
192 : }
193 :
194 : static PyObject *
195 24 : gen_close(PyGenObject *gen, PyObject *args)
196 : {
197 : PyObject *retval;
198 24 : PyObject *yf = gen_yf(gen);
199 24 : int err = 0;
200 :
201 24 : if (yf) {
202 0 : gen->gi_running = 1;
203 0 : err = gen_close_iter(yf);
204 0 : gen->gi_running = 0;
205 0 : Py_DECREF(yf);
206 : }
207 24 : if (err == 0)
208 24 : PyErr_SetNone(PyExc_GeneratorExit);
209 24 : retval = gen_send_ex(gen, Py_None, 1);
210 24 : if (retval) {
211 0 : Py_DECREF(retval);
212 0 : PyErr_SetString(PyExc_RuntimeError,
213 : "generator ignored GeneratorExit");
214 0 : return NULL;
215 : }
216 24 : if (PyErr_ExceptionMatches(PyExc_StopIteration)
217 24 : || PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
218 24 : PyErr_Clear(); /* ignore these errors */
219 24 : Py_INCREF(Py_None);
220 24 : return Py_None;
221 : }
222 0 : return NULL;
223 : }
224 :
225 : static void
226 24 : gen_del(PyObject *self)
227 : {
228 : PyObject *res;
229 : PyObject *error_type, *error_value, *error_traceback;
230 24 : PyGenObject *gen = (PyGenObject *)self;
231 :
232 24 : if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL)
233 : /* Generator isn't paused, so no need to close */
234 : return;
235 :
236 : /* Temporarily resurrect the object. */
237 : assert(self->ob_refcnt == 0);
238 24 : self->ob_refcnt = 1;
239 :
240 : /* Save the current exception, if any. */
241 24 : PyErr_Fetch(&error_type, &error_value, &error_traceback);
242 :
243 24 : res = gen_close(gen, NULL);
244 :
245 24 : if (res == NULL)
246 0 : PyErr_WriteUnraisable(self);
247 : else
248 24 : Py_DECREF(res);
249 :
250 : /* Restore the saved exception. */
251 24 : PyErr_Restore(error_type, error_value, error_traceback);
252 :
253 : /* Undo the temporary resurrection; can't use DECREF here, it would
254 : * cause a recursive call.
255 : */
256 : assert(self->ob_refcnt > 0);
257 24 : if (--self->ob_refcnt == 0)
258 : return; /* this is the normal path out */
259 :
260 : /* close() resurrected it! Make it look like the original Py_DECREF
261 : * never happened.
262 : */
263 : {
264 0 : Py_ssize_t refcnt = self->ob_refcnt;
265 0 : _Py_NewReference(self);
266 0 : self->ob_refcnt = refcnt;
267 : }
268 : assert(PyType_IS_GC(Py_TYPE(self)) &&
269 : _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED);
270 :
271 : /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so
272 : * we need to undo that. */
273 : _Py_DEC_REFTOTAL;
274 : /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object
275 : * chain, so no more to do there.
276 : * If COUNT_ALLOCS, the original decref bumped tp_frees, and
277 : * _Py_NewReference bumped tp_allocs: both of those need to be
278 : * undone.
279 : */
280 : #ifdef COUNT_ALLOCS
281 : --(Py_TYPE(self)->tp_frees);
282 : --(Py_TYPE(self)->tp_allocs);
283 : #endif
284 : }
285 :
286 :
287 :
288 : PyDoc_STRVAR(throw_doc,
289 : "throw(typ[,val[,tb]]) -> raise exception in generator,\n\
290 : return next yielded value or raise StopIteration.");
291 :
292 : static PyObject *
293 0 : gen_throw(PyGenObject *gen, PyObject *args)
294 : {
295 : PyObject *typ;
296 0 : PyObject *tb = NULL;
297 0 : PyObject *val = NULL;
298 0 : PyObject *yf = gen_yf(gen);
299 : _Py_IDENTIFIER(throw);
300 :
301 0 : if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb))
302 0 : return NULL;
303 :
304 0 : if (yf) {
305 : PyObject *ret;
306 : int err;
307 0 : if (PyErr_GivenExceptionMatches(typ, PyExc_GeneratorExit)) {
308 0 : gen->gi_running = 1;
309 0 : err = gen_close_iter(yf);
310 0 : gen->gi_running = 0;
311 0 : Py_DECREF(yf);
312 0 : if (err < 0)
313 0 : return gen_send_ex(gen, Py_None, 1);
314 0 : goto throw_here;
315 : }
316 0 : if (PyGen_CheckExact(yf)) {
317 0 : gen->gi_running = 1;
318 0 : ret = gen_throw((PyGenObject *)yf, args);
319 0 : gen->gi_running = 0;
320 : } else {
321 0 : PyObject *meth = _PyObject_GetAttrId(yf, &PyId_throw);
322 0 : if (meth == NULL) {
323 0 : if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
324 0 : Py_DECREF(yf);
325 0 : return NULL;
326 : }
327 0 : PyErr_Clear();
328 0 : Py_DECREF(yf);
329 0 : goto throw_here;
330 : }
331 0 : gen->gi_running = 1;
332 0 : ret = PyObject_CallObject(meth, args);
333 0 : gen->gi_running = 0;
334 0 : Py_DECREF(meth);
335 : }
336 0 : Py_DECREF(yf);
337 0 : if (!ret) {
338 : PyObject *val;
339 : /* Pop subiterator from stack */
340 0 : ret = *(--gen->gi_frame->f_stacktop);
341 : assert(ret == yf);
342 0 : Py_DECREF(ret);
343 : /* Termination repetition of YIELD_FROM */
344 0 : gen->gi_frame->f_lasti++;
345 0 : if (_PyGen_FetchStopIterationValue(&val) == 0) {
346 0 : ret = gen_send_ex(gen, val, 0);
347 0 : Py_DECREF(val);
348 : } else {
349 0 : ret = gen_send_ex(gen, Py_None, 1);
350 : }
351 : }
352 0 : return ret;
353 : }
354 :
355 : throw_here:
356 : /* First, check the traceback argument, replacing None with
357 : NULL. */
358 0 : if (tb == Py_None) {
359 0 : tb = NULL;
360 : }
361 0 : else if (tb != NULL && !PyTraceBack_Check(tb)) {
362 0 : PyErr_SetString(PyExc_TypeError,
363 : "throw() third argument must be a traceback object");
364 0 : return NULL;
365 : }
366 :
367 0 : Py_INCREF(typ);
368 0 : Py_XINCREF(val);
369 0 : Py_XINCREF(tb);
370 :
371 0 : if (PyExceptionClass_Check(typ))
372 0 : PyErr_NormalizeException(&typ, &val, &tb);
373 :
374 0 : else if (PyExceptionInstance_Check(typ)) {
375 : /* Raising an instance. The value should be a dummy. */
376 0 : if (val && val != Py_None) {
377 0 : PyErr_SetString(PyExc_TypeError,
378 : "instance exception may not have a separate value");
379 0 : goto failed_throw;
380 : }
381 : else {
382 : /* Normalize to raise <class>, <instance> */
383 0 : Py_XDECREF(val);
384 0 : val = typ;
385 0 : typ = PyExceptionInstance_Class(typ);
386 0 : Py_INCREF(typ);
387 :
388 0 : if (tb == NULL)
389 : /* Returns NULL if there's no traceback */
390 0 : tb = PyException_GetTraceback(val);
391 : }
392 : }
393 : else {
394 : /* Not something you can raise. throw() fails. */
395 0 : PyErr_Format(PyExc_TypeError,
396 : "exceptions must be classes or instances "
397 : "deriving from BaseException, not %s",
398 0 : Py_TYPE(typ)->tp_name);
399 0 : goto failed_throw;
400 : }
401 :
402 0 : PyErr_Restore(typ, val, tb);
403 0 : return gen_send_ex(gen, Py_None, 1);
404 :
405 : failed_throw:
406 : /* Didn't use our arguments, so restore their original refcounts */
407 0 : Py_DECREF(typ);
408 0 : Py_XDECREF(val);
409 0 : Py_XDECREF(tb);
410 0 : return NULL;
411 : }
412 :
413 :
414 : static PyObject *
415 733 : gen_iternext(PyGenObject *gen)
416 : {
417 733 : PyObject *val = NULL;
418 : PyObject *ret;
419 733 : ret = gen_send_ex(gen, val, 0);
420 733 : Py_XDECREF(val);
421 733 : return ret;
422 : }
423 :
424 : /*
425 : * If StopIteration exception is set, fetches its 'value'
426 : * attribute if any, otherwise sets pvalue to None.
427 : *
428 : * Returns 0 if no exception or StopIteration is set.
429 : * If any other exception is set, returns -1 and leaves
430 : * pvalue unchanged.
431 : */
432 :
433 : int
434 0 : _PyGen_FetchStopIterationValue(PyObject **pvalue) {
435 : PyObject *et, *ev, *tb;
436 0 : PyObject *value = NULL;
437 :
438 0 : if (PyErr_ExceptionMatches(PyExc_StopIteration)) {
439 0 : PyErr_Fetch(&et, &ev, &tb);
440 0 : Py_XDECREF(et);
441 0 : Py_XDECREF(tb);
442 0 : if (ev) {
443 0 : value = ((PyStopIterationObject *)ev)->value;
444 0 : Py_INCREF(value);
445 0 : Py_DECREF(ev);
446 : }
447 0 : } else if (PyErr_Occurred()) {
448 0 : return -1;
449 : }
450 0 : if (value == NULL) {
451 0 : value = Py_None;
452 0 : Py_INCREF(value);
453 : }
454 0 : *pvalue = value;
455 0 : return 0;
456 : }
457 :
458 : static PyObject *
459 0 : gen_repr(PyGenObject *gen)
460 : {
461 0 : return PyUnicode_FromFormat("<generator object %S at %p>",
462 0 : ((PyCodeObject *)gen->gi_code)->co_name,
463 : gen);
464 : }
465 :
466 :
467 : static PyObject *
468 0 : gen_get_name(PyGenObject *gen)
469 : {
470 0 : PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name;
471 0 : Py_INCREF(name);
472 0 : return name;
473 : }
474 :
475 :
476 : PyDoc_STRVAR(gen__name__doc__,
477 : "Return the name of the generator's associated code object.");
478 :
479 : static PyGetSetDef gen_getsetlist[] = {
480 : {"__name__", (getter)gen_get_name, NULL, gen__name__doc__},
481 : {NULL}
482 : };
483 :
484 :
485 : static PyMemberDef gen_memberlist[] = {
486 : {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), READONLY},
487 : {"gi_running", T_BOOL, offsetof(PyGenObject, gi_running), READONLY},
488 : {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), READONLY},
489 : {NULL} /* Sentinel */
490 : };
491 :
492 : static PyMethodDef gen_methods[] = {
493 : {"send",(PyCFunction)_PyGen_Send, METH_O, send_doc},
494 : {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc},
495 : {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc},
496 : {NULL, NULL} /* Sentinel */
497 : };
498 :
499 : PyTypeObject PyGen_Type = {
500 : PyVarObject_HEAD_INIT(&PyType_Type, 0)
501 : "generator", /* tp_name */
502 : sizeof(PyGenObject), /* tp_basicsize */
503 : 0, /* tp_itemsize */
504 : /* methods */
505 : (destructor)gen_dealloc, /* tp_dealloc */
506 : 0, /* tp_print */
507 : 0, /* tp_getattr */
508 : 0, /* tp_setattr */
509 : 0, /* tp_reserved */
510 : (reprfunc)gen_repr, /* tp_repr */
511 : 0, /* tp_as_number */
512 : 0, /* tp_as_sequence */
513 : 0, /* tp_as_mapping */
514 : 0, /* tp_hash */
515 : 0, /* tp_call */
516 : 0, /* tp_str */
517 : PyObject_GenericGetAttr, /* tp_getattro */
518 : 0, /* tp_setattro */
519 : 0, /* tp_as_buffer */
520 : Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
521 : 0, /* tp_doc */
522 : (traverseproc)gen_traverse, /* tp_traverse */
523 : 0, /* tp_clear */
524 : 0, /* tp_richcompare */
525 : offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */
526 : PyObject_SelfIter, /* tp_iter */
527 : (iternextfunc)gen_iternext, /* tp_iternext */
528 : gen_methods, /* tp_methods */
529 : gen_memberlist, /* tp_members */
530 : gen_getsetlist, /* tp_getset */
531 : 0, /* tp_base */
532 : 0, /* tp_dict */
533 :
534 : 0, /* tp_descr_get */
535 : 0, /* tp_descr_set */
536 : 0, /* tp_dictoffset */
537 : 0, /* tp_init */
538 : 0, /* tp_alloc */
539 : 0, /* tp_new */
540 : 0, /* tp_free */
541 : 0, /* tp_is_gc */
542 : 0, /* tp_bases */
543 : 0, /* tp_mro */
544 : 0, /* tp_cache */
545 : 0, /* tp_subclasses */
546 : 0, /* tp_weaklist */
547 : gen_del, /* tp_del */
548 : };
549 :
550 : PyObject *
551 254 : PyGen_New(PyFrameObject *f)
552 : {
553 254 : PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type);
554 254 : if (gen == NULL) {
555 0 : Py_DECREF(f);
556 0 : return NULL;
557 : }
558 254 : gen->gi_frame = f;
559 254 : Py_INCREF(f->f_code);
560 254 : gen->gi_code = (PyObject *)(f->f_code);
561 254 : gen->gi_running = 0;
562 254 : gen->gi_weakreflist = NULL;
563 254 : _PyObject_GC_TRACK(gen);
564 254 : return (PyObject *)gen;
565 : }
566 :
567 : int
568 0 : PyGen_NeedsFinalizing(PyGenObject *gen)
569 : {
570 : int i;
571 0 : PyFrameObject *f = gen->gi_frame;
572 :
573 0 : if (f == NULL || f->f_stacktop == NULL)
574 0 : return 0; /* no frame or empty blockstack == no finalization */
575 :
576 : /* Any block type besides a loop requires cleanup. */
577 0 : for (i = 0; i < f->f_iblock; i++)
578 0 : if (f->f_blockstack[i].b_type != SETUP_LOOP)
579 0 : return 1;
580 :
581 : /* No blocks except loops, it's safe to skip finalization. */
582 0 : return 0;
583 : }
|