[pypy-svn] r13220 - in pypy/dist/pypy/rpython: . test

arigo at codespeak.net arigo at codespeak.net
Thu Jun 9 10:44:43 CEST 2005


Author: arigo
Date: Thu Jun  9 10:44:40 2005
New Revision: 13220

Added:
   pypy/dist/pypy/rpython/rslice.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/rlist.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_rlist.py
Log:
Slices and getslice for lists.


Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py	(original)
+++ pypy/dist/pypy/rpython/rlist.py	Thu Jun  9 10:44:40 2005
@@ -4,6 +4,8 @@
 from pypy.rpython.lltype import *
 from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
 from pypy.rpython import rrange
+from pypy.rpython.rslice import SliceRepr
+from pypy.rpython.rslice import startstop_slice_repr, startonly_slice_repr
 
 # ____________________________________________________________
 #
@@ -86,6 +88,17 @@
             llfn = ll_setitem
         return hop.gendirectcall(llfn, v_lst, v_index, v_item)
 
+class __extend__(pairtype(ListRepr, SliceRepr)):
+
+    def rtype_getitem((r_lst, r_slic), hop):
+        if r_slic == startonly_slice_repr:
+            v_lst, v_start = hop.inputargs(r_lst, startonly_slice_repr)
+            return hop.gendirectcall(ll_listslice_startonly, v_lst, v_start)
+        if r_slic == startstop_slice_repr:
+            v_lst, v_slice = hop.inputargs(r_lst, startstop_slice_repr)
+            return hop.gendirectcall(ll_listslice, v_lst, v_slice)
+        raise TyperError(r_slic)
+
 class __extend__(pairtype(ListRepr, ListRepr)):
     def convert_from_to((r_lst1, r_lst2), v, llops):
         if r_lst1.listitem is None or r_lst2.listitem is None:
@@ -170,6 +183,31 @@
         j += 1
     l1.items = newitems
 
+def ll_listslice_startonly(l1, start):
+    len1 = len(l1.items)
+    newitems = malloc(typeOf(l1).TO.items.TO, len1 - start)
+    j = 0
+    while start < len1:
+        newitems[j].item = l1.items[start].item
+        start += 1
+        j += 1
+    l = malloc(typeOf(l1).TO)
+    l.items = newitems
+    return l
+
+def ll_listslice(l1, slice):
+    start = slice.start
+    stop = slice.stop
+    newitems = malloc(typeOf(l1).TO.items.TO, stop - start)
+    j = 0
+    while start < stop:
+        newitems[j].item = l1.items[start].item
+        start += 1
+        j += 1
+    l = malloc(typeOf(l1).TO)
+    l.items = newitems
+    return l
+
 # ____________________________________________________________
 #
 #  Irregular operations.

Added: pypy/dist/pypy/rpython/rslice.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/rslice.py	Thu Jun  9 10:44:40 2005
@@ -0,0 +1,75 @@
+from pypy.annotation.pairtype import pairtype
+from pypy.annotation import model as annmodel
+from pypy.objspace.flow.model import Constant
+from pypy.rpython.lltype import *
+from pypy.rpython.rmodel import Repr, TyperError, IntegerRepr
+import sys
+
+# ____________________________________________________________
+#
+#  Concrete implementation of RPython slice objects:
+#
+#  - if stop is None, use only a Signed
+#  - if stop is not None:
+#
+#      struct slice {
+#          Signed start;
+#          Signed stop;
+#          //     step is always 1
+#      }
+
+SLICE = GcStruct("slice", ("start", Signed), ("stop", Signed))
+
+
+class __extend__(annmodel.SomeSlice):
+    def rtyper_makerepr(self, rtyper):
+        if not self.step.is_constant() or self.step.const not in (None, 1):
+            raise TyperError("only supports slices with step 1")
+        if isinstance(self.start, annmodel.SomeInteger):
+            if not self.start.nonneg:
+                raise TyperError("slice start must be proved non-negative")
+        if isinstance(self.stop, annmodel.SomeInteger):
+            if not self.stop.nonneg:
+                raise TyperError("slice stop must be proved non-negative")
+        if self.stop.is_constant() and self.stop.const is None:
+            return startonly_slice_repr
+        else:
+            return startstop_slice_repr
+    def rtyper_makekey(self):
+        return self.stop.rtyper_makekey(), self.step.rtyper_makekey()
+
+
+class SliceRepr(Repr):
+    pass
+
+startstop_slice_repr = SliceRepr()
+startstop_slice_repr.lowleveltype = Ptr(SLICE)
+startonly_slice_repr = SliceRepr()
+startonly_slice_repr.lowleveltype = Signed
+
+# ____________________________________________________________
+
+def ll_newslice(start, stop):
+    s = malloc(SLICE)
+    s.start = start
+    s.stop = stop
+    return s
+
+def rtype_newslice(hop):
+    sig = []
+    for s in hop.args_s:
+        if s.is_constant() and s.const is None:
+            sig.append(Void)
+        else:
+            sig.append(Signed)
+    v_start, v_stop, v_step = hop.inputargs(*sig)
+    assert isinstance(v_step, Constant) and v_step.value in (None, 1)
+    if isinstance(v_start, Constant) and v_start.value is None:
+        v_start = hop.inputconst(Signed, 0)
+    if isinstance(v_stop, Constant) and v_stop.value is None:
+        # start-only slice
+        # NB. cannot just return v_start in case it is a constant
+        return hop.genop('same_as', [v_start], resulttype=startonly_slice_repr)
+    else:
+        # start-stop slice
+        return hop.gendirectcall(ll_newslice, v_start, v_stop)

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Thu Jun  9 10:44:40 2005
@@ -251,6 +251,9 @@
     def translate_op_newtuple(self, hop):
         return rtuple.rtype_newtuple(hop)
 
+    def translate_op_newslice(self, hop):
+        return rslice.rtype_newslice(hop)
+
     def missing_operation(self, hop):
         raise TyperError("unimplemented operation: '%s'" % hop.spaceop.opname)
 
@@ -410,6 +413,7 @@
 # and the rtyper_chooserepr() methods
 from pypy.rpython import robject
 from pypy.rpython import rint, rbool, rfloat
+from pypy.rpython import rslice
 from pypy.rpython import rlist, rstr, rtuple
 from pypy.rpython import rbuiltin, rpbc
 from pypy.rpython import rptr

Modified: pypy/dist/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rlist.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rlist.py	Thu Jun  9 10:44:40 2005
@@ -2,10 +2,11 @@
 from pypy.rpython.lltype import *
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.rpython.rlist import *
+from pypy.rpython.rslice import ll_newslice
 from pypy.rpython.rint import signed_repr
 
 
-def test_rlist():
+def sample_list():
     rlist = ListRepr(signed_repr)
     rlist.setup()
     l = ll_newlist(rlist.lowleveltype, 3)
@@ -13,20 +14,41 @@
     ll_setitem(l, -2, 43)
     ll_setitem_nonneg(l, 2, 44)
     ll_append(l, 45)
+    return l
+
+def check_list(l1, expected):
+    assert ll_len(l1) == len(expected)
+    for i, x in zip(range(len(expected)), expected):
+        assert ll_getitem_nonneg(l1, i) == x
+
+def test_rlist_basic():
+    l = sample_list()
     assert ll_getitem(l, -4) == 42
     assert ll_getitem_nonneg(l, 1) == 43
     assert ll_getitem(l, 2) == 44
     assert ll_getitem(l, 3) == 45
     assert ll_len(l) == 4
+    check_list(l, [42, 43, 44, 45])
+
+def test_rlist_extend_concat():
+    l = sample_list()
     ll_extend(l, l)
-    assert ll_len(l) == 8
-    for i, x in zip(range(8), [42, 43, 44, 45, 42, 43, 44, 45]):
-        assert ll_getitem_nonneg(l, i) == x
+    check_list(l, [42, 43, 44, 45] * 2)
     l1 = ll_concat(l, l)
     assert l1 != l
-    assert ll_len(l1) == 16
-    for i, x in zip(range(16), [42, 43, 44, 45] * 4):
-        assert ll_getitem_nonneg(l1, i) == x
+    check_list(l1, [42, 43, 44, 45] * 4)
+
+def test_rlist_slice():
+    l = sample_list()
+    check_list(ll_listslice_startonly(l, 0), [42, 43, 44, 45])
+    check_list(ll_listslice_startonly(l, 1), [43, 44, 45])
+    check_list(ll_listslice_startonly(l, 2), [44, 45])
+    check_list(ll_listslice_startonly(l, 3), [45])
+    check_list(ll_listslice_startonly(l, 4), [])
+    for start in range(5):
+        for stop in range(start, 5):
+            s = ll_newslice(start, stop)
+            check_list(ll_listslice(l, s), [42, 43, 44, 45][start:stop])
 
 # ____________________________________________________________
 
@@ -83,3 +105,9 @@
         l += [6,7]
         return l + [8]
     rtype(dummyfn)
+
+def test_slice():
+    def dummyfn():
+        l = [5, 6, 7, 8, 9]
+        return l[:2], l[1:4], l[3:]
+    rtype(dummyfn).view()



More information about the Pypy-commit mailing list