[pypy-svn] r66244 - in pypy/branch/parser-compiler/pypy/interpreter/astcompiler: . test

benjamin at codespeak.net benjamin at codespeak.net
Wed Jul 15 20:25:14 CEST 2009


Author: benjamin
Date: Wed Jul 15 20:25:14 2009
New Revision: 66244

Modified:
   pypy/branch/parser-compiler/pypy/interpreter/astcompiler/symtable.py
   pypy/branch/parser-compiler/pypy/interpreter/astcompiler/test/test_symtable.py
Log:
fix a corner case of passing free vars through class scopes

Modified: pypy/branch/parser-compiler/pypy/interpreter/astcompiler/symtable.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/astcompiler/symtable.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/astcompiler/symtable.py	Wed Jul 15 20:25:14 2009
@@ -33,6 +33,7 @@
         self.roles = {}
         self.varnames = []
         self.children = []
+        self.free_vars = []
         self.has_free = False
         self.child_has_free = False
         self.nested = False
@@ -103,6 +104,7 @@
                 pass
         elif bound and name in bound:
             self.symbols[name] = SCOPE_FREE
+            self.free_vars.append(name)
             free[name] = None
             self.has_free = True
         elif name in globs:
@@ -152,10 +154,16 @@
             except KeyError:
                 if name in bound:
                     self.symbols[name] = SCOPE_FREE
+                    self.free_vars.append(name)
             else:
-                if role_here & (SYM_ASSIGNED | SYM_GLOBAL) and \
+                if role_here & (SYM_BOUND | SYM_GLOBAL) and \
                         self._hide_bound_from_nested_scopes:
-                    self.symbols[name] = SCOPE_FREE
+                    # This happens when a class level attribute or method has
+                    # the same name as a free variable passing through the class
+                    # scope.  We add the name to the class scope's list of free
+                    # vars, so it will be passed through by the interpreter, but
+                    # we leave the scope alone, so it can be local on its own.
+                    self.free_vars.append(name)
         self._check_optimization()
         free.update(new_free)
 

Modified: pypy/branch/parser-compiler/pypy/interpreter/astcompiler/test/test_symtable.py
==============================================================================
--- pypy/branch/parser-compiler/pypy/interpreter/astcompiler/test/test_symtable.py	(original)
+++ pypy/branch/parser-compiler/pypy/interpreter/astcompiler/test/test_symtable.py	Wed Jul 15 20:25:14 2009
@@ -180,6 +180,18 @@
         fscp = cscp.children[0]
         assert fscp.lookup("x") == symtable.SCOPE_FREE
         self.check_unknown(fscp, "a")
+        scp = self.func_scope("""def f(n):
+    class X:
+         def n():
+             return y
+         def x():
+             return n""")
+        assert scp.lookup("n") == symtable.SCOPE_CELL
+        cscp = scp.children[0]
+        assert cscp.lookup("n") == symtable.SCOPE_LOCAL
+        assert "n" in cscp.free_vars
+        xscp = cscp.children[1]
+        assert xscp.lookup("n") == symtable.SCOPE_FREE
 
     def test_lambda(self):
         scp = self.mod_scope("lambda x: y")



More information about the Pypy-commit mailing list