[pypy-commit] pypy SomeString-charclass: Progress, add AsciiChar kind.

amauryfa noreply at buildbot.pypy.org
Tue Jul 15 15:43:46 CEST 2014


Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: SomeString-charclass
Changeset: r72438:58e84b592e0a
Date: 2014-07-13 20:12 +0200
http://bitbucket.org/pypy/pypy/changeset/58e84b592e0a/

Log:	Progress, add AsciiChar kind.

diff --git a/rpython/annotator/model.py b/rpython/annotator/model.py
--- a/rpython/annotator/model.py
+++ b/rpython/annotator/model.py
@@ -220,7 +220,10 @@
 # Character classes.
 
 class AnyChar(object):
+    """A character of any value."""
     no_nul = False
+    is_ascii = False
+
     _instances = {}
 
     def __new__(cls):
@@ -244,6 +247,9 @@
 AnyChar._register()
 
 class NoNulChar(AnyChar):
+    """Any character except NUL '\0'.
+    Strings of this kind can be converted to char* with no loss."""
+
     no_nul = True
 
     def union(self, other):
@@ -253,13 +259,35 @@
             return AnyChar()
 NoNulChar._register()
 
-AsciiChar = AnyChar  # So far
+class AsciiChar(NoNulChar):
+    """A character in the range(1, 128).
+
+    Strings of this kind can be decoded faster to unicode."""
+
+    is_ascii = True
+
+    def union(self, other):
+        if other.is_ascii:
+            return self
+        elif other.no_nul:
+            return NoNulChar()
+        else:
+            return AnyChar()
+AsciiChar._register()
+
 
 def charkind_from_const(value):
+    try:
+        value.decode('ascii')
+    except UnicodeDecodeError:
+        pass
+    else:
+        return AsciiChar()
     if '\x00' not in value:
         return NoNulChar()
     return AnyChar()
 
+
 class SomeStringOrUnicode(SomeObject):
     """Base class for shared implementation of SomeString,
     SomeUnicodeString and SomeByteArray.
@@ -284,14 +312,16 @@
         return self.can_be_None
 
     def nonnoneify(self):
-        return self.__class__(can_be_None=False,
-                              charkind=self.charkind)
+        return self.basestringclass(can_be_None=False, charkind=self.charkind)
+
+    def noneify(self):
+        return self.basestringclass(can_be_None=True, charkind=self.charkind)
 
     def nonnulify(self):
-        if self.charkind == NoNulChar():
-            charkind = NoNulChar()
-        elif self.charkind == AnyChar():
-            charkind = NoNulChar()
+        if self.charkind.no_nul:
+            return self
+        assert type(self.charkind) is AnyChar  # so far the only one.
+        charkind = NoNulChar()
         return self.__class__(can_be_None=self.can_be_None, charkind=charkind)
 
 
@@ -299,17 +329,11 @@
     "Stands for an object which is known to be a string."
     knowntype = str
 
-    def noneify(self):
-        return SomeString(can_be_None=True, charkind=self.charkind)
-
 
 class SomeUnicodeString(SomeStringOrUnicode):
     "Stands for an object which is known to be an unicode string"
     knowntype = unicode
 
-    def noneify(self):
-        return SomeUnicodeString(can_be_None=True, charkind=self.charkind)
-
 
 class SomeByteArray(SomeStringOrUnicode):
     immutable = False
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -487,7 +487,7 @@
 
     def method_split(self, patt, max=-1):
         if max == -1 and patt.is_constant() and patt.const == "\0":
-            charkind = NoNulChar
+            charkind = NoNulChar()
         else:
             charkind = self.charkind
         s_item = self.basestringclass(charkind=charkind)
diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py
--- a/rpython/rlib/rstring.py
+++ b/rpython/rlib/rstring.py
@@ -523,15 +523,9 @@
     _about_ = assert_str0
 
     def compute_result_annotation(self, s_obj):
-        if s_None.contains(s_obj):
+        if s_None.contains(s_obj):  # probably a future str_or_None
             return s_obj
-        assert isinstance(s_obj, (SomeString, SomeUnicodeString))
-        if s_obj.charkind.no_nul:
-            return s_obj
-        new_s_obj = SomeObject.__new__(s_obj.__class__)
-        new_s_obj.__dict__ = s_obj.__dict__.copy()
-        new_s_obj.charkind = NoNulChar()
-        return new_s_obj
+        return s_obj.nonnulify()
 
     def specialize_call(self, hop):
         hop.exception_cannot_occur()


More information about the pypy-commit mailing list