Index: Python/asdl.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/asdl.c,v retrieving revision 1.1.2.5 diff -c -w -r1.1.2.5 asdl.c *** Python/asdl.c 3 Apr 2003 00:55:00 -0000 1.1.2.5 --- Python/asdl.c 22 Mar 2005 03:59:25 -0000 *************** *** 4,11 **** 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; --- 4,17 ---- asdl_seq * asdl_seq_new(int size) { ! asdl_seq *seq = NULL; ! ! if (size) { ! seq = (asdl_seq *)PyObject_Malloc(sizeof(asdl_seq) + sizeof(void *) * (size - 1)); + } else { + seq = (asdl_seq *)PyObject_Malloc(sizeof(asdl_seq)); + } if (!seq) { PyErr_SetString(PyExc_MemoryError, "no memory"); return NULL; Index: Python/ast.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/ast.c,v retrieving revision 1.1.2.56 diff -c -w -r1.1.2.56 ast.c *** Python/ast.c 21 Mar 2005 00:00:54 -0000 1.1.2.56 --- Python/ast.c 22 Mar 2005 03:59:26 -0000 *************** *** 827,836 **** return ListComp(elt, listcomps); } 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); --- 827,996 ---- return ListComp(elt, listcomps); } + /* Count the number of 'for' loop 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 list comprehension. + + Helper for ast_for_listcomp(). + */ + + static int + count_gen_ifs(const node *n) + { + int n_ifs = 0; + + count_gen_iter: + 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); + goto count_gen_iter; + } + + 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 GeneratorComp(elt, genexps); + } + static expr_ty ast_for_atom(struct compiling *c, const node *n) { ! /* atom: '(' [testlist_gexp] ')' | '[' [listmaker] ']' | '{' [dictmaker] '}' | '`' testlist '`' | NAME | NUMBER | STRING+ */ node *ch = CHILD(n, 0); *************** *** 856,862 **** 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) --- 1016,1028 ---- return Num(pynum); } case LPAR: /* some parenthesized expressions */ ! ch = CHILD(n, 1); ! if (TYPE(ch) == RPAR) ! return Tuple(NULL, Load); ! if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for)) { ! return ast_for_genexp(c, ch); ! } ! return ast_for_testlist(c, ch); case LSQB: /* list (or list comprehension) */ ch = CHILD(n, 1); if (TYPE(ch) == RSQB) *************** *** 1292,1308 **** 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) nargs++; ! else if (TYPE(CHILD(CHILD(n, i), 1)) == gen_for) ngens++; else nkeywords++; } ! ! args = asdl_seq_new(nargs); if (!args) goto error; keywords = asdl_seq_new(nkeywords); --- 1458,1479 ---- nargs = 0; nkeywords = 0; ngens = 0; ! 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(ch, 1)) == gen_for) ngens++; else nkeywords++; } ! } ! 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); *************** *** 1320,1327 **** goto error; asdl_seq_SET(args, nargs++, e); } ! else if (TYPE(CHILD(CHILD(n, 0), 1)) == gen_for) { ! /* XXX handle generator comp */ } else { keyword_ty kw; --- 1491,1501 ---- goto error; asdl_seq_SET(args, nargs++, e); } ! 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; *************** *** 1356,1361 **** --- 1530,1536 ---- /* XXX syntax error if more than 255 arguments */ return Call(func, args, keywords, vararg, kwarg); + error: if (args) asdl_seq_free(args); Index: Python/compile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v retrieving revision 2.247.2.2 diff -c -w -r2.247.2.2 compile.c *** Python/compile.c 9 Jul 2002 13:22:01 -0000 2.247.2.2 --- Python/compile.c 22 Mar 2005 03:59:33 -0000 *************** *** 1157,1162 **** --- 1157,1164 ---- 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: Python/newcompile.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/Attic/newcompile.c,v retrieving revision 1.1.2.103 diff -c -w -r1.1.2.103 newcompile.c *** Python/newcompile.c 19 Feb 2005 03:42:35 -0000 1.1.2.103 --- Python/newcompile.c 22 Mar 2005 03:59:41 -0000 *************** *** 1226,1233 **** --- 1226,1235 ---- arguments_ty args = s->v.FunctionDef.args; stmt_ty st; int i, n, docstring; + int was_interactive = c->c_interactive; assert(s->kind == FunctionDef_kind); + c->c_interactive = 0; if (args->defaults) VISIT_SEQ(c, expr, args->defaults); if (!compiler_enter_scope(c, s->v.FunctionDef.name, (void *)s, *************** *** 1274,1279 **** --- 1276,1282 ---- compiler_exit_scope(c); compiler_make_closure(c, co, asdl_seq_LEN(args->defaults)); + c->c_interactive = was_interactive; return compiler_nameop(c, s->v.FunctionDef.name, Store); } *************** *** 2389,2398 **** } static int compiler_generatorcomp(struct compiler *c, expr_ty e) { ! /* XXX handle */ return 0; } static int --- 2392,2499 ---- } static int + compiler_genexp_generator(struct compiler *c, + asdl_seq *generators, int gen_index, + expr_ty elt) + { + /* 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_generatorcomp(struct compiler *c, expr_ty e) { ! PyObject *name; ! PyCodeObject *co; ! expr_ty outermost_iter = ((comprehension_ty)(asdl_seq_GET(e->v.GeneratorComp.generators, 0)))->iter; ! ! name = PyString_FromString(""); ! if (!name) return 0; + + if (!compiler_enter_scope(c, name, (void *)e, c->u->u_lineno)) + return 0; + compiler_genexp_generator(c, e->v.GeneratorComp.generators, 0, e->v.GeneratorComp.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 Index: Python/symtable.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/symtable.c,v retrieving revision 2.10.8.30 diff -c -w -r2.10.8.30 symtable.c *** Python/symtable.c 16 Jan 2005 17:09:12 -0000 2.10.8.30 --- Python/symtable.c 22 Mar 2005 03:59:47 -0000 *************** *** 165,170 **** --- 165,171 ---- 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; *************** *** 945,951 **** break; } case GeneratorComp_kind: { - char tmpname[256]; identifier tmp; /* XXX this is correct/complete */ --- 946,951 ---- *************** *** 953,960 **** --- 953,963 ---- if (!symtable_enter_block(st, tmp, FunctionBlock, (void *)e, 0)) return 0; + if (!symtable_implicit_arg(st, 0)) + return 0; VISIT(st, expr, e->v.GeneratorComp.elt); VISIT_SEQ(st, comprehension, e->v.GeneratorComp.generators); + st->st_cur->ste_generator = 1; symtable_exit_block(st, (void *)e); break; }