[pypy-svn] r25804 - in pypy/dist/pypy/rpython/rctypes: . test

arigo at codespeak.net arigo at codespeak.net
Thu Apr 13 17:25:09 CEST 2006


Author: arigo
Date: Thu Apr 13 17:25:07 2006
New Revision: 25804

Modified:
   pypy/dist/pypy/rpython/rctypes/rarray.py
   pypy/dist/pypy/rpython/rctypes/rstruct.py
   pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py
   pypy/dist/pypy/rpython/rctypes/test/test_rstruct.py
Log:
Implemented structures in rctypes, almost exactly copied from rarray.


Modified: pypy/dist/pypy/rpython/rctypes/rarray.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rarray.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rarray.py	Thu Apr 13 17:25:07 2006
@@ -65,6 +65,15 @@
 
 
 class __extend__(pairtype(ArrayRepr, IntegerRepr)):
+    def rtype_getitem((r_array, r_int), hop):
+        v_array, v_index = hop.inputargs(r_array, lltype.Signed)
+        if isinstance(r_array.r_item, PrimitiveRepr):
+            # primitive case (optimization only)
+            return r_array.get_item_value(hop.llops, v_array, v_index)
+        # normal case
+        v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index)
+        return r_array.r_item.return_c_data(hop.llops, v_c_data)
+
     def rtype_setitem((r_array, r_int), hop):
         v_array, v_index, v_item = hop.inputargs(r_array, lltype.Signed,
                                                  r_array.r_item)
@@ -79,15 +88,6 @@
             v_newvalue = r_array.r_item.getvalue(hop.llops, v_item)
             r_array.set_item_value(hop.llops, v_array, v_index, v_newvalue)
 
-    def rtype_getitem((r_array, r_int), hop):
-        v_array, v_index = hop.inputargs(r_array, lltype.Signed)
-        if isinstance(r_array.r_item, PrimitiveRepr):
-            # primitive case (optimization only)
-            return r_array.get_item_value(hop.llops, v_array, v_index)
-        # normal case
-        v_c_data = r_array.get_c_data_of_item(hop.llops, v_array, v_index)
-        return r_array.r_item.return_c_data(hop.llops, v_c_data)
-
 # ____________________________________________________________
 
 def arraytype_specialize_call(hop):

Modified: pypy/dist/pypy/rpython/rctypes/rstruct.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rstruct.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rstruct.py	Thu Apr 13 17:25:07 2006
@@ -1,12 +1,95 @@
 from ctypes import Structure
 from pypy.annotation.model import SomeCTypesObject, SomeBuiltin
 from pypy.rpython import extregistry
+from pypy.rpython.rmodel import inputconst
+from pypy.rpython.rbuiltin import gen_cast_structfield_pointer
+from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.rctypes.rmodel import CTypesRefRepr, CTypesValueRepr
+from pypy.rpython.rctypes.rmodel import genreccopy
+from pypy.rpython.rctypes.rprimitive import PrimitiveRepr
 
 StructType = type(Structure)
 
+class StructRepr(CTypesRefRepr):
+    def __init__(self, rtyper, s_struct):
+        struct_ctype = s_struct.knowntype
+        
+        # Find the repr and low-level type of the fields from their ctype
+        self.r_fields = {}
+        llfields = []
+        for name, field_ctype in struct_ctype._fields_:
+            r_field = rtyper.getrepr(SomeCTypesObject(field_ctype,
+                                                SomeCTypesObject.MEMORYALIAS))
+            self.r_fields[name] = r_field
+            llfields.append((name, r_field.ll_type))
+
+        # Here, self.c_data_type == self.ll_type
+        c_data_type = lltype.Struct(struct_ctype.__name__, *llfields)
+
+        super(StructRepr, self).__init__(rtyper, s_struct, c_data_type)
+
+    def get_c_data_of_field(self, llops, v_struct, fieldname):
+        v_c_struct = self.get_c_data(llops, v_struct)
+        r_field = self.r_fields[fieldname]
+        if isinstance(r_field, CTypesRefRepr):
+            # ByRef case
+            c_fieldname = inputconst(lltype.Void, fieldname)
+            return llops.genop('getsubstruct', [v_c_struct, c_fieldname],
+                               lltype.Ptr(r_field.c_data_type))
+        else:
+            # ByValue case
+            A = lltype.FixedSizeArray(r_field.ll_type, 1)
+            return gen_cast_structfield_pointer(llops, lltype.Ptr(A),
+                                                v_c_struct, fieldname)
+
+    def get_field_value(self, llops, v_struct, fieldname):
+        # ByValue case only
+        r_field = self.r_fields[fieldname]
+        assert isinstance(r_field, CTypesValueRepr)
+        v_c_struct = self.get_c_data(llops, v_struct)
+        c_fieldname = inputconst(lltype.Void, fieldname)
+        return llops.genop('getfield', [v_c_struct, c_fieldname],
+                           resulttype = r_field.ll_type)
+
+    def set_field_value(self, llops, v_struct, fieldname, v_newvalue):
+        # ByValue case only
+        r_field = self.r_fields[fieldname]
+        assert isinstance(r_field, CTypesValueRepr)
+        v_c_struct = self.get_c_data(llops, v_struct)
+        c_fieldname = inputconst(lltype.Void, fieldname)
+        llops.genop('setfield', [v_c_struct, c_fieldname, v_newvalue])
+
+    def rtype_getattr(self, hop):
+        s_attr = hop.args_s[1]
+        assert s_attr.is_constant()
+        name = s_attr.const
+        r_field = self.r_fields[name]
+        v_struct, v_attr = hop.inputargs(self, lltype.Void)
+        if isinstance(r_field, PrimitiveRepr):
+            # primitive case (optimization only)
+            return self.get_field_value(hop.llops, v_struct, name)
+        # normal case
+        v_c_data = self.get_c_data_of_item(hop.llops, v_struct, name)
+        return r_field.return_c_data(hop.llops, v_c_data)
+
+    def rtype_setattr(self, hop):
+        s_attr = hop.args_s[1]
+        assert s_attr.is_constant()
+        name = s_attr.const
+        r_field = self.r_fields[name]
+        v_struct, v_attr, v_item = hop.inputargs(self, lltype.Void, r_field)
+        if isinstance(r_field, CTypesRefRepr):
+            # ByRef case
+            v_new_c_data = r_field.get_c_data(hop.llops, v_item)
+            v_c_data = self.get_c_data_of_item(hop.llops, v_struct, name)
+            # copy the whole structure's content over
+            genreccopy(hop.llops, v_new_c_data, v_c_data)
+        else:
+            # ByValue case (optimization; the above also works in this case)
+            v_newvalue = r_field.getvalue(hop.llops, v_item)
+            self.set_field_value(hop.llops, v_struct, name, v_newvalue)
 
-
+# ____________________________________________________________
 
 def structtype_specialize_call(hop):
     r_struct = hop.r_result

Modified: pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py	Thu Apr 13 17:25:07 2006
@@ -63,3 +63,18 @@
     assert p[0] == x.value == "world"
     p[0] = "other"
     assert x.value == p.contents.value == p[0] == "other"
+
+def test_struct():
+    class tagpoint(Structure):
+        _fields_ = [('x', c_int),
+                    ('p', POINTER(c_short))]
+
+    y = c_short(123)
+    z = c_short(-33)
+    s = tagpoint()
+    s.p.contents = z
+    assert s.p.contents.value == -33
+    s.p = pointer(y)
+    assert s.p.contents.value == 123
+    s.p.contents.value = 124
+    assert y.value == 124

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rstruct.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rstruct.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rstruct.py	Thu Apr 13 17:25:07 2006
@@ -50,3 +50,42 @@
 
         if conftest.option.view:
             t.view()
+
+    def test_annotate_prebuilt(self):
+        my_struct_2 = tagpoint(5, 7)
+        my_struct_3 = tagpoint(x=6, y=11)
+        def func(i):
+            if i == 2:
+                struct = my_struct_2
+            else:
+                struct = my_struct_3
+            return struct.y
+
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+        if conftest.option.view:
+            a.translator.view()
+        assert s.knowntype == int
+
+class Test_specialization:
+    def test_specialize_struct(self):
+        def create_struct():
+            return tagpoint()
+
+        res = interpret(create_struct, [])
+        c_data = res.c_data
+        assert c_data.x == 0
+        assert c_data.y == 0
+
+    def test_specialize_struct_access(self):
+        def access_struct(n):
+            my_struct = tagpoint()
+            my_struct.x = c_int(1)
+            my_struct.y = 2
+            my_struct.x += n
+
+            return my_struct.x * my_struct.y
+
+        res = interpret(access_struct, [44])
+        assert res == 90



More information about the Pypy-commit mailing list