Commit 3562f871 authored by Jeremy Hylton's avatar Jeremy Hylton

Fix for SF [ 734869 ] Lambda functions in list comprehensions

The compiler was reseting the list comprehension tmpname counter for each function, but the symtable was using the same counter for the entire module.  Repair by move tmpname into the symtable entry.

Bugfix candidate.
parent fb5a375c
...@@ -28,7 +28,6 @@ struct symtable { ...@@ -28,7 +28,6 @@ struct symtable {
int st_nscopes; /* number of scopes */ int st_nscopes; /* number of scopes */
int st_errors; /* number of errors */ int st_errors; /* number of errors */
char *st_private; /* name of current class or NULL */ char *st_private; /* name of current class or NULL */
int st_tmpname; /* temporary name counter */
PyFutureFeatures *st_future; /* module's future features */ PyFutureFeatures *st_future; /* module's future features */
}; };
...@@ -47,6 +46,7 @@ typedef struct _symtable_entry { ...@@ -47,6 +46,7 @@ typedef struct _symtable_entry {
including free refs to globals */ including free refs to globals */
int ste_generator; /* true if namespace is a generator */ int ste_generator; /* true if namespace is a generator */
int ste_opt_lineno; /* lineno of last exec or import * */ int ste_opt_lineno; /* lineno of last exec or import * */
int ste_tmpname; /* temporary name counter */
struct symtable *ste_table; struct symtable *ste_table;
} PySymtableEntryObject; } PySymtableEntryObject;
......
...@@ -60,6 +60,7 @@ classdef ...@@ -60,6 +60,7 @@ classdef
[3, 4, 5] [3, 4, 5]
[(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')] [(1, 'Apple'), (1, 'Banana'), (1, 'Coconut'), (2, 'Apple'), (2, 'Banana'), (2, 'Coconut'), (3, 'Apple'), (3, 'Banana'), (3, 'Coconut'), (4, 'Apple'), (4, 'Banana'), (4, 'Coconut'), (5, 'Apple'), (5, 'Banana'), (5, 'Coconut')]
[(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), (5, 'Banana'), (5, 'Coconut')] [(1, 'Banana'), (1, 'Coconut'), (2, 'Banana'), (2, 'Coconut'), (3, 'Banana'), (3, 'Coconut'), (4, 'Banana'), (4, 'Coconut'), (5, 'Banana'), (5, 'Coconut')]
[[1], [1, 1], [1, 2, 4], [1, 3, 9, 27], [1, 4, 16, 64, 256]]
[False, False, False] [False, False, False]
[[1, 2], [3, 4], [5, 6]] [[1, 2], [3, 4], [5, 6]]
[('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), ('Macdonalds', 'Cheeseburger')] [('Boeing', 'Airliner'), ('Boeing', 'Engine'), ('Ford', 'Engine'), ('Macdonalds', 'Cheeseburger')]
...@@ -701,6 +701,7 @@ print [3 * x for x in nums] ...@@ -701,6 +701,7 @@ print [3 * x for x in nums]
print [x for x in nums if x > 2] print [x for x in nums if x > 2]
print [(i, s) for i in nums for s in strs] print [(i, s) for i in nums for s in strs]
print [(i, s) for i in nums for s in [f for f in strs if "n" in f]] print [(i, s) for i in nums for s in [f for f in strs if "n" in f]]
print [(lambda a:[a**i for i in range(a+1)])(j) for j in range(5)]
def test_in_func(l): def test_in_func(l):
return [None < x < 3 for x in l if x > 2] return [None < x < 3 for x in l if x > 2]
......
...@@ -731,6 +731,7 @@ static void symtable_global(struct symtable *, node *); ...@@ -731,6 +731,7 @@ static void symtable_global(struct symtable *, node *);
static void symtable_import(struct symtable *, node *); static void symtable_import(struct symtable *, node *);
static void symtable_assign(struct symtable *, node *, int); static void symtable_assign(struct symtable *, node *, int);
static void symtable_list_comprehension(struct symtable *, node *); static void symtable_list_comprehension(struct symtable *, node *);
static void symtable_list_for(struct symtable *, node *);
static int symtable_update_free_vars(struct symtable *); static int symtable_update_free_vars(struct symtable *);
static int symtable_undo_free(struct symtable *, PyObject *, PyObject *); static int symtable_undo_free(struct symtable *, PyObject *, PyObject *);
...@@ -1602,6 +1603,8 @@ com_list_comprehension(struct compiling *c, node *n) ...@@ -1602,6 +1603,8 @@ com_list_comprehension(struct compiling *c, node *n)
{ {
/* listmaker: test list_for */ /* listmaker: test list_for */
char tmpname[30]; char tmpname[30];
REQ(n, listmaker);
PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->c_tmpname); PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", ++c->c_tmpname);
com_addoparg(c, BUILD_LIST, 0); com_addoparg(c, BUILD_LIST, 0);
com_addbyte(c, DUP_TOP); /* leave the result on the stack */ com_addbyte(c, DUP_TOP); /* leave the result on the stack */
...@@ -4921,7 +4924,6 @@ symtable_init() ...@@ -4921,7 +4924,6 @@ symtable_init()
st->st_cur = NULL; st->st_cur = NULL;
st->st_nscopes = 0; st->st_nscopes = 0;
st->st_errors = 0; st->st_errors = 0;
st->st_tmpname = 0;
st->st_private = NULL; st->st_private = NULL;
return st; return st;
fail: fail:
...@@ -5123,9 +5125,6 @@ symtable_enter_scope(struct symtable *st, char *name, int type, ...@@ -5123,9 +5125,6 @@ symtable_enter_scope(struct symtable *st, char *name, int type,
if (st->st_cur) { if (st->st_cur) {
prev = st->st_cur; prev = st->st_cur;
if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) { if (PyList_Append(st->st_stack, (PyObject *)st->st_cur) < 0) {
/* Py_DECREF(st->st_cur); */
/* I believe the previous line would lead to a
double-DECREF when st is disposed - JRH */
st->st_errors++; st->st_errors++;
return; return;
} }
...@@ -5395,12 +5394,12 @@ symtable_node(struct symtable *st, node *n) ...@@ -5395,12 +5394,12 @@ symtable_node(struct symtable *st, node *n)
} }
goto loop; goto loop;
case list_iter: case list_iter:
/* only occurs when there are multiple for loops
in a list comprehension */
n = CHILD(n, 0); n = CHILD(n, 0);
if (TYPE(n) == list_for) { if (TYPE(n) == list_for)
st->st_tmpname++; symtable_list_for(st, n);
symtable_list_comprehension(st, n); else {
st->st_tmpname--;
} else {
REQ(n, list_if); REQ(n, list_if);
symtable_node(st, CHILD(n, 1)); symtable_node(st, CHILD(n, 1));
if (NCH(n) == 3) { if (NCH(n) == 3) {
...@@ -5428,10 +5427,7 @@ symtable_node(struct symtable *st, node *n) ...@@ -5428,10 +5427,7 @@ symtable_node(struct symtable *st, node *n)
/* fall through */ /* fall through */
case listmaker: case listmaker:
if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == list_for) { if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == list_for) {
st->st_tmpname++; symtable_list_comprehension(st, n);
symtable_list_comprehension(st, CHILD(n, 1));
symtable_node(st, CHILD(n, 0));
st->st_tmpname--;
break; break;
} }
/* fall through */ /* fall through */
...@@ -5629,10 +5625,23 @@ symtable_global(struct symtable *st, node *n) ...@@ -5629,10 +5625,23 @@ symtable_global(struct symtable *st, node *n)
static void static void
symtable_list_comprehension(struct symtable *st, node *n) symtable_list_comprehension(struct symtable *st, node *n)
{ {
/* listmaker: test list_for */
char tmpname[30]; char tmpname[30];
PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]", st->st_tmpname); REQ(n, listmaker);
PyOS_snprintf(tmpname, sizeof(tmpname), "_[%d]",
++st->st_cur->ste_tmpname);
symtable_add_def(st, tmpname, DEF_LOCAL); symtable_add_def(st, tmpname, DEF_LOCAL);
symtable_list_for(st, CHILD(n, 1));
symtable_node(st, CHILD(n, 0));
--st->st_cur->ste_tmpname;
}
static void
symtable_list_for(struct symtable *st, node *n)
{
REQ(n, list_for);
/* list_for: for v in expr [list_iter] */
symtable_assign(st, CHILD(n, 1), 0); symtable_assign(st, CHILD(n, 1), 0);
symtable_node(st, CHILD(n, 3)); symtable_node(st, CHILD(n, 3));
if (NCH(n) == 5) if (NCH(n) == 5)
......
...@@ -61,6 +61,7 @@ PySymtableEntry_New(struct symtable *st, char *name, int type, int lineno) ...@@ -61,6 +61,7 @@ PySymtableEntry_New(struct symtable *st, char *name, int type, int lineno)
ste->ste_optimized = 0; ste->ste_optimized = 0;
ste->ste_opt_lineno = 0; ste->ste_opt_lineno = 0;
ste->ste_tmpname = 0;
ste->ste_lineno = lineno; ste->ste_lineno = lineno;
switch (type) { switch (type) {
case funcdef: case funcdef:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment