[Python-checkins] CVS: python/dist/src/Python ceval.c,2.246,2.246.2.1 compile.c,2.201,2.201.2.1 graminit.c,2.28,2.28.10.1 marshal.c,1.63,1.63.2.1 symtable.c,2.4,2.4.8.1
Guido van Rossum
gvanrossum@users.sourceforge.net
2001年6月15日 11:56:47 -0700
Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv5899/Python
Modified Files:
Tag: gen-branch
ceval.c compile.c graminit.c marshal.c symtable.c
Log Message:
Neil's generator patch, in the gen-branch.
Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.246
retrieving revision 2.246.2.1
diff -C2 -r2.246 -r2.246.2.1
*** ceval.c 2001年06月08日 04:33:09 2.246
--- ceval.c 2001年06月15日 18:56:44 2.246.2.1
***************
*** 41,44 ****
--- 41,45 ----
PyObject *);
+ static PyObject *eval_frame(PyFrameObject *);
static char *get_func_name(PyObject *);
static char *get_func_desc(PyObject *);
***************
*** 107,110 ****
--- 108,229 ----
+ staticforward PyTypeObject gentype;
+
+ typedef struct {
+ PyObject_HEAD
+ PyFrameObject *frame;
+ int running; /* true if generator is being executed */
+ } genobject;
+
+ static PyObject *
+ gen_new(PyFrameObject *f)
+ {
+ genobject *gen = PyObject_New(genobject, &gentype);
+ if (gen == NULL) {
+ Py_DECREF(f);
+ return NULL;
+ }
+ gen->frame = f;
+ gen->running = 0;
+ return (PyObject *)gen;
+ }
+
+ static void
+ gen_dealloc(genobject *gen)
+ {
+ Py_DECREF(gen->frame);
+ PyObject_DEL(gen);
+ }
+
+ static PyObject *
+ gen_iternext(genobject *gen)
+ {
+ PyFrameObject *f = gen->frame;
+ PyObject *result;
+
+ if (gen->running) {
+ PyErr_SetString(PyExc_ValueError,
+ "generator already executing");
+ return NULL;
+ }
+ if (f->f_stackbottom == NULL) {
+ return NULL;
+ }
+ gen->running = 1;
+ result = eval_frame(f);
+ gen->running = 0;
+ return result;
+ }
+
+ static PyObject *
+ gen_next(genobject *gen, PyObject *args)
+ {
+ PyObject *result;
+
+ if (!PyArg_ParseTuple(args, ":next"))
+ return NULL;
+
+ result = gen_iternext(gen);
+
+ if (result == NULL && !PyErr_Occurred()) {
+ PyErr_SetObject(PyExc_StopIteration, Py_None);
+ return NULL;
+ }
+
+ return result;
+ }
+
+ static PyObject *
+ gen_getiter(PyObject *gen)
+ {
+ Py_INCREF(gen);
+ return gen;
+ }
+
+ static struct PyMethodDef gen_methods[] = {
+ {"next", (PyCFunction)gen_next, METH_VARARGS,
+ "next() -- get the next value, or raise StopIteration"},
+ {NULL, NULL} /* Sentinel */
+ };
+
+ static PyObject *
+ gen_getattr(genobject *gen, char *name)
+ {
+ return Py_FindMethod(gen_methods, (PyObject *)gen, name);
+ }
+
+ statichere PyTypeObject gentype = {
+ PyObject_HEAD_INIT(&PyType_Type)
+ 0, /* ob_size */
+ "generator", /* tp_name */
+ sizeof(genobject), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ /* methods */
+ (destructor)gen_dealloc, /* tp_dealloc */
+ 0, /* tp_print */
+ (getattrfunc)gen_getattr, /* tp_getattr */
+ 0, /* tp_setattr */
+ 0, /* tp_compare */
+ 0, /* tp_repr */
+ 0, /* tp_as_number */
+ 0, /* tp_as_sequence */
+ 0, /* tp_as_mapping */
+ 0, /* tp_hash */
+ 0, /* tp_call */
+ 0, /* tp_str */
+ 0, /* tp_getattro */
+ 0, /* tp_setattro */
+ 0, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT, /* tp_flags */
+ 0, /* tp_doc */
+ 0, /* tp_traverse */
+ 0, /* tp_clear */
+ 0, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ (getiterfunc)gen_getiter, /* tp_iter */
+ (iternextfunc)gen_iternext, /* tp_iternext */
+ };
+
+
#ifdef WITH_THREAD
***************
*** 338,342 ****
WHY_RETURN, /* 'return' statement */
WHY_BREAK, /* 'break' statement */
! WHY_CONTINUE /* 'continue' statement */
};
--- 457,462 ----
WHY_RETURN, /* 'return' statement */
WHY_BREAK, /* 'break' statement */
! WHY_CONTINUE, /* 'continue' statement */
! WHY_YIELD, /* 'yield' operator */
};
***************
*** 359,366 ****
/* Interpreter main loop */
! static PyObject *
! eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
! PyObject **args, int argcount, PyObject **kws, int kwcount,
! PyObject **defs, int defcount, PyObject *closure)
{
#ifdef DXPAIRS
--- 479,484 ----
/* Interpreter main loop */
! PyObject *
! eval_frame(PyFrameObject *f)
{
#ifdef DXPAIRS
***************
*** 379,386 ****
register PyObject *t;
register PyObject *stream = NULL; /* for PRINT opcodes */
- register PyFrameObject *f; /* Current frame */
register PyObject **fastlocals, **freevars;
PyObject *retval = NULL; /* Return value */
PyThreadState *tstate = PyThreadState_GET();
unsigned char *first_instr;
#ifdef LLTRACE
--- 497,504 ----
register PyObject *t;
register PyObject *stream = NULL; /* for PRINT opcodes */
register PyObject **fastlocals, **freevars;
PyObject *retval = NULL; /* Return value */
PyThreadState *tstate = PyThreadState_GET();
+ PyCodeObject *co;
unsigned char *first_instr;
#ifdef LLTRACE
***************
*** 389,393 ****
#if defined(Py_DEBUG) || defined(LLTRACE)
/* Make it easier to find out where we are with a debugger */
! char *filename = PyString_AsString(co->co_filename);
#endif
--- 507,511 ----
#if defined(Py_DEBUG) || defined(LLTRACE)
/* Make it easier to find out where we are with a debugger */
! char *filename;
#endif
***************
*** 427,430 ****
--- 545,551 ----
/* Start of code */
+ if (f == NULL)
+ return NULL;
+
#ifdef USE_STACKCHECK
if (tstate->recursion_depth%10 == 0 && PyOS_CheckStack()) {
***************
*** 433,675 ****
}
#endif
-
- if (globals == NULL) {
- PyErr_SetString(PyExc_SystemError, "eval_code2: NULL globals");
- return NULL;
- }
-
- #ifdef LLTRACE
- lltrace = PyDict_GetItemString(globals, "__lltrace__") != NULL;
- #endif
-
- f = PyFrame_New(tstate, /*back*/
- co, /*code*/
- globals, locals);
- if (f == NULL)
- return NULL;
-
- tstate->frame = f;
- fastlocals = f->f_localsplus;
- freevars = f->f_localsplus + f->f_nlocals;
-
- if (co->co_argcount > 0 ||
- co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
- int i;
- int n = argcount;
- PyObject *kwdict = NULL;
- if (co->co_flags & CO_VARKEYWORDS) {
- kwdict = PyDict_New();
- if (kwdict == NULL)
- goto fail;
- i = co->co_argcount;
- if (co->co_flags & CO_VARARGS)
- i++;
- SETLOCAL(i, kwdict);
- }
- if (argcount > co->co_argcount) {
- if (!(co->co_flags & CO_VARARGS)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes %s %d "
- "%sargument%s (%d given)",
- PyString_AsString(co->co_name),
- defcount ? "at most" : "exactly",
- co->co_argcount,
- kwcount ? "non-keyword " : "",
- co->co_argcount == 1 ? "" : "s",
- argcount);
- goto fail;
- }
- n = co->co_argcount;
- }
- for (i = 0; i < n; i++) {
- x = args[i];
- Py_INCREF(x);
- SETLOCAL(i, x);
- }
- if (co->co_flags & CO_VARARGS) {
- u = PyTuple_New(argcount - n);
- if (u == NULL)
- goto fail;
- SETLOCAL(co->co_argcount, u);
- for (i = n; i < argcount; i++) {
- x = args[i];
- Py_INCREF(x);
- PyTuple_SET_ITEM(u, i-n, x);
- }
- }
- for (i = 0; i < kwcount; i++) {
- PyObject *keyword = kws[2*i];
- PyObject *value = kws[2*i + 1];
- int j;
- if (keyword == NULL || !PyString_Check(keyword)) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() keywords must be strings",
- PyString_AsString(co->co_name));
- goto fail;
- }
- /* XXX slow -- speed up using dictionary? */
- for (j = 0; j < co->co_argcount; j++) {
- PyObject *nm = PyTuple_GET_ITEM(
- co->co_varnames, j);
- int cmp = PyObject_RichCompareBool(
- keyword, nm, Py_EQ);
- if (cmp > 0)
- break;
- else if (cmp < 0)
- goto fail;
- }
- /* Check errors from Compare */
- if (PyErr_Occurred())
- goto fail;
- if (j >= co->co_argcount) {
- if (kwdict == NULL) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() got an unexpected "
- "keyword argument '%.400s'",
- PyString_AsString(co->co_name),
- PyString_AsString(keyword));
- goto fail;
- }
- PyDict_SetItem(kwdict, keyword, value);
- }
- else {
- if (GETLOCAL(j) != NULL) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() got multiple "
- "values for keyword "
- "argument '%.400s'",
- PyString_AsString(co->co_name),
- PyString_AsString(keyword));
- goto fail;
- }
- Py_INCREF(value);
- SETLOCAL(j, value);
- }
- }
- if (argcount < co->co_argcount) {
- int m = co->co_argcount - defcount;
- for (i = argcount; i < m; i++) {
- if (GETLOCAL(i) == NULL) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes %s %d "
- "%sargument%s (%d given)",
- PyString_AsString(co->co_name),
- ((co->co_flags & CO_VARARGS) ||
- defcount) ? "at least"
- : "exactly",
- m, kwcount ? "non-keyword " : "",
- m == 1 ? "" : "s", i);
- goto fail;
- }
- }
- if (n > m)
- i = n - m;
- else
- i = 0;
- for (; i < defcount; i++) {
- if (GETLOCAL(m+i) == NULL) {
- PyObject *def = defs[i];
- Py_INCREF(def);
- SETLOCAL(m+i, def);
- }
- }
- }
- }
- else {
- if (argcount > 0 || kwcount > 0) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes no arguments (%d given)",
- PyString_AsString(co->co_name),
- argcount + kwcount);
- goto fail;
- }
- }
- /* Allocate and initialize storage for cell vars, and copy free
- vars into frame. This isn't too efficient right now. */
- if (f->f_ncells) {
- int i = 0, j = 0, nargs, found;
- char *cellname, *argname;
- PyObject *c;
-
- nargs = co->co_argcount;
- if (co->co_flags & CO_VARARGS)
- nargs++;
- if (co->co_flags & CO_VARKEYWORDS)
- nargs++;
! /* Check for cells that shadow args */
! for (i = 0; i < f->f_ncells && j < nargs; ++i) {
! cellname = PyString_AS_STRING(
! PyTuple_GET_ITEM(co->co_cellvars, i));
! found = 0;
! while (j < nargs) {
! argname = PyString_AS_STRING(
! PyTuple_GET_ITEM(co->co_varnames, j));
! if (strcmp(cellname, argname) == 0) {
! c = PyCell_New(GETLOCAL(j));
! if (c == NULL)
! goto fail;
! GETLOCAL(f->f_nlocals + i) = c;
! found = 1;
! break;
! }
! j++;
! }
! if (found == 0) {
! c = PyCell_New(NULL);
! if (c == NULL)
! goto fail;
! SETLOCAL(f->f_nlocals + i, c);
! }
! }
! /* Initialize any that are left */
! while (i < f->f_ncells) {
! c = PyCell_New(NULL);
! if (c == NULL)
! goto fail;
! SETLOCAL(f->f_nlocals + i, c);
! i++;
! }
! }
! if (f->f_nfreevars) {
! int i;
! for (i = 0; i < f->f_nfreevars; ++i) {
! PyObject *o = PyTuple_GET_ITEM(closure, i);
! Py_INCREF(o);
! freevars[f->f_ncells + i] = o;
! }
! }
!
! if (tstate->sys_tracefunc != NULL) {
! /* tstate->sys_tracefunc, if defined, is a function that
! will be called on *every* entry to a code block.
! Its return value, if not None, is a function that
! will be called at the start of each executed line
! of code. (Actually, the function must return
! itself in order to continue tracing.)
! The trace functions are called with three arguments:
! a pointer to the current frame, a string indicating
! why the function is called, and an argument which
! depends on the situation. The global trace function
! (sys.trace) is also called whenever an exception
! is detected. */
! if (call_trace(&tstate->sys_tracefunc,
! &f->f_trace, f, "call", &str_call,
! Py_None/*XXX how to compute arguments now?*/)) {
! /* Trace function raised an error */
! goto fail;
! }
! }
!
! if (tstate->sys_profilefunc != NULL) {
! /* Similar for sys_profilefunc, except it needn't return
! itself and isn't called for "line" events */
! if (call_trace(&tstate->sys_profilefunc,
! (PyObject**)0, f, "call", &str_call,
! Py_None/*XXX*/)) {
! goto fail;
! }
! }
!
if (++tstate->recursion_depth > recursion_limit) {
--tstate->recursion_depth;
--- 554,559 ----
}
#endif
! /* push frame */
if (++tstate->recursion_depth > recursion_limit) {
--tstate->recursion_depth;
***************
*** 677,687 ****
"maximum recursion depth exceeded");
tstate->frame = f->f_back;
- Py_DECREF(f);
return NULL;
}
_PyCode_GETCODEPTR(co, &first_instr);
! next_instr = first_instr;
! stack_pointer = f->f_valuestack;
why = WHY_NOT;
--- 561,584 ----
"maximum recursion depth exceeded");
tstate->frame = f->f_back;
return NULL;
}
+ f->f_back = tstate->frame;
+ tstate->frame = f;
+
+ co = f->f_code;
+ fastlocals = f->f_localsplus;
+ freevars = f->f_localsplus + f->f_nlocals;
_PyCode_GETCODEPTR(co, &first_instr);
! next_instr = first_instr + f->f_lasti;
! stack_pointer = f->f_stackbottom;
! f->f_stackbottom = NULL;
!
! #ifdef LLTRACE
! lltrace = PyDict_GetItemString(f->f_globals,"__lltrace__") != NULL;
! #endif
! #if defined(Py_DEBUG) || defined(LLTRACE)
! filename = PyString_AsString(co->co_filename);
! #endif
why = WHY_NOT;
***************
*** 1460,1463 ****
--- 1357,1368 ----
break;
+ case YIELD_VALUE:
+ retval = POP();
+ f->f_stackbottom = stack_pointer;
+ f->f_lasti = INSTR_OFFSET();
+ why = WHY_YIELD;
+ break;
+
+
case EXEC_STMT:
w = POP();
***************
*** 1485,1488 ****
--- 1390,1394 ----
why = (enum why_code) PyInt_AsLong(v);
if (why == WHY_RETURN ||
+ why == WHY_YIELD ||
why == CONTINUE_LOOP)
retval = POP();
***************
*** 2226,2230 ****
/* Unwind stacks if a (pseudo) exception occurred */
! while (why != WHY_NOT && f->f_iblock > 0) {
PyTryBlock *b = PyFrame_BlockPop(f);
--- 2132,2136 ----
/* Unwind stacks if a (pseudo) exception occurred */
! while (why != WHY_NOT && why != WHY_YIELD && f->f_iblock > 0) {
PyTryBlock *b = PyFrame_BlockPop(f);
***************
*** 2296,2309 ****
/* Pop remaining stack entries */
while (!EMPTY()) {
v = POP();
Py_XDECREF(v);
}
! if (why != WHY_RETURN)
retval = NULL;
if (f->f_trace) {
! if (why == WHY_RETURN) {
if (call_trace(&f->f_trace, &f->f_trace, f,
"return", &str_return, retval)) {
--- 2202,2217 ----
/* Pop remaining stack entries */
+ /*
while (!EMPTY()) {
v = POP();
Py_XDECREF(v);
}
+ */
! if (why != WHY_RETURN && why != WHY_YIELD)
retval = NULL;
if (f->f_trace) {
! if (why == WHY_RETURN || why == WHY_YIELD) {
if (call_trace(&f->f_trace, &f->f_trace, f,
"return", &str_return, retval)) {
***************
*** 2315,2319 ****
}
! if (tstate->sys_profilefunc && why == WHY_RETURN) {
if (call_trace(&tstate->sys_profilefunc, (PyObject**)0,
f, "return", &str_return, retval)) {
--- 2223,2228 ----
}
! if (tstate->sys_profilefunc &&
! (why == WHY_RETURN || why == WHY_YIELD)) {
if (call_trace(&tstate->sys_profilefunc, (PyObject**)0,
f, "return", &str_return, retval)) {
***************
*** 2326,2340 ****
reset_exc_info(tstate);
--tstate->recursion_depth;
! fail: /* Jump here from prelude on failure */
! /* Restore previous frame and release the current one */
! tstate->frame = f->f_back;
! Py_DECREF(f);
return retval;
}
static void
--- 2235,2503 ----
reset_exc_info(tstate);
+ /* pop frame */
--tstate->recursion_depth;
+ tstate->frame = f->f_back;
! return retval;
! }
!
! static PyObject *
! eval_code2(PyCodeObject *co, PyObject *globals, PyObject *locals,
! PyObject **args, int argcount, PyObject **kws, int kwcount,
! PyObject **defs, int defcount, PyObject *closure)
! {
! register PyFrameObject *f;
! register PyObject *retval = NULL;
! register PyObject **fastlocals, **freevars;
! PyThreadState *tstate = PyThreadState_GET();
! PyObject *x, *u;
! if (globals == NULL) {
! PyErr_SetString(PyExc_SystemError, "eval_code2: NULL globals");
! return NULL;
! }
! f = PyFrame_New(tstate, /*back*/
! co, /*code*/
! globals, locals);
! if (f == NULL)
! return NULL;
!
! fastlocals = f->f_localsplus;
! freevars = f->f_localsplus + f->f_nlocals;
!
! if (co->co_argcount > 0 ||
! co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
! int i;
! int n = argcount;
! PyObject *kwdict = NULL;
! if (co->co_flags & CO_VARKEYWORDS) {
! kwdict = PyDict_New();
! if (kwdict == NULL)
! goto fail;
! i = co->co_argcount;
! if (co->co_flags & CO_VARARGS)
! i++;
! SETLOCAL(i, kwdict);
! }
! if (argcount > co->co_argcount) {
! if (!(co->co_flags & CO_VARARGS)) {
! PyErr_Format(PyExc_TypeError,
! "%.200s() takes %s %d "
! "%sargument%s (%d given)",
! PyString_AsString(co->co_name),
! defcount ? "at most" : "exactly",
! co->co_argcount,
! kwcount ? "non-keyword " : "",
! co->co_argcount == 1 ? "" : "s",
! argcount);
! goto fail;
! }
! n = co->co_argcount;
! }
! for (i = 0; i < n; i++) {
! x = args[i];
! Py_INCREF(x);
! SETLOCAL(i, x);
! }
! if (co->co_flags & CO_VARARGS) {
! u = PyTuple_New(argcount - n);
! if (u == NULL)
! goto fail;
! SETLOCAL(co->co_argcount, u);
! for (i = n; i < argcount; i++) {
! x = args[i];
! Py_INCREF(x);
! PyTuple_SET_ITEM(u, i-n, x);
! }
! }
! for (i = 0; i < kwcount; i++) {
! PyObject *keyword = kws[2*i];
! PyObject *value = kws[2*i + 1];
! int j;
! if (keyword == NULL || !PyString_Check(keyword)) {
! PyErr_Format(PyExc_TypeError,
! "%.200s() keywords must be strings",
! PyString_AsString(co->co_name));
! goto fail;
! }
! /* XXX slow -- speed up using dictionary? */
! for (j = 0; j < co->co_argcount; j++) {
! PyObject *nm = PyTuple_GET_ITEM(
! co->co_varnames, j);
! int cmp = PyObject_RichCompareBool(
! keyword, nm, Py_EQ);
! if (cmp > 0)
! break;
! else if (cmp < 0)
! goto fail;
! }
! /* Check errors from Compare */
! if (PyErr_Occurred())
! goto fail;
! if (j >= co->co_argcount) {
! if (kwdict == NULL) {
! PyErr_Format(PyExc_TypeError,
! "%.200s() got an unexpected "
! "keyword argument '%.400s'",
! PyString_AsString(co->co_name),
! PyString_AsString(keyword));
! goto fail;
! }
! PyDict_SetItem(kwdict, keyword, value);
! }
! else {
! if (GETLOCAL(j) != NULL) {
! PyErr_Format(PyExc_TypeError,
! "%.200s() got multiple "
! "values for keyword "
! "argument '%.400s'",
! PyString_AsString(co->co_name),
! PyString_AsString(keyword));
! goto fail;
! }
! Py_INCREF(value);
! SETLOCAL(j, value);
! }
! }
! if (argcount < co->co_argcount) {
! int m = co->co_argcount - defcount;
! for (i = argcount; i < m; i++) {
! if (GETLOCAL(i) == NULL) {
! PyErr_Format(PyExc_TypeError,
! "%.200s() takes %s %d "
! "%sargument%s (%d given)",
! PyString_AsString(co->co_name),
! ((co->co_flags & CO_VARARGS) ||
! defcount) ? "at least"
! : "exactly",
! m, kwcount ? "non-keyword " : "",
! m == 1 ? "" : "s", i);
! goto fail;
! }
! }
! if (n > m)
! i = n - m;
! else
! i = 0;
! for (; i < defcount; i++) {
! if (GETLOCAL(m+i) == NULL) {
! PyObject *def = defs[i];
! Py_INCREF(def);
! SETLOCAL(m+i, def);
! }
! }
! }
! }
! else {
! if (argcount > 0 || kwcount > 0) {
! PyErr_Format(PyExc_TypeError,
! "%.200s() takes no arguments (%d given)",
! PyString_AsString(co->co_name),
! argcount + kwcount);
! goto fail;
! }
! }
! /* Allocate and initialize storage for cell vars, and copy free
! vars into frame. This isn't too efficient right now. */
! if (f->f_ncells) {
! int i = 0, j = 0, nargs, found;
! char *cellname, *argname;
! PyObject *c;
!
! nargs = co->co_argcount;
! if (co->co_flags & CO_VARARGS)
! nargs++;
! if (co->co_flags & CO_VARKEYWORDS)
! nargs++;
!
! /* Check for cells that shadow args */
! for (i = 0; i < f->f_ncells && j < nargs; ++i) {
! cellname = PyString_AS_STRING(
! PyTuple_GET_ITEM(co->co_cellvars, i));
! found = 0;
! while (j < nargs) {
! argname = PyString_AS_STRING(
! PyTuple_GET_ITEM(co->co_varnames, j));
! if (strcmp(cellname, argname) == 0) {
! c = PyCell_New(GETLOCAL(j));
! if (c == NULL)
! goto fail;
! GETLOCAL(f->f_nlocals + i) = c;
! found = 1;
! break;
! }
! j++;
! }
! if (found == 0) {
! c = PyCell_New(NULL);
! if (c == NULL)
! goto fail;
! SETLOCAL(f->f_nlocals + i, c);
! }
! }
! /* Initialize any that are left */
! while (i < f->f_ncells) {
! c = PyCell_New(NULL);
! if (c == NULL)
! goto fail;
! SETLOCAL(f->f_nlocals + i, c);
! i++;
! }
! }
! if (f->f_nfreevars) {
! int i;
! for (i = 0; i < f->f_nfreevars; ++i) {
! PyObject *o = PyTuple_GET_ITEM(closure, i);
! Py_INCREF(o);
! freevars[f->f_ncells + i] = o;
! }
! }
!
! if (tstate->sys_tracefunc != NULL) {
! /* tstate->sys_tracefunc, if defined, is a function that
! will be called on *every* entry to a code block.
! Its return value, if not None, is a function that
! will be called at the start of each executed line
! of code. (Actually, the function must return
! itself in order to continue tracing.)
! The trace functions are called with three arguments:
! a pointer to the current frame, a string indicating
! why the function is called, and an argument which
! depends on the situation. The global trace function
! (sys.trace) is also called whenever an exception
! is detected. */
! if (call_trace(&tstate->sys_tracefunc,
! &f->f_trace, f, "call", &str_call,
! Py_None/*XXX how to compute arguments now?*/)) {
! /* Trace function raised an error */
! goto fail;
! }
! }
+ if (tstate->sys_profilefunc != NULL) {
+ /* Similar for sys_profilefunc, except it needn't return
+ itself and isn't called for "line" events */
+ if (call_trace(&tstate->sys_profilefunc,
+ (PyObject**)0, f, "call", &str_call,
+ Py_None/*XXX*/)) {
+ goto fail;
+ }
+ }
+
+ if (co->co_flags & CO_GENERATOR) {
+ /* create a new generator that owns the ready to run frame
+ * and return that as the value */
+ return gen_new(f);
+ }
+
+ retval = eval_frame(f);
+
+ fail: /* Jump here from prelude on failure */
+
+ Py_DECREF(f);
return retval;
}
+
static void
Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.201
retrieving revision 2.201.2.1
diff -C2 -r2.201 -r2.201.2.1
*** compile.c 2001年06月09日 09:26:21 2.201
--- compile.c 2001年06月15日 18:56:44 2.201.2.1
***************
*** 2635,2649 ****
com_error(c, PyExc_SyntaxError, "'return' outside function");
}
! if (NCH(n) < 2) {
! com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
com_push(c, 1);
}
! else
! com_node(c, CHILD(n, 1));
! com_addbyte(c, RETURN_VALUE);
com_pop(c, 1);
}
static void
com_raise_stmt(struct compiling *c, node *n)
{
--- 2635,2673 ----
com_error(c, PyExc_SyntaxError, "'return' outside function");
}
! if (c->c_flags & CO_GENERATOR) {
! if (NCH(n) > 1) {
! com_error(c, PyExc_SyntaxError,
! "'return' with argument inside generator");
! }
! com_addoparg(c, LOAD_CONST,
! com_addconst(c, PyExc_StopIteration));
com_push(c, 1);
+ com_addoparg(c, RAISE_VARARGS, 1);
}
! else {
! if (NCH(n) < 2) {
! com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
! com_push(c, 1);
! }
! else
! com_node(c, CHILD(n, 1));
! com_addbyte(c, RETURN_VALUE);
! }
com_pop(c, 1);
}
static void
+ com_yield_stmt(struct compiling *c, node *n)
+ {
+ REQ(n, yield_stmt); /* 'yield' testlist */
+ if (!c->c_infunction) {
+ com_error(c, PyExc_SyntaxError, "'yield' outside function");
+ }
+ com_node(c, CHILD(n, 1));
+ com_addbyte(c, YIELD_VALUE);
+ com_pop(c, 1);
+ }
+
+ static void
com_raise_stmt(struct compiling *c, node *n)
{
***************
*** 3456,3459 ****
--- 3480,3486 ----
com_return_stmt(c, n);
break;
+ case yield_stmt:
+ com_yield_stmt(c, n);
+ break;
case raise_stmt:
com_raise_stmt(c, n);
***************
*** 3675,3682 ****
com_node(c, CHILD(n, 4));
c->c_infunction = 0;
! com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
! com_push(c, 1);
! com_addbyte(c, RETURN_VALUE);
! com_pop(c, 1);
}
--- 3702,3718 ----
com_node(c, CHILD(n, 4));
c->c_infunction = 0;
! if (c->c_flags & CO_GENERATOR) {
! com_addoparg(c, LOAD_CONST,
! com_addconst(c, PyExc_StopIteration));
! com_push(c, 1);
! com_addoparg(c, RAISE_VARARGS, 1);
! com_pop(c, 1);
! }
! else {
! com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
! com_push(c, 1);
! com_addbyte(c, RETURN_VALUE);
! com_pop(c, 1);
! }
}
***************
*** 4343,4346 ****
--- 4379,4384 ----
if (c->c_future && c->c_future->ff_nested_scopes)
c->c_flags |= CO_NESTED;
+ if (ste->ste_generator)
+ c->c_flags |= CO_GENERATOR;
if (ste->ste_type != TYPE_MODULE)
c->c_flags |= CO_NEWLOCALS;
***************
*** 4901,4904 ****
--- 4939,4946 ----
symtable_assign(st, CHILD(n, 1), 0);
break;
+ case yield_stmt:
+ st->st_cur->ste_generator = 1;
+ n = CHILD(n, 1);
+ goto loop;
case expr_stmt:
if (NCH(n) == 1)
Index: graminit.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/graminit.c,v
retrieving revision 2.28
retrieving revision 2.28.10.1
diff -C2 -r2.28 -r2.28.10.1
*** graminit.c 2000年08月24日 20:11:32 2.28
--- graminit.c 2001年06月15日 18:56:44 2.28.10.1
***************
*** 342,350 ****
{1, arcs_15_1},
};
! static arc arcs_16_0[4] = {
{54, 1},
{55, 1},
{56, 1},
{57, 1},
};
static arc arcs_16_1[1] = {
--- 342,351 ----
[...2505 lines suppressed...]
{25, 0},
{2, 0},
{3, 0},
! {319, 0},
{1, "lambda"},
! {316, 0},
{309, 0},
{310, 0},
+ {311, 0},
{1, "class"},
{317, 0},
! {318, 0},
! {320, 0},
};
grammar _PyParser_Grammar = {
! 65,
dfas,
! {144, labels},
256
};
Index: marshal.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/marshal.c,v
retrieving revision 1.63
retrieving revision 1.63.2.1
diff -C2 -r1.63 -r1.63.2.1
*** marshal.c 2001年05月08日 15:19:57 1.63
--- marshal.c 2001年06月15日 18:56:45 1.63.2.1
***************
*** 18,21 ****
--- 18,22 ----
#define TYPE_NULL '0'
#define TYPE_NONE 'N'
+ #define TYPE_STOPITER 'S'
#define TYPE_ELLIPSIS '.'
#define TYPE_INT 'i'
***************
*** 121,124 ****
--- 122,128 ----
w_byte(TYPE_NONE, p);
}
+ else if (v == PyExc_StopIteration) {
+ w_byte(TYPE_STOPITER, p);
+ }
else if (v == Py_Ellipsis) {
w_byte(TYPE_ELLIPSIS, p);
***************
*** 376,379 ****
--- 380,387 ----
Py_INCREF(Py_None);
return Py_None;
+
+ case TYPE_STOPITER:
+ Py_INCREF(PyExc_StopIteration);
+ return PyExc_StopIteration;
case TYPE_ELLIPSIS:
Index: symtable.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v
retrieving revision 2.4
retrieving revision 2.4.8.1
diff -C2 -r2.4 -r2.4.8.1
*** symtable.c 2001年02月27日 19:07:02 2.4
--- symtable.c 2001年06月15日 18:56:45 2.4.8.1
***************
*** 70,73 ****
--- 70,74 ----
ste->ste_nested = 0;
ste->ste_child_free = 0;
+ ste->ste_generator = 0;
if (PyDict_SetItem(st->st_symbols, ste->ste_id, (PyObject *)ste) < 0)