[pypy-svn] pypy default: Add RPython support for str.rsplit(char, maxsplit=-1)

amauryfa commits-noreply at bitbucket.org
Wed Mar 30 19:53:59 CEST 2011


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: 
Changeset: r43025:7be96def7147
Date: 2011-03-30 11:47 +0200
http://bitbucket.org/pypy/pypy/changeset/7be96def7147/

Log:	Add RPython support for str.rsplit(char, maxsplit=-1)

diff --git a/pypy/rpython/test/test_rstr.py b/pypy/rpython/test/test_rstr.py
--- a/pypy/rpython/test/test_rstr.py
+++ b/pypy/rpython/test/test_rstr.py
@@ -576,30 +576,51 @@
                 res = self.interpret(f, [i, newlines])
                 assert res == f(i, newlines)
 
-    def test_split(self):
+    def _make_split_test(self, split_fn):
         const = self.const
         def fn(i):
             s = [const(''), const('0.1.2.4.8'), const('.1.2'), const('1.2.'), const('.1.2.4.')][i]
-            l = s.split(const('.'))
+            l = getattr(s, split_fn)(const('.'))
             sum = 0
             for num in l:
                  if len(num):
                      sum += ord(num[0]) - ord(const('0')[0])
             return sum + len(l) * 100
+        return fn
+
+    def test_split(self):
+        fn = self._make_split_test('split')
         for i in range(5):
             res = self.interpret(fn, [i])
             assert res == fn(i)
 
-    def test_split_limit(self):
+    def test_rsplit(self):
+        fn = self._make_split_test('rsplit')
+        for i in range(5):
+            res = self.interpret(fn, [i])
+            assert res == fn(i)
+
+    def _make_split_limit_test(self, split_fn):
         const = self.const
         def fn(i, j):
             s = [const(''), const('0.1.2.4.8'), const('.1.2'), const('1.2.'), const('.1.2.4.')][i]
-            l = s.split(const('.'), j)
+            l = getattr(s, split_fn)(const('.'), j)
             sum = 0
             for num in l:
                  if len(num):
                      sum += ord(num[0]) - ord(const('0')[0])
             return sum + len(l) * 100
+        return fn
+
+    def test_split_limit(self):
+        fn = self._make_split_limit_test('split')
+        for i in range(5):
+            for j in range(4):
+                res = self.interpret(fn, [i, j])
+                assert res == fn(i, j)
+
+    def test_rsplit_limit(self):
+        fn = self._make_split_limit_test('split')
         for i in range(5):
             for j in range(4):
                 res = self.interpret(fn, [i, j])

diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -234,6 +234,21 @@
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll.ll_split_chr, cLIST, v_str, v_chr, v_max)
 
+    def rtype_method_rsplit(self, hop):
+        rstr = hop.args_r[0].repr
+        if hop.nb_args == 3:
+            v_str, v_chr, v_max = hop.inputargs(rstr.repr, rstr.char_repr, Signed)
+        else:
+            v_str, v_chr = hop.inputargs(rstr.repr, rstr.char_repr)
+            v_max = hop.inputconst(Signed, -1)
+        try:
+            list_type = hop.r_result.lowleveltype.TO
+        except AttributeError:
+            list_type = hop.r_result.lowleveltype
+        cLIST = hop.inputconst(Void, list_type)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(self.ll.ll_rsplit_chr, cLIST, v_str, v_chr, v_max)
+
     def rtype_method_replace(self, hop):
         rstr = hop.args_r[0].repr
         if not (hop.args_r[1] == rstr.char_repr and hop.args_r[2] == rstr.char_repr):

diff --git a/pypy/rpython/ootypesystem/ootype.py b/pypy/rpython/ootypesystem/ootype.py
--- a/pypy/rpython/ootypesystem/ootype.py
+++ b/pypy/rpython/ootypesystem/ootype.py
@@ -444,6 +444,7 @@
             "ll_lower": Meth([], self.SELFTYPE_T),
             "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count)
             "ll_split_chr": Meth([self.CHAR, Signed], Array(self.SELFTYPE_T)), # XXX this is not pure!
+            "ll_rsplit_chr": Meth([self.CHAR, Signed], Array(self.SELFTYPE_T)), # XXX this is not pure!
             "ll_contains": Meth([self.CHAR], Bool),
             "ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T),
             })
@@ -1487,6 +1488,13 @@
         res._array[:] = l
         return res
 
+    def ll_rsplit_chr(self, ch, max):
+        # NOT_RPYTHON
+        l = [self.make_string(s) for s in self._str.rsplit(ch, max)]
+        res = _array(Array(self._TYPE), len(l))
+        res._array[:] = l
+        return res
+
     def ll_contains(self, ch):
         # NOT_RPYTHON
         return ch in self._str

diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -756,6 +756,41 @@
         item.copy_contents(s, item, i, 0, j - i)
         return res
 
+    def ll_rsplit_chr(LIST, s, c, max):
+        chars = s.chars
+        strlen = len(chars)
+        count = 1
+        i = 0
+        if max == 0:
+            i = strlen
+        while i < strlen:
+            if chars[i] == c:
+                count += 1
+                if max >= 0 and count > max:
+                    break
+            i += 1
+        res = LIST.ll_newlist(count)
+        items = res.ll_items()
+        i = strlen
+        j = strlen
+        resindex = count - 1
+        assert resindex >= 0
+        if max == 0:
+            j = 0
+        while j > 0:
+            j -= 1
+            if chars[j] == c:
+                item = items[resindex] = s.malloc(i - j - 1)
+                item.copy_contents(s, item, j + 1, 0, i - j - 1)
+                resindex -= 1
+                i = j
+                if resindex == 0:
+                    j = 0
+                    break
+        item = items[resindex] = s.malloc(i - j)
+        item.copy_contents(s, item, j, 0, i - j)
+        return res
+
     @purefunction
     def ll_replace_chr_chr(s, c1, c2):
         length = len(s.chars)

diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -503,6 +503,10 @@
         getbookkeeper().count("str_split", str, patt)
         return getbookkeeper().newlist(str.basestringclass())
 
+    def method_rsplit(str, patt, max=-1):
+        getbookkeeper().count("str_rsplit", str, patt)
+        return getbookkeeper().newlist(str.basestringclass())
+
     def method_replace(str, s1, s2):
         return str.basestringclass()
 

diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -214,6 +214,9 @@
     def ll_split_chr(RESULT, s, c, max):
         return RESULT.ll_convert_from_array(s.ll_split_chr(c, max))
 
+    def ll_rsplit_chr(RESULT, s, c, max):
+        return RESULT.ll_convert_from_array(s.ll_rsplit_chr(c, max))
+
     def ll_int(s, base):
         if not 2 <= base <= 36:
             raise ValueError


More information about the Pypy-commit mailing list