Author: Ronan Lamy <[email protected]>
Branch: 
Changeset: r68367:bb3fa3d8d35b
Date: 2013-12-03 16:26 +0000
http://bitbucket.org/pypy/pypy/changeset/bb3fa3d8d35b/

Log:    Handle empty cells in flowspace: don't explode if they are not
        actually used, give a nice error message if they are.

diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -329,7 +329,7 @@
         if closure is None:
             self.closure = []
         else:
-            self.closure = [const(c.cell_contents) for c in closure]
+            self.closure = list(closure)
         assert len(self.closure) == len(self.pycode.co_freevars)
 
     def init_locals_stack(self, code):
@@ -846,7 +846,13 @@
     LOOKUP_METHOD = LOAD_ATTR
 
     def LOAD_DEREF(self, varindex):
-        self.pushvalue(self.closure[varindex])
+        cell = self.closure[varindex]
+        try:
+            content = cell.cell_contents
+        except ValueError:
+            name = self.pycode.co_freevars[varindex]
+            raise FlowingError("Undefined closure variable '%s'" % name)
+        self.pushvalue(const(content))
 
     def STORE_FAST(self, varindex):
         w_newvalue = self.popvalue()
diff --git a/rpython/flowspace/test/test_objspace.py 
b/rpython/flowspace/test/test_objspace.py
--- a/rpython/flowspace/test/test_objspace.py
+++ b/rpython/flowspace/test/test_objspace.py
@@ -1212,6 +1212,39 @@
         graph = self.codetest(f)
         assert 'getattr' in self.all_operations(graph)
 
+    def test_empty_cell_unused(self):
+        def test(flag):
+            if flag:
+                b = 5
+            def g():
+                if flag:
+                    return b
+                else:
+                    return 1
+            return g
+        g1 = test(False)
+        graph = self.codetest(g1)
+        assert not self.all_operations(graph)
+        g2 = test(True)
+        graph = self.codetest(g2)
+        assert not self.all_operations(graph)
+
+    def test_empty_cell_error(self):
+        def test(flag):
+            if not flag:
+                b = 5
+            def g():
+                if flag:
+                    return b
+                else:
+                    return 1
+            return g
+        g = test(True)
+        with py.test.raises(FlowingError) as excinfo:
+            graph = self.codetest(g)
+        assert "Undefined closure variable 'b'" in str(excinfo.value)
+
+
 DATA = {'x': 5,
         'y': 6}
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to