[pypy-commit] pypy flow-no-local-exception: Adapt lists

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


Author: Armin Rigo <arigo at tunes.org>
Branch: flow-no-local-exception
Changeset: r65870:608476b35886
Date: 2013-07-31 12:53 +0200
http://bitbucket.org/pypy/pypy/changeset/608476b35886/

Log:	Adapt lists

diff --git a/pypy/objspace/std/iterobject.py b/pypy/objspace/std/iterobject.py
--- a/pypy/objspace/std/iterobject.py
+++ b/pypy/objspace/std/iterobject.py
@@ -81,7 +81,7 @@
     """Sequence iterator specialized for lists."""
 
     def descr_next(self, space):
-        from pypy.objspace.std.listobject import W_ListObject
+        from pypy.objspace.std.listobject import W_ListObject, ListIndexError
         w_seq = self.w_seq
         if w_seq is None:
             raise OperationError(space.w_StopIteration, space.w_None)
@@ -89,7 +89,7 @@
         index = self.index
         try:
             w_item = w_seq.getitem(index)
-        except IndexError:
+        except ListIndexError:
             self.w_seq = None
             raise OperationError(space.w_StopIteration, space.w_None)
         self.index = index + 1
@@ -108,9 +108,10 @@
         if self.tupleitems is None:
             raise OperationError(space.w_StopIteration, space.w_None)
         index = self.index
-        try:
+        assert index >= 0
+        if index < len(self.tupleitems):
             w_item = self.tupleitems[index]
-        except IndexError:
+        else:
             self.tupleitems = None
             self.w_seq = None
             raise OperationError(space.w_StopIteration, space.w_None)
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -29,6 +29,7 @@
 from pypy.objspace.std.unicodeobject import W_UnicodeObject
 from pypy.objspace.std.util import get_positive_index, negate
 from rpython.rlib import debug, jit, rerased
+from rpython.rlib.rarithmetic import r_uint
 from rpython.rlib.listsort import make_timsort_class
 from rpython.rlib.objectmodel import (
     instantiate, newlist_hint, resizelist_hint, specialize)
@@ -37,6 +38,10 @@
 __all__ = ['W_ListObject', 'make_range_list', 'make_empty_list_with_size']
 
 
+class ListIndexError(Exception):
+    """A custom RPython class, raised by getitem() and similar methods."""
+
+
 UNROLL_CUTOFF = 5
 
 
@@ -245,13 +250,13 @@
     def getitem(self, index):
         """Returns the wrapped object that is found in the
         list at the given index. The index must be unwrapped.
-        May raise IndexError."""
+        May raise ListIndexError."""
         return self.strategy.getitem(self, index)
 
     def getslice(self, start, stop, step, length):
         """Returns a slice of the list defined by the arguments. Arguments must
         be normalized (i.e. using normalize_simple_slice or W_Slice.indices4).
-        May raise IndexError."""
+        May raise ListIndexError."""
         return self.strategy.getslice(self, start, stop, step, length)
 
     def getitems(self):
@@ -309,7 +314,7 @@
 
     def pop(self, index):
         """Pops an item from the list. Index must be normalized.
-        May raise IndexError."""
+        May raise ListIndexError."""
         return self.strategy.pop(self, index)
 
     def pop_end(self):
@@ -318,7 +323,7 @@
 
     def setitem(self, index, w_item):
         """Inserts a wrapped item at the given (unwrapped) index.
-        May raise IndexError."""
+        May raise ListIndexError."""
         self.strategy.setitem(self, index, w_item)
 
     def setslice(self, start, step, slicelength, sequence_w):
@@ -491,7 +496,7 @@
         try:
             index = space.getindex_w(w_index, space.w_IndexError, "list index")
             return self.getitem(index)
-        except IndexError:
+        except ListIndexError:
             raise OperationError(space.w_IndexError,
                                  space.wrap("list index out of range"))
 
@@ -519,7 +524,7 @@
         idx = space.getindex_w(w_index, space.w_IndexError, "list index")
         try:
             self.setitem(idx, w_any)
-        except IndexError:
+        except ListIndexError:
             raise OperationError(space.w_IndexError,
                                  space.wrap("list index out of range"))
 
@@ -546,7 +551,7 @@
             idx += self.length()
         try:
             self.pop(idx)
-        except IndexError:
+        except ListIndexError:
             raise OperationError(space.w_IndexError,
                                  space.wrap("list index out of range"))
 
@@ -597,7 +602,7 @@
             index += length
         try:
             return self.pop(index)
-        except IndexError:
+        except ListIndexError:
             raise OperationError(space.w_IndexError,
                                  space.wrap("pop index out of range"))
 
@@ -865,7 +870,7 @@
         return 0
 
     def getitem(self, w_list, index):
-        raise IndexError
+        raise ListIndexError
 
     def getslice(self, w_list, start, stop, step, length):
         # will never be called because the empty list case is already caught in
@@ -913,10 +918,10 @@
     def pop(self, w_list, index):
         # will not be called because IndexError was already raised in
         # list_pop__List_ANY
-        raise IndexError
+        raise ListIndexError
 
     def setitem(self, w_list, index, w_item):
-        raise IndexError
+        raise ListIndexError
 
     def setslice(self, w_list, start, step, slicelength, w_other):
         strategy = w_other.strategy
@@ -1052,9 +1057,9 @@
         if i < 0:
             i += length
             if i < 0:
-                raise IndexError
+                raise ListIndexError
         elif i >= length:
-            raise IndexError
+            raise ListIndexError
         return start + i * step
 
     def getitems_int(self, w_list):
@@ -1235,13 +1240,21 @@
     def length(self, w_list):
         return len(self.unerase(w_list.lstorage))
 
+    @staticmethod
+    def _getidx(l, index):
+        ulength = r_uint(len(l))
+        uindex = r_uint(index)
+        if uindex >= ulength:
+            # out of bounds -or- negative index
+            uindex += ulength
+            if uindex >= ulength:
+                raise ListIndexError
+        return uindex
+
     def getitem(self, w_list, index):
         l = self.unerase(w_list.lstorage)
-        try:
-            r = l[index]
-        except IndexError:  # make RPython raise the exception
-            raise
-        return self.wrap(r)
+        uindex = self._getidx(l, index)
+        return self.wrap(l[uindex])
 
     @jit.look_inside_iff(lambda self, w_list:
             jit.loop_unrolling_heuristic(w_list, w_list.length(),
@@ -1276,11 +1289,10 @@
             subitems_w = [self._none_value] * length
             l = self.unerase(w_list.lstorage)
             for i in range(length):
-                try:
-                    subitems_w[i] = l[start]
-                    start += step
-                except IndexError:
-                    raise
+                # I believe that the following 'l[start]' cannot raise
+                # an IndexError
+                subitems_w[i] = l[start]
+                start += step
             storage = self.erase(subitems_w)
             return W_ListObject.from_storage_and_strategy(
                     self.space, storage, self)
@@ -1319,10 +1331,8 @@
         l = self.unerase(w_list.lstorage)
 
         if self.is_correct_type(w_item):
-            try:
-                l[index] = self.unwrap(w_item)
-            except IndexError:
-                raise
+            uindex = self._getidx(l, index)
+            l[uindex] = self.unwrap(w_item)
             return
 
         w_list.switch_to_object_strategy()
@@ -1432,15 +1442,8 @@
 
     def pop(self, w_list, index):
         l = self.unerase(w_list.lstorage)
-        # not sure if RPython raises IndexError on pop
-        # so check again here
-        if index < 0:
-            raise IndexError
-        try:
-            item = l.pop(index)
-        except IndexError:
-            raise
-
+        uindex = self._getidx(l, index)
+        item = l.pop(uindex)
         w_item = self.wrap(item)
         return w_item
 


More information about the pypy-commit mailing list