diff options
Diffstat (limited to 'Python/ast.c')
| -rw-r--r-- | Python/ast.c | 126 | 
1 files changed, 90 insertions, 36 deletions
diff --git a/Python/ast.c b/Python/ast.c index f3e611b8e3..ca832aa5e1 100644 --- a/Python/ast.c +++ b/Python/ast.c @@ -339,7 +339,7 @@ set_context(expr_ty e, expr_context_ty ctx, const node *n)      /* The ast defines augmented store and load contexts, but the         implementation here doesn't actually use them.  The code may be         a little more complex than necessary as a result.  It also means -       that expressions in an augmented assignment have no context. +       that expressions in an augmented assignment have a Store context.         Consider restructuring so that augmented assignment uses         set_context(), too.      */ @@ -387,6 +387,9 @@ set_context(expr_ty e, expr_context_ty ctx, const node *n)          case GeneratorExp_kind:              expr_name = "generator expression";              break; +        case Yield_kind: +            expr_name = "yield expression"; +            break;          case ListComp_kind:              expr_name = "list comprehension";              break; @@ -619,10 +622,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 go to NULL; nothing allocated */ +    	return NULL; /* Don't need to goto error; no objects allocated */      defaults = (n_defaults ? asdl_seq_new(n_defaults, c->c_arena) : NULL);      if (!defaults && n_defaults) -        goto error; +    	return NULL; /* Don't need to goto error; no objects allocated */      /* fpdef: NAME | '(' fplist ')'         fplist: fpdef (',' fpdef)* [','] @@ -638,8 +641,11 @@ ast_for_arguments(struct compiling *c, const node *n)                     anything other than EQUAL or a comma? */                  /* XXX Should NCH(n) check be made a separate check? */                  if (i + 1 < NCH(n) && TYPE(CHILD(n, i + 1)) == EQUAL) { -                    asdl_seq_SET(defaults, j++,  -				    ast_for_expr(c, CHILD(n, i + 2))); +                    expr_ty expression = ast_for_expr(c, CHILD(n, i + 2)); +                    if (!expression) +                            goto error; +                    assert(defaults != NULL); +                    asdl_seq_SET(defaults, j++, expression);                      i += 2;  		    found_default = 1;                  } @@ -1484,6 +1490,57 @@ ast_for_trailer(struct compiling *c, const node *n, expr_ty left_expr)  }  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)* @@ -1662,30 +1719,12 @@ ast_for_expr(struct compiling *c, const node *n)  	    }  	    return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena);  	} -        case factor: { -            expr_ty expression; -             +        case factor:              if (NCH(n) == 1) {                  n = CHILD(n, 0);                  goto loop;              } - -            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))); -            break; -        } +	    return ast_for_factor(c, n);          case power:              return ast_for_power(c, n);          default: @@ -1893,20 +1932,19 @@ ast_for_expr_stmt(struct compiling *c, const node *n)          operator_ty newoperator;  	node *ch = CHILD(n, 0); -	if (TYPE(ch) == testlist) -	    expr1 = ast_for_testlist(c, ch); -	else -	    expr1 = Yield(ast_for_expr(c, CHILD(ch, 0)), LINENO(ch), n->n_col_offset, -                          c->c_arena); - +	expr1 = ast_for_testlist(c, ch);          if (!expr1)              return NULL; -        /* TODO(jhylton): Figure out why set_context() can't be used here. */ +        /* 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")) { @@ -1923,12 +1961,13 @@ ast_for_expr_stmt(struct compiling *c, const node *n)                            "assignment");                  return NULL;          } +	set_context(expr1, Store, ch);  	ch = CHILD(n, 2);  	if (TYPE(ch) == testlist)  	    expr2 = ast_for_testlist(c, ch);  	else -	    expr2 = Yield(ast_for_expr(c, ch), LINENO(ch), ch->n_col_offset, c->c_arena); +	    expr2 = ast_for_expr(c, ch);          if (!expr2)              return NULL; @@ -2142,7 +2181,14 @@ alias_for_import_name(struct compiling *c, const node *n)   loop:      switch (TYPE(n)) {          case import_as_name: -            str = (NCH(n) == 3) ? NEW_IDENTIFIER(CHILD(n, 2)) : NULL; +            str = NULL; +            if (NCH(n) == 3) { +                if (strcmp(STR(CHILD(n, 1)), "as") != 0) { +                    ast_error(n, "must use 'as' in import"); +                    return NULL; +                } +                str = NEW_IDENTIFIER(CHILD(n, 2)); +            }              return alias(NEW_IDENTIFIER(CHILD(n, 0)), str, c->c_arena);          case dotted_as_name:              if (NCH(n) == 1) { @@ -2151,6 +2197,10 @@ alias_for_import_name(struct compiling *c, const node *n)              }              else {                  alias_ty a = alias_for_import_name(c, CHILD(n, 0)); +                if (strcmp(STR(CHILD(n, 1)), "as") != 0) { +                    ast_error(n, "must use 'as' in import"); +                    return NULL; +                }                  assert(!a->asname);                  a->asname = NEW_IDENTIFIER(CHILD(n, 2));                  return a; @@ -2621,6 +2671,7 @@ ast_for_for_stmt(struct compiling *c, const node *n)      asdl_seq *_target, *seq = NULL, *suite_seq;      expr_ty expression;      expr_ty target; +    const node *node_target;      /* for_stmt: 'for' exprlist 'in' testlist ':' suite ['else' ':' suite] */      REQ(n, for_stmt); @@ -2630,10 +2681,13 @@ ast_for_for_stmt(struct compiling *c, const node *n)              return NULL;      } -    _target = ast_for_exprlist(c, CHILD(n, 1), Store); +    node_target = CHILD(n, 1); +    _target = ast_for_exprlist(c, node_target, Store);      if (!_target)          return NULL; -    if (asdl_seq_LEN(_target) == 1) +    /* Check the # of children rather than the length of _target, since +       for x, in ... has 1 element in _target, but still requires a Tuple. */ +    if (NCH(node_target) == 1)  	target = (expr_ty)asdl_seq_GET(_target, 0);      else  	target = Tuple(_target, Store, LINENO(n), n->n_col_offset, c->c_arena);  | 
