[pypy-commit] pypy py3k: emit&implement DELETE_DEREF. This is equivalent to CPython's revision 25cc226dc9bd
antocuni
noreply at buildbot.pypy.org
Mon Sep 3 20:52:46 CEST 2012
Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: py3k
Changeset: r57107:50f3bcb78348
Date: 2012-09-03 20:52 +0200
http://bitbucket.org/pypy/pypy/changeset/50f3bcb78348/
Log: emit&implement DELETE_DEREF. This is equivalent to CPython's
revision 25cc226dc9bd
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
@@ -580,6 +580,7 @@
ops.LOAD_CLOSURE : 1,
ops.LOAD_DEREF : 1,
ops.STORE_DEREF : -1,
+ ops.DELETE_DEREF: 0,
ops.LOAD_CONST : 1,
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -35,6 +35,7 @@
name_ops_deref = misc.dict_to_switch({
ast.Load : ops.LOAD_DEREF,
ast.Store : ops.STORE_DEREF,
+ ast.Del : ops.DELETE_DEREF,
})
name_ops_global = misc.dict_to_switch({
@@ -213,12 +214,7 @@
op = name_ops_deref(ctx)
container = self.free_vars
elif scope == symtable.SCOPE_CELL:
- try:
- op = name_ops_deref(ctx)
- except KeyError:
- assert ctx == ast.Del
- raise SyntaxError("Can't delete variable used in "
- "nested scopes: '%s'" % (identifier,))
+ op = name_ops_deref(ctx)
container = self.cell_vars
elif scope == symtable.SCOPE_GLOBAL_IMPLICIT:
if self.scope.optimized:
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
@@ -478,14 +478,6 @@
yield self.st, decl, 'A,A1,A2,B2,C,C1,C2,D1,E,G,G1,G2,N1', \
(6,6 ,4 ,1 ,5,5 ,5 ,3 ,8,2,2 ,2 ,7 )
- source = """if 1:
- def f(a):
- del a
- def x():
- a
- """
- exc = py.test.raises(SyntaxError, self.run, source).value
- assert exc.msg == "Can't delete variable used in nested scopes: 'a'"
def test_try_except_finally(self):
yield self.simple_test, """
diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -202,15 +202,7 @@
try:
w_value = cell.get()
except ValueError:
- varname = self.getfreevarname(varindex)
- if self.iscellvar(varindex):
- message = "local variable '%s' referenced before assignment"%varname
- w_exc_type = self.space.w_UnboundLocalError
- else:
- message = ("free variable '%s' referenced before assignment"
- " in enclosing scope"%varname)
- w_exc_type = self.space.w_NameError
- raise OperationError(w_exc_type, self.space.wrap(message))
+ self.raise_exc_unbound(varindex)
else:
self.pushvalue(w_value)
@@ -221,7 +213,24 @@
cell.set(w_newvalue)
def DELETE_DEREF(self, varindex, next_instr):
- raise NotImplementedError
+ cell = self.cells[varindex]
+ try:
+ cell.get()
+ except ValueError:
+ self.raise_exc_unbound(varindex)
+ else:
+ cell.set(None)
+
+ def raise_exc_unbound(self, varindex):
+ varname = self.getfreevarname(varindex)
+ if self.iscellvar(varindex):
+ message = "local variable '%s' referenced before assignment"%varname
+ w_exc_type = self.space.w_UnboundLocalError
+ else:
+ message = ("free variable '%s' referenced before assignment"
+ " in enclosing scope"%varname)
+ w_exc_type = self.space.w_NameError
+ raise OperationError(w_exc_type, self.space.wrap(message))
@jit.unroll_safe
def MAKE_CLOSURE(self, oparg, next_instr):
diff --git a/pypy/interpreter/test/test_nestedscope.py b/pypy/interpreter/test/test_nestedscope.py
--- a/pypy/interpreter/test/test_nestedscope.py
+++ b/pypy/interpreter/test/test_nestedscope.py
@@ -122,3 +122,27 @@
return x
return m
assert f()() == 12
+
+
+ def test_unbound_local_after_del(self):
+ """
+ # #4617: It is now legal to delete a cell variable.
+ # The following functions must obviously compile,
+ # and give the correct error when accessing the deleted name.
+ def errorInOuter():
+ y = 1
+ del y
+ print(y)
+ def inner():
+ return y
+
+ def errorInInner():
+ def inner():
+ return y
+ y = 1
+ del y
+ inner()
+
+ raises(UnboundLocalError, "errorInOuter()")
+ raises(NameError, "errorInInner()")
+ """
diff --git a/pypy/interpreter/test/test_syntax.py b/pypy/interpreter/test/test_syntax.py
--- a/pypy/interpreter/test/test_syntax.py
+++ b/pypy/interpreter/test/test_syntax.py
@@ -671,6 +671,18 @@
raises(SyntaxError, exec, program)
'''
+ def test_exception_target_in_nested_scope(self):
+ # issue 4617: This used to raise a SyntaxError
+ # "can not delete variable 'e' referenced in nested scope"
+ def print_error():
+ e
+ try:
+ something
+ except Exception as e:
+ print_error()
+ # implicit "del e" here
+
+
if __name__ == '__main__':
# only to check on top of CPython (you need 2.4)
from py.test import raises
@@ -690,3 +702,4 @@
print s
print '%s: %s' % (e.__class__, e)
print '-'*60
+
More information about the pypy-commit
mailing list