[pypy-svn] r77785 - in pypy/trunk/pypy: config objspace/std objspace/std/test rlib rlib/test rpython rpython/lltypesystem rpython/test
arigo at codespeak.net
arigo at codespeak.net
Mon Oct 11 14:35:17 CEST 2010
Author: arigo
Date: Mon Oct 11 14:35:15 2010
New Revision: 77785
Added:
pypy/trunk/pypy/objspace/std/strbufobject.py
pypy/trunk/pypy/objspace/std/test/test_strbufobject.py
Modified:
pypy/trunk/pypy/config/pypyoption.py
pypy/trunk/pypy/objspace/std/model.py
pypy/trunk/pypy/objspace/std/stringobject.py
pypy/trunk/pypy/objspace/std/stringtype.py
pypy/trunk/pypy/rlib/rstring.py
pypy/trunk/pypy/rlib/test/test_rstring.py
pypy/trunk/pypy/rpython/lltypesystem/rbuilder.py
pypy/trunk/pypy/rpython/rbuilder.py
pypy/trunk/pypy/rpython/test/test_rbuilder.py
Log:
Experimental (disabled by default): add a W_StringBufferObject,
similar to W_StringJoinObject but based on the StringBuilder class.
Modified: pypy/trunk/pypy/config/pypyoption.py
==============================================================================
--- pypy/trunk/pypy/config/pypyoption.py (original)
+++ pypy/trunk/pypy/config/pypyoption.py Mon Oct 11 14:35:15 2010
@@ -198,6 +198,9 @@
BoolOption("withstrslice", "use strings optimized for slicing",
default=False),
+ BoolOption("withstrbuf", "use strings optimized for addition (ver 2)",
+ default=False),
+
BoolOption("withprebuiltchar",
"use prebuilt single-character string objects",
default=False),
@@ -210,7 +213,8 @@
BoolOption("withrope", "use ropes as the string implementation",
default=False,
requires=[("objspace.std.withstrslice", False),
- ("objspace.std.withstrjoin", False)],
+ ("objspace.std.withstrjoin", False),
+ ("objspace.std.withstrbuf", False)],
suggests=[("objspace.std.withprebuiltchar", True),
("objspace.std.sharesmallstr", True)]),
Modified: pypy/trunk/pypy/objspace/std/model.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/model.py (original)
+++ pypy/trunk/pypy/objspace/std/model.py Mon Oct 11 14:35:15 2010
@@ -18,6 +18,7 @@
"withsmallint" : ["smallintobject.W_SmallIntObject"],
"withstrslice" : ["strsliceobject.W_StringSliceObject"],
"withstrjoin" : ["strjoinobject.W_StringJoinObject"],
+ "withstrbuf" : ["strbufobject.W_StringBufferObject"],
"withrope" : ["ropeobject.W_RopeObject",
"ropeobject.W_RopeIterObject"],
"withropeunicode": ["ropeunicodeobject.W_RopeUnicodeObject",
@@ -75,6 +76,7 @@
from pypy.objspace.std import ropeunicodeobject
from pypy.objspace.std import strsliceobject
from pypy.objspace.std import strjoinobject
+ from pypy.objspace.std import strbufobject
from pypy.objspace.std import typeobject
from pypy.objspace.std import sliceobject
from pypy.objspace.std import longobject
@@ -222,6 +224,13 @@
(unicodeobject.W_UnicodeObject,
strjoinobject.delegate_join2unicode)
]
+ elif config.objspace.std.withstrbuf:
+ self.typeorder[strbufobject.W_StringBufferObject] += [
+ (stringobject.W_StringObject,
+ strbufobject.delegate_buf2str),
+ (unicodeobject.W_UnicodeObject,
+ strbufobject.delegate_buf2unicode)
+ ]
if config.objspace.std.withrangelist:
self.typeorder[rangeobject.W_RangeListObject] += [
(listobject.W_ListObject,
Added: pypy/trunk/pypy/objspace/std/strbufobject.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/objspace/std/strbufobject.py Mon Oct 11 14:35:15 2010
@@ -0,0 +1,76 @@
+from pypy.objspace.std.model import registerimplementation, W_Object
+from pypy.objspace.std.register_all import register_all
+from pypy.objspace.std.stringobject import W_StringObject
+from pypy.objspace.std.unicodeobject import delegate_String2Unicode
+from pypy.rlib.rstring import StringBuilder
+from pypy.interpreter.buffer import Buffer
+
+class W_StringBufferObject(W_Object):
+ from pypy.objspace.std.stringtype import str_typedef as typedef
+
+ w_str = None
+
+ def __init__(self, builder):
+ self.builder = builder # StringBuilder
+ self.length = builder.getlength()
+
+ def force(self):
+ if self.w_str is None:
+ s = self.builder.build()
+ if self.length < len(s):
+ s = s[:self.length]
+ self.w_str = W_StringObject(s)
+ return s
+ else:
+ return self.w_str._value
+
+ def __repr__(w_self):
+ """ representation for debugging purposes """
+ return "%s(%r[:%d])" % (
+ w_self.__class__.__name__, w_self.builder, w_self.length)
+
+ def unwrap(self, space):
+ return self.force()
+
+registerimplementation(W_StringBufferObject)
+
+# ____________________________________________________________
+
+def joined2(str1, str2):
+ builder = StringBuilder()
+ builder.append(str1)
+ builder.append(str2)
+ return W_StringBufferObject(builder)
+
+# ____________________________________________________________
+
+def delegate_buf2str(space, w_strbuf):
+ w_strbuf.force()
+ return w_strbuf.w_str
+
+def delegate_buf2unicode(space, w_strbuf):
+ w_strbuf.force()
+ return delegate_String2Unicode(space, w_strbuf.w_str)
+
+def len__StringBuffer(space, w_self):
+ return space.wrap(w_self.length)
+
+def str_w__StringBuffer(space, w_strbuf):
+ return w_strbuf.force()
+
+def add__StringBuffer_String(space, w_self, w_other):
+ if w_self.builder.getlength() != w_self.length:
+ builder = StringBuilder()
+ builder.append(w_self.force())
+ else:
+ builder = w_self.builder
+ builder.append(w_other._value)
+ return W_StringBufferObject(builder)
+
+def str__StringBuffer(space, w_self):
+ # you cannot get subclasses of W_StringBufferObject here
+ assert type(w_self) is W_StringBufferObject
+ return w_self
+
+from pypy.objspace.std import stringtype
+register_all(vars(), stringtype)
Modified: pypy/trunk/pypy/objspace/std/stringobject.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/stringobject.py (original)
+++ pypy/trunk/pypy/objspace/std/stringobject.py Mon Oct 11 14:35:15 2010
@@ -14,7 +14,7 @@
from pypy.rlib.rstring import StringBuilder, string_repeat
from pypy.interpreter.buffer import StringBuffer
-from pypy.objspace.std.stringtype import sliced, joined, wrapstr, wrapchar, \
+from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
stringendswith, stringstartswith, joined2
from pypy.objspace.std.formatting import mod_format
Modified: pypy/trunk/pypy/objspace/std/stringtype.py
==============================================================================
--- pypy/trunk/pypy/objspace/std/stringtype.py (original)
+++ pypy/trunk/pypy/objspace/std/stringtype.py Mon Oct 11 14:35:15 2010
@@ -55,19 +55,14 @@
return W_StringSliceObject(s, start, stop)
return wrapstr(space, s[start:stop])
-def joined(space, strlist):
- assert not space.config.objspace.std.withrope
- if space.config.objspace.std.withstrjoin:
- from pypy.objspace.std.strjoinobject import W_StringJoinObject
- return W_StringJoinObject(strlist)
- else:
- return wrapstr(space, "".join(strlist))
-
def joined2(space, str1, str2):
assert not space.config.objspace.std.withrope
if space.config.objspace.std.withstrjoin:
from pypy.objspace.std.strjoinobject import W_StringJoinObject
return W_StringJoinObject([str1, str2])
+ elif space.config.objspace.std.withstrbuf:
+ from pypy.objspace.std.strbufobject import joined2
+ return joined2(str1, str2)
else:
return wrapstr(space, str1 + str2)
Added: pypy/trunk/pypy/objspace/std/test/test_strbufobject.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/objspace/std/test/test_strbufobject.py Mon Oct 11 14:35:15 2010
@@ -0,0 +1,78 @@
+import py
+
+from pypy.objspace.std.test import test_stringobject
+from pypy.conftest import gettestobjspace
+
+class AppTestStringObject(test_stringobject.AppTestStringObject):
+
+ def setup_class(cls):
+ cls.space = gettestobjspace(**{"objspace.std.withstrbuf": True})
+
+ def test_basic(self):
+ import __pypy__
+ # cannot do "Hello, " + "World!" because cpy2.5 optimises this
+ # away on AST level
+ s = "Hello, ".__add__("World!")
+ assert type(s) is str
+ assert 'W_StringBufferObject' in __pypy__.internal_repr(s)
+
+ def test_add_twice(self):
+ x = "a".__add__("b")
+ y = x + "c"
+ c = x + "d"
+ assert y == "abc"
+ assert c == "abd"
+
+ def test_add(self):
+ import __pypy__
+ all = ""
+ for i in range(20):
+ all += str(i)
+ assert 'W_StringBufferObject' in __pypy__.internal_repr(all)
+ assert all == "012345678910111213141516171819"
+
+ def test_hash(self):
+ import __pypy__
+ def join(s): return s[:len(s) // 2] + s[len(s) // 2:]
+ t = 'a' * 101
+ s = join(t)
+ assert 'W_StringBufferObject' in __pypy__.internal_repr(s)
+ assert hash(s) == hash(t)
+
+ def test_len(self):
+ s = "a".__add__("b")
+ r = "c".__add__("d")
+ t = s + r
+ assert len(s) == 2
+ assert len(r) == 2
+ assert len(t) == 4
+
+ def test_add_strbuf(self):
+ # make three strbuf objects
+ s = 'a'.__add__('b')
+ t = 'x'.__add__('c')
+ u = 'y'.__add__('d')
+
+ # add two different strbufs to the same string
+ v = s + t
+ w = s + u
+
+ # check that insanity hasn't resulted.
+ assert v == "abxc"
+ assert w == "abyd"
+
+ def test_more_adding_fun(self):
+ s = 'a'.__add__('b') # s is a strbuf now
+ t = s + 'c'
+ u = s + 'd'
+ v = s + 'e'
+ assert v == 'abe'
+ assert u == 'abd'
+ assert t == 'abc'
+
+ def test_buh_even_more(self):
+ a = 'a'.__add__('b')
+ b = a + 'c'
+ c = '0'.__add__('1')
+ x = c + a
+ assert x == '01ab'
Modified: pypy/trunk/pypy/rlib/rstring.py
==============================================================================
--- pypy/trunk/pypy/rlib/rstring.py (original)
+++ pypy/trunk/pypy/rlib/rstring.py Mon Oct 11 14:35:15 2010
@@ -54,6 +54,7 @@
self.l = []
def append(self, s):
+ assert isinstance(s, self._type)
self.l.append(s)
def append_slice(self, s, start, end):
@@ -63,11 +64,16 @@
def append_multiple_char(self, c, times):
self.l.append(c * times)
+ def getlength(self):
+ return len(self.build())
+
class StringBuilder(AbstractStringBuilder):
+ _type = str
def build(self):
return "".join(self.l)
class UnicodeBuilder(AbstractStringBuilder):
+ _type = unicode
def build(self):
return u''.join(self.l)
@@ -121,9 +127,12 @@
assert s_times.nonneg
return s_None
+ def method_getlength(self):
+ return SomeInteger(nonneg=True)
+
def method_build(self):
return SomeString()
-
+
def rtyper_makerepr(self, rtyper):
return rtyper.type_system.rbuilder.stringbuilder_repr
@@ -146,6 +155,9 @@
assert s_times.nonneg
return s_None
+ def method_getlength(self):
+ return SomeInteger(nonneg=True)
+
def method_build(self):
return SomeUnicodeString()
Modified: pypy/trunk/pypy/rlib/test/test_rstring.py
==============================================================================
--- pypy/trunk/pypy/rlib/test/test_rstring.py (original)
+++ pypy/trunk/pypy/rlib/test/test_rstring.py Mon Oct 11 14:35:15 2010
@@ -29,6 +29,7 @@
s = StringBuilder()
s.append("a")
s.append("abc")
+ assert s.getlength() == len('aabc')
s.append("a")
s.append_slice("abc", 1, 2)
s.append_multiple_char('d', 4)
@@ -39,6 +40,7 @@
s.append(u'a')
s.append(u'abc')
s.append_slice(u'abcdef', 1, 2)
+ assert s.getlength() == len('aabcb')
s.append_multiple_char('d', 4)
assert s.build() == 'aabcbdddd'
assert isinstance(s.build(), unicode)
Modified: pypy/trunk/pypy/rpython/lltypesystem/rbuilder.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/rbuilder.py (original)
+++ pypy/trunk/pypy/rpython/lltypesystem/rbuilder.py Mon Oct 11 14:35:15 2010
@@ -100,6 +100,10 @@
ll_builder.used = used
@staticmethod
+ def ll_getlength(ll_builder):
+ return ll_builder.used
+
+ @staticmethod
def ll_build(ll_builder):
final_size = ll_builder.used
assert final_size >= 0
Modified: pypy/trunk/pypy/rpython/rbuilder.py
==============================================================================
--- pypy/trunk/pypy/rpython/rbuilder.py (original)
+++ pypy/trunk/pypy/rpython/rbuilder.py Mon Oct 11 14:35:15 2010
@@ -36,8 +36,12 @@
hop.exception_cannot_occur()
return hop.gendirectcall(self.ll_append_multiple_char, *vlist)
+ def rtype_method_getlength(self, hop):
+ vlist = hop.inputargs(self)
+ hop.exception_cannot_occur()
+ return hop.gendirectcall(self.ll_getlength, *vlist)
+
def rtype_method_build(self, hop):
vlist = hop.inputargs(self)
hop.exception_cannot_occur()
return hop.gendirectcall(self.ll_build, *vlist)
-
Modified: pypy/trunk/pypy/rpython/test/test_rbuilder.py
==============================================================================
--- pypy/trunk/pypy/rpython/test/test_rbuilder.py (original)
+++ pypy/trunk/pypy/rpython/test/test_rbuilder.py Mon Oct 11 14:35:15 2010
@@ -1,4 +1,4 @@
-
+import py
from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
from pypy.rpython.lltypesystem.rbuilder import *
from pypy.rpython.annlowlevel import llstr, hlstr
@@ -55,8 +55,29 @@
assert res == 'aabcabcdefbuuuu'
assert isinstance(res, unicode)
+ def test_string_getlength(self):
+ def func():
+ s = StringBuilder()
+ s.append("a")
+ s.append("abc")
+ return s.getlength()
+ res = self.interpret(func, [])
+ assert res == 4
+
+ def test_unicode_getlength(self):
+ def func():
+ s = UnicodeBuilder()
+ s.append(u"a")
+ s.append(u"abc")
+ return s.getlength()
+ res = self.interpret(func, [])
+ assert res == 4
+
class TestLLtype(BaseTestStringBuilder, LLRtypeMixin):
pass
class TestOOtype(BaseTestStringBuilder, OORtypeMixin):
- pass
+ def test_string_getlength(self):
+ py.test.skip("getlength(): not implemented on ootype")
+ def test_unicode_getlength(self):
+ py.test.skip("getlength(): not implemented on ootype")
More information about the Pypy-commit
mailing list