[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