diff options
| author | Anthony Baxter <anthonybaxter@gmail.com> | 2001-11-21 06:21:18 (GMT) |
|---|---|---|
| committer | Anthony Baxter <anthonybaxter@gmail.com> | 2001-11-21 06:21:18 (GMT) |
| commit | 55aa02bb43b9d4ccce62f673057a4d461e2248a6 (patch) | |
| tree | 22737e06a5d3cc7d34f2ae8ace3d74a7bb09c0f5 /Python | |
| parent | d2d88aedce3c1fa07d7def9ae2b54b9a461d8b55 (diff) | |
| download | cpython-55aa02bb43b9d4ccce62f673057a4d461e2248a6.zip cpython-55aa02bb43b9d4ccce62f673057a4d461e2248a6.tar.gz cpython-55aa02bb43b9d4ccce62f673057a4d461e2248a6.tar.bz2 | |
backport of jeremy's 2.227:
Fix for SF bug [ #471928 ] global made w/nested list comprehensions
. Initially I was going to just rip out the bits of this that fixed this
bug, but the rest of the code looks (after a fair amount of staring at
it) like it's ok - variable renames, that sort of thing.
flames and "hey, no way!" to me, or to python-dev.
It felt safer to just go with the full patch, rather than butchering
it.
Diffstat (limited to 'Python')
| -rw-r--r-- | Python/compile.c | 70 |
1 files changed, 51 insertions, 19 deletions
diff --git a/Python/compile.c b/Python/compile.c index 7af8433..088b766 100644 --- a/Python/compile.c +++ b/Python/compile.c @@ -4823,7 +4823,7 @@ symtable_add_def_o(struct symtable *st, PyObject *dict, static void symtable_node(struct symtable *st, node *n) { - int i, start = 0; + int i; loop: switch (TYPE(n)) { @@ -4929,36 +4929,62 @@ symtable_node(struct symtable *st, node *n) } } goto loop; - /* watchout for fall-through logic below */ + case list_iter: + n = CHILD(n, 0); + if (TYPE(n) == list_for) { + st->st_tmpname++; + symtable_list_comprehension(st, n); + st->st_tmpname--; + } else { + REQ(n, list_if); + symtable_node(st, CHILD(n, 1)); + if (NCH(n) == 3) { + n = CHILD(n, 2); + goto loop; + } + } + break; + case for_stmt: + symtable_assign(st, CHILD(n, 1), 0); + for (i = 3; i < NCH(n); ++i) + if (TYPE(CHILD(n, i)) >= single_input) + symtable_node(st, CHILD(n, i)); + break; + /* The remaining cases fall through to default except in + special circumstances. This requires the individual cases + to be coded with great care, even though they look like + rather innocuous. Each case must double-check TYPE(n). + */ case argument: - if (NCH(n) == 3) { + if (TYPE(n) == argument && NCH(n) == 3) { n = CHILD(n, 2); goto loop; } + /* fall through */ case listmaker: if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == list_for) { st->st_tmpname++; symtable_list_comprehension(st, CHILD(n, 1)); symtable_node(st, CHILD(n, 0)); st->st_tmpname--; - return; + break; } + /* fall through */ case atom: if (TYPE(n) == atom && TYPE(CHILD(n, 0)) == NAME) { symtable_add_use(st, STR(CHILD(n, 0))); break; } - case for_stmt: - if (TYPE(n) == for_stmt) { - symtable_assign(st, CHILD(n, 1), 0); - start = 3; - } + /* fall through */ default: + /* Walk over every non-token child with a special case + for one child. + */ if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } - for (i = start; i < NCH(n); ++i) + for (i = 0; i < NCH(n); ++i) if (TYPE(CHILD(n, i)) >= single_input) symtable_node(st, CHILD(n, i)); } @@ -5189,8 +5215,14 @@ symtable_import(struct symtable *st, node *n) } } +/* The third argument to symatble_assign() is a flag to be passed to + symtable_add_def() if it is eventually called. The flag is useful + to specify the particular type of assignment that should be + recorded, e.g. an assignment caused by import. + */ + static void -symtable_assign(struct symtable *st, node *n, int flag) +symtable_assign(struct symtable *st, node *n, int def_flag) { node *tmp; int i; @@ -5222,7 +5254,7 @@ symtable_assign(struct symtable *st, node *n, int flag) return; } else { for (i = 0; i < NCH(n); i += 2) - symtable_assign(st, CHILD(n, i), flag); + symtable_assign(st, CHILD(n, i), def_flag); } return; case exprlist: @@ -5234,7 +5266,7 @@ symtable_assign(struct symtable *st, node *n, int flag) else { int i; for (i = 0; i < NCH(n); i += 2) - symtable_assign(st, CHILD(n, i), flag); + symtable_assign(st, CHILD(n, i), def_flag); return; } goto loop; @@ -5246,24 +5278,24 @@ symtable_assign(struct symtable *st, node *n, int flag) } else if (TYPE(tmp) == NAME) { if (strcmp(STR(tmp), "__debug__") == 0) symtable_warn(st, ASSIGN_DEBUG); - symtable_add_def(st, STR(tmp), DEF_LOCAL | flag); + symtable_add_def(st, STR(tmp), DEF_LOCAL | def_flag); } return; case dotted_as_name: if (NCH(n) == 3) symtable_add_def(st, STR(CHILD(n, 2)), - DEF_LOCAL | flag); + DEF_LOCAL | def_flag); else symtable_add_def(st, STR(CHILD(CHILD(n, 0), 0)), - DEF_LOCAL | flag); + DEF_LOCAL | def_flag); return; case dotted_name: - symtable_add_def(st, STR(CHILD(n, 0)), DEF_LOCAL | flag); + symtable_add_def(st, STR(CHILD(n, 0)), DEF_LOCAL | def_flag); return; case NAME: - symtable_add_def(st, STR(n), DEF_LOCAL | flag); + symtable_add_def(st, STR(n), DEF_LOCAL | def_flag); return; default: if (NCH(n) == 0) @@ -5276,6 +5308,6 @@ symtable_assign(struct symtable *st, node *n, int flag) which will be caught in the next pass. */ for (i = 0; i < NCH(n); ++i) if (TYPE(CHILD(n, i)) >= single_input) - symtable_assign(st, CHILD(n, i), flag); + symtable_assign(st, CHILD(n, i), def_flag); } } |
