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

arigo at codespeak.net arigo at codespeak.net
Tue Dec 5 18:11:42 CET 2006


Author: arigo
Date: Tue Dec  5 18:11:37 2006
New Revision: 35315

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rlist.py
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/lltypesystem/rtuple.py
   pypy/dist/pypy/rpython/ootypesystem/rlist.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/rtuple.py
   pypy/dist/pypy/rpython/rlist.py
   pypy/dist/pypy/rpython/rptr.py
   pypy/dist/pypy/rpython/rtuple.py
   pypy/dist/pypy/rpython/test/test_rptr.py
   pypy/dist/pypy/rpython/test/test_rtuple.py
Log:
(pedronis, arre, arigo)

A typesystem-independent way to write ll string building.
Allowed us to write ll_str() for lists in a generic way,
as well as add ll_str() for tuples and rptrs.



Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rlist.py	Tue Dec  5 18:11:37 2006
@@ -37,6 +37,7 @@
 #
 
 class BaseListRepr(AbstractBaseListRepr):
+    rstr_ll = rstr.LLHelpers
 
     def __init__(self, rtyper, item_repr, listitem=None):
         self.rtyper = rtyper
@@ -64,24 +65,6 @@
     def make_iterator_repr(self):
         return ListIteratorRepr(self)
 
-    def ll_str(self, l):
-        items = l.ll_items()
-        length = l.ll_length()
-        item_repr = self.item_repr
-
-        temp = malloc(TEMP, length)
-        i = 0
-        while i < length:
-            temp[i] = item_repr.ll_str(items[i])
-            i += 1
-
-        return rstr.ll_strconcat(
-            rstr.list_str_open_bracket,
-            rstr.ll_strconcat(rstr.ll_join(rstr.list_str_sep,
-                                           length,
-                                           temp),
-                              rstr.list_str_close_bracket))
-
     def get_itemarray_lowleveltype(self):
         ITEM = self.item_repr.lowleveltype
         ITEMARRAY = GcArray(ITEM,
@@ -364,8 +347,6 @@
 ll_append_noresize.oopspec = 'list.append(l, newitem)'
 
 
-TEMP = GcArray(Ptr(rstr.STR))
-
 def ll_both_none(lst1, lst2):
     return not lst1 and not lst2
         

Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Tue Dec  5 18:11:37 2006
@@ -667,13 +667,33 @@
             raise ValueError
         return sign * val
 
+    # interface to build strings:
+    #   x = ll_build_start(n)
+    #   ll_build_push(x, next_string, 0)
+    #   ll_build_push(x, next_string, 1)
+    #   ...
+    #   ll_build_push(x, next_string, n-1)
+    #   s = ll_build_finish(x)
+
+    def ll_build_start(parts_count):
+        return malloc(TEMP, parts_count)
+
+    def ll_build_push(builder, next_string, index):
+        builder[index] = next_string
+
+    def ll_build_finish(builder):
+        return LLHelpers.ll_join_strs(len(builder), builder)
+
+    def ll_constant(s):
+        return string_repr.convert_const(s)
+    ll_constant._annspecialcase_ = 'specialize:memo'
+
     def do_stringformat(cls, hop, sourcevarsrepr):
         s_str = hop.args_s[0]
         assert s_str.is_constant()
         s = s_str.const
         things = cls.parse_fmt_string(s)
         size = inputconst(Signed, len(things)) # could be unsigned?
-        TEMP = GcArray(Ptr(STR))
         cTEMP = inputconst(Void, TEMP)
         vtemp = hop.genop("malloc_varsize", [cTEMP, size],
                           resulttype=Ptr(TEMP))
@@ -719,6 +739,8 @@
         return hop.gendirectcall(cls.ll_join_strs, size, vtemp)
     do_stringformat = classmethod(do_stringformat)
 
+TEMP = GcArray(Ptr(STR))
+
 
 # TODO: make the public interface of the rstr module cleaner
 ll_strconcat = LLHelpers.ll_strconcat
@@ -771,8 +793,4 @@
 unboxed_instance_str_prefix = string_repr.convert_const("<unboxed ")
 unboxed_instance_str_suffix = string_repr.convert_const(">")
 
-list_str_open_bracket = string_repr.convert_const("[")
-list_str_close_bracket = string_repr.convert_const("]")
-list_str_sep = string_repr.convert_const(", ")
-
 percent_f = string_repr.convert_const("%f")

Modified: pypy/dist/pypy/rpython/lltypesystem/rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rtuple.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rtuple.py	Tue Dec  5 18:11:37 2006
@@ -5,6 +5,7 @@
 from pypy.rpython.lltypesystem.lltype import \
      Ptr, GcStruct, Void, Signed, malloc, typeOf, nullptr
 from pypy.rpython.lltypesystem.rtupletype import TUPLE_TYPE
+from pypy.rpython.lltypesystem import rstr
 
 # ____________________________________________________________
 #
@@ -18,6 +19,7 @@
 #    }
 
 class TupleRepr(AbstractTupleRepr):
+    rstr_ll = rstr.LLHelpers
 
     def __init__(self, rtyper, items_r):
         AbstractTupleRepr.__init__(self, rtyper, items_r)

Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rlist.py	Tue Dec  5 18:11:37 2006
@@ -11,6 +11,7 @@
 
 
 class BaseListRepr(AbstractBaseListRepr):
+    rstr_ll = rstr.LLHelpers
 
     def __init__(self, rtyper, item_repr, listitem=None):
         self.rtyper = rtyper
@@ -58,24 +59,6 @@
     def make_iterator_repr(self):
         return ListIteratorRepr(self)
 
-    def ll_str(self, lst):
-        item_repr = self.item_repr
-        length = lst.ll_length()        
-        buf = ootype.new(ootype.StringBuilder)
-        buf.ll_append_char('[')
-        i = 0
-        while i < length-1:
-            item = lst.ll_getitem_fast(i)
-            buf.ll_append(item_repr.ll_str(item))
-            buf.ll_append_char(',')
-            buf.ll_append_char(' ')
-            i += 1
-        if length > 0:
-            lastitem = lst.ll_getitem_fast(i)
-            buf.ll_append(item_repr.ll_str(lastitem))
-        buf.ll_append_char(']')
-        return buf.ll_build()
-
     def rtype_hint(self, hop):
         hints = hop.args_s[-1].const
         if 'maxlength' in hints:

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Tue Dec  5 18:11:37 2006
@@ -193,6 +193,27 @@
             raise ValueError
         return sign * val
 
+    # interface to build strings:
+    #   x = ll_build_start(n)
+    #   ll_build_push(x, next_string, 0)
+    #   ll_build_push(x, next_string, 1)
+    #   ...
+    #   ll_build_push(x, next_string, n-1)
+    #   s = ll_build_finish(x)
+
+    def ll_build_start(parts_count):
+        return ootype.new(ootype.StringBuilder)
+
+    def ll_build_push(buf, next_string, index):
+        buf.ll_append(next_string)
+
+    def ll_build_finish(buf):
+        return buf.ll_build()
+
+    def ll_constant(s):
+        return ootype.make_string(s)
+    ll_constant._annspecialcase_ = 'specialize:memo'
+
     def do_stringformat(cls, hop, sourcevarsrepr):
         InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr
         string_repr = hop.rtyper.type_system.rstr.string_repr

Modified: pypy/dist/pypy/rpython/ootypesystem/rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rtuple.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rtuple.py	Tue Dec  5 18:11:37 2006
@@ -1,9 +1,11 @@
 from pypy.rpython.rmodel import inputconst
 from pypy.rpython.rtuple import AbstractTupleRepr, AbstractTupleIteratorRepr
 from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.ootypesystem import rstr
 
 
 class TupleRepr(AbstractTupleRepr):
+    rstr_ll = rstr.LLHelpers
 
     def __init__(self, rtyper, items_r):
         AbstractTupleRepr.__init__(self, rtyper, items_r)

Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py	(original)
+++ pypy/dist/pypy/rpython/rlist.py	Tue Dec  5 18:11:37 2006
@@ -84,6 +84,29 @@
     def prepare_const(self, nitems):
         raise NotImplementedError
 
+    def ll_str(self, l):
+        constant = self.rstr_ll.ll_constant
+        start    = self.rstr_ll.ll_build_start
+        push     = self.rstr_ll.ll_build_push
+        finish   = self.rstr_ll.ll_build_finish
+
+        length = l.ll_length()
+        if length == 0:
+            return constant("[]")
+
+        buf = start(2 * length + 1)
+        push(buf, constant("["), 0)
+        item_repr = self.item_repr
+        i = 0
+        while i < length:
+            if i > 0:
+                push(buf, constant(", "), 2 * i)
+            item = l.ll_getitem_fast(i)
+            push(buf, item_repr.ll_str(item), 2 * i + 1)
+            i += 1
+        push(buf, constant("]"), 2 * length)
+        return finish(buf)
+
     def rtype_bltn_list(self, hop):
         v_lst = hop.inputarg(self, 0)
         cRESLIST = hop.inputconst(Void, hop.r_result.LIST)

Modified: pypy/dist/pypy/rpython/rptr.py
==============================================================================
--- pypy/dist/pypy/rpython/rptr.py	(original)
+++ pypy/dist/pypy/rpython/rptr.py	Tue Dec  5 18:11:37 2006
@@ -1,10 +1,10 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow import model as flowmodel
-from pypy.rpython.lltypesystem.lltype import \
-     Ptr, ContainerType, Void, Signed, Bool, FuncType, typeOf, FixedSizeArray
+from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import Repr, IntegerRepr
+from pypy.rlib.rarithmetic import r_uint
 
 
 class __extend__(annmodel.SomePtr):
@@ -23,33 +23,38 @@
 class PtrRepr(Repr):
 
     def __init__(self, ptrtype):
-        assert isinstance(ptrtype, Ptr)
+        assert isinstance(ptrtype, lltype.Ptr)
         self.lowleveltype = ptrtype
 
+    def ll_str(self, p):
+        from pypy.rpython.lltypesystem.rstr import LLHelpers, ll_str
+        id = lltype.cast_ptr_to_int(p)
+        return ll_str.ll_int2hex(r_uint(id), True)
+
     def rtype_getattr(self, hop):
         attr = hop.args_s[1].const
         if isinstance(hop.s_result, annmodel.SomeLLADTMeth):
             return hop.inputarg(hop.r_result, arg=0)
         FIELD_TYPE = getattr(self.lowleveltype.TO, attr)
-        if isinstance(FIELD_TYPE, ContainerType):
+        if isinstance(FIELD_TYPE, lltype.ContainerType):
             newopname = 'getsubstruct'
         else:
             newopname = 'getfield'
-        vlist = hop.inputargs(self, Void)
+        vlist = hop.inputargs(self, lltype.Void)
         return hop.genop(newopname, vlist,
                          resulttype = hop.r_result.lowleveltype)
 
     def rtype_setattr(self, hop):
         attr = hop.args_s[1].const
         FIELD_TYPE = getattr(self.lowleveltype.TO, attr)
-        assert not isinstance(FIELD_TYPE, ContainerType)
-        vlist = hop.inputargs(self, Void, hop.args_r[2])
+        assert not isinstance(FIELD_TYPE, lltype.ContainerType)
+        vlist = hop.inputargs(self, lltype.Void, hop.args_r[2])
         hop.genop('setfield', vlist)
 
     def rtype_len(self, hop):
         ARRAY = hop.args_r[0].lowleveltype.TO
-        if isinstance(ARRAY, FixedSizeArray):
-            return hop.inputconst(Signed, ARRAY.length)
+        if isinstance(ARRAY, lltype.FixedSizeArray):
+            return hop.inputconst(lltype.Signed, ARRAY.length)
         else:
             vlist = hop.inputargs(self)
             return hop.genop('getarraysize', vlist,
@@ -57,10 +62,10 @@
 
     def rtype_is_true(self, hop):
         vlist = hop.inputargs(self)
-        return hop.genop('ptr_nonzero', vlist, resulttype=Bool)
+        return hop.genop('ptr_nonzero', vlist, resulttype=lltype.Bool)
 
     def rtype_simple_call(self, hop):
-        if not isinstance(self.lowleveltype.TO, FuncType):
+        if not isinstance(self.lowleveltype.TO, lltype.FuncType):
             raise TyperError("calling a non-function %r", self.lowleveltype.TO)
         vlist = hop.inputargs(*hop.args_r)
         nexpected = len(self.lowleveltype.TO.ARGS)
@@ -74,7 +79,7 @@
             opname = 'direct_call'
         else:
             opname = 'indirect_call'
-            vlist.append(hop.inputconst(Void, None))
+            vlist.append(hop.inputconst(lltype.Void, None))
         hop.exception_is_here()
         return hop.genop(opname, vlist,
                          resulttype = self.lowleveltype.TO.RESULT)
@@ -92,19 +97,19 @@
     def rtype_getitem((r_ptr, r_int), hop):
         ARRAY = r_ptr.lowleveltype.TO
         ITEM_TYPE = ARRAY.OF
-        if isinstance(ITEM_TYPE, ContainerType):
+        if isinstance(ITEM_TYPE, lltype.ContainerType):
             newopname = 'getarraysubstruct'
         else:
             newopname = 'getarrayitem'
-        vlist = hop.inputargs(r_ptr, Signed)
+        vlist = hop.inputargs(r_ptr, lltype.Signed)
         return hop.genop(newopname, vlist,
                          resulttype = hop.r_result.lowleveltype)
 
     def rtype_setitem((r_ptr, r_int), hop):
         ARRAY = r_ptr.lowleveltype.TO
         ITEM_TYPE = ARRAY.OF
-        assert not isinstance(ITEM_TYPE, ContainerType)
-        vlist = hop.inputargs(r_ptr, Signed, hop.args_r[2])
+        assert not isinstance(ITEM_TYPE, lltype.ContainerType)
+        vlist = hop.inputargs(r_ptr, lltype.Signed, hop.args_r[2])
         hop.genop('setarrayitem', vlist)
 
 # ____________________________________________________________
@@ -112,10 +117,10 @@
 #  Null Pointers
 
 ##class NullPtrRepr(Repr):
-##    lowleveltype = Void
+##    lowleveltype = lltype.Void
 
 ##    def rtype_is_true(self, hop):
-##        return hop.inputconst(Bool, False)
+##        return hop.inputconst(lltype.Bool, False)
 
 ##nullptr_repr = NullPtrRepr()
 
@@ -132,22 +137,22 @@
 
     def rtype_eq((r_ptr, r_any), hop):
         vlist = hop.inputargs(r_ptr, r_ptr)
-        return hop.genop('ptr_eq', vlist, resulttype=Bool)
+        return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool)
 
     def rtype_ne((r_ptr, r_any), hop):
         vlist = hop.inputargs(r_ptr, r_ptr)
-        return hop.genop('ptr_ne', vlist, resulttype=Bool)
+        return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool)
 
 
 class __extend__(pairtype(Repr, PtrRepr)):
 
     def rtype_eq((r_any, r_ptr), hop):
         vlist = hop.inputargs(r_ptr, r_ptr)
-        return hop.genop('ptr_eq', vlist, resulttype=Bool)
+        return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool)
 
     def rtype_ne((r_any, r_ptr), hop):
         vlist = hop.inputargs(r_ptr, r_ptr)
-        return hop.genop('ptr_ne', vlist, resulttype=Bool)
+        return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool)
 
 # ________________________________________________________________
 # ADT  methods

Modified: pypy/dist/pypy/rpython/rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/rtuple.py	(original)
+++ pypy/dist/pypy/rpython/rtuple.py	Tue Dec  5 18:11:37 2006
@@ -23,6 +23,7 @@
 
 _gen_eq_function_cache = {}
 _gen_hash_function_cache = {}
+_gen_str_function_cache = {}
 
 def gen_eq_function(items_r):
     eq_funcs = [r_item.get_ll_eq_function() or operator.eq for r_item in items_r]
@@ -68,6 +69,41 @@
         _gen_hash_function_cache[key] = ll_hash
         return ll_hash
 
+def gen_str_function(tuplerepr):
+    items_r = tuplerepr.items_r
+    str_funcs = [r_item.ll_str for r_item in items_r]
+    key = tuplerepr.rstr_ll, tuple(str_funcs)
+    try:
+        return _gen_str_function_cache[key]
+    except KeyError:
+        autounrolling_funclist = unrolling_iterable(enumerate(str_funcs))
+
+        constant = tuplerepr.rstr_ll.ll_constant
+        start    = tuplerepr.rstr_ll.ll_build_start
+        push     = tuplerepr.rstr_ll.ll_build_push
+        finish   = tuplerepr.rstr_ll.ll_build_finish
+        length = len(items_r)
+
+        def ll_str(t):
+            if length == 0:
+                return constant("()")
+            buf = start(2 * length + 1)
+            push(buf, constant("("), 0)
+            for i, str_func in autounrolling_funclist:
+                attrname = 'item%d' % i
+                item = getattr(t, attrname)
+                if i > 0:
+                    push(buf, constant(", "), 2 * i)
+                push(buf, str_func(item), 2 * i + 1)
+            if length == 1:
+                push(buf, constant(",)"), 2 * length)
+            else:
+                push(buf, constant(")"), 2 * length)
+            return finish(buf)
+
+        _gen_str_function_cache[key] = ll_str
+        return ll_str
+
 
 class AbstractTupleRepr(Repr):
 
@@ -133,6 +169,8 @@
     def get_ll_hash_function(self):
         return gen_hash_function(self.items_r)    
 
+    ll_str = property(gen_str_function)
+
     def make_iterator_repr(self):
         if len(self.items_r) == 1:
             # subclasses are supposed to set the IteratorRepr attribute

Modified: pypy/dist/pypy/rpython/test/test_rptr.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rptr.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rptr.py	Tue Dec  5 18:11:37 2006
@@ -204,3 +204,15 @@
         fptr(*(x,y))
 
     py.test.raises(TypeError, "interpret(wrong, [1, 2])")
+
+
+def test_ptr_str():
+    def f():
+        return str(p)
+
+    S = GcStruct('S', ('x', Signed))
+    p = malloc(S)
+
+    res = interpret(f, [])
+    assert res.chars[0] == '0'
+    assert res.chars[1] == 'x'

Modified: pypy/dist/pypy/rpython/test/test_rtuple.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rtuple.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rtuple.py	Tue Dec  5 18:11:37 2006
@@ -286,6 +286,14 @@
         res = self.interpret(f, [3])
         assert res is True
 
+    def test_tuple_str(self):
+        def f(n):
+            assert str(()) == "()"
+            assert str((n,)) == "(%d,)" % n
+            assert str((n, 6)) == "(%d, 6)" % n
+            assert str(((n,),)) == "((%d,),)" % n
+        self.interpret(f, [3])
+
 class TestLLtype(BaseTestRtuple, LLRtypeMixin):
     pass
 



More information about the Pypy-commit mailing list