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