[pypy-svn] r17436 - in pypy/dist/pypy: rpython rpython/test translator/c/test

tismer at codespeak.net tismer at codespeak.net
Sat Sep 10 01:10:41 CEST 2005


Author: tismer
Date: Sat Sep 10 01:10:39 2005
New Revision: 17436

Modified:
   pypy/dist/pypy/rpython/rlist.py
   pypy/dist/pypy/rpython/rrange.py
   pypy/dist/pypy/rpython/test/test_rrange.py
   pypy/dist/pypy/translator/c/test/test_typed.py
Log:
added specialization for index checking to (x)range.
reversed dependencies of imports.

Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py	(original)
+++ pypy/dist/pypy/rpython/rlist.py	Sat Sep 10 01:10:39 2005
@@ -3,7 +3,6 @@
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, inputconst
 from pypy.rpython.rmodel import IteratorRepr
-from pypy.rpython import rrange
 from pypy.rpython.rslice import SliceRepr
 from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr
 from pypy.rpython.rslice import minusone_slice_repr
@@ -29,6 +28,7 @@
 
 class __extend__(annmodel.SomeList):
     def rtyper_makerepr(self, rtyper):
+        from pypy.rpython import rrange
         listitem = self.listdef.listitem
         s_value = listitem.s_value
         if listitem.range_step and not listitem.mutated:

Modified: pypy/dist/pypy/rpython/rrange.py
==============================================================================
--- pypy/dist/pypy/rpython/rrange.py	(original)
+++ pypy/dist/pypy/rpython/rrange.py	Sat Sep 10 01:10:39 2005
@@ -3,6 +3,7 @@
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr, IteratorRepr
 from pypy.rpython.lltype import Ptr, GcStruct, Signed, malloc, Void
 from pypy.objspace.flow.model import Constant
+from pypy.rpython.rlist import ll_newlist, dum_nocheck, dum_checkidx
 
 # ____________________________________________________________
 #
@@ -34,9 +35,12 @@
 class __extend__(pairtype(RangeRepr, IntegerRepr)):
 
     def rtype_getitem((r_rng, r_int), hop):
+        from pypy.rpython.rlist import dum_nocheck, dum_checkidx
         if hop.has_implicit_exception(IndexError):
-            s = "getitem on range with try, except: block not supported."
-            raise TyperError, s
+            spec = dum_checkidx
+        else:
+            spec = dum_nocheck
+        v_func = hop.inputconst(Void, spec)
         v_lst, v_index = hop.inputargs(r_rng, Signed)
         cstep = hop.inputconst(Signed, r_rng.step)
         if hop.args_s[1].nonneg:
@@ -44,12 +48,17 @@
         else:
             llfn = ll_rangeitem
         hop.exception_is_here()
-        return hop.gendirectcall(llfn, v_lst, v_index, cstep)
+        return hop.gendirectcall(llfn, v_func, v_lst, v_index, cstep)
 
 # ____________________________________________________________
 #
 #  Low-level methods.
 
+# XXX I think range could be simplified and generalized by storing the
+# range length and a current index, but no stop value at all.
+# The iterator would always use indexing, which implies a multiplication
+# in the range, but that's low cost.
+
 def _ll_rangelen(start, stop, step):
     if step > 0:
         result = (stop - start + (step-1)) // step
@@ -62,14 +71,23 @@
 def ll_rangelen(l, step):
     return _ll_rangelen(l.start, l.stop, step)
 
-def ll_rangeitem_nonneg(l, i, step):
-    return l.start + i*step
-
-def ll_rangeitem(l, i, step):
-    if i < 0:
-        length = ll_rangelen(l, step)
-        i += length
-    return l.start + i*step
+def ll_rangeitem_nonneg(func, l, index, step):
+    if func is dum_checkidx and index >= _ll_rangelen(l.start, l.stop, step):
+        raise IndexError
+    return l.start + index * step
+
+def ll_rangeitem(func, l, index, step):
+    if func is dum_checkidx:
+        length = _ll_rangelen(l.start, l.stop, step)
+        if index < 0:
+            index += length
+        if index < 0 or index >= length:
+            raise IndexError
+    else:
+        if index < 0:
+            length = _ll_rangelen(l.start, l.stop, step)
+            index += length
+    return l.start + index * step
 
 # ____________________________________________________________
 #
@@ -103,7 +121,6 @@
 rtype_builtin_xrange = rtype_builtin_range
 
 def ll_range2list(LISTPTR, start, stop, step):
-    from pypy.rpython.rlist import ll_newlist
     length = _ll_rangelen(start, stop, step)
     l = ll_newlist(LISTPTR, length)
     idx = 0

Modified: pypy/dist/pypy/rpython/test/test_rrange.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rrange.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rrange.py	Sat Sep 10 01:10:39 2005
@@ -8,11 +8,11 @@
         length = len(expected)
         l = ll_newrange(start, stop)
         assert ll_rangelen(l, step) == length
-        lst = [ll_rangeitem(l, i, step) for i in range(length)]
+        lst = [ll_rangeitem(dum_nocheck, l, i, step) for i in range(length)]
         assert lst == expected
-        lst = [ll_rangeitem_nonneg(l, i, step) for i in range(length)]
+        lst = [ll_rangeitem_nonneg(dum_nocheck, l, i, step) for i in range(length)]
         assert lst == expected
-        lst = [ll_rangeitem(l, i-length, step) for i in range(length)]
+        lst = [ll_rangeitem(dum_nocheck, l, i-length, step) for i in range(length)]
         assert lst == expected
 
     for start in (-10, 0, 1, 10):
@@ -74,6 +74,5 @@
         r.reverse()
         return r[0]
     start, stop = 10, 17
-    res = interpret(dummyfn, [start, stop])#, view=True)
+    res = interpret(dummyfn, [start, stop]))
     assert res == dummyfn(start, stop)
-

Modified: pypy/dist/pypy/translator/c/test/test_typed.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_typed.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_typed.py	Sat Sep 10 01:10:39 2005
@@ -357,3 +357,14 @@
             return r[0]
         f = self.getcompiled(fn)
         assert f() == fn()
+
+    def test_range_idx(self):
+        def fn(idx=int):
+            r = range(10, 37, 4)
+            try:
+                return r[idx]
+            except: raise
+        f = self.getcompiled(fn)
+        assert f(0) == fn(0)
+        assert f(-1) == fn(-1)
+        raises(IndexError, f, 42)
\ No newline at end of file



More information about the Pypy-commit mailing list