[pypy-commit] pypy flow-no-local-exception: Fix the flow space and the annotator

arigo noreply at buildbot.pypy.org
Thu Aug 1 10:42:19 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: flow-no-local-exception
Changeset: r65868:82f7913e20b5
Date: 2013-07-31 12:26 +0200
http://bitbucket.org/pypy/pypy/changeset/82f7913e20b5/

Log:	Fix the flow space and the annotator

diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py
--- a/rpython/annotator/binaryop.py
+++ b/rpython/annotator/binaryop.py
@@ -32,7 +32,6 @@
                          'and_', 'or_', 'xor',
                          'lshift', 'rshift',
                          'getitem', 'setitem', 'delitem',
-                         'getitem_idx', 'getitem_key', 'getitem_idx_key',
                          'inplace_add', 'inplace_sub', 'inplace_mul',
                          'inplace_truediv', 'inplace_floordiv', 'inplace_div',
                          'inplace_mod',
@@ -181,20 +180,6 @@
         else:
             return obj
 
-    # checked getitems
-
-    def _getitem_can_only_throw(s_c1, s_o2):
-        impl = pair(s_c1, s_o2).getitem
-        return read_can_only_throw(impl, s_c1, s_o2)
-
-    def getitem_idx_key((s_c1, s_o2)):
-        impl = pair(s_c1, s_o2).getitem
-        return impl()
-    getitem_idx_key.can_only_throw = _getitem_can_only_throw
-
-    getitem_idx = getitem_idx_key
-    getitem_key = getitem_idx_key
-
 
 class __extend__(pairtype(SomeType, SomeType)):
 
@@ -419,9 +404,11 @@
 class __extend__(pairtype(SomeByteArray, SomeInteger)):
     def getitem((s_b, s_i)):
         return SomeInteger()
+    getitem.can_only_throw = []
 
     def setitem((s_b, s_i), s_i2):
         assert isinstance(s_i2, SomeInteger)
+    setitem.can_only_throw = []
 
 class __extend__(pairtype(SomeString, SomeByteArray),
                  pairtype(SomeByteArray, SomeString),
@@ -614,11 +601,12 @@
             try:
                 return tup1.items[int2.const]
             except IndexError:
-                return s_ImpossibleValue
+                raise Exception("tuple of %d elements indexed with [%s]" % (
+                    len(tup1.items), int2.const))
         else:
             getbookkeeper().count("tuple_random_getitem", tup1)
             return unionof(*tup1.items)
-    getitem.can_only_throw = [IndexError]
+    getitem.can_only_throw = []
 
 
 class __extend__(pairtype(SomeList, SomeInteger)):
@@ -631,25 +619,16 @@
         return lst1.listdef.read_item()
     getitem.can_only_throw = []
 
-    getitem_key = getitem
-
-    def getitem_idx((lst1, int2)):
-        getbookkeeper().count("list_getitem", int2)
-        return lst1.listdef.read_item()
-    getitem_idx.can_only_throw = [IndexError]
-
-    getitem_idx_key = getitem_idx
-
     def setitem((lst1, int2), s_value):
         getbookkeeper().count("list_setitem", int2)
         lst1.listdef.mutate()
         lst1.listdef.generalize(s_value)
-    setitem.can_only_throw = [IndexError]
+    setitem.can_only_throw = []
 
     def delitem((lst1, int2)):
         getbookkeeper().count("list_delitem", int2)
         lst1.listdef.resize()
-    delitem.can_only_throw = [IndexError]
+    delitem.can_only_throw = []
 
 class __extend__(pairtype(SomeString, SomeInteger)):
 
@@ -658,15 +637,6 @@
         return SomeChar(no_nul=str1.no_nul)
     getitem.can_only_throw = []
 
-    getitem_key = getitem
-
-    def getitem_idx((str1, int2)):
-        getbookkeeper().count("str_getitem", int2)
-        return SomeChar(no_nul=str1.no_nul)
-    getitem_idx.can_only_throw = [IndexError]
-
-    getitem_idx_key = getitem_idx
-
     def mul((str1, int2)): # xxx do we want to support this
         getbookkeeper().count("str_mul", str1, int2)
         return SomeString(no_nul=str1.no_nul)
@@ -677,15 +647,6 @@
         return SomeUnicodeCodePoint()
     getitem.can_only_throw = []
 
-    getitem_key = getitem
-
-    def getitem_idx((str1, int2)):
-        getbookkeeper().count("str_getitem", int2)
-        return SomeUnicodeCodePoint()
-    getitem_idx.can_only_throw = [IndexError]
-
-    getitem_idx_key = getitem_idx
-
     def mul((str1, int2)): # xxx do we want to support this
         getbookkeeper().count("str_mul", str1, int2)
         return SomeUnicodeString()
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -634,10 +634,10 @@
 
     def test_operation_always_raising(self):
         def operation_always_raising(n):
-            lst = []
+            dct = {}
             try:
-                return lst[n]
-            except IndexError:
+                return dct[n]
+            except KeyError:
                 return 24
         a = self.RPythonAnnotator()
         s = a.build_types(operation_always_raising, [int])
@@ -799,13 +799,13 @@
         def f(l):
             try:
                 l[0]
-            except (KeyError, IndexError),e:
+            except KeyError, e:    # ignored because 'l' is a list
                 return e
             return None
 
         a = self.RPythonAnnotator()
         s = a.build_types(f, [somelist(annmodel.s_Int)])
-        assert s.classdef is a.bookkeeper.getuniqueclassdef(IndexError)  # KeyError ignored because l is a list
+        assert s == annmodel.s_None
 
     def test_freeze_protocol(self):
         class Stuff:
diff --git a/rpython/flowspace/objspace.py b/rpython/flowspace/objspace.py
--- a/rpython/flowspace/objspace.py
+++ b/rpython/flowspace/objspace.py
@@ -186,6 +186,11 @@
         if check_class in (NotImplementedError, AssertionError):
             raise FlowingError(self.frame,
                 "Catching %s is not valid in RPython" % check_class.__name__)
+        if check_class == IndexError:
+            raise FlowingError(self.frame,
+                "Catching IndexError is not valid any more in RPython.  "
+                "You should check explicitly that the index is valid "
+                "before you use it")
         if not isinstance(check_class, tuple):
             # the simple case
             return self.exception_issubclass_w(w_exc_type, w_check_class)
diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py
--- a/rpython/flowspace/operation.py
+++ b/rpython/flowspace/operation.py
@@ -247,18 +247,17 @@
 
 op_appendices = {
     OverflowError: 'ovf',
-    IndexError: 'idx',
     KeyError: 'key',
     ZeroDivisionError: 'zer',
     ValueError: 'val',
     }
 
-# specifying IndexError, and KeyError beyond Exception,
+# specifying KeyError beyond Exception,
 # allows the annotator to be more precise, see test_reraiseAnything/KeyError in
 # the annotator tests
-op.getitem.canraise = [IndexError, KeyError, Exception]
-op.setitem.canraise = [IndexError, KeyError, Exception]
-op.delitem.canraise = [IndexError, KeyError, Exception]
+op.getitem.canraise = [KeyError, Exception]
+op.setitem.canraise = [KeyError, Exception]
+op.delitem.canraise = [KeyError, Exception]
 op.contains.canraise = [Exception]    # from an r_dict
 
 def _add_exceptions(names, exc):
diff --git a/rpython/flowspace/test/test_objspace.py b/rpython/flowspace/test/test_objspace.py
--- a/rpython/flowspace/test/test_objspace.py
+++ b/rpython/flowspace/test/test_objspace.py
@@ -329,7 +329,7 @@
                         found[link.args[0].value] = True
                     else:
                         found[link.exitcase] = None
-        assert found == {IndexError: True, KeyError: True, Exception: None}
+        assert found == {KeyError: True, Exception: None}
 
     def reraiseAnything(x):
         try:
@@ -372,7 +372,7 @@
 
     #__________________________________________________________
     def raise1(msg):
-        raise IndexError
+        raise ValueError
 
     def test_raise1(self):
         x = self.codetest(self.raise1)
@@ -381,7 +381,7 @@
         ops = x.startblock.operations
         assert len(ops) == 2
         assert ops[0].opname == 'simple_call'
-        assert ops[0].args == [Constant(IndexError)]
+        assert ops[0].args == [Constant(ValueError)]
         assert ops[1].opname == 'type'
         assert ops[1].args == [ops[0].result]
         assert x.startblock.exits[0].args == [ops[1].result, ops[0].result]
@@ -389,7 +389,7 @@
 
     #__________________________________________________________
     def raise2(msg):
-        raise IndexError, msg
+        raise ValueError, msg
 
     def test_raise2(self):
         x = self.codetest(self.raise2)
@@ -397,7 +397,7 @@
 
     #__________________________________________________________
     def raise3(msg):
-        raise IndexError(msg)
+        raise ValueError(msg)
 
     def test_raise3(self):
         x = self.codetest(self.raise3)
@@ -421,7 +421,7 @@
     def raise_and_catch_1(exception_instance):
         try:
             raise exception_instance
-        except IndexError:
+        except ValueError:
             return -1
         return 0
 
@@ -432,7 +432,7 @@
     def catch_simple_call():
         try:
             user_defined_function()
-        except IndexError:
+        except ValueError:
             return -1
         return 0
 
@@ -443,7 +443,7 @@
     def multiple_catch_simple_call():
         try:
             user_defined_function()
-        except (IndexError, OSError):
+        except (ValueError, OSError):
             return -1
         return 0
 
@@ -455,7 +455,7 @@
         links = entrymap[graph.returnblock]
         assert len(links) == 3
         assert (dict.fromkeys([link.exitcase for link in links]) ==
-                dict.fromkeys([None, IndexError, OSError]))
+                dict.fromkeys([None, ValueError, OSError]))
         links = entrymap[graph.exceptblock]
         assert len(links) == 1
         assert links[0].exitcase is Exception
@@ -815,7 +815,7 @@
                 raise
         graph = self.codetest(f)
         simplify_graph(graph)
-        assert self.all_operations(graph) == {'getitem_idx_key': 1}
+        assert self.all_operations(graph) == {'getitem': 1}
 
         g = lambda: None
         def f(c, x):
@@ -825,7 +825,7 @@
                 g()
         graph = self.codetest(f)
         simplify_graph(graph)
-        assert self.all_operations(graph) == {'getitem_idx_key': 1,
+        assert self.all_operations(graph) == {'getitem': 1,
                                               'simple_call': 2}
 
         def f(c, x):
@@ -833,9 +833,8 @@
                 return c[x]
             except IndexError:
                 raise
-        graph = self.codetest(f)
-        simplify_graph(graph)
-        assert self.all_operations(graph) == {'getitem_idx': 1}
+        py.test.raises(FlowingError, self.codetest, f)
+        # 'except IndexError' is not RPython any more
 
         def f(c, x):
             try:
@@ -844,7 +843,7 @@
                 raise
         graph = self.codetest(f)
         simplify_graph(graph)
-        assert self.all_operations(graph) == {'getitem_key': 1}
+        assert self.all_operations(graph) == {'getitem': 1}
 
         def f(c, x):
             try:
@@ -863,16 +862,7 @@
         graph = self.codetest(f)
         simplify_graph(graph)
         self.show(graph)
-        assert self.all_operations(graph) == {'getitem_idx_key': 1}
-
-        def f(c, x):
-            try:
-                return c[x]
-            except IndexError:
-                return -1
-        graph = self.codetest(f)
-        simplify_graph(graph)
-        assert self.all_operations(graph) == {'getitem_idx': 1}
+        assert self.all_operations(graph) == {'getitem': 1}
 
         def f(c, x):
             try:
@@ -881,7 +871,7 @@
                 return -1
         graph = self.codetest(f)
         simplify_graph(graph)
-        assert self.all_operations(graph) == {'getitem_key': 1}
+        assert self.all_operations(graph) == {'getitem': 1}
 
         def f(c, x):
             try:
diff --git a/rpython/translator/simplify.py b/rpython/translator/simplify.py
--- a/rpython/translator/simplify.py
+++ b/rpython/translator/simplify.py
@@ -206,21 +206,6 @@
             exits.append(link)
         block.recloseblock(*(preserve + exits))
 
-def transform_xxxitem(graph):
-    # xxx setitem too
-    for block in graph.iterblocks():
-        if block.operations and block.exitswitch == c_last_exception:
-            last_op = block.operations[-1]
-            if last_op.opname == 'getitem':
-                postfx = []
-                for exit in block.exits:
-                    if exit.exitcase is IndexError:
-                        postfx.append('idx')
-                    elif exit.exitcase is KeyError:
-                        postfx.append('key')
-                if postfx:
-                    last_op.opname = last_op.opname + '_' + '_'.join(postfx)
-
 
 def remove_dead_exceptions(graph):
     """Exceptions can be removed if they are unreachable"""
@@ -984,7 +969,6 @@
     remove_identical_vars,
     transform_ovfcheck,
     simplify_exceptions,
-    transform_xxxitem,
     remove_dead_exceptions,
     ]
 


More information about the pypy-commit mailing list