[pypy-svn] r48332 - in pypy/branch/pypy-rpython-unicode/rpython: . lltypesystem test

fijal at codespeak.net fijal at codespeak.net
Tue Nov 6 12:38:03 CET 2007


Author: fijal
Date: Tue Nov  6 12:38:02 2007
New Revision: 48332

Modified:
   pypy/branch/pypy-rpython-unicode/rpython/lltypesystem/rstr.py
   pypy/branch/pypy-rpython-unicode/rpython/rstr.py
   pypy/branch/pypy-rpython-unicode/rpython/test/test_rstr.py
   pypy/branch/pypy-rpython-unicode/rpython/test/test_runicode.py
Log:
Some support for unicode strings. This is work in progress, not all tests
are really testing what they should.


Modified: pypy/branch/pypy-rpython-unicode/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/branch/pypy-rpython-unicode/rpython/lltypesystem/rstr.py	(original)
+++ pypy/branch/pypy-rpython-unicode/rpython/lltypesystem/rstr.py	Tue Nov  6 12:38:02 2007
@@ -12,7 +12,7 @@
 from pypy.rpython.lltypesystem import ll_str
 from pypy.rpython.lltypesystem.lltype import \
      GcStruct, Signed, Array, Char, UniChar, Ptr, malloc, \
-     Bool, Void, GcArray, nullptr, pyobjectptr, cast_primitive
+     Bool, Void, GcArray, nullptr, pyobjectptr, cast_primitive, typeOf
 
 
 # ____________________________________________________________
@@ -31,6 +31,7 @@
                    ('chars', Array(UniChar, hints={'immutable': True})))
 SIGNED_ARRAY = GcArray(Signed)
 CONST_STR_CACHE = WeakValueDictionary()
+CONST_UNICODE_CACHE = WeakValueDictionary()
 
 class BaseStringRepr(AbstractStringRepr):
     def __init__(self, *args):
@@ -44,20 +45,21 @@
         if not isinstance(value, self.basetype):
             raise TyperError("not a str: %r" % (value,))
         try:
-            return CONST_STR_CACHE[value]
+            return self.CACHE[value]
         except KeyError:
             p = self.malloc(len(value))
             for i in range(len(value)):
                 p.chars[i] = cast_primitive(self.base, value[i])
             p.hash = 0
             self.ll.ll_strhash(p)   # precompute the hash
-            CONST_STR_CACHE[value] = p
+            self.CACHE[value] = p
             return p
 
     def make_iterator_repr(self):
         return string_iterator_repr
 
     def can_ll_be_null(self, s_value):
+        # XXX unicode
         if self is string_repr:
             return s_value.can_be_none()
         else:
@@ -75,6 +77,7 @@
     lowleveltype = Ptr(STR)
     basetype = str
     base = Char
+    CACHE = CONST_STR_CACHE
 
     def __init__(self, *args):
         BaseStringRepr.__init__(self, *args)
@@ -84,6 +87,7 @@
     lowleveltype = Ptr(UNICODE)
     basetype = basestring
     base = UniChar
+    CACHE = CONST_UNICODE_CACHE
 
     def __init__(self, *args):
         BaseStringRepr.__init__(self, *args)
@@ -163,9 +167,13 @@
 class LLHelpers(AbstractLLHelpers):
 
     def ll_char_mul(ch, times):
+        if typeOf(ch) is Char:
+            malloc = mallocstr
+        else:
+            malloc = mallocunicode
         if times < 0:
             times = 0
-        newstr = mallocstr(times)
+        newstr = malloc(times)
         j = 0
         while j < times:
             newstr.chars[j] = ch
@@ -183,7 +191,11 @@
     ll_stritem_nonneg._annenforceargs_ = [None, int]
 
     def ll_chr2str(ch):
-        s = mallocstr(1)
+        if typeOf(ch) is Char:
+            malloc = mallocstr
+        else:
+            malloc = mallocunicode
+        s = malloc(1)
         s.chars[0] = ch
         return s
 
@@ -204,7 +216,12 @@
     def ll_strconcat(s1, s2):
         len1 = len(s1.chars)
         len2 = len(s2.chars)
-        newstr = mallocstr(len1 + len2)
+        if typeOf(s1).TO.chars.OF is Char and typeOf(s2).TO.chars.OF is Char:
+            malloc = mallocstr
+        else:
+            malloc = mallocunicode
+
+        newstr = malloc(len1 + len2)
         j = 0
         while j < len1:
             newstr.chars[j] = s1.chars[j]

Modified: pypy/branch/pypy-rpython-unicode/rpython/rstr.py
==============================================================================
--- pypy/branch/pypy-rpython-unicode/rpython/rstr.py	(original)
+++ pypy/branch/pypy-rpython-unicode/rpython/rstr.py	Tue Nov  6 12:38:02 2007
@@ -47,6 +47,9 @@
 
 class __extend__(AbstractStringRepr):
 
+    def _str_reprs(self, hop):
+        return hop.args_r[0].repr, hop.args_r[1].repr
+
     def get_ll_eq_function(self):
         return self.ll.ll_streq
 
@@ -64,7 +67,7 @@
     def rtype_is_true(self, hop):
         s_str = hop.args_s[0]
         if s_str.can_be_None:
-            string_repr = hop.rtyper.type_system.rstr.string_repr
+            string_repr = hop.args_r[0].repr
             v_str, = hop.inputargs(string_repr)
             return hop.gendirectcall(self.ll.ll_str_is_true, v_str)
         else:
@@ -72,25 +75,26 @@
             return super(AbstractStringRepr, self).rtype_is_true(hop)
 
     def rtype_ord(self, hop):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
+        string_repr = hop.args_r[0].repr
         v_str, = hop.inputargs(string_repr)
         c_zero = inputconst(Signed, 0)
         v_chr = hop.gendirectcall(self.ll.ll_stritem_nonneg, v_str, c_zero)
         return hop.genop('cast_char_to_int', [v_chr], resulttype=Signed)
 
     def rtype_method_startswith(self, hop):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
-        v_str, v_value = hop.inputargs(string_repr, string_repr)
+        str1_repr, str2_repr = self._str_reprs(hop)
+        v_str, v_value = hop.inputargs(str1_repr, str2_repr)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll.ll_startswith, v_str, v_value)
 
     def rtype_method_endswith(self, hop):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
-        v_str, v_value = hop.inputargs(string_repr, string_repr)
+        str1_repr, str2_repr = self._str_reprs(hop)
+        v_str, v_value = hop.inputargs(str1_repr, str2_repr)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll.ll_endswith, v_str, v_value)
 
     def rtype_method_find(self, hop, reverse=False):
+        # XXX binaryop
         rstr = hop.rtyper.type_system.rstr        
         v_str = hop.inputarg(rstr.string_repr, arg=0)
         if hop.args_r[1] == rstr.char_repr:
@@ -294,13 +298,20 @@
             return hop.gendirectcall(r_str.ll.ll_stringslice_minusone, v_str)
         raise TyperError(r_slic)
 
+def most_general_strrepr(repr1, repr2, rtyper):
+    string_repr = rtyper.type_system.rstr.string_repr
+    if repr1 is string_repr and repr2 is string_repr:
+        return string_repr
+    return rtyper_type_system.rstr.unicode_repr
 
 class __extend__(pairtype(AbstractStringRepr, AbstractStringRepr)):
     def rtype_add((r_str1, r_str2), hop):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
+        str1_repr = r_str1.repr
+        str2_repr = r_str2.repr
         if hop.s_result.is_constant():
-            return hop.inputconst(string_repr, hop.s_result.const)
-        v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
+            res_repr = most_general_strrepr(str1_repr, str2_repr, hop.rtyper)
+            return hop.inputconst(res_repr, hop.s_result.const)
+        v_str1, v_str2 = hop.inputargs(str1_repr, str2_repr)
         return hop.gendirectcall(r_str1.ll.ll_strconcat, v_str1, v_str2)
     rtype_inplace_add = rtype_add
 

Modified: pypy/branch/pypy-rpython-unicode/rpython/test/test_rstr.py
==============================================================================
--- pypy/branch/pypy-rpython-unicode/rpython/test/test_rstr.py	(original)
+++ pypy/branch/pypy-rpython-unicode/rpython/test/test_rstr.py	Tue Nov  6 12:38:02 2007
@@ -14,26 +14,31 @@
     assert parse('%s') == [('s',)]
     assert parse("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
 
-class BaseTestRstr(BaseRtypingTest):
-
+class AbstractTestRstr(BaseRtypingTest):
     def test_simple(self):
+        const = self.const
         def fn(i):
-            s = 'hello'
+            s = const('hello')
             return s[i]
         for i in range(5):
             res = self.interpret(fn, [i])
-            assert res == 'hello'[i]
+            expected = fn(i)
+            assert res == expected
+            assert res.__class__ is expected.__class__
 
     def test_implicit_index_error(self):
+        const = self.const
         def fn(i):
-            s = 'hello'
+            s = const('hello')
             try:
                 return s[i]
             except IndexError:
-                return '*'
+                return const('*')
         for i in range(-5, 5):
             res = self.interpret(fn, [i])
-            assert res == 'hello'[i]
+            expected = fn(i)
+            assert res == expected
+            assert res.__class__ is expected.__class__
         res = self.interpret(fn, [5])
         assert res == '*'
         res = self.interpret(fn, [6])
@@ -42,8 +47,9 @@
         assert res == '*'
 
     def test_nonzero(self):
+        const = self.const
         def fn(i, j):
-            s = ['', 'xx'][j]
+            s = [const(''), const('xx')][j]
             if i < 0:
                 s = None
             if i > -2:
@@ -56,9 +62,10 @@
                 assert res is fn(i, j)
 
     def test_concat(self):
+        const = self.const
         def fn(i, j):
-            s1 = ['', 'a', 'ab']
-            s2 = ['', 'x', 'xy']
+            s1 = [const(''), const('a'), const('ab')]
+            s2 = [const(''), const('x'), const('xy')]
             return s1[i] + s2[j]
         for i in range(3):
             for j in range(3):
@@ -779,6 +786,9 @@
     res = interpret(g, [-2])
     assert res._obj.value == 42
 
+class BaseTestRstr(AbstractTestRstr):
+    const = str
+
 class TestLLtype(BaseTestRstr, LLRtypeMixin):
 
     EMPTY_STRING_HASH = -1

Modified: pypy/branch/pypy-rpython-unicode/rpython/test/test_runicode.py
==============================================================================
--- pypy/branch/pypy-rpython-unicode/rpython/test/test_runicode.py	(original)
+++ pypy/branch/pypy-rpython-unicode/rpython/test/test_runicode.py	Tue Nov  6 12:38:02 2007
@@ -1,19 +1,12 @@
 
 
-from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin
+from pypy.rpython.test.tool import LLRtypeMixin
+from pypy.rpython.test.test_rstr import AbstractTestRstr
 
-class BaseTestRUnicode(BaseRtypingTest):
-    def test_simple(self):
-        def f(n):
-            if n % 2 == 0:
-                x = 'xxx'
-            else:
-                x = u'x\u221Ex'
-            return x[n]
+# ====> test_rstr.py
 
-        for i in range(0, 3):
-            res = self.interpret(f, [i])
-            assert res == f(i)
+class BaseTestRUnicode(AbstractTestRstr):
+    const = unicode
 
 class TestLLtype(BaseTestRUnicode, LLRtypeMixin):
     pass



More information about the Pypy-commit mailing list