diff Python/compile.c @ 21037:5981dfdda857 2.1

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.
author Anthony Baxter <anthonybaxter@gmail.com>
date Wed, 21 Nov 2001 06:21:18 +0000
parents 071c957221ec
children
line wrap: on
line diff
--- a/Python/compile.c	Wed Nov 21 05:41:03 2001 +0000
+++ b/Python/compile.c	Wed Nov 21 06:21:18 2001 +0000
@@ -4823,7 +4823,7 @@
 static void
 symtable_node(struct symtable *st, node *n)
 {
-	int i, start = 0;
+	int i;
 
  loop:
 	switch (TYPE(n)) {
@@ -4929,36 +4929,62 @@
 			}
 		}
 		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 @@
 	}
 }
 
+/* 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 @@
 			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 @@
 		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 @@
 		} 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 @@
 		   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);
 	}
 }