[Python-checkins] CVS: python/dist/src/Python compile.c,2.183,2.184

Jeremy Hylton jhylton@users.sourceforge.net
Wed, 28 Feb 2001 22:09:36 -0800


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

Modified Files:
	compile.c 
Log Message:
Fix core dump in example from Samuele Pedroni:

from __future__ import nested_scopes
x=7
def f():
    x=1
    def g():
        global x
        def i():
            def h():
                return x
            return h()
        return i()
    return g()

print f()
print x

This kind of code didn't work correctly because x was treated as free
in i, leading to an attempt to load x in g to make a closure for i.

Solution is to make global decl apply to nested scopes unless their is
an assignment.  Thus, x in h is global.



Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.183
retrieving revision 2.184
diff -C2 -r2.183 -r2.184
*** compile.c	2001/03/01 00:42:55	2.183
--- compile.c	2001/03/01 06:09:34	2.184
***************
*** 180,183 ****
--- 180,185 ----
  }
  
+ /* XXX code objects need to participate in GC? */
+ 
  PyTypeObject PyCode_Type = {
  	PyObject_HEAD_INIT(&PyType_Type)
***************
*** 2133,2138 ****
  			arg = com_lookup_arg(c->c_freevars, name);
  		if (arg == -1) {
! 			fprintf(stderr, "lookup %s in %s %d %d\n",
! 				PyObject_REPR(name), c->c_name, reftype, arg);
  			Py_FatalError("com_make_closure()");
  		}
--- 2135,2145 ----
  			arg = com_lookup_arg(c->c_freevars, name);
  		if (arg == -1) {
! 			fprintf(stderr, "lookup %s in %s %d %d\n"
! 				"freevars of %s: %s\n",
! 				PyObject_REPR(name), 
! 				c->c_name, 
! 				reftype, arg,
! 				PyString_AS_STRING(co->co_name),
! 				PyObject_REPR(co->co_freevars));
  			Py_FatalError("com_make_closure()");
  		}
***************
*** 4425,4430 ****
  			PyList_GET_ITEM(ste->ste_children, i);
  		while (PyDict_Next(child->ste_symbols, &pos, &name, &o)) {
! 			int v = PyInt_AS_LONG(o);
! 			if (!(is_free(v)))
  				continue; /* avoids indentation */
  			if (list == NULL) {
--- 4432,4437 ----
  			PyList_GET_ITEM(ste->ste_children, i);
  		while (PyDict_Next(child->ste_symbols, &pos, &name, &o)) {
! 			int flags = PyInt_AS_LONG(o);
! 			if (!(is_free(flags)))
  				continue; /* avoids indentation */
  			if (list == NULL) {
***************
*** 4439,4454 ****
  			}
  		}
- /*
- 		if (st->st_nested_scopes == 0 
- 		    && list && PyList_GET_SIZE(list) > 0) {
- 			fprintf(stderr, "function %s has children with "
- 				"the following free vars:\n%s\n",
- 				PyString_AS_STRING(ste->ste_name),
- 				PyObject_REPR(list));
- 			continue; 
- 		}
- */
  		for (j = 0; list && j < PyList_GET_SIZE(list); j++) {
  			name = PyList_GET_ITEM(list, j);
  			if (ste->ste_nested) {
  				if (symtable_add_def_o(st, ste->ste_symbols,
--- 4446,4467 ----
  			}
  		}
  		for (j = 0; list && j < PyList_GET_SIZE(list); j++) {
+ 			PyObject *v;
  			name = PyList_GET_ITEM(list, j);
+ 			v = PyDict_GetItem(ste->ste_symbols, name);
+ 			/* If a name N is declared global in scope A and
+ 			   referenced in scope B contained (perhaps
+ 			   indirectly) in A and there are no scopes
+ 			   with bindings for N between B and A, then N
+ 			   is global in B.
+ 			*/
+ 			if (v) {
+ 				int flags = PyInt_AS_LONG(v); 
+ 				if (flags & DEF_GLOBAL) {
+ 					symtable_undo_free(st, child->ste_id,
+ 							   name);
+ 					continue;
+ 				}
+ 			}
  			if (ste->ste_nested) {
  				if (symtable_add_def_o(st, ste->ste_symbols,
***************
*** 4482,4486 ****
  	int v;
  	PySymtableEntryObject *ste = st->st_cur;
! 
  	if (ste->ste_type == TYPE_CLASS)
  		return symtable_undo_free(st, child, name);
--- 4495,4499 ----
  	int v;
  	PySymtableEntryObject *ste = st->st_cur;
! 			
  	if (ste->ste_type == TYPE_CLASS)
  		return symtable_undo_free(st, child, name);
***************
*** 4489,4492 ****
--- 4502,4506 ----
  		return symtable_undo_free(st, child, name);
  	v = PyInt_AS_LONG(o);
+ 
  	if (is_free(v) || (v & DEF_GLOBAL)) 
  		return symtable_undo_free(st, child, name);
***************
*** 4507,4510 ****
--- 4521,4525 ----
  	if (ste == NULL)
  		return -1;
+ 
  	info = PyDict_GetItem(ste->ste_symbols, name);
  	if (info == NULL)
***************
*** 4939,4942 ****
--- 4954,4958 ----
  
  	if (st->st_nscopes == 1) {
+ 		/* XXX must check that we are compiling file_input */
  		if (symtable_warn(st, 
  		  "global statement has no meaning at module level") < 0)