[pypy-svn] r27139 - in pypy/dist/pypy/rpython: . lltypesystem ootypesystem test

antocuni at codespeak.net antocuni at codespeak.net
Fri May 12 17:01:03 CEST 2006


Author: antocuni
Date: Fri May 12 17:00:53 2006
New Revision: 27139

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
More work on rstr:

  - Added support for null strings in ootypesystem
  
  - Part of LLHelpers has been factored out and placed in
    AbstractLLHelpers so that can be shared by the two typesystems

  - Added support for stritem, strlen, strconcat to ootypesystem

  - Some tests have been made typesystem-aware.



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Fri May 12 17:00:53 2006
@@ -1,11 +1,12 @@
 from weakref import WeakValueDictionary
-from pypy.tool.staticmethods import StaticMethods
 from pypy.annotation.pairtype import pairtype
+from pypy.rpython.error import TyperError
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rarithmetic import _hash_string
 from pypy.rpython.rmodel import inputconst, IntegerRepr
-from pypy.rpython.rstr import AbstractStringRepr, \
-     AbstractCharRepr, AbstractUniCharRepr, AbstractStringIteratorRepr
+from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
+     AbstractUniCharRepr, AbstractStringIteratorRepr,\
+     AbstractLLHelpers
 from pypy.rpython import rint
 from pypy.rpython.lltypesystem.lltype import \
      GcStruct, Signed, Array, Char, UniChar, Ptr, malloc, \
@@ -108,41 +109,7 @@
 #  get flowed and annotated, mostly with SomePtr.
 #
 
-class LLHelpers:
-    __metaclass__ = StaticMethods
-
-    def ll_char_isspace(ch):
-        c = ord(ch) 
-        return c == 32 or (c <= 13 and c >= 9)   # c in (9, 10, 11, 12, 13, 32)
-
-    def ll_char_isdigit(ch):
-        c = ord(ch)
-        return c <= 57 and c >= 48
-
-    def ll_char_isalpha(ch):
-        c = ord(ch)
-        if c >= 97:
-            return c <= 122
-        else:
-            return 65 <= c <= 90
-
-    def ll_char_isalnum(ch):
-        c = ord(ch)
-        if c >= 65:
-            if c >= 97:
-                return c <= 122
-            else:
-                return c <= 90
-        else:
-            return 48 <= c <= 57
-
-    def ll_char_isupper(ch):
-        c = ord(ch)
-        return 65 <= c <= 90
-
-    def ll_char_islower(ch):   
-        c = ord(ch)
-        return 97 <= c <= 122
+class LLHelpers(AbstractLLHelpers):
 
     def ll_char_mul(ch, times):
         newstr = malloc(STR, times)
@@ -152,39 +119,12 @@
             j += 1
         return newstr
 
-    def ll_char_hash(ch):
-        return ord(ch)
-
-    def ll_unichar_hash(ch):
-        return ord(ch)
-
     def ll_strlen(s):
         return len(s.chars)
 
     def ll_stritem_nonneg(s, i):
         return s.chars[i]
 
-    def ll_stritem_nonneg_checked(s, i):
-        if i >= len(s.chars):
-            raise IndexError
-        return s.chars[i]
-
-    def ll_stritem(s, i):
-        if i < 0:
-            i += len(s.chars)
-        return s.chars[i]
-
-    def ll_stritem_checked(s, i):
-        if i < 0:
-            i += len(s.chars)
-        if i >= len(s.chars) or i < 0:
-            raise IndexError
-        return s.chars[i]
-
-    def ll_str_is_true(s):
-        # check if a string is True, allowing for None
-        return bool(s) and len(s.chars) != 0
-
     def ll_chr2str(ch):
         s = malloc(STR, 1)
         s.chars[0] = ch
@@ -736,7 +676,7 @@
 do_stringformat = LLHelpers.do_stringformat
 
 string_repr = StringRepr()
-char_repr   = CharRepr()
+char_repr = CharRepr()
 unichar_repr = UniCharRepr()
 char_repr.ll = LLHelpers
 unichar_repr.ll = LLHelpers

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Fri May 12 17:00:53 2006
@@ -268,15 +268,20 @@
 
 # WARNING: the name 'String' is rebound at the end of file
 class String(BuiltinADTType):
+    SELFTYPE_T = object()
 
     def __init__(self):
+        self._null = _null_string(self)
+
+        generic_types = { self.SELFTYPE_T: self }
         self._GENERIC_METHODS = frozendict({
             "ll_stritem_nonneg": Meth([Signed], Char),
-            "ll_stritem": Meth([Signed], Char),
+            "ll_strlen": Meth([], Signed),
+            "ll_strconcat": Meth([self.SELFTYPE_T], self.SELFTYPE_T)
         })
+        self._setup_methods(generic_types)
 
-        self._setup_methods({})
-
+    # TODO: should it return _null or ''?
     def _defl(self):
         return make_string("")
     
@@ -770,15 +775,19 @@
         self._str = value
         self._TYPE = STRING
 
-    def ll_stritem(self, i):
-        # NOT_RPYTHON
-        return self._str[i]
-
     def ll_stritem_nonneg(self, i):
         # NOT_RPYTHON
         assert i >= 0
         return self._str[i]
 
+    def ll_strlen(self):
+        # NOT_RPYTHON
+        return len(self._str)
+
+    def ll_strconcat(self, s):
+        # NOT_RPYTHON
+        return make_string(self._str + s._str)
+
     # delegate missing ll_* methods to self._str
     def __getattr__(self, attr):
         if attr.startswith('ll_'):
@@ -803,8 +812,11 @@
                 return res
         return f
 
-class _list(_builtin_type):
+class _null_string(_null_mixin(_string), _string):
+    def __init__(self, STRING):
+        self.__dict__["_TYPE"] = STRING
 
+class _list(_builtin_type):
     def __init__(self, LIST):
         self._TYPE = LIST
         self._list = []

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Fri May 12 17:00:53 2006
@@ -1,6 +1,7 @@
-from pypy.tool.staticmethods import StaticMethods
-from pypy.rpython.rstr import AbstractStringRepr, \
-     AbstractCharRepr, AbstractUniCharRepr, AbstractStringIteratorRepr
+from pypy.rpython.error import TyperError
+from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
+     AbstractUniCharRepr, AbstractStringIteratorRepr,\
+     AbstractLLHelpers
 from pypy.rpython.lltypesystem.lltype import Ptr, Char, UniChar
 from pypy.rpython.ootypesystem.ootype import Signed, Record, String, make_string
 
@@ -29,9 +30,8 @@
         self.ll = LLHelpers
 
     def convert_const(self, value):
-        # XXX what do we do about null strings?
-        #if value is None:
-        #    return nullptr(STR)
+        if value is None:
+            return String._null
         if not isinstance(value, str):
             raise TyperError("not a str: %r" % (value,))
         return make_string(value)
@@ -46,19 +46,22 @@
 class UniCharRepr(AbstractUniCharRepr):
     lowleveltype = UniChar
 
-class LLHelpers:
-    __metaclass__ = StaticMethods
+class LLHelpers(AbstractLLHelpers):
 
     def ll_stritem_nonneg(s, i):
         return s.ll_stritem_nonneg(i)
 
-    def ll_stritem(s, i):
-        return s.ll_stritem(i)
+    def ll_strlen(s):
+        return s.ll_strlen()
 
+    def ll_strconcat(s1, s2):
+        return s1.ll_strconcat(s2)
 
 string_repr = StringRepr()
 char_repr = CharRepr()
 unichar_repr = UniCharRepr()
+char_repr.ll = LLHelpers
+unichar_repr.ll = LLHelpers
 
 class StringIteratorRepr(AbstractStringIteratorRepr):
 

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Fri May 12 17:00:53 2006
@@ -1,3 +1,4 @@
+from pypy.tool.staticmethods import StaticMethods
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.rpython.error import TyperError
@@ -463,3 +464,82 @@
         hop.exception_is_here()
         return hop.gendirectcall(self.ll_strnext, v_iter)
 
+
+# ____________________________________________________________
+#
+#  Low-level methods.  These can be run for testing, but are meant to
+#  be direct_call'ed from rtyped flow graphs, which means that they will
+#  get flowed and annotated, mostly with SomePtr.
+#
+
+# this class contains low level helpers used both by lltypesystem and
+# ootypesystem; each typesystem should subclass it and add its own
+# primitives.
+class AbstractLLHelpers:
+    __metaclass__ = StaticMethods
+
+    def ll_char_isspace(ch):
+        c = ord(ch) 
+        return c == 32 or (c <= 13 and c >= 9)   # c in (9, 10, 11, 12, 13, 32)
+
+    def ll_char_isdigit(ch):
+        c = ord(ch)
+        return c <= 57 and c >= 48
+
+    def ll_char_isalpha(ch):
+        c = ord(ch)
+        if c >= 97:
+            return c <= 122
+        else:
+            return 65 <= c <= 90
+
+    def ll_char_isalnum(ch):
+        c = ord(ch)
+        if c >= 65:
+            if c >= 97:
+                return c <= 122
+            else:
+                return c <= 90
+        else:
+            return 48 <= c <= 57
+
+    def ll_char_isupper(ch):
+        c = ord(ch)
+        return 65 <= c <= 90
+
+    def ll_char_islower(ch):   
+        c = ord(ch)
+        return 97 <= c <= 122
+
+    def ll_char_hash(ch):
+        return ord(ch)
+
+    def ll_unichar_hash(ch):
+        return ord(ch)
+
+    @classmethod
+    def ll_str_is_true(cls, s):
+        # check if a string is True, allowing for None
+        return bool(s) and cls.ll_strlen(s) != 0
+
+    @classmethod
+    def ll_stritem_nonneg_checked(cls, s, i):
+        if i >= cls.ll_strlen(s):
+            raise IndexError
+        return cls.ll_stritem_nonneg(s, i)
+
+    @classmethod
+    def ll_stritem(cls, s, i):
+        if i < 0:
+            i += cls.ll_strlen(s)
+        return cls.ll_stritem_nonneg(s, i)
+
+    @classmethod
+    def ll_stritem_checked(cls, s, i):
+        length = cls.ll_strlen(s)
+        if i < 0:
+            i += length
+        if i >= length or i < 0:
+            raise IndexError
+        return cls.ll_stritem_nonneg(s, i)
+

Modified: pypy/dist/pypy/rpython/test/test_rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rstr.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rstr.py	Fri May 12 17:00:53 2006
@@ -43,59 +43,46 @@
             res = self.interpret(fn, [i])
             assert res == 'hello'[i]
 
-def test_implicit_index_error():
-    def fn(i):
-        s = 'hello'
-        try:
-            return s[i]
-        except IndexError:
-            return '*'
-    for i in range(-5, 5):
-        res = interpret(fn, [i])
-        assert res == 'hello'[i]
-    res = interpret(fn, [5])
-    assert res == '*'
-    res = interpret(fn, [6])
-    assert res == '*'
-    res = interpret(fn, [-42])
-    assert res == '*'
-    
-
-def test_nonzero():
-    def fn(i, j):
-        s = ['', 'xx'][j]
-        if i < 0:
-            s = None
-        if i > -2:
-            return bool(s)
-        else:
-            return False
-    for i in [-2, -1, 0]:
-        for j in range(2):
-            res = interpret(fn, [i, j])
-            assert res is fn(i, j)
-
-def test_hash():
-    def fn(i):
-        if i == 0:
-            s = ''
-        else:
-            s = "xxx"
-        return hash(s)
-    res = interpret(fn, [0])
-    assert res == -1
-    res = interpret(fn, [1])
-    assert typeOf(res) == Signed
-
-def test_concat():
-    def fn(i, j):
-        s1 = ['', 'a', 'ab']
-        s2 = ['', 'x', 'xy']
-        return s1[i] + s2[j]
-    for i in range(3):
-        for j in range(3):
-            res = interpret(fn, [i,j])
-            assert ''.join(res.chars) == fn(i, j)
+    def test_implicit_index_error(self):
+        def fn(i):
+            s = 'hello'
+            try:
+                return s[i]
+            except IndexError:
+                return '*'
+        for i in range(-5, 5):
+            res = self.interpret(fn, [i])
+            assert res == 'hello'[i]
+        res = self.interpret(fn, [5])
+        assert res == '*'
+        res = self.interpret(fn, [6])
+        assert res == '*'
+        res = self.interpret(fn, [-42])
+        assert res == '*'
+
+    def test_nonzero(self):
+        def fn(i, j):
+            s = ['', 'xx'][j]
+            if i < 0:
+                s = None
+            if i > -2:
+                return bool(s)
+            else:
+                return False
+        for i in [-2, -1, 0]:
+            for j in range(2):
+                res = self.interpret(fn, [i, j])
+                assert res is fn(i, j)
+
+    def test_concat(self):
+        def fn(i, j):
+            s1 = ['', 'a', 'ab']
+            s2 = ['', 'x', 'xy']
+            return s1[i] + s2[j]
+        for i in range(3):
+            for j in range(3):
+                res = self.interpret(fn, [i,j])
+                assert self.ll_to_string(res) == fn(i, j)
 
 def test_iter():
     def fn(i):
@@ -581,5 +568,24 @@
 class TestLltype(AbstractTestRstr):
     ts = "lltype"
 
+    def ll_to_string(self, s):
+        return ''.join(s.chars)
+
+    def test_hash(self):
+        def fn(i):
+            if i == 0:
+                s = ''
+            else:
+                s = "xxx"
+            return hash(s)
+        res = self.interpret(fn, [0])
+        assert res == -1
+        res = self.interpret(fn, [1])
+        assert typeOf(res) == Signed
+
+
 class TestOotype(AbstractTestRstr):
     ts = "ootype"
+
+    def ll_to_string(self, s):
+        return s._str



More information about the Pypy-commit mailing list