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

arigo at codespeak.net arigo at codespeak.net
Sat May 12 13:43:42 CEST 2007


Author: arigo
Date: Sat May 12 13:43:41 2007
New Revision: 43283

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

    lst += char * count
    lst += count * char

Also check that 'lst' is really a list of chars, and complain clearly
if it something else like a list of strings.


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:43:41 2007
@@ -4,7 +4,7 @@
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import Repr, IteratorRepr, IntegerRepr, inputconst
 from pypy.rpython.rslice import AbstractSliceRepr
-from pypy.rpython.rstr import AbstractStringRepr
+from pypy.rpython.rstr import AbstractStringRepr, AbstractCharRepr
 from pypy.rpython.lltypesystem.lltype import typeOf, Ptr, Void, Signed, Bool
 from pypy.rpython.lltypesystem.lltype import nullptr, Char, UniChar
 from pypy.rpython import robject
@@ -354,6 +354,9 @@
 class __extend__(pairtype(AbstractListRepr, AbstractStringRepr)):
 
     def rtype_inplace_add((r_lst1, r_str2), hop):
+        if r_lst1.item_repr.lowleveltype != Char:
+            raise TyperError('"lst += string" only supported with a list '
+                             'of chars')
         string_repr = r_lst1.rtyper.type_system.rstr.string_repr
         v_lst1, v_str2 = hop.inputargs(r_lst1, string_repr)
         c_strlen  = hop.inputconst(Void, string_repr.ll.ll_strlen)
@@ -363,6 +366,9 @@
         return v_lst1
 
     def rtype_extend_with_str_slice((r_lst1, r_str2), hop):
+        if r_lst1.item_repr.lowleveltype != Char:
+            raise TyperError('"lst += string" only supported with a list '
+                             'of chars')
         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)
@@ -383,6 +389,17 @@
                              (r_slic,))
         return v_lst1
 
+class __extend__(pairtype(AbstractListRepr, AbstractCharRepr)):
+
+    def rtype_extend_with_char_count((r_lst1, r_chr2), hop):
+        if r_lst1.item_repr.lowleveltype != Char:
+            raise TyperError('"lst += string" only supported with a list '
+                             'of chars')
+        char_repr = r_lst1.rtyper.type_system.rstr.char_repr
+        v_lst1, v_chr, v_count = hop.inputargs(r_lst1, char_repr, Signed)
+        hop.gendirectcall(ll_extend_with_char_count, v_lst1, v_chr, v_count)
+        return v_lst1
+
 
 class __extend__(pairtype(AbstractBaseListRepr, AbstractSliceRepr)):
 
@@ -774,6 +791,17 @@
         i += 1
         j += 1
 
+def ll_extend_with_char_count(lst, char, count):
+    if count <= 0:
+        return
+    len1 = lst.ll_length()
+    newlength = len1 + count
+    lst._ll_resize_ge(newlength)
+    j = len1
+    while j < newlength:
+        lst.ll_setitem_fast(j, char)
+        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:43:41 2007
@@ -581,6 +581,11 @@
         r_arg2 = hop.args_r[1]
         return pair(r_arg1, r_arg2).rtype_extend_with_str_slice(hop)
 
+    def translate_op_extend_with_char_count(self, hop):
+        r_arg1 = hop.args_r[0]
+        r_arg2 = hop.args_r[1]
+        return pair(r_arg1, r_arg2).rtype_extend_with_char_count(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:43:41 2007
@@ -1,5 +1,6 @@
 import sys
 from pypy.translator.translator import TranslationContext
+from pypy.rpython.error import TyperError
 from pypy.rpython.lltypesystem.lltype import *
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.rlist import *
@@ -1171,7 +1172,7 @@
         else:
             assert False
 
-    def test_charlist_extensions(self):
+    def test_charlist_extension_1(self):
         def f(n):
             s = 'hello%d' % n
             l = ['a', 'b']
@@ -1180,6 +1181,15 @@
         res = self.interpret(f, [58])
         assert self.ll_to_string(res) == 'abhello58'
 
+    def test_extend_a_non_char_list_1(self):
+        def f(n):
+            s = 'hello%d' % n
+            l = ['foo', 'bar']
+            l += s          # NOT SUPPORTED for now if l is not a list of chars
+            return ''.join(l)
+        py.test.raises(TyperError, self.interpret, f, [58])
+
+    def test_charlist_extension_2(self):
         def f(n, i):
             s = 'hello%d' % n
             assert 0 <= i <= len(s)
@@ -1189,6 +1199,16 @@
         res = self.interpret(f, [9381701, 3])
         assert self.ll_to_string(res) == 'ablo9381701'
 
+    def test_extend_a_non_char_list_2(self):
+        def f(n, i):
+            s = 'hello%d' % n
+            assert 0 <= i <= len(s)
+            l = ['foo', 'bar']
+            l += s[i:]      # NOT SUPPORTED for now if l is not a list of chars
+            return ''.join(l)
+        py.test.raises(TyperError, self.interpret, f, [9381701, 3])
+
+    def test_charlist_extension_3(self):
         def f(n, i, j):
             s = 'hello%d' % n
             assert 0 <= i <= j <= len(s)
@@ -1198,6 +1218,7 @@
         res = self.interpret(f, [9381701, 3, 7])
         assert self.ll_to_string(res) == 'ablo93'
 
+    def test_charlist_extension_4(self):
         def f(n):
             s = 'hello%d' % n
             l = ['a', 'b']
@@ -1206,6 +1227,34 @@
         res = self.interpret(f, [9381701])
         assert self.ll_to_string(res) == 'abhello938170'
 
+    def test_charlist_extension_5(self):
+        def f(count):
+            l = ['a', 'b']
+            l += '.' * count     # char * count
+            return ''.join(l)
+        res = self.interpret(f, [7])
+        assert self.ll_to_string(res) == 'ab.......'
+        res = self.interpret(f, [0])
+        assert self.ll_to_string(res) == 'ab'
+
+    def test_charlist_extension_6(self):
+        def f(count):
+            l = ['a', 'b']
+            l += count * '.'     # count * char
+            return ''.join(l)
+        res = self.interpret(f, [7])
+        assert self.ll_to_string(res) == 'ab.......'
+        res = self.interpret(f, [0])
+        assert self.ll_to_string(res) == 'ab'
+
+    def test_extend_a_non_char_list_6(self):
+        def f(count):
+            l = ['foo', 'bar']
+            # NOT SUPPORTED for now if l is not a list of chars
+            l += count * '.'
+            return ''.join(l)
+        py.test.raises(TyperError, self.interpret, f, [5])
+
 
 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:43:41 2007
@@ -81,6 +81,37 @@
                                         op.result)
                 block.operations[i] = new_op
 
+# lst += char*count        [or count*char]
+# -->
+# b = mul(char, count)     [or count, char]
+# c = inplace_add(lst, b)
+# -->
+# c = extend_with_char_count(lst, char, count)
+
+def transform_extend_with_char_count(self, block_subset):
+    """Transforms lst += char*count to extend_with_char_count"""
+    for block in block_subset:
+        mul_sources = {}    # maps b to (char, count) in the above notation
+        for i in range(len(block.operations)):
+            op = block.operations[i]
+            if op.opname == 'mul':
+                s0 = self.binding(op.args[0], None)
+                s1 = self.binding(op.args[1], None)
+                if (isinstance(s0, annmodel.SomeChar) and
+                    isinstance(s1, annmodel.SomeInteger)):
+                    mul_sources[op.result] = op.args[0], op.args[1]
+                elif (isinstance(s1, annmodel.SomeChar) and
+                      isinstance(s0, annmodel.SomeInteger)):
+                    mul_sources[op.result] = op.args[1], op.args[0]
+            elif (op.opname == 'inplace_add' and
+                  op.args[1] in mul_sources and
+                  self.gettype(op.args[0]) is list):
+                v_char, v_count = mul_sources[op.args[1]]
+                new_op = SpaceOperation('extend_with_char_count',
+                                        [op.args[0], v_char, v_count],
+                                        op.result)
+                block.operations[i] = new_op
+
 # a[b:c]
 # -->
 # d = newslice(b, c, None)
@@ -243,6 +274,7 @@
 default_extra_passes = [
     transform_allocate,
     transform_extend_with_str_slice,
+    transform_extend_with_char_count,
     ]
 
 def transform_graph(ann, extra_passes=None, block_subset=None):



More information about the Pypy-commit mailing list