[Python-checkins] CVS: python/dist/src/Python ceval.c,2.231,2.232 compile.c,2.188,2.189

Jeremy Hylton jhylton@users.sourceforge.net
Wed, 21 Mar 2001 08:43:49 -0800


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv32376/Python

Modified Files:
	ceval.c compile.c 
Log Message:
Fix PyFrame_FastToLocals() and counterpart to deal with cells and
frees.  Note there doesn't seem to be any way to test LocalsToFast(),
because the instructions that trigger it are illegal in nested scopes
with free variables.

Fix allocation strategy for cells that are also formal parameters.
Instead of emitting LOAD_FAST / STORE_DEREF pairs for each parameter,
have the argument handling code in eval_code2() do the right thing.

A side-effect of this change is that cell variables that are also
arguments are listed at the front of co_cellvars in the order they
appear in the argument list.



Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.231
retrieving revision 2.232
diff -C2 -r2.231 -r2.232
*** ceval.c	2001/03/13 01:58:21	2.231
--- ceval.c	2001/03/21 16:43:46	2.232
***************
*** 571,579 ****
  		}
  	}
! 	/* Allocate storage for cell vars and copy free vars into frame */ 
  	if (f->f_ncells) {
! 		int i;
! 		for (i = 0; i < f->f_ncells; ++i)
! 			freevars[i] = PyCell_New(NULL);
  	}
  	if (f->f_nfreevars) {
--- 571,620 ----
  		}
  	}
! 	/* 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) {

Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.188
retrieving revision 2.189
diff -C2 -r2.188 -r2.189
*** compile.c	2001/03/20 00:25:43	2.188
--- compile.c	2001/03/21 16:43:47	2.189
***************
*** 3553,3566 ****
  		REQ(ch, fpdef); /* fpdef: NAME | '(' fplist ')' */
  		fp = CHILD(ch, 0);
! 		if (TYPE(fp) == NAME) {
! 			PyObject *v;
! 			name = STR(fp); 
! 			v = PyDict_GetItemString(c->c_cellvars, name);
! 			if (v) {
! 				com_addoparg(c, LOAD_FAST, narg);
! 				com_addoparg(c, STORE_DEREF, 
! 					     PyInt_AS_LONG(v));
! 			}
! 		} else {
  			name = nbuf;
  			sprintf(nbuf, ".%d", i);
--- 3553,3557 ----
  		REQ(ch, fpdef); /* fpdef: NAME | '(' fplist ')' */
  		fp = CHILD(ch, 0);
! 		if (TYPE(fp) != NAME) {
  			name = nbuf;
  			sprintf(nbuf, ".%d", i);
***************
*** 3577,3621 ****
  			REQ(ch, COMMA);
  	}
- 	/* Handle *arguments */
- 	if (i < nch) {
- 		node *ch;
- 		ch = CHILD(n, i);
- 		if (TYPE(ch) != DOUBLESTAR) {
- 			REQ(ch, STAR);
- 			ch = CHILD(n, i+1);
- 			if (TYPE(ch) == NAME) {
- 				PyObject *v;
- 				i += 3;
- 				v = PyDict_GetItemString(c->c_cellvars,
- 							 STR(ch));
- 				if (v) {
- 					com_addoparg(c, LOAD_FAST, narg);
- 					com_addoparg(c, STORE_DEREF, 
- 						     PyInt_AS_LONG(v));
- 			}
- 				narg++;
- 		}
- 	}
- 	}
- 	/* Handle **keywords */
- 	if (i < nch) {
- 		PyObject *v;
- 		node *ch;
- 		ch = CHILD(n, i);
- 		if (TYPE(ch) != DOUBLESTAR) {
- 			REQ(ch, STAR);
- 			ch = CHILD(n, i+1);
- 			REQ(ch, STAR);
- 			ch = CHILD(n, i+2);
- 		}
- 		else
- 			ch = CHILD(n, i+1);
- 		REQ(ch, NAME);
- 		v = PyDict_GetItemString(c->c_cellvars, STR(ch));
- 		if (v) {
- 			com_addoparg(c, LOAD_FAST, narg);
- 			com_addoparg(c, STORE_DEREF, PyInt_AS_LONG(v));
- 		}			
- 	}
  	if (complex) {
  		/* Generate code for complex arguments only after
--- 3568,3571 ----
***************
*** 4138,4141 ****
--- 4088,4154 ----
  }
  
+ /* If a variable is a cell and an argument, make sure that appears in
+    co_cellvars before any variable to its right in varnames. 
+ */
+ 
+ 
+ static int
+ symtable_cellvar_offsets(PyObject **cellvars, int argcount, 
+ 			 PyObject *varnames, int flags) 
+ {
+ 	PyObject *v, *w, *d, *list = NULL;
+ 	int i, pos;
+ 
+ 	if (flags & CO_VARARGS)
+ 		argcount++;
+ 	if (flags & CO_VARKEYWORDS)
+ 		argcount++;
+ 	for (i = argcount; --i >= 0; ) {
+ 		v = PyList_GET_ITEM(varnames, i);
+ 		if (PyDict_GetItem(*cellvars, v)) {
+ 			if (list == NULL) {
+ 				list = PyList_New(1);
+ 				if (list == NULL)
+ 					return -1;
+ 				PyList_SET_ITEM(list, 0, v);
+ 				Py_INCREF(v);
+ 			} else
+ 				PyList_Insert(list, 0, v);
+ 		}
+ 	}
+ 	if (list == NULL || PyList_GET_SIZE(list) == 0)
+ 		return 0;
+ 	/* There are cellvars that are also arguments.  Create a dict
+ 	   to replace cellvars and put the args at the front.
+ 	*/
+ 	d = PyDict_New();
+ 	for (i = PyList_GET_SIZE(list); --i >= 0; ) {
+ 		v = PyInt_FromLong(i);
+ 		if (v == NULL) 
+ 			goto fail;
+ 		if (PyDict_SetItem(d, PyList_GET_ITEM(list, i), v) < 0)
+ 			goto fail;
+ 		if (PyDict_DelItem(*cellvars, PyList_GET_ITEM(list, i)) < 0)
+ 			goto fail;
+ 	}
+ 	pos = 0;
+ 	i = PyList_GET_SIZE(list);
+ 	Py_DECREF(list);
+ 	while (PyDict_Next(*cellvars, &pos, &v, &w)) {
+ 		w = PyInt_FromLong(i++);  /* don't care about the old key */
+ 		if (PyDict_SetItem(d, v, w) < 0) {
+ 			Py_DECREF(w);
+ 			goto fail;
+ 		}
+ 		Py_DECREF(w);
+ 	}
+ 	Py_DECREF(*cellvars);
+ 	*cellvars = d;
+ 	return 1;
+  fail:
+ 	Py_DECREF(d);
+ 	return -1;
+ }
+ 
  static int
  symtable_freevar_offsets(PyObject *freevars, int offset)
***************
*** 4387,4390 ****
--- 4400,4408 ----
  	}
  
+ 	if (si.si_ncells > 1) { /* one cell is always in order */
+ 		if (symtable_cellvar_offsets(&c->c_cellvars, c->c_argcount,
+ 					     c->c_varnames, c->c_flags) < 0)
+ 			return -1;
+ 	}
  	if (symtable_freevar_offsets(c->c_freevars, si.si_ncells) < 0)
  		return -1;