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

arigo at codespeak.net arigo at codespeak.net
Mon Apr 3 19:49:08 CEST 2006


Author: arigo
Date: Mon Apr  3 19:49:06 2006
New Revision: 25267

Added:
   pypy/dist/pypy/rpython/rctypes/rmodel.py
Modified:
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/rpython/rctypes/rpointer.py
   pypy/dist/pypy/rpython/rctypes/rprimitive.py
   pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py
Log:
(arre, goden, arigo)

Introduced a base class CTypesRepr handling the common parts of the ll
structs.  Not all Reprs have been converted to inherit from it so far.

Removed the rpointer.py support for calling POINTER() at run-time.
Registering meta-classes instead :-)



Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Mon Apr  3 19:49:06 2006
@@ -652,7 +652,7 @@
             else:
                 if extregistry.is_registered_type(cto.knowntype):
                     entry = extregistry.lookup_type(cto.knowntype)
-                    s_value = entry.fields_s[attr]
+                    s_value = entry.get_field_annotation(cto, attr)
                     return s_value
                 else:
                     atype = cto.knowntype._fields_def_[attr]

Added: pypy/dist/pypy/rpython/rctypes/rmodel.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/rctypes/rmodel.py	Mon Apr  3 19:49:06 2006
@@ -0,0 +1,72 @@
+from pypy.rpython.rmodel import Repr, inputconst
+from pypy.rpython.error import TyperError
+from pypy.rpython.lltypesystem import lltype
+from pypy.annotation.model import SomeCTypesObject
+
+
+
+class CTypesRepr(Repr):
+    "Base class for the Reprs representing ctypes object."
+
+    def __init__(self, rtyper, s_ctypesobject, ll_type):
+        # s_ctypesobject: the annotation to represent
+        # ll_type: the low-level type representing the raw
+        #          data, which is then embedded in a box.
+        ctype = s_ctypesobject.knowntype
+        memorystate = s_ctypesobject.memorystate
+
+        self.rtyper = rtyper
+        self.ctype = ctype
+        self.ll_type = ll_type
+        if memorystate == SomeCTypesObject.OWNSMEMORY:
+            self.ownsmemory = True
+        elif memorystate == SomeCTypesObject.MEMORYALIAS:
+            self.ownsmemory = False
+        else:
+            raise TyperError("unsupported ctypes memorystate %r" % memorystate)
+
+        if isinstance(ll_type, lltype.ContainerType):
+            self.c_data_type = ll_type
+        else:
+            self.c_data_type = lltype.Struct('C_Data_%s' % (ctype.__name__,),
+                                                ('value', ll_type) )
+
+        if self.ownsmemory:
+            self.lowleveltype = lltype.Ptr(
+                lltype.GcStruct( "CtypesBox_%s" % (ctype.__name__,),
+                    ( "c_data", self.c_data_type )
+                )
+            )
+        else:
+            self.lowleveltype = lltype.Ptr(
+                lltype.GcStruct( "CtypesBox_%s" % (ctype.__name__,),
+                    ( "c_data_ref", lltype.Ptr(self.c_data_type) )
+                )
+            )
+        # XXX keepalives...
+        self.const_cache = {} # store generated const values+original value
+
+    def get_c_data(self, llops, v_box):
+        if self.ownsmemory:
+            inputargs = [v_box, inputconst(lltype.Void, "c_data")]
+            return llops.genop('getsubstruct', inputargs,
+                        lltype.Ptr(self.c_data_type) )
+        else:
+            inputargs = [v_box, inputconst(lltype.Void, "c_data_ref")]
+            return llops.genop('getfield', inputargs,
+                        lltype.Ptr(self.c_data_type) )
+
+    def setvalue(self, llops, v_box, v_value):
+        """Writes the 'value' field of the raw data
+           (only if ll_type is not a container type)"""
+        v_c_data = self.get_c_data(llops, v_box)
+        cname = inputconst(lltype.Void, 'value')
+        llops.genop('setfield', [v_c_data, cname, v_value])
+
+    def getvalue(self, llops, v_box):
+        """Reads the 'value' field of the raw data
+           (only if ll_type is not a container type)"""
+        v_c_data = self.get_c_data(llops, v_box)
+        cname = inputconst(lltype.Void, 'value')
+        return llops.genop('getfield', [v_c_data, cname],
+                resulttype=self.ll_type)

Modified: pypy/dist/pypy/rpython/rctypes/rpointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rpointer.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rpointer.py	Mon Apr  3 19:49:06 2006
@@ -3,7 +3,7 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.annotation import model as annmodel
 
-from ctypes import POINTER
+from ctypes import POINTER, c_int
 
 class PointerRepr(Repr):
     """XXX: todo
@@ -34,78 +34,112 @@
             )
         )
 
-def registerPointerType(ptrtype):
-    """Adds a new pointer type to the extregistry.
-
-    Since pointers can be created to primitive ctypes objects, arrays,
-    structs and structs are not predefined each new pointer type is
-    registered in the extregistry as it is identified.
-
-    The new pointers that are created have a "contents" attribute
-    which, when retrieved, in effect dereferences the pointer and
-    returns the referenced value.
-    """
-    def compute_result_annotation(s_self, s_arg):
-        return annmodel.SomeCTypesObject(ptrtype,
+#def registerPointerType(ptrtype):
+#    """Adds a new pointer type to the extregistry.
+#
+#    Since pointers can be created to primitive ctypes objects, arrays,
+#    structs and structs are not predefined each new pointer type is
+#    registered in the extregistry as it is identified.
+#
+#    The new pointers that are created have a "contents" attribute
+#    which, when retrieved, in effect dereferences the pointer and
+#    returns the referenced value.
+#    """
+#    def compute_result_annotation(s_self, s_arg):
+#        return annmodel.SomeCTypesObject(ptrtype,
+#                annmodel.SomeCTypesObject.OWNSMEMORY)
+#
+#    def specialize_call(hop):
+#        raise RuntimeError('foo')
+#
+#    contentsType = annmodel.SomeCTypesObject(ptrtype._type_,
+#                                    annmodel.SomeCTypesObject.MEMORYALIAS)
+#
+#    def get_repr(rtyper, s_pointer):
+#        return PointerRepr(rtyper, s_pointer, contentsType)
+#        
+#    type_entry = extregistry.register_type(ptrtype,
+#                            specialize_call=specialize_call,
+#                            get_repr=get_repr)
+#    type_entry.get_field_annotation = {'contents': contentsType}.__getitem__
+#
+#    return extregistry.register_value(ptrtype,
+#                        compute_result_annotation=compute_result_annotation,
+#                        specialize_call=specialize_call)
+#
+#def pointer_compute_annotation(metatype, the_type):
+#    """compute the annotation of POINTER() calls to create a ctypes
+#    pointer for the given type
+#    """
+#
+#    def pointer_compute_result_annotation(s_arg):
+#        """Called to compute the result annotation of
+#        POINTER(<ctypes type>).  This happens to return a new
+#        class which itself is treated as SomeBuiltin because when
+#        called it creates a new pointer.
+#
+#        NOTE: To handle a myriad of possible pointer types, each
+#              ctypes type that is passed to POINTER() calls is itself
+#              registered if it isn't already.
+#        """
+#        ptrtype = POINTER(s_arg.const)
+#
+#        if not extregistry.is_registered_type(ptrtype):
+#            entry = registerPointerType(ptrtype)
+#        else:
+#            entry = extregistry.lookup(ptrtype)
+#
+#        s_self = annmodel.SomeCTypesObject(ptrtype,
+#                            annmodel.SomeCTypesObject.OWNSMEMORY)
+#                        
+#
+#        return annmodel.SomeBuiltin(entry.compute_result_annotation,
+#                s_self=s_self,
+#                methodname=ptrtype.__name__)
+#
+#    # annotation of POINTER (not the call) is SomeBuitin which provides
+#    # a way of computing the result annotation of POINTER(<ctypes type>)
+#    return annmodel.SomeBuiltin(pointer_compute_result_annotation,
+#                                methodname=the_type.__name__)
+#
+#def pointer_specialize_call(hop):
+#    raise RuntimeError("foo")
+#
+# handles POINTER() calls
+#value_entry = extregistry.register_value(POINTER,
+#        compute_annotation=pointer_compute_annotation,
+#        specialize_call=pointer_specialize_call)
+
+def pointertype_compute_annotation(metatype, type):
+    def compute_result_annotation(*arg_s):
+        return annmodel.SomeCTypesObject(type,
                 annmodel.SomeCTypesObject.OWNSMEMORY)
+    return annmodel.SomeBuiltin(compute_result_annotation, 
+                                methodname=type.__name__)
 
-    def specialize_call(hop):
-        raise RuntimeError('foo')
+def pointertype_specialize_call(hop):
+    xxx #...
 
-    contentsType = annmodel.SomeCTypesObject(ptrtype._type_,
-                                    annmodel.SomeCTypesObject.MEMORYALIAS)
-
-    def get_repr(rtyper, s_pointer):
-        return PointerRepr(rtyper, s_pointer, contentsType)
-        
-    type_entry = extregistry.register_type(ptrtype,
-                            specialize_call=specialize_call,
-                            get_repr=get_repr)
-    type_entry.fields_s = {'contents': contentsType}
-
-    return extregistry.register_value(ptrtype,
-                        compute_result_annotation=compute_result_annotation,
-                        specialize_call=specialize_call)
-
-def pointer_compute_annotation(metatype, the_type):
-    """compute the annotation of POINTER() calls to create a ctypes
-    pointer for the given type
-    """
-
-    def pointer_compute_result_annotation(s_arg):
-        """Called to compute the result annotation of
-        POINTER(<ctypes type>).  This happens to return a new
-        class which itself is treated as SomeBuiltin because when
-        called it creates a new pointer.
-
-        NOTE: To handle a myriad of possible pointer types, each
-              ctypes type that is passed to POINTER() calls is itself
-              registered if it isn't already.
-        """
-        ptrtype = POINTER(s_arg.const)
-
-        if not extregistry.is_registered_type(ptrtype):
-            entry = registerPointerType(ptrtype)
-        else:
-            entry = extregistry.lookup(ptrtype)
-
-        s_self = annmodel.SomeCTypesObject(ptrtype,
-                            annmodel.SomeCTypesObject.OWNSMEMORY)
-                        
-
-        return annmodel.SomeBuiltin(entry.compute_result_annotation,
-                s_self=s_self,
-                methodname=ptrtype.__name__)
-
-    # annotation of POINTER (not the call) is SomeBuitin which provides
-    # a way of computing the result annotation of POINTER(<ctypes type>)
-    return annmodel.SomeBuiltin(pointer_compute_result_annotation,
-                                methodname=the_type.__name__)
-
-def pointer_specialize_call(hop):
-    raise RuntimeError("foo")
-
-# handles POINTER() calls
-value_entry = extregistry.register_value(POINTER,
-        compute_annotation=pointer_compute_annotation,
-        specialize_call=pointer_specialize_call)
+def pointerinstance_compute_annotation(type, instance):
+    return annmodel.SomeCTypesObject(type,
+            annmodel.SomeCTypesObject.OWNSMEMORY)
+
+def pointerinstance_field_annotation(s_pointer, fieldname):
+    assert fieldname == "contents"
+    ptrtype = s_pointer.knowntype
+    return annmodel.SomeCTypesObject(ptrtype._type_,
+                                     annmodel.SomeCTypesObject.MEMORYALIAS)
+
+def pointerinstance_get_repr(rtyper, s_pointer):
+    s_contents = pointerinstance_field_annotation(s_pointer, "contents")
+    return PointerRepr(rtyper, s_pointer, s_contents)
+
+PointerType = type(POINTER(c_int))
+extregistry.register_type(PointerType,
+        compute_annotation=pointertype_compute_annotation,
+        specialize_call=pointertype_specialize_call)
+
+entry = extregistry.register_metatype(PointerType,
+        compute_annotation=pointerinstance_compute_annotation,
+        get_repr=pointerinstance_get_repr)
+entry.get_field_annotation = pointerinstance_field_annotation

Modified: pypy/dist/pypy/rpython/rctypes/rprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rprimitive.py	Mon Apr  3 19:49:06 2006
@@ -7,6 +7,7 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.annotation.pairtype import pairtype
 from pypy.rpython.rmodel import IntegerRepr
+from pypy.rpython.rctypes.rmodel import CTypesRepr
 
 ctypes_annotation_list = [
     (c_char,          lltype.Char),
@@ -24,37 +25,7 @@
     (c_double,        lltype.Float),
 ]
 
-class PrimitiveRepr(Repr):
-    def __init__(self, rtyper, ctype, ll_type):
-        self.ctype = ctype
-        self.ll_type = ll_type
-        self.c_data_type = lltype.Struct('C_Data_%s' % (ctype.__name__,),
-                                            ('value', ll_type) )
-
-        self.lowleveltype = lltype.Ptr(
-            lltype.GcStruct( "CtypesBox_%s" % (ctype.__name__,),
-                ( "c_data", self.c_data_type )
-            )
-        )
-
-        self.const_cache = {} # store generated const values+original value
-
-    def get_c_data(self, llops, v_primitive):
-        inputargs = [v_primitive, inputconst(lltype.Void, "c_data")]
-        return llops.genop('getsubstruct', inputargs,
-                    lltype.Ptr(self.lowleveltype.TO.c_data) )
-
-    def setfield(self, llops, v_primitive, v_value):
-        v_c_data = self.get_c_data(llops, v_primitive)
-        cname = inputconst(lltype.Void, 'value')
-        llops.genop('setfield', [v_c_data, cname, v_value])
-
-    def getfield(self, llops, v_primitive):
-        v_c_data = self.get_c_data(llops, v_primitive)
-
-        cname = inputconst(lltype.Void, 'value')
-        return llops.genop('getfield', [v_c_data, cname],
-                resulttype=self.ll_type)
+class PrimitiveRepr(CTypesRepr):
 
     def convert_const(self, ctype_value):
         assert isinstance(ctype_value, self.ctype)
@@ -73,7 +44,7 @@
         assert s_attr.is_constant()
         assert s_attr.const == 'value'
         v_primitive = hop.inputarg(self, 0)
-        return self.getfield(hop.llops, v_primitive)
+        return self.getvalue(hop.llops, v_primitive)
 
     def rtype_setattr(self, hop):
         s_attr = hop.args_s[1]
@@ -81,7 +52,7 @@
         assert s_attr.const == 'value'
         v_primitive, v_attr, v_value = hop.inputargs(self, lltype.Void,
                                                         self.ll_type)
-        self.setfield(hop.llops, v_primitive, v_value)
+        self.setvalue(hop.llops, v_primitive, v_value)
 
 # need to extend primitive repr to implement convert_from_to() for various
 # conversions, firstly the conversion from c_long() to Signed
@@ -90,7 +61,7 @@
     def convert_from_to((r_from, r_to), v, llops):
         assert r_from.ll_type == r_to.lowleveltype
 
-        return r_from.getfield(llops, v)
+        return r_from.getvalue(llops, v)
 
 def primitive_specialize_call(hop):
     r_primitive = hop.r_result
@@ -98,7 +69,7 @@
     v_result = hop.genop("malloc", [c1], resulttype=r_primitive.lowleveltype)
     if len(hop.args_s):
         v_value, = hop.inputargs(r_primitive.ll_type)
-        r_primitive.setfield(hop.llops, v_result, v_value)
+        r_primitive.setvalue(hop.llops, v_result, v_value)
     return v_result
 
 def do_register(the_type, ll_type):
@@ -116,13 +87,16 @@
                 annmodel.SomeCTypesObject.OWNSMEMORY)
 
     def primitive_get_repr(rtyper, s_primitive):
-        return PrimitiveRepr(rtyper, s_primitive.knowntype, ll_type)
+        return PrimitiveRepr(rtyper, s_primitive, ll_type)
 
     entry = extregistry.register_type(the_type,
             compute_annotation=compute_prebuilt_instance_annotation,
             get_repr=primitive_get_repr,
             )
-    entry.fields_s = {'value': annmodel.lltype_to_annotation(ll_type)}
+    def primitive_get_field_annotation(s_primitive, fieldname):
+        assert fieldname == 'value'
+        return annmodel.lltype_to_annotation(ll_type)
+    entry.get_field_annotation = primitive_get_field_annotation
     entry.lowleveltype = ll_type
 
 for the_type, ll_type in ctypes_annotation_list:

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rpointer.py	Mon Apr  3 19:49:06 2006
@@ -18,9 +18,9 @@
         assert res.value == ptrres.contents.value
 
     def test_annotate_c_int_ptr(self):
+        ptrtype = POINTER(c_int)
         def func():
             res = c_int(42)
-            ptrtype  = POINTER(c_int)
             ptrres  = ptrtype(res)
             return ptrres.contents.value
         
@@ -34,9 +34,9 @@
         assert s.knowntype == int
 
     def test_annotate_c_float_ptr(self):
+        ptrtype = POINTER(c_float)
         def func():
             res = c_float(4.2)
-            ptrtype  = POINTER(c_float)
             ptrres  = ptrtype(res)
             return ptrres.contents.value
         
@@ -50,14 +50,13 @@
         assert s.knowntype == float
 
 class Test_specialization:
-    def x_test_specialize_c_int_ptr(self):
+    def test_specialize_c_int_ptr(self):
+        py.test.skip("in-progress")
+        ptrtype = POINTER(c_int)
         def func():
             res = c_int(42)
-            ptrtype  = POINTER(c_int)
-            ptrres  = ptrtype(res)
-
+            ptrres = ptrtype(res)
             return ptrres.contents.value
 
         res = interpret(func, [])
-
         assert res == 42



More information about the Pypy-commit mailing list