[pypy-commit] pypy py3k: follow up to 1f716034739d: use a set (actually a dict) to avoid potential

pjenvey noreply at buildbot.pypy.org
Sun Aug 3 01:04:58 CEST 2014


Author: Philip Jenvey <pjenvey at underboss.org>
Branch: py3k
Changeset: r72656:ae5b2d7eb9e3
Date: 2014-08-02 16:03 -0700
http://bitbucket.org/pypy/pypy/changeset/ae5b2d7eb9e3/

Log:	follow up to 1f716034739d: use a set (actually a dict) to avoid
	potential duplicates in free_vars and ensure has_free is now set

diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -7,7 +7,7 @@
 from pypy.tool import stdlib_opcode as ops
 
 from pypy.interpreter.error import OperationError
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import specialize, we_are_translated
 from rpython.rlib import rfloat
 
 
@@ -141,11 +141,12 @@
             i += 1
     return result
 
-def _list_to_dict(l, offset=0):
+ at specialize.argtype(0)
+def _iter_to_dict(iterable, offset=0):
     result = {}
     index = offset
-    for i in range(len(l)):
-        result[l[i]] = index
+    for item in iterable:
+        result[item] = index
         index += 1
     return result
 
@@ -161,10 +162,10 @@
         self.first_block = self.new_block()
         self.use_block(self.first_block)
         self.names = {}
-        self.var_names = _list_to_dict(scope.varnames)
+        self.var_names = _iter_to_dict(scope.varnames)
         self.cell_vars = _make_index_dict_filter(scope.symbols,
                                                  symtable.SCOPE_CELL)
-        self.free_vars = _list_to_dict(scope.free_vars, len(self.cell_vars))
+        self.free_vars = _iter_to_dict(scope.free_vars, len(self.cell_vars))
         self.w_consts = space.newdict()
         self.argcount = 0
         self.kwonlyargcount = 0
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
@@ -37,7 +37,7 @@
         self.roles = {}
         self.varnames = []
         self.children = []
-        self.free_vars = []
+        self.free_vars = {}
         self.temp_name_counter = 1
         self.has_free = False
         self.child_has_free = False
@@ -136,8 +136,9 @@
                 err = "no binding for nonlocal '%s' found" % (name,)
                 raise SyntaxError(err, self.lineno, self.col_offset)
             self.symbols[name] = SCOPE_FREE
-            self.free_vars.append(name)
+            self.free_vars[name] = None
             free[name] = None
+            self.has_free = True
         elif flags & SYM_BOUND:
             self.symbols[name] = SCOPE_LOCAL
             local[name] = None
@@ -147,7 +148,7 @@
                 pass
         elif bound and name in bound:
             self.symbols[name] = SCOPE_FREE
-            self.free_vars.append(name)
+            self.free_vars[name] = None
             free[name] = None
             self.has_free = True
         elif name in globs:
@@ -204,7 +205,7 @@
             except KeyError:
                 if name in bound:
                     self.symbols[name] = SCOPE_FREE
-                    self.free_vars.append(name)
+                    self.free_vars[name] = None
             else:
                 if role_here & (SYM_BOUND | SYM_GLOBAL) and \
                         self._hide_bound_from_nested_scopes:
@@ -213,7 +214,7 @@
                     # 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.free_vars[name] = None
         self._check_optimization()
         free.update(new_free)
 
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -819,6 +819,17 @@
             return test2()"""
         yield self.st, test, "test1(2)", 2
 
+    def test_class_nonlocal_from_arg(self):
+        test = """if 1:
+        def f(x):
+            class c:
+                nonlocal x
+                x += 1
+                def get(self):
+                    return x
+            return c().get()"""
+        yield self.st, test, "f(3)", 4
+
     def test_lots_of_loops(self):
         source = "for x in y: pass\n" * 1000
         compile_with_astcompiler(source, 'exec', self.space)


More information about the pypy-commit mailing list