return NULL; if (slc->kind != Index_kind) simple = false; asdl_seq_SET(slices, j / 2, slc); } if (!simple) { return Subscript(left_expr, ExtSlice(slices, c->c_arena), Load, LINENO(n), n->n_col_offset, c->c_arena); } /* extract Index values and put them in a Tuple */ elts = asdl_seq_new(asdl_seq_LEN(slices), c->c_arena); if (!elts) return NULL; for (j = 0; j < asdl_seq_LEN(slices); ++j) { slc = (slice_ty)asdl_seq_GET(slices, j); assert(slc->kind == Index_kind && slc->v.Index.value); asdl_seq_SET(elts, j, slc->v.Index.value); } e = Tuple(elts, Load, LINENO(n), n->n_col_offset, c->c_arena); if (!e) return NULL; return Subscript(left_expr, Index(e, c->c_arena), Load, LINENO(n), n->n_col_offset, c->c_arena); } }} static expr_tyast_for_factor(struct compiling *c, const node *n){ node *pfactor, *ppower, *patom, *pnum; expr_ty expression; /* If the unary - operator is applied to a constant, don't generate a UNARY_NEGATIVE opcode. Just store the approriate value as a constant. The peephole optimizer already does something like this but it doesn't handle the case where the constant is (sys.maxint - 1). In that case, we want a PyIntObject, not a PyLongObject. */ if (TYPE(CHILD(n, 0)) == MINUS && NCH(n) == 2 && TYPE((pfactor = CHILD(n, 1))) == factor && NCH(pfactor) == 1 && TYPE((ppower = CHILD(pfactor, 0))) == power && NCH(ppower) == 1 && TYPE((patom = CHILD(ppower, 0))) == atom && TYPE((pnum = CHILD(patom, 0))) == NUMBER) { char *s = PyObject_MALLOC(strlen(STR(pnum)) + 2); if (s == NULL) return NULL; s[0] = '-'; strcpy(s + 1, STR(pnum)); PyObject_FREE(STR(pnum)); STR(pnum) = s; return ast_for_atom(c, patom); } expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; switch (TYPE(CHILD(n, 0))) { case PLUS: return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset, c->c_arena); case MINUS: return UnaryOp(USub, expression, LINENO(n), n->n_col_offset, c->c_arena); case TILDE: return UnaryOp(Invert, expression, LINENO(n), n->n_col_offset, c->c_arena); } PyErr_Format(PyExc_SystemError, "unhandled factor: %d", TYPE(CHILD(n, 0))); return NULL;} static expr_tyast_for_power(struct compiling *c, const node *n){ /* power: atom trailer* ('**' factor)* */ int i; expr_ty e, tmp; REQ(n, power); e = ast_for_atom(c, CHILD(n, 0)); if (!e) return NULL; if (NCH(n) == 1) return e; for (i = 1; i < NCH(n); i++) { node *ch = CHILD(n, i); if (TYPE(ch) != trailer) break; tmp = ast_for_trailer(c, ch, e); if (!tmp) return NULL; tmp->lineno = e->lineno; tmp->col_offset = e->col_offset; e = tmp; } if (TYPE(CHILD(n, NCH(n) - 1)) == factor) { expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1)); if (!f) return NULL; tmp = BinOp(e, Pow, f, LINENO(n), n->n_col_offset, c->c_arena); if (!tmp) return NULL; e = tmp; } return e;} /* Do not name a variable 'expr'! Will cause a compile error.*/ static expr_tyast_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)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom trailer* ('**' factor)* As well as modified versions that exist for backward compatibility, 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 */ asdl_seq *seq; int i; loop: switch (TYPE(n)) { case test: case old_test: if (TYPE(CHILD(n, 0)) == lambdef || TYPE(CHILD(n, 0)) == old_lambdef) return ast_for_lambdef(c, CHILD(n, 0)); else if (NCH(n) > 1) return ast_for_ifexpr(c, n); /* Fallthrough */ case or_test: case and_test: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); if (!seq) return NULL; for (i = 0; i < NCH(n); i += 2) { expr_ty e = ast_for_expr(c, CHILD(n, i)); if (!e) return NULL; asdl_seq_SET(seq, i / 2, e); } if (!strcmp(STR(CHILD(n, 1)), "and")) return BoolOp(And, seq, LINENO(n), n->n_col_offset, c->c_arena); assert(!strcmp(STR(CHILD(n, 1)), "or")); return BoolOp(Or, seq, LINENO(n), n->n_col_offset, c->c_arena); case not_test: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } else { expr_ty expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; return UnaryOp(Not, expression, LINENO(n), n->n_col_offset, c->c_arena); } case comparison: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } else { expr_ty expression; asdl_int_seq *ops; asdl_seq *cmps; ops = asdl_int_seq_new(NCH(n) / 2, c->c_arena); if (!ops) return NULL; cmps = asdl_seq_new(NCH(n) / 2, c->c_arena); if (!cmps) { return NULL; } for (i = 1; i < NCH(n); i += 2) { cmpop_ty newoperator; newoperator = ast_for_comp_op(CHILD(n, i)); if (!newoperator) { return NULL; } expression = ast_for_expr(c, CHILD(n, i + 1)); if (!expression) { return NULL; } asdl_seq_SET(ops, i / 2, newoperator); asdl_seq_SET(cmps, i / 2, expression); } expression = ast_for_expr(c, CHILD(n, 0)); if (!expression) { return NULL; } return Compare(expression, ops, cmps, LINENO(n), n->n_col_offset, c->c_arena); } break; /* The next five cases all handle BinOps. The main body of code is the same in each case, but the switch turned inside out to reuse the code for each type of operator. */ case expr: case xor_expr: case and_expr: case shift_expr: case arith_expr: case term: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } return ast_for_binop(c, n); case yield_expr: { expr_ty exp = NULL; if (NCH(n) == 2) { exp = ast_for_testlist(c, CHILD(n, 1)); if (!exp) return NULL; } return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena); } case factor: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } return ast_for_factor(c, n); case power: return ast_for_power(c, n); default: PyErr_Format(PyExc_SystemError, "unhandled expr: %d", TYPE(n)); return NULL; } /* should never get here unless if error is set */ return NULL;} static expr_tyast_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 */ int i, nargs, nkeywords, ngens; asdl_seq *args; asdl_seq *keywords; expr_ty vararg = NULL, kwarg = NULL; REQ(n, arglist); 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 parenthesized " "if not sole argument"); return NULL; } if (nargs + nkeywords + ngens > 255) { ast_error(n, "more than 255 arguments"); return NULL; } args = asdl_seq_new(nargs + ngens, c->c_arena); if (!args) return NULL; keywords = asdl_seq_new(nkeywords, c->c_arena); if (!keywords) return NULL; nargs = 0; nkeywords = 0; for (i = 0; i < NCH(n); i++) { node *ch = CHILD(n, i); if (TYPE(ch) == argument) { expr_ty e; if (NCH(ch) == 1) { if (nkeywords) { ast_error(CHILD(ch, 0), "non-keyword arg after keyword arg"); return NULL; } e = ast_for_expr(c, CHILD(ch, 0)); if (!e) return NULL; asdl_seq_SET(args, nargs++, e); } else if (TYPE(CHILD(ch, 1)) == gen_for) { e = ast_for_genexp(c, ch); if (!e) return NULL; asdl_seq_SET(args, nargs++, e); } else { keyword_ty kw; identifier key; /* CHILD(ch, 0) is test, but must be an identifier? */ e = ast_for_expr(c, CHILD(ch, 0)); if (!e) return NULL; /* f(lambda x: x[0] = 3) ends up getting parsed with * LHS test = lambda x: x[0], and RHS test = 3. * SF bug 132313 points out that complaining about a keyword * then is very confusing. */ if (e->kind == Lambda_kind) { ast_error(CHILD(ch, 0), "lambda cannot contain assignment"); return NULL; } else if (e->kind != Name_kind) { ast_error(CHILD(ch, 0), "keyword can't be an expression"); return NULL; } key = e->v.Name.id; e = ast_for_expr(c, CHILD(ch, 2)); if (!e) return NULL; kw = keyword(key, e, c->c_arena); if (!kw) return NULL; asdl_seq_SET(keywords, nkeywords++, kw); } } else if (TYPE(ch) == STAR) { vararg = ast_for_expr(c, CHILD(n, i+1)); i++; } else if (TYPE(ch) == DOUBLESTAR) { kwarg = ast_for_expr(c, CHILD(n, i+1)); i++; } } return Call(func, args, keywords, vararg, kwarg, func->lineno, func->col_offset, c->c_arena);} static expr_tyast_for_testlist(struct compiling *c, const node* n){ /* testlist_gexp: test (',' test)* [','] */ /* testlist: test (',' test)* [','] */ /* testlist_safe: test (',' test)+ [','] */ /* testlist1: test (',' test)* */ assert(NCH(n) > 0); if (TYPE(n) == testlist_gexp) { if (NCH(n) > 1) assert(TYPE(CHILD(n, 1)) != gen_for); } else { assert(TYPE(n) == testlist || TYPE(n) == testlist_safe || TYPE(n) == testlist1); } if (NCH(n) == 1) return ast_for_expr(c, CHILD(n, 0)); else { asdl_seq *tmp = seq_for_testlist(c, n); if (!tmp) return NULL; return Tuple(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena); }} static expr_tyast_for_testlist_gexp(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) return ast_for_genexp(c, n); return ast_for_testlist(c, n);} /* like ast_for_testlist() but returns a sequence */static asdl_seq*ast_for_class_bases(struct compiling *c, const node* n){ /* testlist: test (',' test)* [','] */ assert(NCH(n) > 0); REQ(n, testlist); if (NCH(n) == 1) { expr_ty base; asdl_seq *bases = asdl_seq_new(1, c->c_arena); if (!bases) return NULL; base = ast_for_expr(c, CHILD(n, 0)); if (!base) return NULL; asdl_seq_SET(bases, 0, base); return bases; } return seq_for_testlist(c, n);} static stmt_tyast_for_expr_stmt(struct compiling *c, const node *n){ REQ(n, expr_stmt); /* expr_stmt: testlist (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist))*) testlist: test (',' test)* [','] augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=' test: ... here starts the operator precendence dance */ if (NCH(n) == 1) { expr_ty e = ast_for_testlist(c, CHILD(n, 0)); if (!e) return NULL; return Expr(e, LINENO(n), n->n_col_offset, c->c_arena); } else if (TYPE(CHILD(n, 1)) == augassign) { expr_ty expr1, expr2; operator_ty newoperator; node *ch = CHILD(n, 0); expr1 = ast_for_testlist(c, ch); if (!expr1) return NULL; /* TODO(nas): Remove duplicated error checks (set_context does it) */ 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 = PyString_AS_STRING(expr1->v.Name.id); if (var_name[0] == 'N' && !strcmp(var_name, "None")) { ast_error(ch, "assignment to None"); return NULL; } break; } case Attribute_kind: case Subscript_kind: break; default: ast_error(ch, "illegal expression for augmented " "assignment"); return NULL; } if (!set_context(expr1, Store, ch))Lines 1501–2000 of 3292. Previous lines Load more
return NULL; if (slc->kind != Index_kind) simple = false; asdl_seq_SET(slices, j / 2, slc); } if (!simple) { return Subscript(left_expr, ExtSlice(slices, c->c_arena), Load, LINENO(n), n->n_col_offset, c->c_arena); } /* extract Index values and put them in a Tuple */ elts = asdl_seq_new(asdl_seq_LEN(slices), c->c_arena); if (!elts) return NULL; for (j = 0; j < asdl_seq_LEN(slices); ++j) { slc = (slice_ty)asdl_seq_GET(slices, j); assert(slc->kind == Index_kind && slc->v.Index.value); asdl_seq_SET(elts, j, slc->v.Index.value); } e = Tuple(elts, Load, LINENO(n), n->n_col_offset, c->c_arena); if (!e) return NULL; return Subscript(left_expr, Index(e, c->c_arena), Load, LINENO(n), n->n_col_offset, c->c_arena); } } } static expr_ty ast_for_factor(struct compiling *c, const node *n) { node *pfactor, *ppower, *patom, *pnum; expr_ty expression; /* If the unary - operator is applied to a constant, don't generate a UNARY_NEGATIVE opcode. Just store the approriate value as a constant. The peephole optimizer already does something like this but it doesn't handle the case where the constant is (sys.maxint - 1). In that case, we want a PyIntObject, not a PyLongObject. */ if (TYPE(CHILD(n, 0)) == MINUS && NCH(n) == 2 && TYPE((pfactor = CHILD(n, 1))) == factor && NCH(pfactor) == 1 && TYPE((ppower = CHILD(pfactor, 0))) == power && NCH(ppower) == 1 && TYPE((patom = CHILD(ppower, 0))) == atom && TYPE((pnum = CHILD(patom, 0))) == NUMBER) { char *s = PyObject_MALLOC(strlen(STR(pnum)) + 2); if (s == NULL) return NULL; s[0] = '-'; strcpy(s + 1, STR(pnum)); PyObject_FREE(STR(pnum)); STR(pnum) = s; return ast_for_atom(c, patom); } expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; switch (TYPE(CHILD(n, 0))) { case PLUS: return UnaryOp(UAdd, expression, LINENO(n), n->n_col_offset, c->c_arena); case MINUS: return UnaryOp(USub, expression, LINENO(n), n->n_col_offset, c->c_arena); case TILDE: return UnaryOp(Invert, expression, LINENO(n), n->n_col_offset, c->c_arena); } PyErr_Format(PyExc_SystemError, "unhandled factor: %d", TYPE(CHILD(n, 0))); return NULL; } static expr_ty ast_for_power(struct compiling *c, const node *n) { /* power: atom trailer* ('**' factor)* */ int i; expr_ty e, tmp; REQ(n, power); e = ast_for_atom(c, CHILD(n, 0)); if (!e) return NULL; if (NCH(n) == 1) return e; for (i = 1; i < NCH(n); i++) { node *ch = CHILD(n, i); if (TYPE(ch) != trailer) break; tmp = ast_for_trailer(c, ch, e); if (!tmp) return NULL; tmp->lineno = e->lineno; tmp->col_offset = e->col_offset; e = tmp; } if (TYPE(CHILD(n, NCH(n) - 1)) == factor) { expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1)); if (!f) return NULL; tmp = BinOp(e, Pow, f, LINENO(n), n->n_col_offset, c->c_arena); if (!tmp) return NULL; e = tmp; } return e; } /* Do not name a variable 'expr'! Will cause a compile error. */ static expr_ty 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)* and_test: not_test ('and' not_test)* not_test: 'not' not_test | comparison comparison: expr (comp_op expr)* expr: xor_expr ('|' xor_expr)* xor_expr: and_expr ('^' and_expr)* and_expr: shift_expr ('&' shift_expr)* shift_expr: arith_expr (('<<'|'>>') arith_expr)* arith_expr: term (('+'|'-') term)* term: factor (('*'|'/'|'%'|'//') factor)* factor: ('+'|'-'|'~') factor | power power: atom trailer* ('**' factor)* As well as modified versions that exist for backward compatibility, 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 */ asdl_seq *seq; int i; loop: switch (TYPE(n)) { case test: case old_test: if (TYPE(CHILD(n, 0)) == lambdef || TYPE(CHILD(n, 0)) == old_lambdef) return ast_for_lambdef(c, CHILD(n, 0)); else if (NCH(n) > 1) return ast_for_ifexpr(c, n); /* Fallthrough */ case or_test: case and_test: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } seq = asdl_seq_new((NCH(n) + 1) / 2, c->c_arena); if (!seq) return NULL; for (i = 0; i < NCH(n); i += 2) { expr_ty e = ast_for_expr(c, CHILD(n, i)); if (!e) return NULL; asdl_seq_SET(seq, i / 2, e); } if (!strcmp(STR(CHILD(n, 1)), "and")) return BoolOp(And, seq, LINENO(n), n->n_col_offset, c->c_arena); assert(!strcmp(STR(CHILD(n, 1)), "or")); return BoolOp(Or, seq, LINENO(n), n->n_col_offset, c->c_arena); case not_test: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } else { expr_ty expression = ast_for_expr(c, CHILD(n, 1)); if (!expression) return NULL; return UnaryOp(Not, expression, LINENO(n), n->n_col_offset, c->c_arena); } case comparison: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } else { expr_ty expression; asdl_int_seq *ops; asdl_seq *cmps; ops = asdl_int_seq_new(NCH(n) / 2, c->c_arena); if (!ops) return NULL; cmps = asdl_seq_new(NCH(n) / 2, c->c_arena); if (!cmps) { return NULL; } for (i = 1; i < NCH(n); i += 2) { cmpop_ty newoperator; newoperator = ast_for_comp_op(CHILD(n, i)); if (!newoperator) { return NULL; } expression = ast_for_expr(c, CHILD(n, i + 1)); if (!expression) { return NULL; } asdl_seq_SET(ops, i / 2, newoperator); asdl_seq_SET(cmps, i / 2, expression); } expression = ast_for_expr(c, CHILD(n, 0)); if (!expression) { return NULL; } return Compare(expression, ops, cmps, LINENO(n), n->n_col_offset, c->c_arena); } break; /* The next five cases all handle BinOps. The main body of code is the same in each case, but the switch turned inside out to reuse the code for each type of operator. */ case expr: case xor_expr: case and_expr: case shift_expr: case arith_expr: case term: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } return ast_for_binop(c, n); case yield_expr: { expr_ty exp = NULL; if (NCH(n) == 2) { exp = ast_for_testlist(c, CHILD(n, 1)); if (!exp) return NULL; } return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena); } case factor: if (NCH(n) == 1) { n = CHILD(n, 0); goto loop; } return ast_for_factor(c, n); case power: return ast_for_power(c, n); default: PyErr_Format(PyExc_SystemError, "unhandled expr: %d", TYPE(n)); return NULL; } /* should never get here unless if error is set */ return NULL; } static expr_ty 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 */ int i, nargs, nkeywords, ngens; asdl_seq *args; asdl_seq *keywords; expr_ty vararg = NULL, kwarg = NULL; REQ(n, arglist); 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 parenthesized " "if not sole argument"); return NULL; } if (nargs + nkeywords + ngens > 255) { ast_error(n, "more than 255 arguments"); return NULL; } args = asdl_seq_new(nargs + ngens, c->c_arena); if (!args) return NULL; keywords = asdl_seq_new(nkeywords, c->c_arena); if (!keywords) return NULL; nargs = 0; nkeywords = 0; for (i = 0; i < NCH(n); i++) { node *ch = CHILD(n, i); if (TYPE(ch) == argument) { expr_ty e; if (NCH(ch) == 1) { if (nkeywords) { ast_error(CHILD(ch, 0), "non-keyword arg after keyword arg"); return NULL; } e = ast_for_expr(c, CHILD(ch, 0)); if (!e) return NULL; asdl_seq_SET(args, nargs++, e); } else if (TYPE(CHILD(ch, 1)) == gen_for) { e = ast_for_genexp(c, ch); if (!e) return NULL; asdl_seq_SET(args, nargs++, e); } else { keyword_ty kw; identifier key; /* CHILD(ch, 0) is test, but must be an identifier? */ e = ast_for_expr(c, CHILD(ch, 0)); if (!e) return NULL; /* f(lambda x: x[0] = 3) ends up getting parsed with * LHS test = lambda x: x[0], and RHS test = 3. * SF bug 132313 points out that complaining about a keyword * then is very confusing. */ if (e->kind == Lambda_kind) { ast_error(CHILD(ch, 0), "lambda cannot contain assignment"); return NULL; } else if (e->kind != Name_kind) { ast_error(CHILD(ch, 0), "keyword can't be an expression"); return NULL; } key = e->v.Name.id; e = ast_for_expr(c, CHILD(ch, 2)); if (!e) return NULL; kw = keyword(key, e, c->c_arena); if (!kw) return NULL; asdl_seq_SET(keywords, nkeywords++, kw); } } else if (TYPE(ch) == STAR) { vararg = ast_for_expr(c, CHILD(n, i+1)); i++; } else if (TYPE(ch) == DOUBLESTAR) { kwarg = ast_for_expr(c, CHILD(n, i+1)); i++; } } return Call(func, args, keywords, vararg, kwarg, func->lineno, func->col_offset, c->c_arena); } static expr_ty ast_for_testlist(struct compiling *c, const node* n) { /* testlist_gexp: test (',' test)* [','] */ /* testlist: test (',' test)* [','] */ /* testlist_safe: test (',' test)+ [','] */ /* testlist1: test (',' test)* */ assert(NCH(n) > 0); if (TYPE(n) == testlist_gexp) { if (NCH(n) > 1) assert(TYPE(CHILD(n, 1)) != gen_for); } else { assert(TYPE(n) == testlist || TYPE(n) == testlist_safe || TYPE(n) == testlist1); } if (NCH(n) == 1) return ast_for_expr(c, CHILD(n, 0)); else { asdl_seq *tmp = seq_for_testlist(c, n); if (!tmp) return NULL; return Tuple(tmp, Load, LINENO(n), n->n_col_offset, c->c_arena); } } static expr_ty ast_for_testlist_gexp(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) return ast_for_genexp(c, n); return ast_for_testlist(c, n); } /* like ast_for_testlist() but returns a sequence */ static asdl_seq* ast_for_class_bases(struct compiling *c, const node* n) { /* testlist: test (',' test)* [','] */ assert(NCH(n) > 0); REQ(n, testlist); if (NCH(n) == 1) { expr_ty base; asdl_seq *bases = asdl_seq_new(1, c->c_arena); if (!bases) return NULL; base = ast_for_expr(c, CHILD(n, 0)); if (!base) return NULL; asdl_seq_SET(bases, 0, base); return bases; } return seq_for_testlist(c, n); } static stmt_ty ast_for_expr_stmt(struct compiling *c, const node *n) { REQ(n, expr_stmt); /* expr_stmt: testlist (augassign (yield_expr|testlist) | ('=' (yield_expr|testlist))*) testlist: test (',' test)* [','] augassign: '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>>=' | '**=' | '//=' test: ... here starts the operator precendence dance */ if (NCH(n) == 1) { expr_ty e = ast_for_testlist(c, CHILD(n, 0)); if (!e) return NULL; return Expr(e, LINENO(n), n->n_col_offset, c->c_arena); } else if (TYPE(CHILD(n, 1)) == augassign) { expr_ty expr1, expr2; operator_ty newoperator; node *ch = CHILD(n, 0); expr1 = ast_for_testlist(c, ch); if (!expr1) return NULL; /* TODO(nas): Remove duplicated error checks (set_context does it) */ 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 = PyString_AS_STRING(expr1->v.Name.id); if (var_name[0] == 'N' && !strcmp(var_name, "None")) { ast_error(ch, "assignment to None"); return NULL; } break; } case Attribute_kind: case Subscript_kind: break; default: ast_error(ch, "illegal expression for augmented " "assignment"); return NULL; } if (!set_context(expr1, Store, ch))