Author: Ronan Lamy <[email protected]>
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
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit