[pypy-svn] r35743 - in pypy/dist/pypy: rlib rlib/rctypes rlib/rctypes/test rlib/test rpython rpython/rctypes rpython/test

arigo at codespeak.net arigo at codespeak.net
Thu Dec 14 16:04:57 CET 2006


Author: arigo
Date: Thu Dec 14 16:04:53 2006
New Revision: 35743

Added:
   pypy/dist/pypy/rlib/rctypes/   (props changed)
   pypy/dist/pypy/rlib/rctypes/__init__.py   (contents, props changed)
   pypy/dist/pypy/rlib/rctypes/implementation.py   (contents, props changed)
   pypy/dist/pypy/rlib/rctypes/rarray.py   (contents, props changed)
   pypy/dist/pypy/rlib/rctypes/rctypesobject.py
      - copied unchanged from r35732, pypy/dist/pypy/rlib/rctypesobject.py
   pypy/dist/pypy/rlib/rctypes/rpointer.py   (contents, props changed)
   pypy/dist/pypy/rlib/rctypes/rprimitive.py
      - copied, changed from r35732, pypy/dist/pypy/rpython/rctypes/aprimitive.py
   pypy/dist/pypy/rlib/rctypes/test/   (props changed)
   pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py
      - copied, changed from r35732, pypy/dist/pypy/rlib/test/test_rctypesobject.py
   pypy/dist/pypy/rlib/rctypes/test/test_rprimitive.py
      - copied, changed from r35732, pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py
Removed:
   pypy/dist/pypy/rlib/rctypesobject.py
   pypy/dist/pypy/rlib/test/test_rctypesobject.py
Modified:
   pypy/dist/pypy/rpython/controllerentry.py
   pypy/dist/pypy/rpython/rcontrollerentry.py
   pypy/dist/pypy/rpython/rctypes/implementation.py
   pypy/dist/pypy/rpython/test/test_controllerentry.py
Log:
Start implementing rctypes on top of rctypesobject using the
controllerentry mechanism.  It seems to work.  It's completely obscure,
though.



Added: pypy/dist/pypy/rlib/rctypes/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rlib/rctypes/__init__.py	Thu Dec 14 16:04:53 2006
@@ -0,0 +1 @@
+# empty

Added: pypy/dist/pypy/rlib/rctypes/implementation.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rlib/rctypes/implementation.py	Thu Dec 14 16:04:53 2006
@@ -0,0 +1,151 @@
+from pypy.annotation import model as annmodel
+from pypy.rlib.rctypes import rctypesobject
+from pypy.rpython import extregistry, controllerentry
+from pypy.rpython.controllerentry import Controller, ControllerEntry
+from pypy.rpython.controllerentry import ControllerEntryForPrebuilt
+from pypy.rpython.controllerentry import SomeControlledInstance
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.rctypes import rcarithmetic as rcarith
+
+import ctypes
+if ctypes.__version__ < '0.9.9.6':  # string comparison... good enough?
+    raise ImportError("requires ctypes >= 0.9.9.6, got %s" % (
+        ctypes.__version__,))
+
+
+class CTypeController(Controller):
+
+    def __init__(self, ctype):
+        self.ctype = ctype
+        self.instance_cache = {}
+
+    def register_for_type(cls, ctype):
+        class Entry(CTypesCallEntry):
+            _about_ = ctype
+            _controller_ = cls
+        class Entry(CTypesObjEntry):
+            _type_ = ctype
+            _controller_ = cls
+    register_for_type = classmethod(register_for_type)
+
+    def register_for_metatype(cls, ctype):
+        class Entry(CTypesCallEntry):
+            _type_ = ctype
+            _controller_ = cls
+        class Entry(CTypesObjEntry):
+            _metatype_ = ctype
+            _controller_ = cls
+    register_for_metatype = classmethod(register_for_metatype)
+
+    def convert(self, x):
+        assert isinstance(x, self.ctype)
+        key = id(x)
+        try:
+            return self.instance_cache[key]
+        except KeyError:
+            obj = self.new()
+            self.instance_cache[key] = obj
+            self.initialize_prebuilt(obj, x)
+            return obj
+
+    def return_value(self, obj):
+        return obj
+    return_value._annspecialcase_ = 'specialize:arg(0)'
+
+    # extension to the setattr/setitem support: if the new value is actually
+    # a CTypeControlled instance as well, reveal it automatically (i.e. turn
+    # it into an rctypesobject) and call a method with a different name.
+
+    def setboxattr(self, obj, attr, value):
+        return getattr(self, 'setbox_' + attr)(obj, value)
+    setboxattr._annspecialcase_ = 'specialize:arg(2)'
+
+    def ctrl_setattr(self, s_obj, s_attr, s_value):
+        if s_is_box(s_value):
+            return controllerentry.delegate(self.setboxattr,
+                                            s_obj, s_attr, s_value.s_real_obj)
+        else:
+            return controllerentry.delegate(self.setattr,
+                                            s_obj, s_attr, s_value)
+
+    def rtype_setattr(self, hop):
+        r_controlled_instance = hop.args_r[0]
+        if s_is_box(hop.args_s[2]):
+            hop2 = revealbox(hop, 2)
+            return r_controlled_instance.rtypedelegate(self.setboxattr, hop2)
+        else:
+            return r_controlled_instance.rtypedelegate(self.setattr, hop)
+
+    def ctrl_setitem(self, s_obj, s_key, s_value):
+        if s_is_box(s_value):
+            return controllerentry.delegate(self.setboxitem,
+                                            s_obj, s_key, s_value.s_real_obj)
+        else:
+            return controllerentry.delegate(self.setitem,
+                                            s_obj, s_key, s_value)
+
+    def rtype_setitem(self, hop):
+        r_controlled_instance = hop.args_r[0]
+        if s_is_box(hop.args_s[2]):
+            hop2 = revealbox(hop, 2)
+            return r_controlled_instance.rtypedelegate(self.setboxitem, hop2)
+        else:
+            return r_controlled_instance.rtypedelegate(self.setitem, hop)
+
+
+class CTypesCallEntry(ControllerEntry):
+    def getcontroller(self, *args_s):
+        ctype = self.instance
+        return self._controller_(ctype)
+
+class CTypesObjEntry(ControllerEntryForPrebuilt):
+    def getcontroller(self):
+        ctype = self.type
+        return self._controller_(ctype)
+
+def getcontroller(ctype):
+    """Return the CTypeController instance corresponding to the given ctype."""
+    entry = extregistry.lookup_type(ctype)
+    return entry.getcontroller()
+
+def s_is_box(s_value):
+    return (isinstance(s_value, SomeControlledInstance) and
+            isinstance(s_value.controller, CTypeController))
+
+def revealbox(hop, argindex):
+    hop2 = hop.copy()
+    r_value = hop2.args_r[argindex]
+    s_value, r_value = r_value.reveal(r_value)
+    hop2.args_s[argindex] = s_value
+    hop2.args_r[argindex] = r_value
+    return hop2
+
+def register_function_impl(builtinfn, controllingfn,
+                           revealargs=[], revealresult=None):
+
+    class Entry(extregistry.ExtRegistryEntry):
+        _about_ = builtinfn
+
+        def compute_result_annotation(self, *args_s):
+            real_args_s = list(args_s)
+            for index in revealargs:
+                real_args_s[index] = args_s[index].s_real_obj
+            if annmodel.s_ImpossibleValue in real_args_s:
+                return annmodel.s_ImpossibleValue   # temporarily hopefully
+            s_result = controllerentry.delegate(controllingfn, *real_args_s)
+            if revealresult:
+                result_ctype = revealresult(*args_s)
+                controller = getcontroller(result_ctype)
+                s_result = SomeControlledInstance(s_result, controller)
+            return s_result
+
+        def specialize_call(self, hop):
+            import pdb; pdb.set_trace()
+
+# ____________________________________________________________
+#
+# Imports for side-effects
+
+import pypy.rlib.rctypes.rprimitive
+import pypy.rlib.rctypes.rarray
+import pypy.rlib.rctypes.rpointer

Added: pypy/dist/pypy/rlib/rctypes/rarray.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rlib/rctypes/rarray.py	Thu Dec 14 16:04:53 2006
@@ -0,0 +1,44 @@
+from pypy.rlib.rctypes.implementation import CTypeController, getcontroller
+from pypy.rlib.rctypes import rctypesobject
+from pypy.rpython.lltypesystem import lltype
+
+from ctypes import ARRAY, c_int, c_char
+
+
+ArrayType = type(ARRAY(c_int, 10))
+
+
+class ArrayCTypeController(CTypeController):
+
+    def __init__(self, ctype):
+        CTypeController.__init__(self, ctype)
+        self.itemcontroller = getcontroller(ctype._type_)
+        self.length = ctype._length_
+        self.knowntype = rctypesobject.RFixedArray(
+            self.itemcontroller.knowntype,
+            self.length)
+
+    def new(self, *args_s):
+        if len(args_s) > self.length:
+            raise ValueError("too many arguments for an array of length %d" % (
+                self.length,))
+        obj = self.knowntype.allocate()
+        if len(args_s) > 0:
+            lst_s = list(args_s)
+            for i in range(len(args_s)):
+                self.setitem(obj, i, lst_s[i])
+        return obj
+    new._annspecialcase_ = 'specialize:arg(0)'
+
+    def getitem(self, obj, i):
+        itemobj = obj.ref(i)
+        return self.itemcontroller.return_value(itemobj)
+    getitem._annspecialcase_ = 'specialize:arg(0)'
+
+    def setitem(self, obj, i, value):
+        itemobj = obj.ref(i)
+        self.itemcontroller.set_value(itemobj, value)
+    setitem._annspecialcase_ = 'specialize:arg(0)'
+
+
+ArrayCTypeController.register_for_metatype(ArrayType)

Added: pypy/dist/pypy/rlib/rctypes/rpointer.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rlib/rctypes/rpointer.py	Thu Dec 14 16:04:53 2006
@@ -0,0 +1,38 @@
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rlib.rctypes.implementation import CTypeController, getcontroller
+from pypy.rlib.rctypes.implementation import register_function_impl
+from pypy.rlib.rctypes import rctypesobject
+from pypy.rpython.lltypesystem import lltype
+
+from ctypes import pointer, POINTER, byref, c_int
+
+
+PointerType = type(POINTER(c_int))
+
+
+class PointerCTypeController(CTypeController):
+
+    def __init__(self, ctype):
+        CTypeController.__init__(self, ctype)
+        self.contentscontroller = getcontroller(ctype._type_)
+        self.knowntype = rctypesobject.RPointer(
+            self.contentscontroller.knowntype)
+
+    def new(self):
+        obj = self.knowntype.allocate()
+        #...
+        return obj
+
+    def getitem(self, obj, index):
+        if index != 0:
+            raise ValueError("can only access item 0 of pointers")
+        contentsobj = obj.get_contents()
+        return self.contentscontroller.return_value(contentsobj)
+    getitem._annspecialcase_ = 'specialize:arg(0)'
+
+PointerCTypeController.register_for_metatype(PointerType)
+
+register_function_impl(pointer, rctypesobject.pointer,
+                       revealargs   = [0],
+                       revealresult = lambda s_obj: POINTER(s_obj.controller
+                                                            .ctype))

Modified: pypy/dist/pypy/rpython/controllerentry.py
==============================================================================
--- pypy/dist/pypy/rpython/controllerentry.py	(original)
+++ pypy/dist/pypy/rpython/controllerentry.py	Thu Dec 14 16:04:53 2006
@@ -10,8 +10,7 @@
     def compute_result_annotation(self, *args_s):
         cls = self.instance
         controller = self.getcontroller(*args_s)
-        s_real_obj = controller.ctrl_new(*args_s)
-        return SomeControlledInstance(s_real_obj, controller)
+        return controller.ctrl_new(*args_s)
 
     def getcontroller(self, *args_s):
         return self._controller_()
@@ -40,7 +39,8 @@
         return True
 
     def ctrl_new(self, *args_s):
-        return delegate(self.new, *args_s)
+        s_real_obj = delegate(self.new, *args_s)
+        return SomeControlledInstance(s_real_obj, controller=self)
 
     def rtype_new(self, hop):
         r_controlled_instance = hop.r_result
@@ -70,6 +70,20 @@
         r_controlled_instance = hop.args_r[0]
         return r_controlled_instance.rtypedelegate(self.setattr, hop)
 
+    def ctrl_getitem(self, s_obj, s_key):
+        return delegate(self.getitem, s_obj, s_key)
+
+    def rtype_getitem(self, hop):
+        r_controlled_instance = hop.args_r[0]
+        return r_controlled_instance.rtypedelegate(self.getitem, hop)
+
+    def ctrl_setitem(self, s_obj, s_key, s_value):
+        return delegate(self.setitem, s_obj, s_key, s_value)
+
+    def rtype_setitem(self, hop):
+        r_controlled_instance = hop.args_r[0]
+        return r_controlled_instance.rtypedelegate(self.setitem, hop)
+
 
 def delegate(boundmethod, *args_s):
     bk = getbookkeeper()
@@ -106,6 +120,15 @@
         s_cin.controller.ctrl_setattr(s_cin.s_real_obj, s_attr, s_value)
 
 
+class __extend__(pairtype(SomeControlledInstance, annmodel.SomeObject)):
+
+    def getitem((s_cin, s_key)):
+        return s_cin.controller.ctrl_getitem(s_cin.s_real_obj, s_key)
+
+    def setitem((s_cin, s_key), s_value):
+        s_cin.controller.ctrl_setitem(s_cin.s_real_obj, s_key, s_value)
+
+
 class __extend__(pairtype(SomeControlledInstance, SomeControlledInstance)):
 
     def union((s_cin1, s_cin2)):

Modified: pypy/dist/pypy/rpython/rcontrollerentry.py
==============================================================================
--- pypy/dist/pypy/rpython/rcontrollerentry.py	(original)
+++ pypy/dist/pypy/rpython/rcontrollerentry.py	Thu Dec 14 16:04:53 2006
@@ -1,3 +1,4 @@
+from pypy.tool.pairtype import pairtype
 from pypy.objspace.flow.model import Constant
 from pypy.rpython.rmodel import Repr
 from pypy.rpython.error import TyperError
@@ -41,3 +42,12 @@
 
     def rtype_setattr(self, hop):
         return self.controller.rtype_setattr(hop)
+
+
+class __extend__(pairtype(ControlledInstanceRepr, Repr)):
+
+    def rtype_getitem((r_controlled, r_key), hop):
+        return r_controlled.controller.rtype_getitem(hop)
+
+    def rtype_setitem((r_controlled, r_key), hop):
+        return r_controlled.controller.rtype_setitem(hop)

Modified: pypy/dist/pypy/rpython/rctypes/implementation.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/implementation.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/implementation.py	Thu Dec 14 16:04:53 2006
@@ -3,6 +3,8 @@
 from pypy.rpython import extregistry
 from pypy.rpython.extregistry import ExtRegistryEntry
 
+DONT_IMPORT_ME
+
 import ctypes
 if ctypes.__version__ < '0.9.9.6':  # string comparison... good enough?
     raise ImportError("requires ctypes >= 0.9.9.6, got %s" % (

Modified: pypy/dist/pypy/rpython/test/test_controllerentry.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_controllerentry.py	(original)
+++ pypy/dist/pypy/rpython/test/test_controllerentry.py	Thu Dec 14 16:04:53 2006
@@ -29,6 +29,12 @@
     def set_foo(self, obj, value):
         value.append(obj)
 
+    def getitem(self, obj, key):
+        return obj + key
+
+    def setitem(self, obj, key, value):
+        value.append(obj + key)
+
 class Entry(ControllerEntry):
     _about_ = C
     _controller_ = C_Controller
@@ -72,3 +78,19 @@
     assert ''.join(res.chars) == "512"
     res = interpret(fun2, [False])
     assert ''.join(res.chars) == "76542"
+
+def fun3(a):
+    lst = []
+    c = C(a)
+    c['foo'] = lst    # side-effect on lst!  well, it's a test
+    return c['bar'], lst[0]
+
+def test_getsetitem_annotate():
+    a = RPythonAnnotator()
+    s = a.build_types(fun3, [a.bookkeeper.immutablevalue("4")])
+    assert s.const == ("4_bar", "4_foo")
+
+def test_getsetitem_specialize():
+    res = interpret(fun3, ["4"])
+    assert ''.join(res.item0.chars) == "4_bar"
+    assert ''.join(res.item1.chars) == "4_foo"



More information about the Pypy-commit mailing list