Commits

Antonio Cuni  committed 50f3bcb

emit&implement DELETE_DEREF. This is equivalent to CPython's revision 25cc226dc9bd

  • Participants
  • Parent commits 9b692e4
  • Branches py3k

Comments (0)

Files changed (6)

File pypy/interpreter/astcompiler/assemble.py

     ops.LOAD_CLOSURE : 1,
     ops.LOAD_DEREF : 1,
     ops.STORE_DEREF : -1,
+    ops.DELETE_DEREF: 0,
 
     ops.LOAD_CONST : 1,
 

File pypy/interpreter/astcompiler/codegen.py

 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({
             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:

File pypy/interpreter/astcompiler/test/test_compiler.py

         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, """

File pypy/interpreter/nestedscope.py

         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)
 
         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):

File pypy/interpreter/test/test_nestedscope.py

                 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()")
+        """

File pypy/interpreter/test/test_syntax.py

         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
             print s
             print '%s: %s' % (e.__class__, e)
             print '-'*60
+