[pypy-commit] pypy utf8-unicode2: Add support for str.join([<list of chars>])

waedt noreply at buildbot.pypy.org
Tue Aug 5 10:59:53 CEST 2014


Author: Tyler Wade <wayedt at gmail.com>
Branch: utf8-unicode2
Changeset: r72696:9661a2f7dd0f
Date: 2014-08-04 14:36 -0500
http://bitbucket.org/pypy/pypy/changeset/9661a2f7dd0f/

Log:	Add support for str.join([<list of chars>])

diff --git a/rpython/rtyper/lltypesystem/rstr.py b/rpython/rtyper/lltypesystem/rstr.py
--- a/rpython/rtyper/lltypesystem/rstr.py
+++ b/rpython/rtyper/lltypesystem/rstr.py
@@ -820,6 +820,32 @@
             i += 1
         return result
 
+    def ll_join_chars_with_str(s, length, chars):
+        s_chars = s.chars
+        s_len = len(s_chars)
+        num_chars = length
+        if num_chars == 0:
+            return s.empty()
+
+        try:
+            seplen = ovfcheck(s_len * (num_chars - 1))
+        except OverflowError:
+            raise MemoryError
+
+        # a single '+' at the end is allowed to overflow: it gets
+        # a negative result, and the gc will complain
+        result = s.malloc(num_chars + seplen)
+        res_index = 1
+        result.chars[0] = chars[0]
+        i = 1
+        while i < num_chars:
+            s.copy_contents(s, result, 0, res_index, s_len)
+            res_index += s_len
+            result.chars[res_index] = chars[i]
+            res_index += 1
+            i += 1
+        return result
+
     @jit.oopspec('stroruni.slice(s1, start, stop)')
     @signature(types.any(), types.int(), types.int(), returns=types.any())
     @jit.elidable
diff --git a/rpython/rtyper/rstr.py b/rpython/rtyper/rstr.py
--- a/rpython/rtyper/rstr.py
+++ b/rpython/rtyper/rstr.py
@@ -235,6 +235,8 @@
         else:
             if r_lst.item_repr == rstr.repr:
                 llfn = self.ll.ll_join
+            elif r_lst.item_repr == char_repr:
+                llfn = self.ll.ll_join_chars_with_str
             else:
                 raise TyperError("sep.join() of non-string list: %r" % r_lst)
             return hop.gendirectcall(llfn, v_str, v_length, v_items)
diff --git a/rpython/rtyper/test/test_rstr.py b/rpython/rtyper/test/test_rstr.py
--- a/rpython/rtyper/test/test_rstr.py
+++ b/rpython/rtyper/test/test_rstr.py
@@ -516,6 +516,9 @@
         res = self.interpret(lambda: const('.').join([const('abc'), const('def')]), [])
         assert self.ll_to_string(res) == const('abc.def')
 
+        res = self.interpret(lambda: const('  ').join([const('a'), const('b'), const('c')]), [])
+        assert self.ll_to_string(res) == const('a  b  c')
+
         def fn(i, j):
             s1 = [ const(''), const(','), const(' and ')]
             s2 = [ [], [const('foo')], [const('bar'), const('baz'), const('bazz')]]


More information about the pypy-commit mailing list