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