[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