/Objects/genobject.c
C | 414 lines | 313 code | 61 blank | 40 comment | 68 complexity | 6b8900670385e90a1bc4623d9c0597a0 MD5 | raw file
1/* Generator object implementation */ 2 3#include "Python.h" 4#include "frameobject.h" 5#include "genobject.h" 6#include "eval.h" 7#include "structmember.h" 8#include "opcode.h" 9 10static int 11gen_traverse(PyGenObject *gen, visitproc visit, void *arg) 12{ 13 Py_VISIT((PyObject *)gen->gi_frame); 14 Py_VISIT(gen->gi_code); 15 return 0; 16} 17 18static void 19gen_dealloc(PyGenObject *gen) 20{ 21 PyObject *self = (PyObject *) gen; 22 23 _PyObject_GC_UNTRACK(gen); 24 25 if (gen->gi_weakreflist != NULL) 26 PyObject_ClearWeakRefs(self); 27 28 _PyObject_GC_TRACK(self); 29 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. :( */ 35 } 36 37 _PyObject_GC_UNTRACK(self); 38 Py_CLEAR(gen->gi_frame); 39 Py_CLEAR(gen->gi_code); 40 PyObject_GC_Del(gen); 41} 42 43 44static PyObject * 45gen_send_ex(PyGenObject *gen, PyObject *arg, int exc) 46{ 47 PyThreadState *tstate = PyThreadState_GET(); 48 PyFrameObject *f = gen->gi_frame; 49 PyObject *result; 50 51 if (gen->gi_running) { 52 PyErr_SetString(PyExc_ValueError, 53 "generator already executing"); 54 return NULL; 55 } 56 if (f==NULL || f->f_stacktop == NULL) { 57 /* Only set exception if called from send() */ 58 if (arg && !exc) 59 PyErr_SetNone(PyExc_StopIteration); 60 return NULL; 61 } 62 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"); 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 } 76 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; 82 83#ifdef WITH_LLVM 84 f->f_bailed_from_llvm = _PYFRAME_NO_BAIL; 85#endif 86 87 gen->gi_running = 1; 88 f->f_throwflag = exc; 89 result = PyEval_EvalFrame(f); 90 f->f_throwflag = 0; 91 gen->gi_running = 0; 92 93 /* Don't keep the reference to f_back any longer than necessary. It 94 * may keep a chain of frames alive or it could create a reference 95 * cycle. */ 96 assert(f->f_back == tstate->frame); 97 Py_CLEAR(f->f_back); 98 99 /* If the generator just returned (as opposed to yielding), signal 100 * that the generator is exhausted. */ 101 if (result == Py_None && f->f_stacktop == NULL) { 102 Py_DECREF(result); 103 result = NULL; 104 /* Set exception if not called by gen_iternext() */ 105 if (arg) 106 PyErr_SetNone(PyExc_StopIteration); 107 } 108 109 if (!result || f->f_stacktop == NULL) { 110 /* generator can't be rerun, so release the frame */ 111 Py_DECREF(f); 112 gen->gi_frame = NULL; 113 } 114 115 return result; 116} 117 118PyDoc_STRVAR(send_doc, 119"send(arg) -> send 'arg' into generator,\n\ 120return next yielded value or raise StopIteration."); 121 122static PyObject * 123gen_send(PyGenObject *gen, PyObject *arg) 124{ 125 return gen_send_ex(gen, arg, 0); 126} 127 128PyDoc_STRVAR(close_doc, 129"close(arg) -> raise GeneratorExit inside generator."); 130 131static PyObject * 132gen_close(PyGenObject *gen, PyObject *args) 133{ 134 PyObject *retval; 135 PyErr_SetNone(PyExc_GeneratorExit); 136 retval = gen_send_ex(gen, Py_None, 1); 137 if (retval) { 138 Py_DECREF(retval); 139 PyErr_SetString(PyExc_RuntimeError, 140 "generator ignored GeneratorExit"); 141 return NULL; 142 } 143 if (PyErr_ExceptionMatches(PyExc_StopIteration) 144 || PyErr_ExceptionMatches(PyExc_GeneratorExit)) 145 { 146 PyErr_Clear(); /* ignore these errors */ 147 Py_INCREF(Py_None); 148 return Py_None; 149 } 150 return NULL; 151} 152 153static void 154gen_del(PyObject *self) 155{ 156 PyObject *res; 157 PyObject *error_type, *error_value, *error_traceback; 158 PyGenObject *gen = (PyGenObject *)self; 159 160 if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL) 161 /* Generator isn't paused, so no need to close */ 162 return; 163 164 /* Temporarily resurrect the object. */ 165 assert(self->ob_refcnt == 0); 166 self->ob_refcnt = 1; 167 168 /* Save the current exception, if any. */ 169 PyErr_Fetch(&error_type, &error_value, &error_traceback); 170 171 res = gen_close(gen, NULL); 172 173 if (res == NULL) 174 PyErr_WriteUnraisable(self); 175 else 176 Py_DECREF(res); 177 178 /* Restore the saved exception. */ 179 PyErr_Restore(error_type, error_value, error_traceback); 180 181 /* Undo the temporary resurrection; can't use DECREF here, it would 182 * cause a recursive call. 183 */ 184 assert(self->ob_refcnt > 0); 185 if (--self->ob_refcnt == 0) 186 return; /* this is the normal path out */ 187 188 /* close() resurrected it! Make it look like the original Py_DECREF 189 * never happened. 190 */ 191 { 192 Py_ssize_t refcnt = self->ob_refcnt; 193 _Py_NewReference(self); 194 self->ob_refcnt = refcnt; 195 } 196 assert(PyType_IS_GC(self->ob_type) && 197 _Py_AS_GC(self)->gc.gc_refs != _PyGC_REFS_UNTRACKED); 198 199 /* If Py_REF_DEBUG, _Py_NewReference bumped _Py_RefTotal, so 200 * we need to undo that. */ 201 _Py_DEC_REFTOTAL; 202 /* If Py_TRACE_REFS, _Py_NewReference re-added self to the object 203 * chain, so no more to do there. 204 * If COUNT_ALLOCS, the original decref bumped tp_frees, and 205 * _Py_NewReference bumped tp_allocs: both of those need to be 206 * undone. 207 */ 208#ifdef COUNT_ALLOCS 209 --self->ob_type->tp_frees; 210 --self->ob_type->tp_allocs; 211#endif 212} 213 214 215 216PyDoc_STRVAR(throw_doc, 217"throw(typ[,val[,tb]]) -> raise exception in generator,\n\ 218return next yielded value or raise StopIteration."); 219 220static PyObject * 221gen_throw(PyGenObject *gen, PyObject *typ, PyObject *val, PyObject *tb) 222{ 223 /* First, check the traceback argument, replacing None with 224 NULL. */ 225 if (tb == Py_None) 226 tb = NULL; 227 else if (tb != NULL && !PyTraceBack_Check(tb)) { 228 PyErr_SetString(PyExc_TypeError, 229 "throw() third argument must be a traceback object"); 230 return NULL; 231 } 232 233 Py_INCREF(typ); 234 Py_XINCREF(val); 235 Py_XINCREF(tb); 236 237 if (PyExceptionClass_Check(typ)) { 238 PyErr_NormalizeException(&typ, &val, &tb); 239 } 240 241 else if (PyExceptionInstance_Check(typ)) { 242 /* Raising an instance. The value should be a dummy. */ 243 if (val && val != Py_None) { 244 PyErr_SetString(PyExc_TypeError, 245 "instance exception may not have a separate value"); 246 goto failed_throw; 247 } 248 else { 249 /* Normalize to raise <class>, <instance> */ 250 Py_XDECREF(val); 251 val = typ; 252 typ = PyExceptionInstance_Class(typ); 253 Py_INCREF(typ); 254 } 255 } 256 else { 257 /* Not something you can raise. throw() fails. */ 258 PyErr_Format(PyExc_TypeError, 259 "exceptions must be classes, or instances, not %s", 260 typ->ob_type->tp_name); 261 goto failed_throw; 262 } 263 264 PyErr_Restore(typ, val, tb); 265 return gen_send_ex(gen, Py_None, 1); 266 267failed_throw: 268 /* Didn't use our arguments, so restore their original refcounts */ 269 Py_DECREF(typ); 270 Py_XDECREF(val); 271 Py_XDECREF(tb); 272 return NULL; 273} 274 275 276static PyObject * 277gen_iternext(PyGenObject *gen) 278{ 279 return gen_send_ex(gen, NULL, 0); 280} 281 282 283static PyObject * 284gen_repr(PyGenObject *gen) 285{ 286 char *code_name; 287 code_name = PyString_AsString(((PyCodeObject *)gen->gi_code)->co_name); 288 if (code_name == NULL) 289 return NULL; 290 return PyString_FromFormat("<generator object %.200s at %p>", 291 code_name, gen); 292} 293 294 295static PyObject * 296gen_get_name(PyGenObject *gen) 297{ 298 PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name; 299 Py_INCREF(name); 300 return name; 301} 302 303 304PyDoc_STRVAR(gen__name__doc__, 305"Return the name of the generator's associated code object."); 306 307static PyGetSetDef gen_getsetlist[] = { 308 {"__name__", (getter)gen_get_name, NULL, gen__name__doc__}, 309 {NULL} 310}; 311 312 313static PyMemberDef gen_memberlist[] = { 314 {"gi_frame", T_OBJECT, offsetof(PyGenObject, gi_frame), RO}, 315 {"gi_running", T_INT, offsetof(PyGenObject, gi_running), RO}, 316 {"gi_code", T_OBJECT, offsetof(PyGenObject, gi_code), RO}, 317 {NULL} /* Sentinel */ 318}; 319 320static PyMethodDef gen_methods[] = { 321 {"send",(PyCFunction)gen_send, METH_O, send_doc}, 322 {"throw",(PyCFunction)gen_throw, METH_ARG_RANGE, throw_doc, 323 /*min_arity=*/1, /*max_arity=*/3}, 324 {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc}, 325 {NULL, NULL} /* Sentinel */ 326}; 327 328PyTypeObject PyGen_Type = { 329 PyVarObject_HEAD_INIT(&PyType_Type, 0) 330 "generator", /* tp_name */ 331 sizeof(PyGenObject), /* tp_basicsize */ 332 0, /* tp_itemsize */ 333 /* methods */ 334 (destructor)gen_dealloc, /* tp_dealloc */ 335 0, /* tp_print */ 336 0, /* tp_getattr */ 337 0, /* tp_setattr */ 338 0, /* tp_compare */ 339 (reprfunc)gen_repr, /* tp_repr */ 340 0, /* tp_as_number */ 341 0, /* tp_as_sequence */ 342 0, /* tp_as_mapping */ 343 0, /* tp_hash */ 344 0, /* tp_call */ 345 0, /* tp_str */ 346 PyObject_GenericGetAttr, /* tp_getattro */ 347 0, /* tp_setattro */ 348 0, /* tp_as_buffer */ 349 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */ 350 0, /* tp_doc */ 351 (traverseproc)gen_traverse, /* tp_traverse */ 352 0, /* tp_clear */ 353 0, /* tp_richcompare */ 354 offsetof(PyGenObject, gi_weakreflist), /* tp_weaklistoffset */ 355 PyObject_SelfIter, /* tp_iter */ 356 (iternextfunc)gen_iternext, /* tp_iternext */ 357 gen_methods, /* tp_methods */ 358 gen_memberlist, /* tp_members */ 359 gen_getsetlist, /* tp_getset */ 360 0, /* tp_base */ 361 0, /* tp_dict */ 362 363 0, /* tp_descr_get */ 364 0, /* tp_descr_set */ 365 0, /* tp_dictoffset */ 366 0, /* tp_init */ 367 0, /* tp_alloc */ 368 0, /* tp_new */ 369 0, /* tp_free */ 370 0, /* tp_is_gc */ 371 0, /* tp_bases */ 372 0, /* tp_mro */ 373 0, /* tp_cache */ 374 0, /* tp_subclasses */ 375 0, /* tp_weaklist */ 376 gen_del, /* tp_del */ 377}; 378 379PyObject * 380PyGen_New(PyFrameObject *f) 381{ 382 PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type); 383 if (gen == NULL) { 384 Py_DECREF(f); 385 return NULL; 386 } 387 gen->gi_frame = f; 388 Py_INCREF(f->f_code); 389 gen->gi_code = (PyObject *)(f->f_code); 390 gen->gi_running = 0; 391 gen->gi_weakreflist = NULL; 392 _PyObject_GC_TRACK(gen); 393 return (PyObject *)gen; 394} 395 396int 397PyGen_NeedsFinalizing(PyGenObject *gen) 398{ 399 int i; 400 PyFrameObject *f = gen->gi_frame; 401 402 if (f == NULL || f->f_stacktop == NULL || f->f_iblock <= 0) 403 return 0; /* no frame or empty blockstack == no finalization */ 404 405 /* Any block type besides a loop requires cleanup. */ 406 i = f->f_iblock; 407 while (--i >= 0) { 408 if (f->f_blockstack[i].b_type != SETUP_LOOP) 409 return 1; 410 } 411 412 /* No blocks except loops, it's safe to skip finalization. */ 413 return 0; 414}