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

gromit at codespeak.net gromit at codespeak.net
Sun Jan 29 17:47:31 CET 2006


Author: gromit
Date: Sun Jan 29 17:47:28 2006
New Revision: 22849

Modified:
   pypy/dist/pypy/rpython/rctypes/implementation.py
   pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py
Log:
ADD: We now can compile ctypes structures that manage their own memory.

Modified: pypy/dist/pypy/rpython/rctypes/implementation.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/implementation.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/implementation.py	Sun Jan 29 17:47:28 2006
@@ -11,7 +11,11 @@
 from pypy.annotation.model import SomeInteger, SomeCTypesObject, \
         SomeString, SomeFloat
 from pypy.rpython.lltypesystem.lltype import Signed, SignedLongLong, \
-        Unsigned, UnsignedLongLong, Char, Float
+        Unsigned, UnsignedLongLong, Char, Float, Ptr, GcStruct, \
+        Void
+from pypy.rpython.rmodel import Repr, IntegerRepr, inputconst
+from pypy.rpython.error import TyperError
+
 
 # ctypes_annotation_list contains various attributes that
 # are used by the pypy annotation.
@@ -118,8 +122,12 @@
         return SomeCTypesObject(cls)
     compute_annotation = classmethod(compute_annotation)
 
-    def specialize(self, hop):
-        raise NotImplementedError
+    def specialize( cls, highLevelOperation ):
+        ctypesStructureType = highLevelOperation.r_result.lowleveltype  
+        return highLevelOperation.llops.genop(
+                "malloc", [ inputconst( Void, ctypesStructureType ) ],
+                highLevelOperation.r_result )
+    specialize = classmethod(specialize)
 
     def compute_result_annotation(cls, *args_s):
         """
@@ -128,6 +136,21 @@
         return SomeCTypesObject(cls,SomeCTypesObject.OWNSMEMORY)
     compute_result_annotation = classmethod(compute_result_annotation)
 
+    def createLowLevelRepresentation( rtyper, annotationObject ):
+        """
+        Answer the correspondending low level object.
+        """
+        if annotationObject.memorystate == annotationObject.OWNSMEMORY:
+            return CtypesMemoryOwningStructureRepresentation( 
+                    rtyper, annotationObject )
+        elif annotationObject.memorystate == annotationObject.MEMORYALIAS:
+            return CtypesMemoryAliasStructureRepresentation(
+                    rtyper, annotationObject )
+        else:
+            raise TyperError( "Unkown memory state in %r" % annotationObject )
+    createLowLevelRepresentation = staticmethod( createLowLevelRepresentation )
+
+
 class RByrefObj(object):
 
     default_memorystate = SomeCTypesObject.MEMORYALIAS
@@ -158,6 +181,9 @@
         assert answer is cls
         return SomeCTypesObject(cls)
     answer.compute_result_annotation = classmethod(compute_result_annotation)
+    # We specialcased accessing pointers be getting their contents attribute
+    # because we can't use the memory state from 'cls'.
+    # So the obvious way to do it is obsolete (#o#).
     #o#answer._fields_def_ = {"contents": cls}
     answer.default_memorystate = SomeCTypesObject.MEMORYALIAS
     return answer
@@ -202,3 +228,61 @@
     return answer
 
 
+class AbstractCtypesRepresentation( Repr ):
+    """
+    The abstract base class of all ctypes low level representations.
+    """
+
+
+class AbstractCtypesStructureRepresentation( AbstractCtypesRepresentation ):
+    """
+    The abstract base class of ctypes structures' low level representation.
+    """
+
+    def __init__( self, rtyper, annotationObject ):
+        # XXX This .ll_type may not work for pointers or structures
+        # conating structures
+        fields = [ ( name, ctypesType.ll_type )
+                        for name, ctypesType in annotationObject.knowntype._fields_ ]
+        self.lowleveltype = Ptr(
+                GcStruct( 
+                    'CtypesStructure_%s' %
+                    annotationObject.knowntype.__name__, *fields ) )
+
+
+class CtypesMemoryOwningStructureRepresentation( AbstractCtypesStructureRepresentation ):
+    """
+    The lowlevel representation of a ctypes structure that owns its memory.
+    """
+
+    def rtype_setattr( self, highLevelOperation ):
+        #d#print highLevelOperation.args_v
+        #d#print highLevelOperation.args_r
+        #d#print highLevelOperation.args_s
+        highLevelOperation.genop( 
+                "setfield", 
+                highLevelOperation.inputargs(
+                    *highLevelOperation.args_r[ :3 ] ) )
+
+    def rtype_getattr( self, highLevelOperation ):
+        return highLevelOperation.genop( 
+                "getfield", 
+                highLevelOperation.inputargs(
+                    *highLevelOperation.args_r[ :2 ] ),
+                highLevelOperation.r_result )
+
+
+
+class CtypesMemoryAliasStructureRepresentation( AbstractCtypesStructureRepresentation ):
+    """
+    The lowlevel representation of a ctypes structure that is an alias to
+    someone else's memory.
+    """
+
+class __extend__( SomeCTypesObject ):
+    def rtyper_makerepr( self, rtyper ):
+        return self.knowntype.createLowLevelRepresentation( rtyper, self )
+        
+    def rtyper_makekey( self ):
+        return self.__class__, self.knowntype, self.memorystate
+

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rctypes.py	Sun Jan 29 17:47:28 2006
@@ -1,10 +1,34 @@
 import py.test
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.translator.translator import TranslationContext
-from pypy.translator.c.test.test_genc import compile
+from pypy.translator.c.test.test_genc import compile, compile_db
+#o#from pypy.translator.c import compile
 from pypy.translator.tool.cbuild import compile_c_module
 from pypy.annotation.model import SomeCTypesObject, SomeObject
 import sys
+
+
+def compile(fn, argtypes, view=False):
+    from pypy.translator.c.database import LowLevelDatabase
+    from pypy.rpython.lltypesystem.lltype import pyobjectptr
+    t = TranslationContext()
+    a = t.buildannotator()
+    a.build_types(fn, argtypes)
+    t.buildrtyper().specialize()
+    if view:
+        t.view()
+    #t#backend_optimizations(t)
+    db = LowLevelDatabase(t)
+    entrypoint = db.get(pyobjectptr(fn))
+    db.complete()
+    module = compile_db(db)
+    compiled_fn = getattr(module, entrypoint)
+    def checking_fn(*args, **kwds):
+        res = compiled_fn(*args, **kwds)
+        mallocs, frees = module.malloc_counters()
+        assert mallocs == frees
+        return res
+    return checking_fn
     
 try:
     import ctypes
@@ -174,6 +198,15 @@
 
     return p.x
 
+def _py_test_compile_struct( p, x, y ):
+    p.x = x
+    p.y = y
+
+    return p
+
+def py_test_compile_struct( x, y ):
+    return _py_test_compile_struct( tagpoint(), x, y ).x
+    
 
 class Test_rctypes:
 
@@ -321,14 +354,34 @@
         s = a.build_types(py_test_simple_ctypes_non_const,[])
         assert s.knowntype == c_float
 
-    def x_test_specialize_struct(self):
+    def test_specialize_struct(self):
         t = TranslationContext()
         a = t.buildannotator()
         s = a.build_types(py_test_specialize_struct, [])
         # result should be an integer
         assert s.knowntype == int
-        t.buildrtyper().specialize()
+        try:
+            t.buildrtyper().specialize()
+        finally:
+            #d#t.view()
+            pass
+
+    def test_specialize_struct_1(self):
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types( py_test_compile_struct, [ int, int ] )
         #d#t.view()
+        try:
+            t.buildrtyper().specialize()
+        finally:
+            #d#t.view()
+            pass
+
+    def test_compile_struct(self):
+        fn = compile( py_test_compile_struct, [ int, int ], True )
+        res = fn( 42, -42 )
+        assert res == 42
+
 
 class Test_array:
 
@@ -357,13 +410,13 @@
         a = t.buildannotator()
         s = a.build_types(py_test_annotate_pointer_content,[])
         assert s.knowntype == int
-        #t#t.view()
+        #d#t.view()
 
     def test_annotate_array_slice_access(self):
         t = TranslationContext()
         a = t.buildannotator()
         s = a.build_types(py_test_annotate_array_slice_content,[])
-        #t#t.view()
+        #d#t.view()
         #d#print "v90:", s, type(s)
         assert s.knowntype == list
         s.listdef.listitem.s_value.knowntype == int



More information about the Pypy-commit mailing list