| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 1 | /* Generator object implementation */ | 
 | 2 |  | 
 | 3 | #include "Python.h" | 
 | 4 | #include "frameobject.h" | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 5 | #include "structmember.h" | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 6 | #include "opcode.h" | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 7 |  | 
 | 8 | static int | 
 | 9 | gen_traverse(PyGenObject *gen, visitproc visit, void *arg) | 
 | 10 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 11 |     Py_VISIT((PyObject *)gen->gi_frame); | 
 | 12 |     Py_VISIT(gen->gi_code); | 
 | 13 |     return 0; | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 14 | } | 
 | 15 |  | 
 | 16 | static void | 
 | 17 | gen_dealloc(PyGenObject *gen) | 
 | 18 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 19 |     PyObject *self = (PyObject *) gen; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 20 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 21 |     _PyObject_GC_UNTRACK(gen); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 22 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 23 |     if (gen->gi_weakreflist != NULL) | 
 | 24 |         PyObject_ClearWeakRefs(self); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 25 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 26 |     _PyObject_GC_TRACK(self); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 27 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 28 |     if (gen->gi_frame != NULL && gen->gi_frame->f_stacktop != NULL) { | 
 | 29 |         /* Generator is paused, so we need to close */ | 
 | 30 |         Py_TYPE(gen)->tp_del(self); | 
 | 31 |         if (self->ob_refcnt > 0) | 
 | 32 |             return;                     /* resurrected.  :( */ | 
 | 33 |     } | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 34 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 35 |     _PyObject_GC_UNTRACK(self); | 
 | 36 |     Py_CLEAR(gen->gi_frame); | 
 | 37 |     Py_CLEAR(gen->gi_code); | 
 | 38 |     PyObject_GC_Del(gen); | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 39 | } | 
 | 40 |  | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 41 |  | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 42 | static PyObject * | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 43 | gen_send_ex(PyGenObject *gen, PyObject *arg, int exc) | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 44 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 45 |     PyThreadState *tstate = PyThreadState_GET(); | 
 | 46 |     PyFrameObject *f = gen->gi_frame; | 
 | 47 |     PyObject *result; | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 48 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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 |     } | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 60 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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 |     } | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 74 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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; | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 80 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 81 |     gen->gi_running = 1; | 
 | 82 |     result = PyEval_EvalFrameEx(f, exc); | 
 | 83 |     gen->gi_running = 0; | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 84 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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); | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 90 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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 |     } | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 100 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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 |     } | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 106 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 107 |     return result; | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 108 | } | 
 | 109 |  | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 110 | PyDoc_STRVAR(send_doc, | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 111 | "send(arg) -> send 'arg' into generator,\n\ | 
 | 112 | return next yielded value or raise StopIteration."); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 113 |  | 
 | 114 | static PyObject * | 
 | 115 | gen_send(PyGenObject *gen, PyObject *arg) | 
 | 116 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 117 |     return gen_send_ex(gen, arg, 0); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 118 | } | 
 | 119 |  | 
 | 120 | PyDoc_STRVAR(close_doc, | 
 | 121 | "close(arg) -> raise GeneratorExit inside generator."); | 
 | 122 |  | 
 | 123 | static PyObject * | 
 | 124 | gen_close(PyGenObject *gen, PyObject *args) | 
 | 125 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 143 | } | 
 | 144 |  | 
 | 145 | static void | 
 | 146 | gen_del(PyObject *self) | 
 | 147 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 148 |     PyObject *res; | 
 | 149 |     PyObject *error_type, *error_value, *error_traceback; | 
 | 150 |     PyGenObject *gen = (PyGenObject *)self; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 151 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 152 |     if (gen->gi_frame == NULL || gen->gi_frame->f_stacktop == NULL) | 
 | 153 |         /* Generator isn't paused, so no need to close */ | 
 | 154 |         return; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 155 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 156 |     /* Temporarily resurrect the object. */ | 
 | 157 |     assert(self->ob_refcnt == 0); | 
 | 158 |     self->ob_refcnt = 1; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 159 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 160 |     /* Save the current exception, if any. */ | 
 | 161 |     PyErr_Fetch(&error_type, &error_value, &error_traceback); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 162 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 163 |     res = gen_close(gen, NULL); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 164 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 165 |     if (res == NULL) | 
 | 166 |         PyErr_WriteUnraisable(self); | 
 | 167 |     else | 
 | 168 |         Py_DECREF(res); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 169 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 170 |     /* Restore the saved exception. */ | 
 | 171 |     PyErr_Restore(error_type, error_value, error_traceback); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 172 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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 */ | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 179 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 190 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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 |      */ | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 200 | #ifdef COUNT_ALLOCS | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 201 |     --self->ob_type->tp_frees; | 
 | 202 |     --self->ob_type->tp_allocs; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 203 | #endif | 
 | 204 | } | 
 | 205 |  | 
 | 206 |  | 
 | 207 |  | 
 | 208 | PyDoc_STRVAR(throw_doc, | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 209 | "throw(typ[,val[,tb]]) -> raise exception in generator,\n\ | 
 | 210 | return next yielded value or raise StopIteration."); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 211 |  | 
 | 212 | static PyObject * | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 213 | gen_throw(PyGenObject *gen, PyObject *args) | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 214 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 215 |     PyObject *typ; | 
 | 216 |     PyObject *tb = NULL; | 
 | 217 |     PyObject *val = NULL; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 218 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 219 |     if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) | 
 | 220 |         return NULL; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 221 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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 |     } | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 231 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 232 |     Py_INCREF(typ); | 
 | 233 |     Py_XINCREF(val); | 
 | 234 |     Py_XINCREF(tb); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 235 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 236 |     if (PyExceptionClass_Check(typ)) { | 
 | 237 |         PyErr_NormalizeException(&typ, &val, &tb); | 
 | 238 |     } | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 239 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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 " | 
 | 259 |                      "deriving from BaseException, not %s", | 
 | 260 |                      typ->ob_type->tp_name); | 
 | 261 |             goto failed_throw; | 
 | 262 |     } | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 263 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 264 |     PyErr_Restore(typ, val, tb); | 
 | 265 |     return gen_send_ex(gen, Py_None, 1); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 266 |  | 
 | 267 | failed_throw: | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 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; | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 273 | } | 
 | 274 |  | 
 | 275 |  | 
 | 276 | static PyObject * | 
 | 277 | gen_iternext(PyGenObject *gen) | 
 | 278 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 279 |     return gen_send_ex(gen, NULL, 0); | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 280 | } | 
 | 281 |  | 
 | 282 |  | 
| Alexandre Vassalotti | e9f305f | 2008-05-16 04:39:54 +0000 | [diff] [blame] | 283 | static PyObject * | 
 | 284 | gen_repr(PyGenObject *gen) | 
 | 285 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 286 |     return PyUnicode_FromFormat("<generator object %S at %p>", | 
 | 287 |                                 ((PyCodeObject *)gen->gi_code)->co_name, | 
 | 288 |                                 gen); | 
| Alexandre Vassalotti | e9f305f | 2008-05-16 04:39:54 +0000 | [diff] [blame] | 289 | } | 
 | 290 |  | 
 | 291 |  | 
 | 292 | static PyObject * | 
 | 293 | gen_get_name(PyGenObject *gen) | 
 | 294 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 295 |     PyObject *name = ((PyCodeObject *)gen->gi_code)->co_name; | 
 | 296 |     Py_INCREF(name); | 
 | 297 |     return name; | 
| Alexandre Vassalotti | e9f305f | 2008-05-16 04:39:54 +0000 | [diff] [blame] | 298 | } | 
 | 299 |  | 
 | 300 |  | 
 | 301 | PyDoc_STRVAR(gen__name__doc__, | 
 | 302 | "Return the name of the generator's associated code object."); | 
 | 303 |  | 
 | 304 | static PyGetSetDef gen_getsetlist[] = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 305 |     {"__name__", (getter)gen_get_name, NULL, gen__name__doc__}, | 
 | 306 |     {NULL} | 
| Alexandre Vassalotti | e9f305f | 2008-05-16 04:39:54 +0000 | [diff] [blame] | 307 | }; | 
 | 308 |  | 
 | 309 |  | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 310 | static PyMemberDef gen_memberlist[] = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 311 |     {"gi_frame",        T_OBJECT, offsetof(PyGenObject, gi_frame),      READONLY}, | 
 | 312 |     {"gi_running",      T_INT,    offsetof(PyGenObject, gi_running),    READONLY}, | 
 | 313 |     {"gi_code",     T_OBJECT, offsetof(PyGenObject, gi_code),  READONLY}, | 
 | 314 |     {NULL}      /* Sentinel */ | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 315 | }; | 
 | 316 |  | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 317 | static PyMethodDef gen_methods[] = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 318 |     {"send",(PyCFunction)gen_send, METH_O, send_doc}, | 
 | 319 |     {"throw",(PyCFunction)gen_throw, METH_VARARGS, throw_doc}, | 
 | 320 |     {"close",(PyCFunction)gen_close, METH_NOARGS, close_doc}, | 
 | 321 |     {NULL, NULL}        /* Sentinel */ | 
| Phillip J. Eby | 0d6615f | 2005-08-02 00:46:46 +0000 | [diff] [blame] | 322 | }; | 
 | 323 |  | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 324 | PyTypeObject PyGen_Type = { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 325 |     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 Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 358 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 359 |     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 */ | 
 | 372 |     gen_del,                                    /* tp_del */ | 
| Martin v. Löwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 373 | }; | 
 | 374 |  | 
 | 375 | PyObject * | 
 | 376 | PyGen_New(PyFrameObject *f) | 
 | 377 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 378 |     PyGenObject *gen = PyObject_GC_New(PyGenObject, &PyGen_Type); | 
 | 379 |     if (gen == NULL) { | 
 | 380 |         Py_DECREF(f); | 
 | 381 |         return NULL; | 
 | 382 |     } | 
 | 383 |     gen->gi_frame = f; | 
 | 384 |     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öwis | e440e47 | 2004-06-01 15:22:42 +0000 | [diff] [blame] | 390 | } | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 391 |  | 
 | 392 | int | 
 | 393 | PyGen_NeedsFinalizing(PyGenObject *gen) | 
 | 394 | { | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 395 |     int i; | 
 | 396 |     PyFrameObject *f = gen->gi_frame; | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 397 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 398 |     if (f == NULL || f->f_stacktop == NULL || f->f_iblock <= 0) | 
 | 399 |         return 0; /* no frame or empty blockstack == no finalization */ | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 400 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 401 |     /* Any block type besides a loop requires cleanup. */ | 
 | 402 |     i = f->f_iblock; | 
 | 403 |     while (--i >= 0) { | 
 | 404 |         if (f->f_blockstack[i].b_type != SETUP_LOOP) | 
 | 405 |             return 1; | 
 | 406 |     } | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 407 |  | 
| Antoine Pitrou | f95a1b3 | 2010-05-09 15:52:27 +0000 | [diff] [blame] | 408 |     /* No blocks except loops, it's safe to skip finalization. */ | 
 | 409 |     return 0; | 
| Thomas Wouters | 49fd7fa | 2006-04-21 10:40:58 +0000 | [diff] [blame] | 410 | } |