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

Reply via email to