Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7889107

Browse files
committed
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.
1 parent a52e8fe commit 7889107

1 file changed

Lines changed: 31 additions & 15 deletions

File tree

Python/compile.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,8 @@ code_hash(PyCodeObject *co)
179179
return h;
180180
}
181181

182+
/* XXX code objects need to participate in GC? */
183+
182184
PyTypeObject PyCode_Type = {
183185
PyObject_HEAD_INIT(&PyType_Type)
184186
0,
@@ -2132,8 +2134,13 @@ com_make_closure(struct compiling *c, PyCodeObject *co)
21322134
else /* (reftype == FREE) */
21332135
arg = com_lookup_arg(c->c_freevars, name);
21342136
if (arg == -1) {
2135-
fprintf(stderr, "lookup %s in %s %d %d\n",
2136-
PyObject_REPR(name), c->c_name, reftype, arg);
2137+
fprintf(stderr, "lookup %s in %s %d %d\n"
2138+
"freevars of %s: %s\n",
2139+
PyObject_REPR(name),
2140+
c->c_name,
2141+
reftype, arg,
2142+
PyString_AS_STRING(co->co_name),
2143+
PyObject_REPR(co->co_freevars));
21372144
Py_FatalError("com_make_closure()");
21382145
}
21392146
com_addoparg(c, LOAD_CLOSURE, arg);
@@ -4424,8 +4431,8 @@ symtable_update_free_vars(struct symtable *st)
44244431
child = (PySymtableEntryObject *)
44254432
PyList_GET_ITEM(ste->ste_children, i);
44264433
while (PyDict_Next(child->ste_symbols, &pos, &name, &o)) {
4427-
int v = PyInt_AS_LONG(o);
4428-
if (!(is_free(v)))
4434+
int flags = PyInt_AS_LONG(o);
4435+
if (!(is_free(flags)))
44294436
continue; /* avoids indentation */
44304437
if (list == NULL) {
44314438
list = PyList_New(0);
@@ -4438,18 +4445,24 @@ symtable_update_free_vars(struct symtable *st)
44384445
return -1;
44394446
}
44404447
}
4441-
/*
4442-
if (st->st_nested_scopes == 0
4443-
&& list && PyList_GET_SIZE(list) > 0) {
4444-
fprintf(stderr, "function %s has children with "
4445-
"the following free vars:\n%s\n",
4446-
PyString_AS_STRING(ste->ste_name),
4447-
PyObject_REPR(list));
4448-
continue;
4449-
}
4450-
*/
44514448
for (j = 0; list && j < PyList_GET_SIZE(list); j++) {
4449+
PyObject *v;
44524450
name = PyList_GET_ITEM(list, j);
4451+
v = PyDict_GetItem(ste->ste_symbols, name);
4452+
/* If a name N is declared global in scope A and
4453+
referenced in scope B contained (perhaps
4454+
indirectly) in A and there are no scopes
4455+
with bindings for N between B and A, then N
4456+
is global in B.
4457+
*/
4458+
if (v) {
4459+
int flags = PyInt_AS_LONG(v);
4460+
if (flags & DEF_GLOBAL) {
4461+
symtable_undo_free(st, child->ste_id,
4462+
name);
4463+
continue;
4464+
}
4465+
}
44534466
if (ste->ste_nested) {
44544467
if (symtable_add_def_o(st, ste->ste_symbols,
44554468
name, def) < 0) {
@@ -4481,13 +4494,14 @@ symtable_check_global(struct symtable *st, PyObject *child, PyObject *name)
44814494
PyObject *o;
44824495
int v;
44834496
PySymtableEntryObject *ste = st->st_cur;
4484-
4497+
44854498
if (ste->ste_type == TYPE_CLASS)
44864499
return symtable_undo_free(st, child, name);
44874500
o = PyDict_GetItem(ste->ste_symbols, name);
44884501
if (o == NULL)
44894502
return symtable_undo_free(st, child, name);
44904503
v = PyInt_AS_LONG(o);
4504+
44914505
if (is_free(v) || (v & DEF_GLOBAL))
44924506
return symtable_undo_free(st, child, name);
44934507
else
@@ -4506,6 +4520,7 @@ symtable_undo_free(struct symtable *st, PyObject *id,
45064520
ste = (PySymtableEntryObject *)PyDict_GetItem(st->st_symbols, id);
45074521
if (ste == NULL)
45084522
return -1;
4523+
45094524
info = PyDict_GetItem(ste->ste_symbols, name);
45104525
if (info == NULL)
45114526
return 0;
@@ -4938,6 +4953,7 @@ symtable_global(struct symtable *st, node *n)
49384953
int i;
49394954

49404955
if (st->st_nscopes == 1) {
4956+
/* XXX must check that we are compiling file_input */
49414957
if (symtable_warn(st,
49424958
"global statement has no meaning at module level") < 0)
49434959
return;

0 commit comments

Comments
 (0)