[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)

AltStyle によって変換されたページ (->オリジナル) /