[pypy-commit] pypy pep526: Handle AnnAssign in symtable building (WIP).

alcarithemad pypy.commits at gmail.com
Thu Mar 1 05:07:54 EST 2018


Author: Colin Valliant <alcarithemad at gmail.com>
Branch: pep526
Changeset: r93916:e3f0d3b1a562
Date: 2018-02-13 23:25 -0800
http://bitbucket.org/pypy/pypy/changeset/e3f0d3b1a562/

Log:	Handle AnnAssign in symtable building (WIP).

diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py
--- a/pypy/interpreter/astcompiler/symtable.py
+++ b/pypy/interpreter/astcompiler/symtable.py
@@ -12,6 +12,7 @@
 SYM_PARAM = 2 << 1
 SYM_NONLOCAL = 2 << 2
 SYM_USED = 2 << 3
+SYM_ANNOTATED = 2 << 4
 SYM_BOUND = (SYM_PARAM | SYM_ASSIGNED)
 
 # codegen.py actually deals with these:
@@ -44,6 +45,7 @@
         self.child_has_free = False
         self.nested = False
         self.doc_removable = False
+        self.contains_annotated = False
         self._in_try_body_depth = 0
 
     def lookup(self, name):
@@ -139,7 +141,7 @@
                 self.free_vars.append(name)
             free[name] = None
             self.has_free = True
-        elif flags & SYM_BOUND:
+        elif flags & (SYM_BOUND | SYM_ANNOTATED):
             self.symbols[name] = SCOPE_LOCAL
             local[name] = None
             try:
@@ -420,6 +422,18 @@
         self.scope.note_return(ret)
         ast.GenericASTVisitor.visit_Return(self, ret)
 
+    def visit_AnnAssign(self, assign):
+        # __annotations__ is not setup or used in functions.
+        if not isinstance(self.scope, FunctionScope):
+            self.scope.contains_annotated = True
+        target = assign.target
+        if isinstance(target, ast.Name):
+            scope = SYM_ANNOTATED
+            name = target.id
+            if assign.value:
+                scope |= SYM_USED
+            self.note_symbol(name, scope)
+
     def visit_ClassDef(self, clsdef):
         self.note_symbol(clsdef.name, SYM_ASSIGNED)
         self.visit_sequence(clsdef.bases)
@@ -485,10 +499,13 @@
                 msg = "name '%s' is nonlocal and global" % (name,)
                 raise SyntaxError(msg, glob.lineno, glob.col_offset)
 
-            if old_role & (SYM_USED | SYM_ASSIGNED):
+            if old_role & (SYM_USED | SYM_ASSIGNED | SYM_ANNOTATED):
                 if old_role & SYM_ASSIGNED:
                     msg = "name '%s' is assigned to before global declaration"\
                         % (name,)
+                elif old_role & SYM_ANNOTATED:
+                    msg = "annotated name '%s' can't be global" \
+                        % (name,)
                 else:
                     msg = "name '%s' is used prior to global declaration" % \
                         (name,)
@@ -498,6 +515,7 @@
     def visit_Nonlocal(self, nonl):
         for name in nonl.names:
             old_role = self.scope.lookup_role(name)
+            print(name, old_role)
             msg = ""
             if old_role & SYM_GLOBAL:
                 msg = "name '%s' is nonlocal and global" % (name,)
@@ -505,6 +523,9 @@
                 msg = "name '%s' is parameter and nonlocal" % (name,)
             if isinstance(self.scope, ModuleScope):
                 msg = "nonlocal declaration not allowed at module level"
+            if old_role & SYM_ANNOTATED:
+                msg = "annotated name '%s' can't be nonlocal" \
+                    % (name,)
             if msg is not "":
                 raise SyntaxError(msg, nonl.lineno, nonl.col_offset)
 


More information about the pypy-commit mailing list