[pypy-svn] r25695 - in pypy/dist/pypy: annotation rpython/rctypes rpython/rctypes/test

arigo at codespeak.net arigo at codespeak.net
Tue Apr 11 12:39:52 CEST 2006


Author: arigo
Date: Tue Apr 11 12:39:50 2006
New Revision: 25695

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/rpython/rctypes/rarray.py
   pypy/dist/pypy/rpython/rctypes/rchar_p.py
   pypy/dist/pypy/rpython/rctypes/rmodel.py
   pypy/dist/pypy/rpython/rctypes/rpointer.py
   pypy/dist/pypy/rpython/rctypes/test/test_rarray.py
   pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py
Log:
rctypes "progress":
* union for SomeCTypesObject
* prebuilt arrays

Blocker: the skipped test in test_rfunc.py.  The problem is that
(c_char*10) is implemented as an array of structs containing each
a 'value' field of type char.  This makes conversion to a regular
array of chars quite difficult.  I am not sure that there is a
better solution than rewriting rctypes pointers to use addresses
systematically.


Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Tue Apr 11 12:39:50 2006
@@ -724,10 +724,14 @@
         return SomeAddress(is_null=False)
 
 class __extend__(pairtype(SomeAddress, SomeImpossibleValue)):
+    # need to override this specifically to hide the 'raise UnionError'
+    # of pairtype(SomeAddress, SomeObject).
     def union((s_addr, s_imp)):
         return s_addr
 
 class __extend__(pairtype(SomeImpossibleValue, SomeAddress)):
+    # need to override this specifically to hide the 'raise UnionError'
+    # of pairtype(SomeObject, SomeAddress).
     def union((s_imp, s_addr)):
         return s_addr
 
@@ -781,3 +785,19 @@
             listdef = ListDef(None, SomeCTypesObject(s_cto.knowntype._type_))
         return SomeList(listdef)
 
+class __extend__(pairtype(SomeCTypesObject, SomeCTypesObject)):
+    def union((s_cto1, s_cto2)):
+        if s_cto1.knowntype == s_cto2.knowntype:
+            states = {}
+            for s in [s_cto1, s_cto2]:
+                if s.memorystate != SomeCTypesObject.NOMEMORY:
+                    states[s.memorystate] = True
+            if len(states) == 0:
+                state = SomeCTypesObject.NOMEMORY
+            elif len(states) == 1:
+                [state] = states.keys()
+            else:
+                state = SomeCTypesObject.MIXEDMEMORYOWNERSHIP
+            return SomeCTypesObject(s_cto1.knowntype, state)
+        else:
+            return SomeObject()

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Tue Apr 11 12:39:50 2006
@@ -434,7 +434,7 @@
     MEMORYALIAS = "MEMORYALIAS"
     MIXEDMEMORYOWNERSHIP = "MIXEDMEMORYOWNERSHIP"
     
-    def __init__(self, knowntype, memorystate=None):
+    def __init__(self, knowntype, memorystate):
         if memorystate is None:
             memorystate = knowntype.default_memorystate
         self.knowntype = knowntype

Modified: pypy/dist/pypy/rpython/rctypes/rarray.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rarray.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rarray.py	Tue Apr 11 12:39:50 2006
@@ -4,7 +4,7 @@
 from pypy.rpython.rmodel import Repr, IntegerRepr, inputconst
 from pypy.rpython.lltypesystem import lltype
 from pypy.annotation.pairtype import pairtype
-from pypy.rpython.rctypes.rmodel import CTypesRefRepr, reccopy
+from pypy.rpython.rctypes.rmodel import CTypesRefRepr, genreccopy, reccopy
 
 ArrayType = type(ARRAY(c_int, 10))
 
@@ -25,6 +25,11 @@
 
         super(ArrayRepr, self).__init__(rtyper, s_array, c_data_type)
 
+    def initialize_const(self, p, value):
+        for i in range(self.length):
+            llitem = self.r_item.convert_const(value[i])
+            reccopy(llitem.c_data, p.c_data[i])
+
     def get_c_data_of_item(self, llops, v_array, v_index):
         v_c_array = self.get_c_data(llops, v_array)
         return llops.genop('getarraysubstruct', [v_c_array, v_index],
@@ -37,7 +42,7 @@
         v_item_c_data = r_array.r_item.get_c_data(hop.llops, v_item)
         v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index)
         # copy the whole structure's content over
-        reccopy(hop.llops, v_item_c_data, v_c_data)
+        genreccopy(hop.llops, v_item_c_data, v_c_data)
 
     def rtype_getitem((r_array, r_int), hop):
         v_array, v_index = hop.inputargs(r_array, lltype.Signed)
@@ -61,7 +66,12 @@
     compute_annotation=arraytype_compute_annotation,
     specialize_call=arraytype_specialize_call)
 
+def array_instance_compute_annotation(type, instance):
+    return SomeCTypesObject(type, SomeCTypesObject.OWNSMEMORY)
+
 def arraytype_get_repr(rtyper, s_array):
     return ArrayRepr(rtyper, s_array)
 
-extregistry.register_metatype(ArrayType, get_repr=arraytype_get_repr)
+extregistry.register_metatype(ArrayType,
+    compute_annotation=array_instance_compute_annotation,
+    get_repr=arraytype_get_repr)

Modified: pypy/dist/pypy/rpython/rctypes/rchar_p.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rchar_p.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rchar_p.py	Tue Apr 11 12:39:50 2006
@@ -1,11 +1,13 @@
 from pypy.rpython import extregistry
+from pypy.rpython.rmodel import inputconst
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.rstr import StringRepr, string_repr
 from pypy.rpython.rctypes.rmodel import CTypesValueRepr
+from pypy.rpython.rctypes.rarray import ArrayRepr
 from pypy.annotation import model as annmodel
 from pypy.annotation.pairtype import pairtype
 
-from ctypes import c_char_p
+from ctypes import c_char, c_char_p
 
 
 class CCharPRepr(CTypesValueRepr):
@@ -51,6 +53,25 @@
         r_temp.setstring(llops, v_owned_box, v)
         return llops.convertvar(v_owned_box, r_temp, r_to)
 
+##class __extend__(pairtype(ArrayRepr, CCharPRepr)):
+##    def convert_from_to((r_from, r_to), v, llops):
+##        if r_from.r_item.ctype != c_char:
+##            return NotImplemented
+##        # warning: no keepalives, only for short-lived conversions like
+##        # in argument passing
+##        r_temp = r_to.r_memoryowner
+##        v_owned_box = r_temp.allocate_instance(llops)
+##        v_char_array_ptr = r_from.get_c_data(llops, v)
+##        v_char_array_adr = llops.genop('cast_ptr_to_adr', [v_char_array_ptr],
+##                                       resulttype = llmemory.Address)
+##        cofs = inputconst(lltype.Signed,
+##                          llmemory.itemoffsetof(r_from.ll_type) +
+##                          llmemory.offsetof(r_from.ll_type.OF, 'value'))
+##        v_first_char_adr = llops.genop('adr_add', [v_char_array_adr, cofs],
+##                                       resulttype = llmemory.Address)
+##        r_temp.setvalue(llops, v_owned_box, v_first_char_adr)
+##        return llops.convertvar(v_owned_box, r_temp, r_to)
+
 
 CCHARP = llmemory.Address    # char *
 FIRSTITEMOFS = llmemory.ArrayItemsOffset(string_repr.lowleveltype.TO.chars)

Modified: pypy/dist/pypy/rpython/rctypes/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rmodel.py	Tue Apr 11 12:39:50 2006
@@ -74,6 +74,32 @@
         "Return extra keepalive fields used for the content of this object."
         return []
 
+    def convert_const(self, value):
+        if isinstance(value, self.ctype):
+            key = "by_id", id(value)
+            keepalive = value
+        else:
+            if self.ownsmemory:
+                raise TyperError("convert_const(%r) but repr owns memory" % (
+                    value,))
+            key = "by_value", value
+            keepalive = None
+        try:
+            return self.const_cache[key][0]
+        except KeyError:
+            p = lltype.malloc(self.r_memoryowner.lowleveltype.TO)
+            self.initialize_const(p, value)
+            if self.ownsmemory:
+                result = p
+            else:
+                # we must return a non-memory-owning box that keeps the
+                # memory-owning box alive
+                result = lltype.malloc(self.lowleveltype.TO)
+                result.c_data = p.c_data    # initialize c_data pointer
+                result.c_data_owner_keepalive = p
+            self.const_cache[key] = result, keepalive
+            return result
+
     def get_c_data(self, llops, v_box):
         if self.ownsmemory:
             inputargs = [v_box, inputconst(lltype.Void, "c_data")]
@@ -173,32 +199,6 @@
         v_c_data = self.get_c_data(llops, v_box)
         self.setvalue_inside_c_data(llops, v_c_data, v_value)
 
-    def convert_const(self, value):
-        if isinstance(value, self.ctype):
-            key = "by_id", id(value)
-            keepalive = value
-        else:
-            if self.ownsmemory:
-                raise TyperError("convert_const(%r) but repr owns memory" % (
-                    value,))
-            key = "by_value", value
-            keepalive = None
-        try:
-            return self.const_cache[key][0]
-        except KeyError:
-            p = lltype.malloc(self.r_memoryowner.lowleveltype.TO)
-            self.initialize_const(p, value)
-            if self.ownsmemory:
-                result = p
-            else:
-                # we must return a non-memory-owning box that keeps the
-                # memory-owning box alive
-                result = lltype.malloc(self.lowleveltype.TO)
-                result.c_data = p.c_data    # initialize c_data pointer
-                result.c_data_owner_keepalive = p
-            self.const_cache[key] = result, keepalive
-            return result
-
     def initialize_const(self, p, value):
         if isinstance(value, self.ctype):
             value = value.value
@@ -206,11 +206,35 @@
 
 # ____________________________________________________________
 
-def reccopy(llops, v_source, v_dest):
-    # helper to copy recursively a structure or array onto another.
+def reccopy(source, dest):
+    # copy recursively a structure or array onto another.
+    T = lltype.typeOf(source).TO
+    assert T == lltype.typeOf(dest).TO
+    assert isinstance(T, lltype.Struct)   # XXX implement arrays
+    for name in T._names:
+        FIELDTYPE = getattr(T, name)
+        if isinstance(FIELDTYPE, lltype.ContainerType):
+            subsrc = getattr(source, name)
+            subdst = getattr(dest,   name)
+            reccopy(subsrc, subdst)
+        else:
+            llvalue = getattr(source, name)
+            setattr(dest, name, llvalue)
+
+def reccopy_arrayitem(source, destarray, destindex):
+    ITEMTYPE = lltype.typeOf(destarray).TO.OF
+    if isinstance(ITEMTYPE, lltype.Primitive):
+        destarray[destindex] = source
+    else:
+        reccopy(source, destarray[destindex])
+
+def genreccopy(llops, v_source, v_dest):
+    # helper to generate the llops that copy recursively a structure
+    # or array onto another.  'v_source' and 'v_dest' can also be pairs
+    # (v, i) to mean the ith item of the array that v points to.
     T = v_source.concretetype.TO
     assert T == v_dest.concretetype.TO
-    assert isinstance(T, lltype.Struct)
+    assert isinstance(T, lltype.Struct)   # XXX implement arrays
     for name in T._names:
         FIELDTYPE = getattr(T, name)
         cname = inputconst(lltype.Void, name)
@@ -218,7 +242,16 @@
             RESTYPE = lltype.Ptr(FIELDTYPE)
             v_subsrc = llops.genop('getsubstruct', [v_source, cname], RESTYPE)
             v_subdst = llops.genop('getsubstruct', [v_dest,   cname], RESTYPE)
-            reccopy(llops, v_subsrc, v_subdst)
+            genreccopy(llops, v_subsrc, v_subdst)
         else:
             v_value = llops.genop('getfield', [v_source, cname], FIELDTYPE)
             llops.genop('setfield', [v_dest, cname, v_value])
+
+def genreccopy_arrayitem(llops, v_source, v_destarray, v_destindex):
+    ITEMTYPE = v_destarray.concretetype.TO.OF
+    if isinstance(ITEMTYPE, lltype.Primitive):
+        llops.genop('setarrayitem', [v_destarray, v_destindex, v_source])
+    else:
+        v_dest = llops.genop('getarraysubstruct', [v_destarray, v_destindex],
+                             resulttype = lltype.Ptr(ITEMTYPE))
+        genreccopy(llops, v_source, v_dest)

Modified: pypy/dist/pypy/rpython/rctypes/rpointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rpointer.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rpointer.py	Tue Apr 11 12:39:50 2006
@@ -4,7 +4,7 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.annotation import model as annmodel
 from pypy.annotation.pairtype import pairtype
-from pypy.rpython.rctypes.rmodel import CTypesValueRepr, reccopy
+from pypy.rpython.rctypes.rmodel import CTypesValueRepr, genreccopy
 
 from ctypes import POINTER, pointer, c_int
 
@@ -86,7 +86,7 @@
             # not supported by ctypes either
             raise TyperError("assignment to pointer[x] with x != 0")
         # copy the whole structure's content over
-        reccopy(hop.llops, v_new_c_data, v_target)
+        genreccopy(hop.llops, v_new_c_data, v_target)
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rarray.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rarray.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rarray.py	Tue Apr 11 12:39:50 2006
@@ -15,7 +15,7 @@
 except ImportError:
     py.test.skip("this test needs ctypes installed")
 
-from ctypes import c_int, ARRAY, POINTER, pointer
+from ctypes import c_int, c_short, ARRAY, POINTER, pointer
 
 c_int_10 = ARRAY(c_int,10)
 
@@ -100,6 +100,23 @@
         
 ##        py.test.raises(IndexError, "s = a.build_types(access_with_invalid_negative_index,[])")
 
+    def test_annotate_prebuilt(self):
+        my_array_2 = (c_short*10)(0, 1, 4, 9, 16, 25, 36, 49, 64, 81)
+        my_array_3 = (c_short*10)(0, 1, 8, 27, 64, 125, 216, 343, 512, 729)
+        def func(i, n):
+            if i == 2:
+                array = my_array_2
+            else:
+                array = my_array_3
+            return array[n]
+
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int, int])
+        if conftest.option.view:
+            a.translator.view()
+        assert s.knowntype == int
+
 class Test_specialization:
     def test_specialize_array(self):
         def create_array():
@@ -124,6 +141,21 @@
         res = interpret(access_array, [44])
         assert res == 1
 
+    def test_specialize_prebuilt(self):
+        my_array_2 = (c_short*10)(0, 1, 4, 9, 16, 25, 36, 49, 64, 81)
+        my_array_3 = (c_short*10)(0, 1, 8, 27, 64, 125, 216, 343, 512, 729)
+        def func(i, n):
+            if i == 2:
+                array = my_array_2
+            else:
+                array = my_array_3
+            return array[n]
+
+        res = interpret(func, [2, 6])
+        assert res == 36
+        res = interpret(func, [3, 7])
+        assert res == 343
+
 class Test_compilation:
     def test_compile_array_access(self):
         def access_array():

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py	Tue Apr 11 12:39:50 2006
@@ -7,7 +7,7 @@
 from pypy.rpython.rstr import string_repr
 from pypy.rpython.lltypesystem import lltype, llmemory
 
-from ctypes import c_int, c_long, c_char_p
+from ctypes import c_int, c_long, c_char_p, c_char
 
 
 labs = mylib.labs
@@ -36,6 +36,17 @@
     assert labs(-42) == 42
     return labs(n)
 
+def test_atoi():
+    assert atoi("") == 0
+    assert atoi("42z7") == 42
+    assert atoi("blah") == 0
+    assert atoi("18238") == 18238
+    A = c_char * 10
+    assert atoi(A('\x00')) == 0
+    assert atoi(A('4', '2', 'z', '7', '\x00')) == 42
+    assert atoi(A('b', 'l', 'a', 'h', '\x00')) == 0
+    assert atoi(A('1', '8', '2', '3', '8', '\x00')) == 18238
+
 def test_ll_atoi():
     keepalive = []
     def str2addr(string):
@@ -78,6 +89,20 @@
         res = [interpret(fn, [i]) for i in range(4)]
         assert res == [0, 42, 0, 18238]
 
+    def test_specialize_atoi_char_array(self):
+        py.test.skip("in-progress")
+        A = c_char * 10
+        choices = [A('\x00'),
+                   A('4', '2', 'z', '7', '\x00'),
+                   A('b', 'l', 'a', 'h', '\x00'),
+                   A('1', '8', '2', '3', '8', '\x00')]
+        def fn(n):
+            return atoi(choices[n])
+
+        assert fn(3) == 18238
+        res = [interpret(fn, [i]) for i in range(4)]
+        assert res == [0, 42, 0, 18238]
+
 class Test_compile:
     def test_compile_labs(self):
         fn = compile(test_labs, [int])



More information about the Pypy-commit mailing list