[Python-checkins] python/dist/src/Python Python-ast.c, 1.1.2.11,
1.1.2.12 asdl.c, 1.1.2.5, 1.1.2.6 ast.c, 1.1.2.58,
1.1.2.59 compile.c, 2.247.2.2, 2.247.2.3 newcompile.c,
1.1.2.105, 1.1.2.106 symtable.c, 2.10.8.31,
2.10.8.32 compile.txt, 1.1.2.13, 1.1.2.14
bcannon at users.sourceforge.net
bcannon at users.sourceforge.net
Wed Apr 13 21:44:44 CEST 2005
Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12515/Python
Modified Files:
Tag: ast-branch
Python-ast.c asdl.c ast.c compile.c newcompile.c symtable.c
compile.txt
Log Message:
Add support for genexps. Required changing the name to GeneratorExp for
consistency in Parser/Python.asdl (and subsequent changes to other files
because of this), regenerating the Python-ast.(h|c) files, and
then the necessary changes to Python/ast.c and Python/newcompile.c .
Also includes a tweak to asdl_seq_new() to not call malloc() with a -1 if an
empty asdl_seq struct is needed. Lastly, it silences output of the results of
functions while they are doing internal calls; allows doctest to work properly.
Not thoroughly tested since test_grammar segfaults before it reaches genexps.
But hand-testing seems to show everything works.
Closes patch #1167628. Thanks Nick Coghlan.
Index: Python-ast.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/Attic/Python-ast.c,v
retrieving revision 1.1.2.11
retrieving revision 1.1.2.12
diff -u -d -r1.1.2.11 -r1.1.2.12
--- Python-ast.c 2 Apr 2005 18:50:06 -0000 1.1.2.11
+++ Python-ast.c 13 Apr 2005 19:44:37 -0000 1.1.2.12
@@ -1,4 +1,4 @@
-/* File automatically generated by ../Parser/asdl_c.py */
+/* File automatically generated by ./Parser/asdl_c.py */
#include "Python.h"
#include "Python-ast.h"
@@ -651,12 +651,12 @@
}
expr_ty
-GeneratorComp(expr_ty elt, asdl_seq * generators)
+GeneratorExp(expr_ty elt, asdl_seq * generators)
{
expr_ty p;
if (!elt) {
PyErr_SetString(PyExc_ValueError,
- "field elt is required for GeneratorComp");
+ "field elt is required for GeneratorExp");
return NULL;
}
p = (expr_ty)malloc(sizeof(*p));
@@ -664,9 +664,9 @@
PyErr_SetString(PyExc_MemoryError, "no memory");
return NULL;
}
- p->kind = GeneratorComp_kind;
- p->v.GeneratorComp.elt = elt;
- p->v.GeneratorComp.generators = generators;
+ p->kind = GeneratorExp_kind;
+ p->v.GeneratorExp.elt = elt;
+ p->v.GeneratorExp.generators = generators;
return p;
}
@@ -1327,9 +1327,9 @@
free_comprehension((comprehension_ty)asdl_seq_GET(seq,
i));
break;
- case GeneratorComp_kind:
- free_expr((expr_ty)o->v.GeneratorComp.elt);
- seq = o->v.GeneratorComp.generators;
+ case GeneratorExp_kind:
+ free_expr((expr_ty)o->v.GeneratorExp.elt);
+ seq = o->v.GeneratorExp.generators;
n = asdl_seq_LEN(seq);
for (i = 0; i < n; i++)
free_comprehension((comprehension_ty)asdl_seq_GET(seq,
@@ -1927,14 +1927,14 @@
(comprehension_ty)elt);
}
break;
- case GeneratorComp_kind:
+ case GeneratorExp_kind:
marshal_write_int(buf, off, 7);
- marshal_write_expr(buf, off, o->v.GeneratorComp.elt);
+ marshal_write_expr(buf, off, o->v.GeneratorExp.elt);
marshal_write_int(buf, off,
- asdl_seq_LEN(o->v.GeneratorComp.generators));
- for (i = 0; i < asdl_seq_LEN(o->v.GeneratorComp.generators);
+ asdl_seq_LEN(o->v.GeneratorExp.generators));
+ for (i = 0; i < asdl_seq_LEN(o->v.GeneratorExp.generators);
i++) {
- void *elt = asdl_seq_GET(o->v.GeneratorComp.generators,
+ void *elt = asdl_seq_GET(o->v.GeneratorExp.generators,
i);
marshal_write_comprehension(buf, off,
(comprehension_ty)elt);
Index: asdl.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/Attic/asdl.c,v
retrieving revision 1.1.2.5
retrieving revision 1.1.2.6
diff -u -d -r1.1.2.5 -r1.1.2.6
--- asdl.c 3 Apr 2003 00:55:00 -0000 1.1.2.5
+++ asdl.c 13 Apr 2005 19:44:37 -0000 1.1.2.6
@@ -4,21 +4,24 @@
asdl_seq *
asdl_seq_new(int size)
{
- asdl_seq *seq = (asdl_seq *)PyObject_Malloc(sizeof(asdl_seq)
- + sizeof(void *) * (size - 1));
- if (!seq) {
- PyErr_SetString(PyExc_MemoryError, "no memory");
- return NULL;
- }
- seq->size = size;
- seq->offset = 0;
- return seq;
+ asdl_seq *seq = NULL;
+
+ seq = (asdl_seq *)PyObject_Malloc(sizeof(asdl_seq)
+ + (size ? (sizeof(void *) * (size - 1)) : 0));
+
+ if (!seq) {
+ PyErr_SetString(PyExc_MemoryError, "no memory");
+ return NULL;
+ }
+ seq->size = size;
+ seq->offset = 0;
+ return seq;
}
void
asdl_seq_free(asdl_seq *seq)
{
- PyObject_Free(seq);
+ PyObject_Free(seq);
}
#define CHECKSIZE(BUF, OFF, MIN) { \
Index: ast.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/Attic/ast.c,v
retrieving revision 1.1.2.58
retrieving revision 1.1.2.59
diff -u -d -r1.1.2.58 -r1.1.2.59
--- ast.c 2 Apr 2005 19:00:35 -0000 1.1.2.58
+++ ast.c 13 Apr 2005 19:44:37 -0000 1.1.2.59
@@ -986,95 +986,270 @@
return ListComp(elt, listcomps);
}
+/*
+ Count the number of 'for' loops in a generator expression.
+
+ Helper for ast_for_genexp().
+*/
+
+static int
+count_gen_fors(const node *n)
+{
+ int n_fors = 0;
+ node *ch = CHILD(n, 1);
+
+ count_gen_for:
+ n_fors++;
+ REQ(ch, gen_for);
+ if (NCH(ch) == 5)
+ ch = CHILD(ch, 4);
+ else
+ return n_fors;
+ count_gen_iter:
+ REQ(ch, gen_iter);
+ ch = CHILD(ch, 0);
+ if (TYPE(ch) == gen_for)
+ goto count_gen_for;
+ else if (TYPE(ch) == gen_if) {
+ if (NCH(ch) == 3) {
+ ch = CHILD(ch, 2);
+ goto count_gen_iter;
+ }
+ else
+ return n_fors;
+ }
+ else {
+ /* Should never be reached */
+ PyErr_SetString(PyExc_Exception, "logic error in count_gen_fors");
+ return -1;
+ }
+}
+
+/* Count the number of 'if' statements in a generator expression.
+
+ Helper for ast_for_genexp().
+*/
+
+static int
+count_gen_ifs(const node *n)
+{
+ int n_ifs = 0;
+
+ while (1) {
+ REQ(n, gen_iter);
+ if (TYPE(CHILD(n, 0)) == gen_for)
+ return n_ifs;
+ n = CHILD(n, 0);
+ REQ(n, gen_if);
+ n_ifs++;
+ if (NCH(n) == 2)
+ return n_ifs;
+ n = CHILD(n, 2);
+ }
+}
+
+static expr_ty
+ast_for_genexp(struct compiling *c, const node *n)
+{
+ /* testlist_gexp: test ( gen_for | (',' test)* [','] )
+ argument: [test '='] test [gen_for] # Really [keyword '='] test */
+ expr_ty elt;
+ asdl_seq *genexps;
+ int i, n_fors;
+ node *ch;
+
+ assert(TYPE(n) == (testlist_gexp) || TYPE(n) == (argument));
+ assert(NCH(n) > 1);
+
+ elt = ast_for_expr(c, CHILD(n, 0));
+ if (!elt)
+ return NULL;
+
+ n_fors = count_gen_fors(n);
+ if (n_fors == -1)
+ return NULL;
+
+ genexps = asdl_seq_new(n_fors);
+ if (!genexps) {
+ /* XXX free(elt); */
+ return NULL;
+ }
+
+ ch = CHILD(n, 1);
+ for (i = 0; i < n_fors; i++) {
+ comprehension_ty ge;
+ asdl_seq *t;
+ expr_ty expression;
+
+ REQ(ch, gen_for);
+
+ t = ast_for_exprlist(c, CHILD(ch, 1), Store);
+ if (!t) {
+ asdl_seq_free(genexps);
+ /* XXX free(elt); */
+ return NULL;
+ }
+ expression = ast_for_testlist(c, CHILD(ch, 3));
+ if (!expression) {
+ asdl_seq_free(genexps);
+ /* XXX free(elt); */
+ return NULL;
+ }
+
+ if (asdl_seq_LEN(t) == 1)
+ ge = comprehension(asdl_seq_GET(t, 0), expression, NULL);
+ else
+ ge = comprehension(Tuple(t, Store), expression, NULL);
+
+ if (!ge) {
+ asdl_seq_free(genexps);
+ /* XXX free(elt); */
+ return NULL;
+ }
+
+ if (NCH(ch) == 5) {
+ int j, n_ifs;
+ asdl_seq *ifs;
+
+ ch = CHILD(ch, 4);
+ n_ifs = count_gen_ifs(ch);
+ if (n_ifs == -1) {
+ asdl_seq_free(genexps);
+ /* XXX free(elt); */
+ return NULL;
+ }
+
+ ifs = asdl_seq_new(n_ifs);
+ if (!ifs) {
+ asdl_seq_free(genexps);
+ /* XXX free(elt); */
+ return NULL;
+ }
+
+ for (j = 0; j < n_ifs; j++) {
+ REQ(ch, gen_iter);
+
+ ch = CHILD(ch, 0);
+ REQ(ch, gen_if);
+
+ asdl_seq_APPEND(ifs, ast_for_expr(c, CHILD(ch, 1)));
+ if (NCH(ch) == 3)
+ ch = CHILD(ch, 2);
+ }
+ /* on exit, must guarantee that ch is a gen_for */
+ if (TYPE(ch) == gen_iter)
+ ch = CHILD(ch, 0);
+ ge->ifs = ifs;
+ }
+ asdl_seq_APPEND(genexps, ge);
+ }
+
+ return GeneratorExp(elt, genexps);
+}
+
static expr_ty
ast_for_atom(struct compiling *c, const node *n)
{
- /* atom: '(' [testlist] ')' | '[' [listmaker] ']'
- | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
- */
- node *ch = CHILD(n, 0);
+ /* atom: '(' [testlist_gexp] ')' | '[' [listmaker] ']'
+ | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+
+ */
+ node *ch = CHILD(n, 0);
- switch (TYPE(ch)) {
- case NAME:
- /* All names start in Load context, but may later be changed. */
- return Name(NEW_IDENTIFIER(ch), Load);
- case STRING: {
- PyObject *str = parsestrplus(c, n);
+ switch (TYPE(ch)) {
+ case NAME:
+ /* All names start in Load context, but may later be
+ changed. */
+ return Name(NEW_IDENTIFIER(ch), Load);
+ case STRING: {
+ PyObject *str = parsestrplus(c, n);
- if (!str)
- return NULL;
+ if (!str)
+ return NULL;
- return Str(str);
- }
- case NUMBER: {
- PyObject *pynum = parsenumber(STR(ch));
+ return Str(str);
+ }
+ case NUMBER: {
+ PyObject *pynum = parsenumber(STR(ch));
- if (!pynum)
- return NULL;
+ if (!pynum)
+ return NULL;
- return Num(pynum);
- }
- case LPAR: /* some parenthesized expressions */
- return ast_for_testlist(c, CHILD(n, 1));
- case LSQB: /* list (or list comprehension) */
- ch = CHILD(n, 1);
- if (TYPE(ch) == RSQB)
- return List(NULL, Load);
- REQ(ch, listmaker);
- if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
- asdl_seq *elts = seq_for_testlist(c, ch);
+ return Num(pynum);
+ }
+ case LPAR: /* some parenthesized expressions */
+ ch = CHILD(n, 1);
- if (!elts)
- return NULL;
+ if (TYPE(ch) == RPAR)
+ return Tuple(NULL, Load);
- return List(elts, Load);
- }
- else
- return ast_for_listcomp(c, ch);
- case LBRACE: {
- /* dictmaker: test ':' test (',' test ':' test)* [','] */
- int i, size;
- asdl_seq *keys, *values;
+ if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for))
+ return ast_for_genexp(c, ch);
- ch = CHILD(n, 1);
- size = (NCH(ch) + 1) / 4; /* plus one in case no trailing comma */
- keys = asdl_seq_new(size);
- if (!keys)
- return NULL;
- values = asdl_seq_new(size);
- if (!values) {
- asdl_seq_free(keys);
- return NULL;
- }
- for (i = 0; i < NCH(ch); i += 4) {
- expr_ty expression;
+ return ast_for_testlist(c, ch);
+ case LSQB: /* list (or list comprehension) */
+ ch = CHILD(n, 1);
- expression = ast_for_expr(c, CHILD(ch, i));
- if (!expression)
- return NULL;
-
- asdl_seq_SET(keys, i / 4, expression);
+ if (TYPE(ch) == RSQB)
+ return List(NULL, Load);
- expression = ast_for_expr(c, CHILD(ch, i + 2));
- if (!expression)
- return NULL;
-
- asdl_seq_SET(values, i / 4, expression);
- }
- return Dict(keys, values);
- }
- case BACKQUOTE: { /* repr */
- expr_ty expression = ast_for_testlist(c, CHILD(n, 1));
+ REQ(ch, listmaker);
+ if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) {
+ asdl_seq *elts = seq_for_testlist(c, ch);
- if (!expression)
- return NULL;
+ if (!elts)
+ return NULL;
- return Repr(expression);
- }
- default:
- PyErr_Format(PyExc_Exception, "unhandled atom %d", TYPE(ch));
- return NULL;
- }
+ return List(elts, Load);
+ }
+ else
+ return ast_for_listcomp(c, ch);
+ case LBRACE: {
+ /* dictmaker: test ':' test (',' test ':' test)* [','] */
+ int i, size;
+ asdl_seq *keys, *values;
+
+ ch = CHILD(n, 1);
+ size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */
+ keys = asdl_seq_new(size);
+ if (!keys)
+ return NULL;
+
+ values = asdl_seq_new(size);
+ if (!values) {
+ asdl_seq_free(keys);
+ return NULL;
+ }
+
+ for (i = 0; i < NCH(ch); i += 4) {
+ expr_ty expression;
+
+ expression = ast_for_expr(c, CHILD(ch, i));
+ if (!expression)
+ return NULL;
+
+ asdl_seq_SET(keys, i / 4, expression);
+
+ expression = ast_for_expr(c, CHILD(ch, i + 2));
+ if (!expression)
+ return NULL;
+
+ asdl_seq_SET(values, i / 4, expression);
+ }
+ return Dict(keys, values);
+ }
+ case BACKQUOTE: { /* repr */
+ expr_ty expression = ast_for_testlist(c, CHILD(n, 1));
+
+ if (!expression)
+ return NULL;
+
+ return Repr(expression);
+ }
+ default:
+ PyErr_Format(PyExc_Exception, "unhandled atom %d",
+ TYPE(ch));
+ return NULL;
+ }
}
static slice_ty
@@ -1451,17 +1626,22 @@
nargs = 0;
nkeywords = 0;
ngens = 0;
- for (i = 0; i < NCH(n); i++)
- if (TYPE(CHILD(n, i)) == argument) {
- if (NCH(CHILD(n, i)) == 1)
+ for (i = 0; i < NCH(n); i++) {
+ node *ch = CHILD(n, i);
+ if (TYPE(ch) == argument) {
+ if (NCH(ch) == 1)
nargs++;
- else if (TYPE(CHILD(CHILD(n, i), 1)) == gen_for)
+ else if (TYPE(CHILD(ch, 1)) == gen_for)
ngens++;
else
nkeywords++;
}
-
- args = asdl_seq_new(nargs);
+ }
+ if (ngens > 1 || (ngens && (nargs || nkeywords))) {
+ ast_error(n, "Generator expression must be parenthesised if not sole argument");
+ return NULL;
+ }
+ args = asdl_seq_new(nargs + ngens);
if (!args)
goto error;
keywords = asdl_seq_new(nkeywords);
@@ -1479,8 +1659,11 @@
goto error;
asdl_seq_SET(args, nargs++, e);
}
- else if (TYPE(CHILD(CHILD(n, 0), 1)) == gen_for) {
- /* XXX handle generator comp */
+ else if (TYPE(CHILD(ch, 1)) == gen_for) {
+ e = ast_for_genexp(c, ch);
+ if (!e)
+ goto error;
+ asdl_seq_SET(args, nargs++, e);
}
else {
keyword_ty kw;
Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.247.2.2
retrieving revision 2.247.2.3
diff -u -d -r2.247.2.2 -r2.247.2.3
--- compile.c 9 Jul 2002 13:22:01 -0000 2.247.2.2
+++ compile.c 13 Apr 2005 19:44:38 -0000 2.247.2.3
@@ -1157,6 +1157,8 @@
return PyLong_FromString(s, (char **)0, 0);
if (s[0] == '0')
x = (long) PyOS_strtoul(s, &end, 0);
+ if (x < 0 && errno == 0)
+ return PyLong_FromString(s, (char **)0, 0);
else
x = PyOS_strtol(s, &end, 0);
if (*end == '\0') {
Index: newcompile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/Attic/newcompile.c,v
retrieving revision 1.1.2.105
retrieving revision 1.1.2.106
diff -u -d -r1.1.2.105 -r1.1.2.106
--- newcompile.c 2 Apr 2005 18:50:06 -0000 1.1.2.105
+++ newcompile.c 13 Apr 2005 19:44:40 -0000 1.1.2.106
@@ -1388,8 +1388,13 @@
asdl_seq* decos = s->v.FunctionDef.decorators;
stmt_ty st;
int i, n, docstring;
+ int was_interactive = c->c_interactive;
+
assert(s->kind == FunctionDef_kind);
+ /* turn off interim results from within function calls while in
+ interactive mode */
+ c->c_interactive = 0;
if (!compiler_decorators(c, decos))
return 0;
if (args->defaults)
@@ -1443,6 +1448,9 @@
ADDOP_I(c, CALL_FUNCTION, 1);
}
+ /* turn flag back on if was interactive */
+ c->c_interactive = was_interactive;
+
return compiler_nameop(c, s->v.FunctionDef.name, Store);
}
@@ -2558,10 +2566,114 @@
}
static int
-compiler_generatorcomp(struct compiler *c, expr_ty e)
+compiler_genexp_generator(struct compiler *c,
+ asdl_seq *generators, int gen_index,
+ expr_ty elt)
{
- /* XXX handle */
+ /* generate code for the iterator, then each of the ifs,
+ and then write to the element */
+
+ comprehension_ty ge;
+ basicblock *start, *anchor, *skip, *if_cleanup, *end;
+ int i, n;
+
+ start = compiler_new_block(c);
+ skip = compiler_new_block(c);
+ if_cleanup = compiler_new_block(c);
+ anchor = compiler_new_block(c);
+ end = compiler_new_block(c);
+
+ if (start == NULL || skip == NULL || if_cleanup == NULL ||
+ anchor == NULL || end == NULL)
+ return 0;
+
+ ge = asdl_seq_GET(generators, gen_index);
+ ADDOP_JREL(c, SETUP_LOOP, end);
+ if (!compiler_push_fblock(c, LOOP, start))
+ return 0;
+
+ if (gen_index == 0) {
+ /* Receive outermost iter as an implicit argument */
+ c->u->u_argcount = 1;
+ ADDOP_I(c, LOAD_FAST, 0);
+ }
+ else {
+ /* Sub-iter - calculate on the fly */
+ VISIT(c, expr, ge->iter);
+ ADDOP(c, GET_ITER);
+ }
+ compiler_use_next_block(c, start);
+ ADDOP_JREL(c, FOR_ITER, anchor);
+ NEXT_BLOCK(c);
+ VISIT(c, expr, ge->target);
+
+ /* XXX this needs to be cleaned up...a lot! */
+ n = asdl_seq_LEN(ge->ifs);
+ for (i = 0; i < n; i++) {
+ expr_ty e = asdl_seq_GET(ge->ifs, i);
+ VISIT(c, expr, e);
+ ADDOP_JREL(c, JUMP_IF_FALSE, if_cleanup);
+ NEXT_BLOCK(c);
+ ADDOP(c, POP_TOP);
+ }
+
+ if (++gen_index < asdl_seq_LEN(generators))
+ if (!compiler_genexp_generator(c, generators, gen_index, elt))
+ return 0;
+
+ /* only append after the last 'for' generator */
+ if (gen_index >= asdl_seq_LEN(generators)) {
+ VISIT(c, expr, elt);
+ ADDOP(c, YIELD_VALUE);
+
+ compiler_use_next_block(c, skip);
+ }
+ for (i = 0; i < n; i++) {
+ ADDOP_I(c, JUMP_FORWARD, 1);
+ if (i == 0)
+ compiler_use_next_block(c, if_cleanup);
+
+ ADDOP(c, POP_TOP);
+ }
+ ADDOP_JABS(c, JUMP_ABSOLUTE, start);
+ compiler_use_next_block(c, anchor);
+ ADDOP(c, POP_BLOCK);
+ compiler_pop_fblock(c, LOOP, start);
+ compiler_use_next_block(c, end);
+
+ return 1;
+}
+
+static int
+compiler_genexp(struct compiler *c, expr_ty e)
+{
+ PyObject *name;
+ PyCodeObject *co;
+ expr_ty outermost_iter = ((comprehension_ty)
+ (asdl_seq_GET(e->v.GeneratorExp.generators,
+ 0)))->iter;
+
+ name = PyString_FromString("<generator expression>");
+ if (!name)
return 0;
+
+ if (!compiler_enter_scope(c, name, (void *)e, c->u->u_lineno))
+ return 0;
+ compiler_genexp_generator(c, e->v.GeneratorExp.generators, 0,
+ e->v.GeneratorExp.elt);
+ co = assemble(c, 1);
+ if (co == NULL)
+ return 0;
+ compiler_exit_scope(c);
+
+ compiler_make_closure(c, co, 0);
+ VISIT(c, expr, outermost_iter);
+ ADDOP(c, GET_ITER);
+ ADDOP_I(c, CALL_FUNCTION, 1);
+ Py_DECREF(name);
+ Py_DECREF(co);
+
+ return 1;
}
static int
@@ -2626,8 +2738,8 @@
break;
case ListComp_kind:
return compiler_listcomp(c, e);
- case GeneratorComp_kind:
- return compiler_generatorcomp(c, e);
+ case GeneratorExp_kind:
+ return compiler_genexp(c, e);
case Compare_kind:
return compiler_compare(c, e);
case Call_kind:
Index: symtable.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v
retrieving revision 2.10.8.31
retrieving revision 2.10.8.32
diff -u -d -r2.10.8.31 -r2.10.8.32
--- symtable.c 2 Apr 2005 18:50:13 -0000 2.10.8.31
+++ symtable.c 13 Apr 2005 19:44:40 -0000 2.10.8.32
@@ -165,6 +165,7 @@
static int symtable_visit_slice(struct symtable *st, slice_ty);
static int symtable_visit_params(struct symtable *st, asdl_seq *args, int top);
static int symtable_visit_params_nested(struct symtable *st, asdl_seq *args);
+static int symtable_implicit_arg(struct symtable *st, int pos);
static identifier top = NULL, lambda = NULL;
@@ -946,8 +947,7 @@
VISIT_SEQ(st, comprehension, e->v.ListComp.generators);
break;
}
- case GeneratorComp_kind: {
- char tmpname[256];
+ case GeneratorExp_kind: {
identifier tmp;
/* XXX this is correct/complete */
@@ -955,8 +955,11 @@
if (!symtable_enter_block(st, tmp, FunctionBlock,
(void *)e, 0))
return 0;
- VISIT(st, expr, e->v.GeneratorComp.elt);
- VISIT_SEQ(st, comprehension, e->v.GeneratorComp.generators);
+ if (!symtable_implicit_arg(st, 0))
+ return 0;
+ VISIT(st, expr, e->v.GeneratorExp.elt);
+ VISIT_SEQ(st, comprehension, e->v.GeneratorExp.generators);
+ st->st_cur->ste_generator = 1;
symtable_exit_block(st, (void *)e);
break;
}
Index: compile.txt
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/Attic/compile.txt,v
retrieving revision 1.1.2.13
retrieving revision 1.1.2.14
diff -u -d -r1.1.2.13 -r1.1.2.14
--- compile.txt 2 Apr 2005 20:21:23 -0000 1.1.2.13
+++ compile.txt 13 Apr 2005 19:44:40 -0000 1.1.2.14
@@ -447,11 +447,7 @@
+ Grammar support (Parser/Python.asdl, Parser/asdl_c.py)
- empty base class list (``class Class(): pass``)
-+ parse tree->AST support (Python/ast.c)
- - generator expressions
-+ AST->bytecode support (Python/newcompile.c)
- - generator expressions
-+ Stdlib support
+ Stdlib support
- AST->Python access?
- rewrite compiler package to mirror AST structure?
+ Documentation
@@ -459,8 +455,6 @@
* byte stream output
* explanation of how symbol table pass works
+ Universal
- - remove "generator comprehension" mentions and change to "generator
- expression"
- make sure entire test suite passes
- fix memory leaks
- make sure return types are properly checked for errors
More information about the Python-checkins
mailing list