Commits

Anonymous committed 6322d76

(simon, arre) modified RangeRepr so that it's low level type supports ll_length and ll_setitem_fast methods

  • Participants
  • Parent commits c0571a2

Comments (0)

Files changed (4)

pypy/rpython/lltypesystem/rrange.py

 #        Signed start, stop, step;    // rare case, for completeness
 #    }
 
-RANGE = GcStruct("range", ("start", Signed), ("stop", Signed))
-RANGEITER = GcStruct("range", ("next", Signed), ("stop", Signed))
+def ll_length(l):
+    if l.step > 0:
+        lo = l.start
+        hi = l.stop
+        step = l.step
+    else:
+        lo = l.stop
+        hi = l.start
+        step = -l.step
+    if hi <= lo:
+        return 0
+    n = (hi - lo - 1) // step + 1
+    return n
 
-RANGEST = GcStruct("range", ("start", Signed), ("stop", Signed),("step", Signed))
+def ll_getitem_fast(l, index):
+    return l.start + index * l.step
+
+RANGEST = GcStruct("range", ("start", Signed), ("stop", Signed), ("step", Signed),
+                    adtmeths = {
+                        "ll_length":ll_length,
+                        "ll_getitem_fast":ll_getitem_fast,
+                    })
 RANGESTITER = GcStruct("range", ("next", Signed), ("stop", Signed), ("step", Signed))
 
 class RangeRepr(AbstractRangeRepr):
 
-    RANGE = Ptr(RANGE)
-    RANGEITER = Ptr(RANGEITER)
-
     RANGEST = Ptr(RANGEST)
     RANGESTITER = Ptr(RANGESTITER)
 
     getfield_opname = "getfield"
 
-    def __init__(self, *args):
-        AbstractRangeRepr.__init__(self, *args)
+    def __init__(self, step, *args):
+        self.RANGE = Ptr(GcStruct("range", ("start", Signed), ("stop", Signed),
+                adtmeths = {
+                    "ll_length":ll_length,
+                    "ll_getitem_fast":ll_getitem_fast,
+                    "step":step,
+                }))
+        self.RANGEITER = Ptr(GcStruct("range", ("next", Signed), ("stop", Signed)))
+        AbstractRangeRepr.__init__(self, step, *args)
         self.ll_newrange = ll_newrange
         self.ll_newrangest = ll_newrangest
 
         return RangeIteratorRepr(self)
 
 
-def ll_newrange(start, stop):
-    l = malloc(RANGE)
+def ll_newrange(RANGE, start, stop):
+    l = malloc(RANGE.TO)
     l.start = start
     l.stop = stop
     return l
     l.step = step
     return l
 
-
 class RangeIteratorRepr(AbstractRangeIteratorRepr):
 
     def __init__(self, *args):

pypy/rpython/ootypesystem/rrange.py

         return RangeIteratorRepr(self)
 
 
-def ll_newrange(start, stop):
+def ll_newrange(_RANGE, start, stop):
     l = new(RANGE)
     l.start = start
     l.stop = stop

pypy/rpython/rrange.py

             raise TyperError("range cannot have a const step of zero")
     if isinstance(hop.r_result, AbstractRangeRepr):
         if hop.r_result.step != 0:
-            return hop.gendirectcall(hop.r_result.ll_newrange, vstart, vstop)
+            c_rng = hop.inputconst(Void, hop.r_result.RANGE)
+            return hop.gendirectcall(hop.r_result.ll_newrange, c_rng, vstart, vstop)
         else:
             return hop.gendirectcall(hop.r_result.ll_newrangest, vstart, vstop, vstep)
     else:

pypy/rpython/test/test_rrange.py

                 l = self.rrange.ll_newrangest(start, stop, step)
                 step = l.step
             else:
-                l = self.rrange.ll_newrange(start,stop)
+                RANGE = self.rrange.RangeRepr(step).RANGE
+                l = self.rrange.ll_newrange(RANGE,start,stop)
             assert ll_rangelen(l, step) == length
             lst = [ll_rangeitem(dum_nocheck, l, i, step) for i in range(length)]
             assert lst == expected