Author: Ronan Lamy <ronan.l...@gmail.com>
Branch: translation-cleanup
Changeset: r57987:e1b4d5fe6b2d
Date: 2012-10-10 20:28 +0100
http://bitbucket.org/pypy/pypy/changeset/e1b4d5fe6b2d/

Log:    Disable closure creation in RPython

        * Trying to build the flow graph of a function whose code object
        contains cellvars (i.e. a function that creates closures, possibly
        in unreachable code) now raises an error up front.
        * Explicitly disable closure-supporting opcodes LOAD_CLOSURE,
        MAKE_CLOSURE, and STORE_DEREF.
        * Xfail tests for closure support (don't delete them yet as they are a
        bit tricky to get right).

diff --git a/pypy/objspace/flow/bytecode.py b/pypy/objspace/flow/bytecode.py
--- a/pypy/objspace/flow/bytecode.py
+++ b/pypy/objspace/flow/bytecode.py
@@ -38,23 +38,8 @@
         self.co_firstlineno = firstlineno
         self.co_lnotab = lnotab
         self.signature = cpython_code_signature(self)
-        self._initialize()
-
-    def _initialize(self):
-        # Precompute what arguments need to be copied into cellvars
-        self._args_as_cellvars = {}
-
         if self.co_cellvars:
-            # Cell vars could shadow already-set arguments.
-            # See comment in PyCode._initialize()
-            argvars  = self.co_varnames
-            cellvars = self.co_cellvars
-            for i in range(len(cellvars)):
-                cellname = cellvars[i]
-                for j in range(self.formalargcount):
-                    if cellname == argvars[j]:
-                        # argument j has the same name as the cell var i
-                        self._args_as_cellvars[i] = j
+            raise ValueError("RPython functions cannot create closures")
 
     @classmethod
     def _from_code(cls, code):
diff --git a/pypy/objspace/flow/flowcontext.py 
b/pypy/objspace/flow/flowcontext.py
--- a/pypy/objspace/flow/flowcontext.py
+++ b/pypy/objspace/flow/flowcontext.py
@@ -252,16 +252,8 @@
 
     def restore_locals_stack(self, items_w):
         self.locals_stack_w[:len(items_w)] = items_w
-        self.init_cells()
         self.dropvaluesuntil(len(items_w))
 
-    def init_cells(self):
-        if self.cells is None:
-            return
-        args_to_copy = self.pycode._args_as_cellvars
-        for cellnum, argnum in args_to_copy.iteritems():
-            self.cells[cellnum].set(self.locals_stack_w[argnum])
-
     def getstate(self):
         # getfastscope() can return real None, for undefined locals
         data = self.save_locals_stack()
@@ -712,6 +704,12 @@
     def MAP_ADD(self, oparg, next_instr):
         raise NotImplementedError("MAP_ADD")
 
+    # Closures
+
+    STORE_DEREF = BAD_OPCODE
+    LOAD_CLOSURE = BAD_OPCODE
+    MAKE_CLOSURE = BAD_OPCODE
+
     def make_arguments(self, nargs):
         return ArgumentsForTranslation(self.space, self.peekvalues(nargs))
     def argument_factory(self, *args):
diff --git a/pypy/objspace/flow/test/test_objspace.py 
b/pypy/objspace/flow/test/test_objspace.py
--- a/pypy/objspace/flow/test/test_objspace.py
+++ b/pypy/objspace/flow/test/test_objspace.py
@@ -1054,6 +1054,7 @@
         with py.test.raises(FlowingError):
             self.codetest(f)
 
+    @py.test.mark.xfail(reason="closures aren't supported")
     def test_cellvar_store(self):
         def f():
             x = 5
@@ -1063,6 +1064,7 @@
         assert len(graph.startblock.exits) == 1
         assert graph.startblock.exits[0].target == graph.returnblock
 
+    @py.test.mark.xfail(reason="closures aren't supported")
     def test_arg_as_cellvar(self):
         def f(x, y, z):
             a, b, c = 1, 2, 3
@@ -1101,6 +1103,25 @@
         with py.test.raises(FlowingError):
             self.codetest(f2)
 
+    @py.test.mark.xfail(reason="closures aren't supported")
+    def test_closure(self):
+        def f():
+            m = 5
+            return lambda n: m * n
+        graph = self.codetest(f)
+        assert len(graph.startblock.exits) == 1
+        assert graph.startblock.exits[0].target == graph.returnblock
+        g = graph.startblock.exits[0].args[0].value
+        assert g(4) == 20
+
+    def test_closure_error(self):
+        def f():
+            m = 5
+            return lambda n: m * n
+        with py.test.raises(ValueError) as excinfo:
+            self.codetest(f)
+        assert "closure" in str(excinfo.value)
+
 DATA = {'x': 5,
         'y': 6}
 
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to