diff options
Diffstat (limited to 'Python/ast.c')
-rw-r--r-- | Python/ast.c | 695 |
1 files changed, 406 insertions, 289 deletions
diff --git a/Python/ast.c b/Python/ast.c index 574a3d817c..88e47450b6 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -31,7 +31,7 @@ static asdl_seq *ast_for_exprlist(struct compiling *, const node *, expr_context_ty); static expr_ty ast_for_testlist(struct compiling *, const node *); static stmt_ty ast_for_classdef(struct compiling *, const node *, asdl_seq *); -static expr_ty ast_for_testlist_gexp(struct compiling *, const node *); +static expr_ty ast_for_testlist_comp(struct compiling *, const node *); /* Note different signature for ast_for_call */ static expr_ty ast_for_call(struct compiling *, const node *, expr_ty); @@ -44,6 +44,9 @@ static PyObject *parsestrplus(struct compiling *, const node *n); #define LINENO(n) ((n)->n_lineno) #endif +#define COMP_GENEXP 0 +#define COMP_SETCOMP 1 + static identifier new_identifier(const char* n, PyArena *arena) { PyObject* id = PyString_InternFromString(n); @@ -131,10 +134,17 @@ static int forbidden_check(struct compiling *c, const node *n, const char *x) { if (!strcmp(x, "None")) - return ast_error(n, "assignment to None"); - if (Py_Py3kWarningFlag && !(strcmp(x, "True") && strcmp(x, "False")) && - !ast_warn(c, n, "assignment to True or False is forbidden in 3.x")) - return 0; + return ast_error(n, "cannot assign to None"); + if (!strcmp(x, "__debug__")) + return ast_error(n, "cannot assign to __debug__"); + if (Py_Py3kWarningFlag) { + if (!(strcmp(x, "True") && strcmp(x, "False")) && + !ast_warn(c, n, "assignment to True or False is forbidden in 3.x")) + return 0; + if (!strcmp(x, "nonlocal") && + !ast_warn(c, n, "nonlocal is a keyword in 3.x")) + return 0; + } return 1; } @@ -190,7 +200,7 @@ num_stmts(const node *n) default: { char buf[128]; - sprintf(buf, "Non-statement found: %d %d\n", + sprintf(buf, "Non-statement found: %d %d", TYPE(n), NCH(n)); Py_FatalError(buf); } @@ -261,7 +271,7 @@ PyAST_FromNode(const node *n, PyCompilerFlags *flags, const char *filename, case eval_input: { expr_ty testlist_ast; - /* XXX Why not gen_for here? */ + /* XXX Why not comp_for here? */ testlist_ast = ast_for_testlist(&c, CHILD(n, 0)); if (!testlist_ast) goto error; @@ -395,10 +405,13 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) s = e->v.List.elts; break; case Tuple_kind: - if (asdl_seq_LEN(e->v.Tuple.elts) == 0) - return ast_error(n, "can't assign to ()"); - e->v.Tuple.ctx = ctx; - s = e->v.Tuple.elts; + if (asdl_seq_LEN(e->v.Tuple.elts)) { + e->v.Tuple.ctx = ctx; + s = e->v.Tuple.elts; + } + else { + expr_name = "()"; + } break; case Lambda_kind: expr_name = "lambda"; @@ -420,7 +433,14 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) case ListComp_kind: expr_name = "list comprehension"; break; + case SetComp_kind: + expr_name = "set comprehension"; + break; + case DictComp_kind: + expr_name = "dict comprehension"; + break; case Dict_kind: + case Set_kind: case Num_kind: case Str_kind: expr_name = "literal"; @@ -435,8 +455,8 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) expr_name = "conditional expression"; break; default: - PyErr_Format(PyExc_SystemError, - "unexpected expression in assignment %d (line %d)", + PyErr_Format(PyExc_SystemError, + "unexpected expression in assignment %d (line %d)", e->kind, e->lineno); return 0; } @@ -451,7 +471,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n) } /* If the LHS is a list or tuple, we need to set the assignment - context for all the contained elements. + context for all the contained elements. */ if (s) { int i; @@ -563,7 +583,7 @@ seq_for_testlist(struct compiling *c, const node *n) int i; assert(TYPE(n) == testlist || TYPE(n) == listmaker || - TYPE(n) == testlist_gexp || + TYPE(n) == testlist_comp || TYPE(n) == testlist_safe || TYPE(n) == testlist1); @@ -668,10 +688,10 @@ ast_for_arguments(struct compiling *c, const node *n) } args = (n_args ? asdl_seq_new(n_args, c->c_arena) : NULL); if (!args && n_args) - return NULL; /* Don't need to goto error; no objects allocated */ + return NULL; defaults = (n_defaults ? asdl_seq_new(n_defaults, c->c_arena) : NULL); if (!defaults && n_defaults) - return NULL; /* Don't need to goto error; no objects allocated */ + return NULL; /* fpdef: NAME | '(' fplist ')' fplist: fpdef (',' fpdef)* [','] @@ -691,7 +711,7 @@ ast_for_arguments(struct compiling *c, const node *n) if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { expr_ty expression = ast_for_expr(c, CHILD(n, i + 2)); if (!expression) - goto error; + return NULL; assert(defaults != NULL); asdl_seq_SET(defaults, j++, expression); i += 2; @@ -702,11 +722,11 @@ ast_for_arguments(struct compiling *c, const node *n) def f((x, (y))): pass will just incur the tuple unpacking warning. */ if (parenthesized && !complex_args) { ast_error(n, "parenthesized arg with default"); - goto error; + return NULL; } - ast_error(n, + ast_error(n, "non-default argument follows default argument"); - goto error; + return NULL; } if (NCH(ch) == 3) { ch = CHILD(ch, 1); @@ -715,11 +735,11 @@ ast_for_arguments(struct compiling *c, const node *n) /* We have complex arguments, setup for unpacking. */ if (Py_Py3kWarningFlag && !ast_warn(c, ch, "tuple parameter unpacking has been removed in 3.x")) - goto error; + return NULL; complex_args = 1; asdl_seq_SET(args, k++, compiler_complex_args(c, ch)); if (!asdl_seq_GET(args, k-1)) - goto error; + return NULL; } else { /* def foo((x)): setup for checking NAME below. */ /* Loop because there can be many parens and tuple @@ -734,55 +754,50 @@ ast_for_arguments(struct compiling *c, const node *n) PyObject *id; expr_ty name; if (!forbidden_check(c, n, STR(CHILD(ch, 0)))) - goto error; + return NULL; id = NEW_IDENTIFIER(CHILD(ch, 0)); if (!id) - goto error; + return NULL; name = Name(id, Param, LINENO(ch), ch->n_col_offset, c->c_arena); if (!name) - goto error; + return NULL; asdl_seq_SET(args, k++, name); - + } i += 2; /* the name and the comma */ if (parenthesized && Py_Py3kWarningFlag && !ast_warn(c, ch, "parenthesized argument names " "are invalid in 3.x")) - goto error; + return NULL; break; } case STAR: if (!forbidden_check(c, CHILD(n, i+1), STR(CHILD(n, i+1)))) - goto error; + return NULL; vararg = NEW_IDENTIFIER(CHILD(n, i+1)); if (!vararg) - goto error; + return NULL; i += 3; break; case DOUBLESTAR: if (!forbidden_check(c, CHILD(n, i+1), STR(CHILD(n, i+1)))) - goto error; + return NULL; kwarg = NEW_IDENTIFIER(CHILD(n, i+1)); if (!kwarg) - goto error; + return NULL; i += 3; break; default: PyErr_Format(PyExc_SystemError, "unexpected node in varargslist: %d @ %d", TYPE(ch), i); - goto error; + return NULL; } } return arguments(args, vararg, kwarg, defaults, c->c_arena); - - error: - Py_XDECREF(vararg); - Py_XDECREF(kwarg); - return NULL; } static expr_ty @@ -823,15 +838,15 @@ ast_for_decorator(struct compiling *c, const node *n) /* decorator: '@' dotted_name [ '(' [arglist] ')' ] NEWLINE */ expr_ty d = NULL; expr_ty name_expr; - + REQ(n, decorator); REQ(CHILD(n, 0), AT); REQ(RCHILD(n, -1), NEWLINE); - + name_expr = ast_for_dotted_name(c, CHILD(n, 1)); if (!name_expr) return NULL; - + if (NCH(n) == 3) { /* No arguments */ d = name_expr; name_expr = NULL; @@ -859,17 +874,17 @@ ast_for_decorators(struct compiling *c, const node *n) asdl_seq* decorator_seq; expr_ty d; int i; - + REQ(n, decorators); decorator_seq = asdl_seq_new(NCH(n), c->c_arena); if (!decorator_seq) return NULL; - + for (i = 0; i < NCH(n); i++) { d = ast_for_decorator(c, CHILD(n, i)); - if (!d) - return NULL; - asdl_seq_SET(decorator_seq, i, d); + if (!d) + return NULL; + asdl_seq_SET(decorator_seq, i, d); } return decorator_seq; } @@ -961,7 +976,7 @@ ast_for_lambdef(struct compiling *c, const node *n) static expr_ty ast_for_ifexpr(struct compiling *c, const node *n) { - /* test: or_test 'if' or_test 'else' test */ + /* test: or_test 'if' or_test 'else' test */ expr_ty expression, body, orelse; assert(NCH(n) == 5); @@ -1052,7 +1067,7 @@ ast_for_listcomp(struct compiling *c, const node *n) list_if: 'if' test [list_iter] testlist_safe: test [(',' test)+ [',']] */ - expr_ty elt; + expr_ty elt, first; asdl_seq *listcomps; int i, n_fors; node *ch; @@ -1078,9 +1093,9 @@ ast_for_listcomp(struct compiling *c, const node *n) asdl_seq *t; expr_ty expression; node *for_ch; - + REQ(ch, list_for); - + for_ch = CHILD(ch, 1); t = ast_for_exprlist(c, for_ch, Store); if (!t) @@ -1088,15 +1103,15 @@ ast_for_listcomp(struct compiling *c, const node *n) expression = ast_for_testlist(c, CHILD(ch, 3)); if (!expression) return NULL; - + /* Check the # of children rather than the length of t, since [x for x, in ... ] has 1 element in t, but still requires a Tuple. */ + first = (expr_ty)asdl_seq_GET(t, 0); if (NCH(for_ch) == 1) - lc = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, NULL, - c->c_arena); + lc = comprehension(first, expression, NULL, c->c_arena); else - lc = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, + lc = comprehension(Tuple(t, Store, first->lineno, first->col_offset, c->c_arena), expression, NULL, c->c_arena); if (!lc) @@ -1120,11 +1135,11 @@ ast_for_listcomp(struct compiling *c, const node *n) REQ(ch, list_iter); ch = CHILD(ch, 0); REQ(ch, list_if); - + list_for_expr = ast_for_expr(c, CHILD(ch, 1)); if (!list_for_expr) return NULL; - + asdl_seq_SET(ifs, j, list_for_expr); if (NCH(ch) == 3) ch = CHILD(ch, 2); @@ -1140,60 +1155,60 @@ ast_for_listcomp(struct compiling *c, const node *n) return ListComp(elt, listcomps, LINENO(n), n->n_col_offset, c->c_arena); } -/* Count the number of 'for' loops in a generator expression. +/* + Count the number of 'for' loops in a comprehension. - Helper for ast_for_genexp(). + Helper for ast_for_comprehension(). */ static int -count_gen_fors(struct compiling *c, const node *n) +count_comp_fors(struct compiling *c, const node *n) { int n_fors = 0; - node *ch = CHILD(n, 1); - count_gen_for: + count_comp_for: n_fors++; - REQ(ch, gen_for); - if (NCH(ch) == 5) - ch = CHILD(ch, 4); + REQ(n, comp_for); + if (NCH(n) == 5) + n = CHILD(n, 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; + count_comp_iter: + REQ(n, comp_iter); + n = CHILD(n, 0); + if (TYPE(n) == comp_for) + goto count_comp_for; + else if (TYPE(n) == comp_if) { + if (NCH(n) == 3) { + n = CHILD(n, 2); + goto count_comp_iter; } else return n_fors; } - + /* Should never be reached */ PyErr_SetString(PyExc_SystemError, - "logic error in count_gen_fors"); + "logic error in count_comp_fors"); return -1; } -/* Count the number of 'if' statements in a generator expression. +/* Count the number of 'if' statements in a comprehension. - Helper for ast_for_genexp(). + Helper for ast_for_comprehension(). */ static int -count_gen_ifs(struct compiling *c, const node *n) +count_comp_ifs(struct compiling *c, const node *n) { int n_ifs = 0; while (1) { - REQ(n, gen_iter); - if (TYPE(CHILD(n, 0)) == gen_for) + REQ(n, comp_iter); + if (TYPE(CHILD(n, 0)) == comp_for) return n_ifs; n = CHILD(n, 0); - REQ(n, gen_if); + REQ(n, comp_if); n_ifs++; if (NCH(n) == 2) return n_ifs; @@ -1201,68 +1216,54 @@ count_gen_ifs(struct compiling *c, const node *n) } } -/* TODO(jhylton): Combine with list comprehension code? */ -static expr_ty -ast_for_genexp(struct compiling *c, const node *n) +static asdl_seq * +ast_for_comprehension(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(c, n); + asdl_seq *comps; + + n_fors = count_comp_fors(c, n); if (n_fors == -1) return NULL; - genexps = asdl_seq_new(n_fors, c->c_arena); - if (!genexps) + comps = asdl_seq_new(n_fors, c->c_arena); + if (!comps) return NULL; - ch = CHILD(n, 1); for (i = 0; i < n_fors; i++) { - comprehension_ty ge; + comprehension_ty comp; asdl_seq *t; - expr_ty expression; + expr_ty expression, first; node *for_ch; - - REQ(ch, gen_for); - - for_ch = CHILD(ch, 1); + + REQ(n, comp_for); + + for_ch = CHILD(n, 1); t = ast_for_exprlist(c, for_ch, Store); if (!t) return NULL; - expression = ast_for_expr(c, CHILD(ch, 3)); + expression = ast_for_expr(c, CHILD(n, 3)); if (!expression) return NULL; /* Check the # of children rather than the length of t, since (x for x, in ...) has 1 element in t, but still requires a Tuple. */ + first = (expr_ty)asdl_seq_GET(t, 0); if (NCH(for_ch) == 1) - ge = comprehension((expr_ty)asdl_seq_GET(t, 0), expression, - NULL, c->c_arena); + comp = comprehension(first, expression, NULL, c->c_arena); else - ge = comprehension(Tuple(t, Store, LINENO(ch), ch->n_col_offset, + comp = comprehension(Tuple(t, Store, first->lineno, first->col_offset, c->c_arena), expression, NULL, c->c_arena); - - if (!ge) + if (!comp) return NULL; - if (NCH(ch) == 5) { + if (NCH(n) == 5) { int j, n_ifs; asdl_seq *ifs; - - ch = CHILD(ch, 4); - n_ifs = count_gen_ifs(c, ch); + + n = CHILD(n, 4); + n_ifs = count_comp_ifs(c, n); if (n_ifs == -1) return NULL; @@ -1271,36 +1272,98 @@ ast_for_genexp(struct compiling *c, const node *n) return NULL; for (j = 0; j < n_ifs; j++) { - REQ(ch, gen_iter); - ch = CHILD(ch, 0); - REQ(ch, gen_if); - - expression = ast_for_expr(c, CHILD(ch, 1)); + REQ(n, comp_iter); + n = CHILD(n, 0); + REQ(n, comp_if); + + expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; asdl_seq_SET(ifs, j, expression); - if (NCH(ch) == 3) - ch = CHILD(ch, 2); + if (NCH(n) == 3) + n = CHILD(n, 2); } - /* on exit, must guarantee that ch is a gen_for */ - if (TYPE(ch) == gen_iter) - ch = CHILD(ch, 0); - ge->ifs = ifs; + /* on exit, must guarantee that n is a comp_for */ + if (TYPE(n) == comp_iter) + n = CHILD(n, 0); + comp->ifs = ifs; } - asdl_seq_SET(genexps, i, ge); + asdl_seq_SET(comps, i, comp); } - - return GeneratorExp(elt, genexps, LINENO(n), n->n_col_offset, c->c_arena); + return comps; +} + +static expr_ty +ast_for_itercomp(struct compiling *c, const node *n, int type) +{ + expr_ty elt; + asdl_seq *comps; + + assert(NCH(n) > 1); + + elt = ast_for_expr(c, CHILD(n, 0)); + if (!elt) + return NULL; + + comps = ast_for_comprehension(c, CHILD(n, 1)); + if (!comps) + return NULL; + + if (type == COMP_GENEXP) + return GeneratorExp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena); + else if (type == COMP_SETCOMP) + return SetComp(elt, comps, LINENO(n), n->n_col_offset, c->c_arena); + else + /* Should never happen */ + return NULL; +} + +static expr_ty +ast_for_dictcomp(struct compiling *c, const node *n) +{ + expr_ty key, value; + asdl_seq *comps; + + assert(NCH(n) > 3); + REQ(CHILD(n, 1), COLON); + + key = ast_for_expr(c, CHILD(n, 0)); + if (!key) + return NULL; + + value = ast_for_expr(c, CHILD(n, 2)); + if (!value) + return NULL; + + comps = ast_for_comprehension(c, CHILD(n, 3)); + if (!comps) + return NULL; + + return DictComp(key, value, comps, LINENO(n), n->n_col_offset, c->c_arena); +} + +static expr_ty +ast_for_genexp(struct compiling *c, const node *n) +{ + assert(TYPE(n) == (testlist_comp) || TYPE(n) == (argument)); + return ast_for_itercomp(c, n, COMP_GENEXP); +} + +static expr_ty +ast_for_setcomp(struct compiling *c, const node *n) +{ + assert(TYPE(n) == (dictorsetmaker)); + return ast_for_itercomp(c, n, COMP_SETCOMP); } static expr_ty ast_for_atom(struct compiling *c, const node *n) { - /* atom: '(' [yield_expr|testlist_gexp] ')' | '[' [listmaker] ']' + /* atom: '(' [yield_expr|testlist_comp] ')' | '[' [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 @@ -1348,23 +1411,20 @@ ast_for_atom(struct compiling *c, const node *n) } case LPAR: /* some parenthesized expressions */ ch = CHILD(n, 1); - + if (TYPE(ch) == RPAR) return Tuple(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); - + if (TYPE(ch) == yield_expr) return ast_for_expr(c, ch); - - if ((NCH(ch) > 1) && (TYPE(CHILD(ch, 1)) == gen_for)) - return ast_for_genexp(c, ch); - - return ast_for_testlist_gexp(c, ch); + + return ast_for_testlist_comp(c, ch); case LSQB: /* list (or list comprehension) */ ch = CHILD(n, 1); - + if (TYPE(ch) == RSQB) return List(NULL, Load, LINENO(n), n->n_col_offset, c->c_arena); - + REQ(ch, listmaker); if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { asdl_seq *elts = seq_for_testlist(c, ch); @@ -1376,36 +1436,65 @@ ast_for_atom(struct compiling *c, const node *n) else return ast_for_listcomp(c, ch); case LBRACE: { - /* dictmaker: test ':' test (',' test ':' test)* [','] */ + /* dictorsetmaker: + * (test ':' test (comp_for | (',' test ':' test)* [','])) | + * (test (comp_for | (',' 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, c->c_arena); - if (!keys) - return NULL; - - values = asdl_seq_new(size, c->c_arena); - if (!values) - return NULL; - - for (i = 0; i < NCH(ch); i += 4) { - expr_ty expression; - - expression = ast_for_expr(c, CHILD(ch, i)); - if (!expression) + if (TYPE(ch) == RBRACE) { + /* it's an empty dict */ + return Dict(NULL, NULL, LINENO(n), n->n_col_offset, c->c_arena); + } else if (NCH(ch) == 1 || TYPE(CHILD(ch, 1)) == COMMA) { + /* it's a simple set */ + asdl_seq *elts; + size = (NCH(ch) + 1) / 2; /* +1 in case no trailing comma */ + elts = asdl_seq_new(size, c->c_arena); + if (!elts) + return NULL; + for (i = 0; i < NCH(ch); i += 2) { + expr_ty expression; + expression = ast_for_expr(c, CHILD(ch, i)); + if (!expression) + return NULL; + asdl_seq_SET(elts, i / 2, expression); + } + return Set(elts, LINENO(n), n->n_col_offset, c->c_arena); + } else if (TYPE(CHILD(ch, 1)) == comp_for) { + /* it's a set comprehension */ + return ast_for_setcomp(c, ch); + } else if (NCH(ch) > 3 && TYPE(CHILD(ch, 3)) == comp_for) { + return ast_for_dictcomp(c, ch); + } else { + /* it's a dict */ + size = (NCH(ch) + 1) / 4; /* +1 in case no trailing comma */ + keys = asdl_seq_new(size, c->c_arena); + if (!keys) return NULL; - asdl_seq_SET(keys, i / 4, expression); - - expression = ast_for_expr(c, CHILD(ch, i + 2)); - if (!expression) + values = asdl_seq_new(size, c->c_arena); + if (!values) return NULL; - asdl_seq_SET(values, i / 4, expression); + 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, LINENO(n), n->n_col_offset, c->c_arena); } - return Dict(keys, values, LINENO(n), n->n_col_offset, c->c_arena); } case BACKQUOTE: { /* repr */ expr_ty expression; @@ -1443,10 +1532,10 @@ ast_for_slice(struct compiling *c, const node *n) if (NCH(n) == 1 && TYPE(ch) == test) { /* 'step' variable hold no significance in terms of being used over other vars */ - step = ast_for_expr(c, ch); + step = ast_for_expr(c, ch); if (!step) return NULL; - + return Index(step, c->c_arena); } @@ -1480,10 +1569,17 @@ ast_for_slice(struct compiling *c, const node *n) ch = CHILD(n, NCH(n) - 1); if (TYPE(ch) == sliceop) { if (NCH(ch) == 1) { - /* No expression, so step is None */ + /* + This is an extended slice (ie "x[::]") with no expression in the + step field. We set this literally to "None" in order to + disambiguate it from x[:]. (The interpreter might have to call + __getslice__ for x[:], but it must call __getitem__ for x[::].) + */ + identifier none = new_identifier("None", c->c_arena); + if (!none) + return NULL; ch = CHILD(ch, 0); - step = Name(new_identifier("None", c->c_arena), Load, - LINENO(ch), ch->n_col_offset, c->c_arena); + step = Name(none, Load, LINENO(ch), ch->n_col_offset, c->c_arena); if (!step) return NULL; } else { @@ -1503,7 +1599,7 @@ static expr_ty ast_for_binop(struct compiling *c, const node *n) { /* Must account for a sequence of expressions. - How should A op B op C by represented? + How should A op B op C by represented? BinOp(BinOp(A, op, B), op, C). */ @@ -1541,10 +1637,10 @@ ast_for_binop(struct compiling *c, const node *n) if (!tmp) return NULL; - tmp_result = BinOp(result, newoperator, tmp, + tmp_result = BinOp(result, newoperator, tmp, LINENO(next_oper), next_oper->n_col_offset, c->c_arena); - if (!tmp_result) + if (!tmp_result) return NULL; result = tmp_result; } @@ -1554,7 +1650,7 @@ ast_for_binop(struct compiling *c, const node *n) static expr_ty ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr) { - /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME + /* trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME subscriptlist: subscript (',' subscript)* [','] subscript: '.' '.' '.' | test | [test] ':' [test] [sliceop] */ @@ -1585,7 +1681,7 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr) c->c_arena); } else { - /* The grammar is ambiguous here. The ambiguity is resolved + /* The grammar is ambiguous here. The ambiguity is resolved by treating the sequence as a tuple literal if there are no slice features. */ @@ -1722,7 +1818,7 @@ ast_for_expr(struct compiling *c, const node *n) { /* handle the full range of simple expressions test: or_test ['if' or_test 'else' test] | lambdef - or_test: and_test ('or' and_test)* + or_test: and_test ('or' and_test)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* @@ -1739,7 +1835,7 @@ ast_for_expr(struct compiling *c, const node *n) to explicitly allow: [ x for x in lambda: 0, lambda: 1 ] (which would be ambiguous without these extra rules) - + old_test: or_test | old_lambdef old_lambdef: 'lambda' [vararglist] ':' old_test @@ -1819,7 +1915,7 @@ ast_for_expr(struct compiling *c, const node *n) if (!expression) { return NULL; } - + asdl_seq_SET(ops, i / 2, newoperator); asdl_seq_SET(cmps, i / 2, expression); } @@ -1827,7 +1923,7 @@ ast_for_expr(struct compiling *c, const node *n) if (!expression) { return NULL; } - + return Compare(expression, ops, cmps, LINENO(n), n->n_col_offset, c->c_arena); } @@ -1879,7 +1975,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) /* arglist: (argument ',')* (argument [',']| '*' test [',' '**' test] | '**' test) - argument: [test '='] test [gen_for] # Really [keyword '='] test + argument: [test '='] test [comp_for] # Really [keyword '='] test */ int i, nargs, nkeywords, ngens; @@ -1897,7 +1993,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) if (TYPE(ch) == argument) { if (NCH(ch) == 1) nargs++; - else if (TYPE(CHILD(ch, 1)) == gen_for) + else if (TYPE(CHILD(ch, 1)) == comp_for) ngens++; else nkeywords++; @@ -1941,8 +2037,8 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) if (!e) return NULL; asdl_seq_SET(args, nargs++, e); - } - else if (TYPE(CHILD(ch, 1)) == gen_for) { + } + else if (TYPE(CHILD(ch, 1)) == comp_for) { e = ast_for_genexp(c, ch); if (!e) return NULL; @@ -1954,7 +2050,7 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) int k; char *tmp; - /* CHILD(ch, 0) is test, but must be an identifier? */ + /* CHILD(ch, 0) is test, but must be an identifier? */ e = ast_for_expr(c, CHILD(ch, 0)); if (!e) return NULL; @@ -2012,14 +2108,14 @@ ast_for_call(struct compiling *c, const node *n, expr_ty func) static expr_ty ast_for_testlist(struct compiling *c, const node* n) { - /* testlist_gexp: test (',' test)* [','] */ + /* testlist_comp: test (',' test)* [','] */ /* testlist: test (',' test)* [','] */ /* testlist_safe: test (',' test)+ [','] */ /* testlist1: test (',' test)* */ assert(NCH(n) > 0); - if (TYPE(n) == testlist_gexp) { + if (TYPE(n) == testlist_comp) { if (NCH(n) > 1) - assert(TYPE(CHILD(n, 1)) != gen_for); + assert(TYPE(CHILD(n, 1)) != comp_for); } else { assert(TYPE(n) == testlist || @@ -2037,12 +2133,12 @@ ast_for_testlist(struct compiling *c, const node* n) } static expr_ty -ast_for_testlist_gexp(struct compiling *c, const node* n) +ast_for_testlist_comp(struct compiling *c, const node* n) { - /* testlist_gexp: test ( gen_for | (',' test)* [','] ) */ - /* argument: test [ gen_for ] */ - assert(TYPE(n) == testlist_gexp || TYPE(n) == argument); - if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == gen_for) + /* testlist_comp: test ( comp_for | (',' test)* [','] ) */ + /* argument: test [ comp_for ] */ + assert(TYPE(n) == testlist_comp || TYPE(n) == argument); + if (NCH(n) > 1 && TYPE(CHILD(n, 1)) == comp_for) return ast_for_genexp(c, n); return ast_for_testlist(c, n); } @@ -2073,7 +2169,7 @@ static stmt_ty ast_for_expr_stmt(struct compiling *c, const node *n) { REQ(n, expr_stmt); - /* expr_stmt: testlist (augassign (yield_expr|testlist) + /* expr_stmt: testlist (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist))*) testlist: test (',' test)* [','] augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' @@ -2096,33 +2192,21 @@ ast_for_expr_stmt(struct compiling *c, const node *n) expr1 = ast_for_testlist(c, ch); if (!expr1) return NULL; - /* TODO(nas): Remove duplicated error checks (set_context does it) */ + if(!set_context(c, expr1, Store, ch)) + return NULL; + /* set_context checks that most expressions are not the left side. + Augmented assignments can only have a name, a subscript, or an + attribute on the left, though, so we have to explicitly check for + those. */ switch (expr1->kind) { - case GeneratorExp_kind: - ast_error(ch, "augmented assignment to generator " - "expression not possible"); - return NULL; - case Yield_kind: - ast_error(ch, "augmented assignment to yield " - "expression not possible"); - return NULL; - case Name_kind: { - const char *var_name = PyBytes_AS_STRING(expr1->v.Name.id); - if ((var_name[0] == 'N' || var_name[0] == 'T' || var_name[0] == 'F') && - !forbidden_check(c, ch, var_name)) - return NULL; - break; - } + case Name_kind: case Attribute_kind: case Subscript_kind: break; default: - ast_error(ch, "illegal expression for augmented " - "assignment"); + ast_error(ch, "illegal expression for augmented assignment"); return NULL; } - if(!set_context(c, expr1, Store, ch)) - return NULL; ch = CHILD(n, 2); if (TYPE(ch) == testlist) @@ -2158,11 +2242,10 @@ ast_for_expr_stmt(struct compiling *c, const node *n) return NULL; } e = ast_for_testlist(c, ch); - - /* set context to assign */ - if (!e) + if (!e) return NULL; + /* set context to assign */ if (!set_context(c, e, Store, CHILD(n, i))) return NULL; @@ -2187,9 +2270,9 @@ ast_for_print_stmt(struct compiling *c, const node *n) | '>>' test [ (',' test)+ [','] ] ) */ expr_ty dest = NULL, expression; - asdl_seq *seq; + asdl_seq *seq = NULL; bool nl; - int i, j, start = 1; + int i, j, values_count, start = 1; REQ(n, print_stmt); if (NCH(n) >= 2 && TYPE(CHILD(n, 1)) == RIGHTSHIFT) { @@ -2198,14 +2281,17 @@ ast_for_print_stmt(struct compiling *c, const node *n) return NULL; start = 4; } - seq = asdl_seq_new((NCH(n) + 1 - start) / 2, c->c_arena); - if (!seq) - return NULL; - for (i = start, j = 0; i < NCH(n); i += 2, ++j) { - expression = ast_for_expr(c, CHILD(n, i)); - if (!expression) + values_count = (NCH(n) + 1 - start) / 2; + if (values_count) { + seq = asdl_seq_new(values_count, c->c_arena); + if (!seq) return NULL; - asdl_seq_SET(seq, j, expression); + for (i = start, j = 0; i < NCH(n); i += 2, ++j) { + expression = ast_for_expr(c, CHILD(n, i)); + if (!expression) + return NULL; + asdl_seq_SET(seq, j, expression); + } } nl = (TYPE(CHILD(n, NCH(n) - 1)) == COMMA) ? false : true; return Print(dest, seq, nl, LINENO(n), n->n_col_offset, c->c_arena); @@ -2238,7 +2324,7 @@ static stmt_ty ast_for_del_stmt(struct compiling *c, const node *n) { asdl_seq *expr_list; - + /* del_stmt: 'del' exprlist */ REQ(n, del_stmt); @@ -2322,7 +2408,7 @@ ast_for_flow_stmt(struct compiling *c, const node *n) expr3 = ast_for_expr(c, CHILD(ch, 5)); if (!expr3) return NULL; - + return Raise(expr1, expr2, expr3, LINENO(n), n->n_col_offset, c->c_arena); } @@ -2337,7 +2423,7 @@ ast_for_flow_stmt(struct compiling *c, const node *n) } static alias_ty -alias_for_import_name(struct compiling *c, const node *n) +alias_for_import_name(struct compiling *c, const node *n, int store) { /* import_as_name: NAME ['as' NAME] @@ -2348,28 +2434,40 @@ alias_for_import_name(struct compiling *c, const node *n) loop: switch (TYPE(n)) { - case import_as_name: + case import_as_name: { + node *name_node = CHILD(n, 0); str = NULL; if (NCH(n) == 3) { - str = NEW_IDENTIFIER(CHILD(n, 2)); + node *str_node = CHILD(n, 2); + if (store && !forbidden_check(c, str_node, STR(str_node))) + return NULL; + str = NEW_IDENTIFIER(str_node); if (!str) return NULL; } - name = NEW_IDENTIFIER(CHILD(n, 0)); + else { + if (!forbidden_check(c, name_node, STR(name_node))) + return NULL; + } + name = NEW_IDENTIFIER(name_node); if (!name) return NULL; return alias(name, str, c->c_arena); + } case dotted_as_name: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } else { - alias_ty a = alias_for_import_name(c, CHILD(n, 0)); + node *asname_node = CHILD(n, 2); + alias_ty a = alias_for_import_name(c, CHILD(n, 0), 0); if (!a) return NULL; assert(!a->asname); - a->asname = NEW_IDENTIFIER(CHILD(n, 2)); + if (!forbidden_check(c, asname_node, STR(asname_node))) + return NULL; + a->asname = NEW_IDENTIFIER(asname_node); if (!a->asname) return NULL; return a; @@ -2377,7 +2475,10 @@ alias_for_import_name(struct compiling *c, const node *n) break; case dotted_name: if (NCH(n) == 1) { - name = NEW_IDENTIFIER(CHILD(n, 0)); + node *name_node = CHILD(n, 0); + if (store && !forbidden_check(c, name_node, STR(name_node))) + return NULL; + name = NEW_IDENTIFIER(name_node); if (!name) return NULL; return alias(name, NULL, c->c_arena); @@ -2451,7 +2552,7 @@ ast_for_import_stmt(struct compiling *c, const node *n) if (!aliases) return NULL; for (i = 0; i < NCH(n); i += 2) { - alias_ty import_alias = alias_for_import_name(c, CHILD(n, i)); + alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1); if (!import_alias) return NULL; asdl_seq_SET(aliases, i / 2, import_alias); @@ -2462,13 +2563,15 @@ ast_for_import_stmt(struct compiling *c, const node *n) int n_children; int idx, ndots = 0; alias_ty mod = NULL; - identifier modname; - + identifier modname = NULL; + /* Count the number of dots (for relative imports) and check for the optional module name */ for (idx = 1; idx < NCH(n); idx++) { if (TYPE(CHILD(n, idx)) == dotted_name) { - mod = alias_for_import_name(c, CHILD(n, idx)); + mod = alias_for_import_name(c, CHILD(n, idx), 0); + if (!mod) + return NULL; idx++; break; } else if (TYPE(CHILD(n, idx)) != DOT) { @@ -2509,14 +2612,14 @@ ast_for_import_stmt(struct compiling *c, const node *n) /* handle "from ... import *" special b/c there's no children */ if (TYPE(n) == STAR) { - alias_ty import_alias = alias_for_import_name(c, n); + alias_ty import_alias = alias_for_import_name(c, n, 1); if (!import_alias) return NULL; asdl_seq_SET(aliases, 0, import_alias); } else { for (i = 0; i < NCH(n); i += 2) { - alias_ty import_alias = alias_for_import_name(c, CHILD(n, i)); + alias_ty import_alias = alias_for_import_name(c, CHILD(n, i), 1); if (!import_alias) return NULL; asdl_seq_SET(aliases, i / 2, import_alias); @@ -2524,8 +2627,6 @@ ast_for_import_stmt(struct compiling *c, const node *n) } if (mod != NULL) modname = mod->name; - else - modname = new_identifier("", c->c_arena); return ImportFrom(modname, aliases, ndots, lineno, col_offset, c->c_arena); } @@ -2609,7 +2710,7 @@ ast_for_assert_stmt(struct compiling *c, const node *n) expr2 = ast_for_expr(c, CHILD(n, 3)); if (!expr2) return NULL; - + return Assert(expr1, expr2, LINENO(n), n->n_col_offset, c->c_arena); } PyErr_Format(PyExc_SystemError, @@ -2636,7 +2737,7 @@ ast_for_suite(struct compiling *c, const node *n) if (TYPE(CHILD(n, 0)) == simple_stmt) { n = CHILD(n, 0); /* simple_stmt always ends with a NEWLINE, - and may have a trailing SEMI + and may have a trailing SEMI */ end = NCH(n) - 1; if (TYPE(CHILD(n, end - 1)) == SEMI) @@ -2701,10 +2802,10 @@ ast_for_if_stmt(struct compiling *c, const node *n) expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; - suite_seq = ast_for_suite(c, CHILD(n, 3)); + suite_seq = ast_for_suite(c, CHILD(n, 3)); if (!suite_seq) return NULL; - + return If(expression, suite_seq, NULL, LINENO(n), n->n_col_offset, c->c_arena); } @@ -2762,8 +2863,8 @@ ast_for_if_stmt(struct compiling *c, const node *n) if (!suite_seq2) return NULL; - asdl_seq_SET(orelse, 0, - If(expression, suite_seq, suite_seq2, + asdl_seq_SET(orelse, 0, + If(expression, suite_seq, suite_seq2, LINENO(CHILD(n, NCH(n) - 6)), CHILD(n, NCH(n) - 6)->n_col_offset, c->c_arena)); @@ -2784,7 +2885,7 @@ ast_for_if_stmt(struct compiling *c, const node *n) return NULL; asdl_seq_SET(newobj, 0, - If(expression, suite_seq, orelse, + If(expression, suite_seq, orelse, LINENO(CHILD(n, off)), CHILD(n, off)->n_col_offset, c->c_arena)); orelse = newobj; @@ -2852,7 +2953,7 @@ ast_for_for_stmt(struct compiling *c, const node *n) { asdl_seq *_target, *seq = NULL, *suite_seq; expr_ty expression; - expr_ty target; + expr_ty target, first; const node *node_target; /* for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] */ REQ(n, for_stmt); @@ -2869,10 +2970,11 @@ ast_for_for_stmt(struct compiling *c, const node *n) return NULL; /* Check the # of children rather than the length of _target, since for x, in ... has 1 element in _target, but still requires a Tuple. */ + first = (expr_ty)asdl_seq_GET(_target, 0); if (NCH(node_target) == 1) - target = (expr_ty)asdl_seq_GET(_target, 0); + target = first; else - target = Tuple(_target, Store, LINENO(n), n->n_col_offset, c->c_arena); + target = Tuple(_target, Store, first->lineno, first->col_offset, c->c_arena); expression = ast_for_testlist(c, CHILD(n, 3)); if (!expression) @@ -2982,7 +3084,7 @@ ast_for_try_stmt(struct compiling *c, const node *n) ast_error(n, "malformed 'try' statement"); return NULL; } - + if (n_except > 0) { int i; stmt_ty except_st; @@ -3017,27 +3119,18 @@ ast_for_try_stmt(struct compiling *c, const node *n) return TryFinally(body, finally, LINENO(n), n->n_col_offset, c->c_arena); } -static expr_ty -ast_for_with_var(struct compiling *c, const node *n) -{ - REQ(n, with_var); - return ast_for_expr(c, CHILD(n, 1)); -} - -/* with_stmt: 'with' test [ with_var ] ':' suite */ +/* with_item: test ['as' expr] */ static stmt_ty -ast_for_with_stmt(struct compiling *c, const node *n) +ast_for_with_item(struct compiling *c, const node *n, asdl_seq *content) { expr_ty context_expr, optional_vars = NULL; - int suite_index = 3; /* skip 'with', test, and ':' */ - asdl_seq *suite_seq; - assert(TYPE(n) == with_stmt); - context_expr = ast_for_expr(c, CHILD(n, 1)); + REQ(n, with_item); + context_expr = ast_for_expr(c, CHILD(n, 0)); if (!context_expr) return NULL; - if (TYPE(CHILD(n, 2)) == with_var) { - optional_vars = ast_for_with_var(c, CHILD(n, 2)); + if (NCH(n) == 3) { + optional_vars = ast_for_expr(c, CHILD(n, 2)); if (!optional_vars) { return NULL; @@ -3045,15 +3138,45 @@ ast_for_with_stmt(struct compiling *c, const node *n) if (!set_context(c, optional_vars, Store, n)) { return NULL; } - suite_index = 4; } - suite_seq = ast_for_suite(c, CHILD(n, suite_index)); - if (!suite_seq) { + return With(context_expr, optional_vars, content, LINENO(n), + n->n_col_offset, c->c_arena); +} + +/* with_stmt: 'with' with_item (',' with_item)* ':' suite */ +static stmt_ty +ast_for_with_stmt(struct compiling *c, const node *n) +{ + int i; + stmt_ty ret; + asdl_seq *inner; + + REQ(n, with_stmt); + + /* process the with items inside-out */ + i = NCH(n) - 1; + /* the suite of the innermost with item is the suite of the with stmt */ + inner = ast_for_suite(c, CHILD(n, i)); + if (!inner) return NULL; + + for (;;) { + i -= 2; + ret = ast_for_with_item(c, CHILD(n, i), inner); + if (!ret) + return NULL; + /* was this the last item? */ + if (i == 1) + break; + /* if not, wrap the result so far in a new sequence */ + inner = asdl_seq_new(1, c->c_arena); + if (!inner) + return NULL; + asdl_seq_SET(inner, 0, ret); } - return With(context_expr, optional_vars, suite_seq, LINENO(n), - n->n_col_offset, c->c_arena); + + return ret; } static stmt_ty @@ -3062,7 +3185,7 @@ ast_for_classdef(struct compiling *c, const node *n, asdl_seq *decorator_seq) /* classdef: 'class' NAME ['(' testlist ')'] ':' suite */ PyObject *classname; asdl_seq *bases, *s; - + REQ(n, classdef); if (!forbidden_check(c, n, STR(CHILD(n, 1)))) @@ -3117,7 +3240,6 @@ ast_for_stmt(struct compiling *c, const node *n) n = CHILD(n, 0); } if (TYPE(n) == small_stmt) { - REQ(n, small_stmt); n = CHILD(n, 0); /* small_stmt: expr_stmt | print_stmt | del_stmt | pass_stmt | flow_stmt | import_stmt | global_stmt | exec_stmt @@ -3210,17 +3332,17 @@ parsenumber(struct compiling *c, const char *s) #ifndef WITHOUT_COMPLEX if (imflag) { complex.real = 0.; - PyFPE_START_PROTECT("atof", return 0) - complex.imag = PyOS_ascii_atof(s); - PyFPE_END_PROTECT(complex) + complex.imag = PyOS_string_to_double(s, (char **)&end, NULL); + if (complex.imag == -1.0 && PyErr_Occurred()) + return NULL; return PyComplex_FromCComplex(complex); } else #endif { - PyFPE_START_PROTECT("atof", return 0) - dx = PyOS_ascii_atof(s); - PyFPE_END_PROTECT(dx) + dx = PyOS_string_to_double(s, NULL, NULL); + if (dx == -1.0 && PyErr_Occurred()) + return NULL; return PyFloat_FromDouble(dx); } } @@ -3251,17 +3373,12 @@ decode_utf8(struct compiling *c, const char **sPtr, const char *end, char* encod static PyObject * decode_unicode(struct compiling *c, const char *s, size_t len, int rawmode, const char *encoding) { - PyObject *v, *u; + PyObject *v; + PyObject *u = NULL; char *buf; char *p; const char *end; - if (encoding == NULL) { - buf = (char *)s; - u = NULL; - } else if (strcmp(encoding, "iso-8859-1") == 0) { - buf = (char *)s; - u = NULL; - } else { + if (encoding != NULL && strcmp(encoding, "iso-8859-1")) { /* check for integer overflow */ if (len > PY_SIZE_MAX / 6) return NULL; @@ -3351,7 +3468,7 @@ parsestr(struct compiling *c, const char *s) s++; len = strlen(s); if (len > INT_MAX) { - PyErr_SetString(PyExc_OverflowError, + PyErr_SetString(PyExc_OverflowError, "string to parse is too long"); return NULL; } |