[pypy-svn] r27271 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem rpython/test

antocuni at codespeak.net antocuni at codespeak.net
Tue May 16 14:12:32 CEST 2006


Author: antocuni
Date: Tue May 16 14:12:17 2006
New Revision: 27271

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/rlist.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added support for string formatting in ootypesystem.



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Tue May 16 14:12:17 2006
@@ -521,9 +521,9 @@
     assert isinstance(i, SomeOOInstance)
     return SomeInteger()
 
-def oostring(obj):
-    assert (isinstance(obj, (SomeInteger, SomeChar)) or
-            isinstance(obj, SomeOOInstance) and obj.ootype is ootype.String)
+def oostring(obj, base):
+    assert isinstance(obj, (SomeInteger, SomeChar, SomeOOInstance))
+    assert isinstance(base, SomeInteger)
     return SomeOOInstance(ootype.String)
 
 BUILTIN_ANALYZERS[ootype.instanceof] = instanceof

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Tue May 16 14:12:17 2006
@@ -1020,8 +1020,8 @@
     def op_ooidentityhash(self, inst):
         return ootype.ooidentityhash(inst)
 
-    def op_oostring(self, obj):
-        return ootype.oostring(obj)
+    def op_oostring(self, obj, base):
+        return ootype.oostring(obj, base)
 
 class Tracer(object):
     Counter = 0

Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Tue May 16 14:12:17 2006
@@ -648,31 +648,6 @@
         return hop.gendirectcall(cls.ll_join_strs, size, vtemp)
     do_stringformat = classmethod(do_stringformat)
 
-    def parse_fmt_string(fmt):
-        # we support x, d, s, f, [r]
-
-        it = iter(fmt)
-        r = []
-        curstr = ''
-        for c in it:
-            if c == '%':
-                f = it.next()
-                if f == '%':
-                    curstr += '%'
-                    continue
-
-                if curstr:
-                    r.append(curstr)
-                curstr = ''
-                if f not in 'xdosrf':
-                    raise TyperError("Unsupported formatting specifier: %r in %r" % (f, fmt))
-
-                r.append((f,))
-            else:
-                curstr += c
-        if curstr:
-            r.append(curstr)
-        return r
 
 
 

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Tue May 16 14:12:17 2006
@@ -1142,8 +1142,20 @@
     assert isinstance(typeOf(inst), (Instance, Record))
     return inst._identityhash()
 
-def oostring(obj):
-    "Convert char, int and str to str"
+def oostring(obj, base):
+    """
+    Convert char, int, float, instances and str to str.
+    
+    Base is used only for formatting int: for other types is ignored
+    and should be set to -1. For int only base 8, 10 and 16 are
+    supported.
+    """
+    if isinstance(obj, int):
+        assert base in (-1, 8, 10, 16)
+        fmt = {-1:'%d', 8:'%o', 10:'%d', 16:'%x'}[base]
+        obj = fmt % obj
+    elif isinstance(obj, _view):
+        obj = '<%s object>' % obj._inst._TYPE._name
     return make_string(str(obj))
 
 def setItemType(LIST, ITEMTYPE):

Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	Tue May 16 14:12:17 2006
@@ -60,7 +60,9 @@
 def rtype_oostring(hop):
     assert isinstance(hop.args_s[0],(annmodel.SomeInteger,
                                      annmodel.SomeChar,
-                                     annmodel.SomeString))
+                                     annmodel.SomeString,
+                                     annmodel.SomeOOInstance))
+    assert isinstance(hop.args_s[1], annmodel.SomeInteger)
     return hop.genop('oostring', hop.args_v, resulttype = ootype.String)
 
 

Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Tue May 16 14:12:17 2006
@@ -379,6 +379,13 @@
         vinst, = hop.inputargs(self)
         return hop.genop('oononnull', [vinst], resulttype=ootype.Bool)
 
+    def ll_const(c):
+        return c
+    ll_const = staticmethod(ll_const)
+
+    def ll_str(self, instance):
+        return ootype.oostring(instance, self.ll_const(-1))
+
     def rtype_type(self, hop):
         vinst, = hop.inputargs(self)
         if hop.args_s[0].can_be_none():

Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rlist.py	Tue May 16 14:12:17 2006
@@ -39,7 +39,6 @@
         result = self.LIST.ll_newlist(n)
         return result
 
-
     def send_message(self, hop, message, can_raise=False, v_args=None):
         if v_args is None:
             v_args = hop.inputargs(self, *hop.args_r[1:])

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Tue May 16 14:12:17 2006
@@ -2,6 +2,7 @@
 from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
      AbstractUniCharRepr, AbstractStringIteratorRepr,\
      AbstractLLHelpers
+from pypy.rpython.rmodel import IntegerRepr
 from pypy.rpython.lltypesystem.lltype import Ptr, Char, UniChar
 from pypy.rpython.ootypesystem import ootype
 
@@ -60,8 +61,11 @@
 
 class LLHelpers(AbstractLLHelpers):
 
+    def ll_const(c):
+        return c
+
     def ll_chr2str(ch):
-        return ootype.oostring(ch)
+        return ootype.oostring(ch, LLHelpers.ll_const(-1))
 
     def ll_char_mul(ch, times):
         buf = ootype.new(ootype.StringBuilder)
@@ -143,6 +147,59 @@
     def ll_stringslice_minusone(s):
         return s.ll_substring(0, s.ll_strlen()-1)
 
+    def do_stringformat(cls, hop, sourcevarsrepr):
+        InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr
+        string_repr = hop.rtyper.type_system.rstr.string_repr
+        s_str = hop.args_s[0]
+        assert s_str.is_constant()
+        s = s_str.const
+
+        c_append = hop.inputconst(ootype.Void, 'll_append')
+        c_build = hop.inputconst(ootype.Void, 'll_build')
+        cm1 = hop.inputconst(ootype.Signed, -1)
+        c8 = hop.inputconst(ootype.Signed, 8)
+        c10 = hop.inputconst(ootype.Signed, 10)
+        c16 = hop.inputconst(ootype.Signed, 16)
+        c_StringBuilder = hop.inputconst(ootype.Void, ootype.StringBuilder)        
+        v_buf = hop.genop("new", [c_StringBuilder], resulttype=ootype.StringBuilder)
+
+        things = cls.parse_fmt_string(s)
+        argsiter = iter(sourcevarsrepr)
+        for thing in things:
+            if isinstance(thing, tuple):
+                code = thing[0]
+                vitem, r_arg = argsiter.next()
+                if not hasattr(r_arg, 'll_str'):
+                    raise TyperError("ll_str unsupported for: %r" % r_arg)
+                if code == 's':
+                    # TODO: for now it works only with types supported by oostring
+                    vchunk = hop.genop('oostring', [vitem, cm1], resulttype=ootype.String)
+                elif code == 'd':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.genop('oostring', [vitem, c10], resulttype=ootype.String)
+                elif code == 'f':
+                    #assert isinstance(r_arg, FloatRepr)
+                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                elif code == 'x':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.genop('oostring', [vitem, c16], resulttype=ootype.String)
+                elif code == 'o':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.genop('oostring', [vitem, c8], resulttype=ootype.String)
+                elif code == 'r' and isinstance(r_arg, InstanceRepr):
+                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                else:
+                    raise TyperError, "%%%s is not RPython" % (code, )
+            else:
+                vchunk = hop.inputconst(string_repr, thing)
+            #i = inputconst(Signed, i)
+            #hop.genop('setarrayitem', [vtemp, i, vchunk])
+            hop.genop('oosend', [c_append, v_buf, vchunk], resulttype=ootype.Void)
+
+        hop.exception_cannot_occur()   # to ignore the ZeroDivisionError of '%'
+        return hop.genop('oosend', [c_build, v_buf], resulttype=ootype.String)        
+    do_stringformat = classmethod(do_stringformat)
+
 def add_helpers():
     dic = {}
     for name, meth in ootype.String._GENERIC_METHODS.iteritems():
@@ -192,3 +249,16 @@
 
 string_iterator_repr = StringIteratorRepr()
 
+
+# these should be in rclass, but circular imports prevent (also it's
+# not that insane that a string constant is built in this file).
+
+instance_str_prefix = string_repr.convert_const("<")
+instance_str_suffix = string_repr.convert_const(" object>")
+
+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(", ")

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Tue May 16 14:12:17 2006
@@ -298,10 +298,15 @@
         r_tuple = hop.args_r[1]
         v_tuple = hop.args_v[1]
 
+        if hop.rtyper.type_system.name == 'ootypesystem':
+            getfield = 'oogetfield'
+        else:
+            getfield = 'getfiel'
+
         sourcevars = []
         for fname, r_arg in zip(r_tuple.fieldnames, r_tuple.items_r):
             cname = hop.inputconst(Void, fname)
-            vitem = hop.genop("getfield", [v_tuple, cname],
+            vitem = hop.genop(getfield, [v_tuple, cname],
                               resulttype=r_arg)
             sourcevars.append((vitem, r_arg))
 
@@ -545,3 +550,28 @@
             raise IndexError
         return cls.ll_stritem_nonneg(s, i)
     ll_stritem_checked = classmethod(ll_stritem_checked)
+
+    def parse_fmt_string(fmt):
+        # we support x, d, s, f, [r]
+        it = iter(fmt)
+        r = []
+        curstr = ''
+        for c in it:
+            if c == '%':
+                f = it.next()
+                if f == '%':
+                    curstr += '%'
+                    continue
+
+                if curstr:
+                    r.append(curstr)
+                curstr = ''
+                if f not in 'xdosrf':
+                    raise TyperError("Unsupported formatting specifier: %r in %r" % (f, fmt))
+
+                r.append((f,))
+            else:
+                curstr += c
+        if curstr:
+            r.append(curstr)
+        return r

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	Tue May 16 14:12:17 2006
@@ -1,5 +1,6 @@
 import random
 from pypy.rpython.lltypesystem.lltype import *
+from pypy.rpython.rstr import AbstractLLHelpers
 from pypy.rpython.lltypesystem.rstr import LLHelpers, STR
 from pypy.rpython.rtyper import RPythonTyper, TyperError
 from pypy.rpython.test.test_llinterp import interpret, interpret_raises
@@ -22,6 +23,11 @@
         res = LLHelpers.ll_rfind(llstr(s1), llstr(s2), 0, n1)
         assert res == s1.rfind(s2)
 
+def test_parse_fmt():
+    assert AbstractLLHelpers.parse_fmt_string('a') == ['a']
+    assert AbstractLLHelpers.parse_fmt_string('%s') == [('s',)]
+    assert AbstractLLHelpers.parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
+
 
 class AbstractTestRstr:
 
@@ -376,100 +382,99 @@
         assert self.ll_to_string(res) == 'hell'
 
 
-def test_parse_fmt():
-    assert LLHelpers.parse_fmt_string('a') == ['a']
-    assert LLHelpers.parse_fmt_string('%s') == [('s',)]
-    assert LLHelpers.parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
-
-def test_strformat():
-    def percentS(s):
-        return "before %s after" % (s,)
+    def test_strformat(self):
+        def percentS(s):
+            return "before %s after" % (s,)
 
-    res = interpret(percentS, ['1'])
-    assert ''.join(res.chars) == 'before 1 after'
+        res = self.interpret(percentS, ['1'])
+        assert self.ll_to_string(res) == 'before 1 after'
 
-    def percentD(i):
-        return "bing %d bang" % (i,)
-    
-    res = interpret(percentD, [23])
-    assert ''.join(res.chars) == 'bing 23 bang'
+        def percentD(i):
+            return "bing %d bang" % (i,)
 
-    def percentX(i):
-        return "bing %x bang" % (i,)
+        res = self.interpret(percentD, [23])
+        assert self.ll_to_string(res) == 'bing 23 bang'
 
-    res = interpret(percentX, [23])
-    assert ''.join(res.chars) == 'bing 17 bang'
+        def percentX(i):
+            return "bing %x bang" % (i,)
 
-    res = interpret(percentX, [-123])
-    assert ''.join(res.chars) == 'bing -7b bang'
+        res = self.interpret(percentX, [23])
+        assert self.ll_to_string(res) == 'bing 17 bang'
 
-    def percentO(i):
-        return "bing %o bang" % (i,)
-    
-    res = interpret(percentO, [23])
-    assert ''.join(res.chars) == 'bing 27 bang'
+        res = self.interpret(percentX, [-123])
+        assert self.ll_to_string(res) == 'bing -7b bang'
 
-    res = interpret(percentO, [-123])
-    assert ''.join(res.chars) == 'bing -173 bang'
+        def percentO(i):
+            return "bing %o bang" % (i,)
 
-    def moreThanOne(s, d, x, o):
-        return "string: %s decimal: %d hex: %x oct: %o" % (s, d, x, o)
+        res = self.interpret(percentO, [23])
+        assert self.ll_to_string(res) == 'bing 27 bang'
 
-    args = 'a', 2, 3, 4
-    res = interpret(moreThanOne, list(args))
-    assert ''.join(res.chars) == moreThanOne(*args)
-
-def test_strformat_nontuple():
-    def percentD(i):
-        return "before %d after" % i
-
-    res = interpret(percentD, [1])
-    assert ''.join(res.chars) == 'before 1 after'
-
-    def percentS(i):
-        return "before %s after" % i
-
-    res = interpret(percentS, ['D'])
-    assert ''.join(res.chars) == 'before D after'
-
-def test_strformat_instance():
-    class C:
-        pass
-    class D(C):
-        pass
-    def dummy(i):
-        if i:
-            x = C()
-        else:
-            x = D()
-        return str(x)
-        
-    res = interpret(dummy, [1])
-    assert ''.join(res.chars) == '<C object>'
+        res = self.interpret(percentO, [-123])
+        assert self.ll_to_string(res) == 'bing -173 bang'
 
-    res = interpret(dummy, [0])
-    assert ''.join(res.chars) == '<D object>'
+        def moreThanOne(s, d, x, o):
+            return "string: %s decimal: %d hex: %x oct: %o" % (s, d, x, o)
 
-def test_percentformat_instance():
-    class C:
-        pass
-    class D(C):
-        pass
-    
-    def dummy(i):
-        if i:
-            x = C()
-            y = D()
-        else:
-            x = D()
-            y = C()
-        return "what a nice %s, much nicer than %r"%(x, y)
-        
-    res = interpret(dummy, [1])
-    assert ''.join(res.chars) == 'what a nice <C object>, much nicer than <D object>'
+        args = 'a', 2, 3, 4
+        res = self.interpret(moreThanOne, list(args))
+        assert self.ll_to_string(res) == moreThanOne(*args)
+
+    def test_strformat_nontuple(self):
+        def percentD(i):
+            return "before %d after" % i
+
+        res = self.interpret(percentD, [1])
+        assert self.ll_to_string(res) == 'before 1 after'
+
+        def percentS(i):
+            return "before %s after" % i
 
-    res = interpret(dummy, [0])
-    assert ''.join(res.chars) == 'what a nice <D object>, much nicer than <C object>'
+        res = self.interpret(percentS, ['D'])
+        assert self.ll_to_string(res) == 'before D after'
+
+    def test_strformat_instance(self):
+        class C:
+            pass
+        class D(C):
+            pass
+        def dummy(i):
+            if i:
+                x = C()
+            else:
+                x = D()
+            return str(x)
+
+        res = self.ll_to_string(self.interpret(dummy, [1]))
+        assert res.startswith('<')
+        assert res.endswith('C object>')
+
+        res = self.ll_to_string(self.interpret(dummy, [0]))
+        assert res.startswith('<')
+        assert res.endswith('D object>')
+
+    def test_percentformat_instance(self):
+        class C:
+            pass
+        class D(C):
+            pass
+
+        def dummy(i):
+            if i:
+                x = C()
+                y = D()
+            else:
+                x = D()
+                y = C()
+            return "what a nice %s, much nicer than %r"%(x, y)
+
+        res = self.ll_to_string(self.interpret(dummy, [1]))
+        res = res.replace('pypy.rpython.test.test_rstr.', '')
+        assert res == 'what a nice <C object>, much nicer than <D object>'
+
+        res = self.ll_to_string(self.interpret(dummy, [0]))
+        res = res.replace('pypy.rpython.test.test_rstr.', '')        
+        assert res == 'what a nice <D object>, much nicer than <C object>'
 
 def test_split():
     def fn(i):



More information about the Pypy-commit mailing list