Author: Colin Valliant <alcarithe...@gmail.com> Branch: pep526 Changeset: r93914:61124ea0a2b7 Date: 2018-02-13 23:23 -0800 http://bitbucket.org/pypy/pypy/changeset/61124ea0a2b7/
Log: Make astbuilder produce AnnAssign nodes for variable annotations. diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py --- a/pypy/interpreter/astcompiler/astbuilder.py +++ b/pypy/interpreter/astcompiler/astbuilder.py @@ -737,6 +737,7 @@ raise AssertionError("unknown statment type") def handle_expr_stmt(self, stmt): + from pypy.interpreter.pyparser.parser import AbstractNonterminal if stmt.num_children() == 1: expression = self.handle_testlist(stmt.get_child(0)) return ast.Expr(expression, stmt.get_lineno(), stmt.get_column()) @@ -754,6 +755,44 @@ operator = augassign_operator_map[op_str] return ast.AugAssign(target_expr, operator, value_expr, stmt.get_lineno(), stmt.get_column()) + elif stmt.get_child(1).type == syms.annassign: + # Variable annotation (PEP 526), which may or may not include assignment. + target = stmt.get_child(0) + target_expr = self.handle_testlist(target) + simple = 0 + # target is a name, nothing funky + if isinstance(target_expr, ast.Name): + # The PEP demands that `(x): T` be treated differently than `x: T` + # however, the parser does not easily expose the wrapping parens, which are a no-op + # they are elided by handle_testlist if they existed. + # so here we walk down the parse tree until we hit a terminal, and check whether it's + # a left paren + simple_test = target.get_child(0) + while isinstance(simple_test, AbstractNonterminal): + simple_test = simple_test.get_child(0) + if simple_test.type != tokens.LPAR: + simple = 1 + # subscripts are allowed with nothing special + elif isinstance(target_expr, ast.Subscript): + pass + # attributes are also fine here + elif isinstance(target_expr, ast.Attribute): + pass + # tuples and lists get special error messages + elif isinstance(target_expr, ast.Tuple): + self.error("only single target (not tuple) can be annotated", target) + elif isinstance(target_expr, ast.List): + self.error("only single target (not list) can be annotated", target) + # and everything else gets a generic error + else: + self.error("illegal target for annoation", target) + self.set_context(target_expr, ast.Store) + second = stmt.get_child(1) + annotation = self.handle_expr(second.get_child(1)) + value_expr = None + if second.num_children() == 4: + value_expr = self.handle_testlist(second.get_child(-1)) + return ast.AnnAssign(target_expr, annotation, value_expr, simple, stmt.get_lineno(), stmt.get_column()) else: # Normal assignment. targets = [] _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit