[pypy-svn] r43277 - in pypy/branch/pypy-string-formatting: rpython rpython/test translator

arigo at codespeak.net arigo at codespeak.net
Sat May 12 13:02:30 CEST 2007


Author: arigo
Date: Sat May 12 13:02:29 2007
New Revision: 43277

Modified:
   pypy/branch/pypy-string-formatting/rpython/rlist.py
   pypy/branch/pypy-string-formatting/rpython/rtyper.py
   pypy/branch/pypy-string-formatting/rpython/test/test_rlist.py
   pypy/branch/pypy-string-formatting/translator/transform.py
Log:
Direct support for the following combined operations:

   lst += string[start:]
   lst += string[start:stop]
   lst += string[:-1]

Lengthy code, so I wouldn't be surprized if there is a bug somewhere
despite the tests.


Modified: pypy/branch/pypy-string-formatting/rpython/rlist.py
==============================================================================
--- pypy/branch/pypy-string-formatting/rpython/rlist.py	(original)
+++ pypy/branch/pypy-string-formatting/rpython/rlist.py	Sat May 12 13:02:29 2007
@@ -362,6 +362,27 @@
                           c_strlen, c_stritem)
         return v_lst1
 
+    def rtype_extend_with_str_slice((r_lst1, r_str2), hop):
+        rs = r_lst1.rtyper.type_system.rslice
+        string_repr = r_lst1.rtyper.type_system.rstr.string_repr
+        c_strlen  = hop.inputconst(Void, string_repr.ll.ll_strlen)
+        c_stritem = hop.inputconst(Void, string_repr.ll.ll_stritem_nonneg)
+        r_slic = hop.args_r[2]
+        v_lst1, v_str2, v_slice = hop.inputargs(r_lst1, string_repr, r_slic)
+        if r_slic == rs.startonly_slice_repr:
+            hop.gendirectcall(ll_extend_with_str_slice_startonly,
+                              v_lst1, v_str2, c_strlen, c_stritem, v_slice)
+        elif r_slic == rs.startstop_slice_repr:
+            hop.gendirectcall(ll_extend_with_str_slice,
+                              v_lst1, v_str2, c_strlen, c_stritem, v_slice)
+        elif r_slic == rs.minusone_slice_repr:
+            hop.gendirectcall(ll_extend_with_str_slice_minusone,
+                              v_lst1, v_str2, c_strlen, c_stritem)
+        else:
+            raise TyperError('lst += str[:] does not support slices with %r' %
+                             (r_slic,))
+        return v_lst1
+
 
 class __extend__(pairtype(AbstractBaseListRepr, AbstractSliceRepr)):
 
@@ -705,17 +726,54 @@
         j += 1
 
 def ll_extend_with_str(lst, s, getstrlen, getstritem):
+    return ll_extend_with_str_slice_startonly(lst, s, getstrlen, getstritem, 0)
+
+def ll_extend_with_str_slice_startonly(lst, s, getstrlen, getstritem, start):
     len1 = lst.ll_length()
     len2 = getstrlen(s)
-    newlength = len1 + len2
+    debug_assert(start >= 0, "unexpectedly negative str slice start")
+    debug_assert(start <= len2, "str slice start larger than str length")
+    newlength = len1 + len2 - start
     lst._ll_resize_ge(newlength)
-    i = 0
+    i = start
     j = len1
     while i < len2:
         lst.ll_setitem_fast(j, getstritem(s, i))
         i += 1
         j += 1
 
+def ll_extend_with_str_slice(lst, s, getstrlen, getstritem, slice):
+    start = slice.start
+    stop = slice.stop
+    len1 = lst.ll_length()
+    len2 = getstrlen(s)
+    debug_assert(start >= 0, "unexpectedly negative str slice start")
+    debug_assert(start <= len2, "str slice start larger than str length")
+    debug_assert(stop >= start, "str slice stop smaller than start")
+    if stop > len2:
+        stop = len2
+    newlength = len1 + stop - start
+    lst._ll_resize_ge(newlength)
+    i = start
+    j = len1
+    while i < stop:
+        lst.ll_setitem_fast(j, getstritem(s, i))
+        i += 1
+        j += 1
+
+def ll_extend_with_str_slice_minusone(lst, s, getstrlen, getstritem):
+    len1 = lst.ll_length()
+    len2m1 = getstrlen(s) - 1
+    debug_assert(len2m1 >= 0, "empty string is sliced with [:-1]")
+    newlength = len1 + len2m1
+    lst._ll_resize_ge(newlength)
+    i = 0
+    j = len1
+    while i < len2m1:
+        lst.ll_setitem_fast(j, getstritem(s, i))
+        i += 1
+        j += 1
+
 def ll_listslice_startonly(RESLIST, l1, start):
     len1 = l1.ll_length()
     debug_assert(start >= 0, "unexpectedly negative list slice start")

Modified: pypy/branch/pypy-string-formatting/rpython/rtyper.py
==============================================================================
--- pypy/branch/pypy-string-formatting/rpython/rtyper.py	(original)
+++ pypy/branch/pypy-string-formatting/rpython/rtyper.py	Sat May 12 13:02:29 2007
@@ -576,6 +576,11 @@
     def translate_op_alloc_and_set(self, hop):
         return rlist.rtype_alloc_and_set(hop)
 
+    def translate_op_extend_with_str_slice(self, hop):
+        r_arg1 = hop.args_r[0]
+        r_arg2 = hop.args_r[1]
+        return pair(r_arg1, r_arg2).rtype_extend_with_str_slice(hop)
+
     def translate_op_newtuple(self, hop):
         return self.type_system.rtuple.rtype_newtuple(hop)
 

Modified: pypy/branch/pypy-string-formatting/rpython/test/test_rlist.py
==============================================================================
--- pypy/branch/pypy-string-formatting/rpython/test/test_rlist.py	(original)
+++ pypy/branch/pypy-string-formatting/rpython/test/test_rlist.py	Sat May 12 13:02:29 2007
@@ -1180,6 +1180,32 @@
         res = self.interpret(f, [58])
         assert self.ll_to_string(res) == 'abhello58'
 
+        def f(n, i):
+            s = 'hello%d' % n
+            assert 0 <= i <= len(s)
+            l = ['a', 'b']
+            l += s[i:]
+            return ''.join(l)
+        res = self.interpret(f, [9381701, 3])
+        assert self.ll_to_string(res) == 'ablo9381701'
+
+        def f(n, i, j):
+            s = 'hello%d' % n
+            assert 0 <= i <= j <= len(s)
+            l = ['a', 'b']
+            l += s[i:j]
+            return ''.join(l)
+        res = self.interpret(f, [9381701, 3, 7])
+        assert self.ll_to_string(res) == 'ablo93'
+
+        def f(n):
+            s = 'hello%d' % n
+            l = ['a', 'b']
+            l += s[:-1]
+            return ''.join(l)
+        res = self.interpret(f, [9381701])
+        assert self.ll_to_string(res) == 'abhello938170'
+
 
 class TestLLtype(BaseTestRlist, LLRtypeMixin):
     rlist = ll_rlist

Modified: pypy/branch/pypy-string-formatting/translator/transform.py
==============================================================================
--- pypy/branch/pypy-string-formatting/translator/transform.py	(original)
+++ pypy/branch/pypy-string-formatting/translator/transform.py	Sat May 12 13:02:29 2007
@@ -55,6 +55,32 @@
                                         op.result)
                 block.operations[i] = new_op
 
+# lst += string[x:y]
+# -->
+# b = getitem(string, slice)
+# c = inplace_add(lst, b)
+# -->
+# c = extend_with_str_slice(lst, string, slice)
+
+def transform_extend_with_str_slice(self, block_subset):
+    """Transforms lst += string[x:y] to extend_with_str_slice"""
+    for block in block_subset:
+        slice_sources = {}    # maps b to [string, slice] in the above notation
+        for i in range(len(block.operations)):
+            op = block.operations[i]
+            if (op.opname == 'getitem' and
+                self.gettype(op.args[0]) is str and
+                self.gettype(op.args[1]) is slice):
+                slice_sources[op.result] = op.args
+            elif (op.opname == 'inplace_add' and
+                  op.args[1] in slice_sources and
+                  self.gettype(op.args[0]) is list):
+                v_string, v_slice = slice_sources[op.args[1]]
+                new_op = SpaceOperation('extend_with_str_slice',
+                                        [op.args[0], v_string, v_slice],
+                                        op.result)
+                block.operations[i] = new_op
+
 # a[b:c]
 # -->
 # d = newslice(b, c, None)
@@ -62,22 +88,23 @@
 # -->
 # e = getslice(a, b, c)
 
-def transform_slice(self, block_subset):
-    """Transforms a[b:c] to getslice(a, b, c)."""
-    for block in block_subset:
-        operations = block.operations[:]
-        n_op = len(operations)
-        for i in range(0, n_op-1):
-            op1 = operations[i]
-            op2 = operations[i+1]
-            if (op1.opname == 'newslice' and
-                self.gettype(op1.args[2]) is types.NoneType and
-                op2.opname == 'getitem' and
-                op1.result is op2.args[1]):
-                new_op = SpaceOperation('getslice',
-                                        (op2.args[0], op1.args[0], op1.args[1]),
-                                        op2.result)
-                block.operations[i+1:i+2] = [new_op]
+##def transform_slice(self, block_subset):              -- not used any more --
+##    """Transforms a[b:c] to getslice(a, b, c)."""
+##    for block in block_subset:
+##        operations = block.operations[:]
+##        n_op = len(operations)
+##        for i in range(0, n_op-1):
+##            op1 = operations[i]
+##            op2 = operations[i+1]
+##            if (op1.opname == 'newslice' and
+##                self.gettype(op1.args[2]) is types.NoneType and
+##                op2.opname == 'getitem' and
+##                op1.result is op2.args[1]):
+##                new_op = SpaceOperation('getslice',
+##                                        (op2.args[0], op1.args[0], op1.args[1]),
+##                                        op2.result)
+##                block.operations[i+1:i+2] = [new_op]
+
 
 def transform_dead_op_vars(self, block_subset):
     # we redo the same simplification from simplify.py,
@@ -215,6 +242,7 @@
 
 default_extra_passes = [
     transform_allocate,
+    transform_extend_with_str_slice,
     ]
 
 def transform_graph(ann, extra_passes=None, block_subset=None):



More information about the Pypy-commit mailing list