[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