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

arigo at codespeak.net arigo at codespeak.net
Wed Jan 3 17:30:24 CET 2007


Author: arigo
Date: Wed Jan  3 17:30:22 2007
New Revision: 36124

Modified:
   pypy/dist/pypy/rlib/rctypes/implementation.py
   pypy/dist/pypy/rlib/rctypes/rchar_p.py
   pypy/dist/pypy/rlib/rctypes/rprimitive.py
   pypy/dist/pypy/rlib/rctypes/rstruct.py
   pypy/dist/pypy/rlib/rctypes/test/test_rstruct.py
   pypy/dist/pypy/rpython/controllerentry.py
Log:
Minimally-tested support for keyword arguments in contructors,
used for the constructor of ctypes Structures.


Modified: pypy/dist/pypy/rlib/rctypes/implementation.py
==============================================================================
--- pypy/dist/pypy/rlib/rctypes/implementation.py	(original)
+++ pypy/dist/pypy/rlib/rctypes/implementation.py	Wed Jan  3 17:30:22 2007
@@ -69,6 +69,9 @@
         raise TypeError("cannot store a value into a non-primitive ctype")
     store_value._annspecialcase_ = 'specialize:arg(0)'
 
+    def default_ctype_value(self):
+        return self.ctype()
+
     # 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.
@@ -111,7 +114,7 @@
 
 
 class CTypesCallEntry(ControllerEntry):
-    def getcontroller(self, *args_s):
+    def getcontroller(self, *args_s, **kwds_s):
         ctype = self.instance
         return _build_controller(self._controller_, ctype)
 

Modified: pypy/dist/pypy/rlib/rctypes/rchar_p.py
==============================================================================
--- pypy/dist/pypy/rlib/rctypes/rchar_p.py	(original)
+++ pypy/dist/pypy/rlib/rctypes/rchar_p.py	Wed Jan  3 17:30:22 2007
@@ -27,6 +27,9 @@
     return_value = get_value
     store_value = set_value
 
+    def default_ctype_value(self):
+        return None
+
     def is_true(self, obj):
         return obj.get_value() is not None
 

Modified: pypy/dist/pypy/rlib/rctypes/rprimitive.py
==============================================================================
--- pypy/dist/pypy/rlib/rctypes/rprimitive.py	(original)
+++ pypy/dist/pypy/rlib/rctypes/rprimitive.py	Wed Jan  3 17:30:22 2007
@@ -80,6 +80,9 @@
     return_value = get_value
     store_value = set_value
 
+    def default_ctype_value(self):
+        return self.ctype().value
+
     def is_true(self, obj):
         llvalue = self.get_value(obj)
         if self.is_char_type:

Modified: pypy/dist/pypy/rlib/rctypes/rstruct.py
==============================================================================
--- pypy/dist/pypy/rlib/rctypes/rstruct.py	(original)
+++ pypy/dist/pypy/rlib/rctypes/rstruct.py	Wed Jan  3 17:30:22 2007
@@ -75,6 +75,61 @@
             fieldbox = controller.convert(getattr(x, name))
             self.setboxattr(obj, name, fieldbox)
 
+    def insert_constructor_keywords(self, lst, prefix, kwds):
+        lst = list(lst)
+        kwds = kwds.copy()
+        for index, (name, field_ctype) in enumerate(self.ctype._fields_):
+            if prefix+name in kwds:
+                value = kwds.pop(prefix+name)
+                while len(lst) <= index:
+                    lst.append(None)
+                if lst[index] is not None:
+                    raise TypeError("duplicate value for argument %r" % name)
+                lst[index] = value
+        if kwds:
+            raise TypeError("unknown keyword(s): %r" % (kwds.keys(),))
+        return lst
+
+    def ctrl_new_ex(self, bookkeeper, *args_s, **kwds_s):
+        if kwds_s:
+            args_s = self.insert_constructor_keywords(args_s, 's_', kwds_s)
+            for i in range(len(args_s)):
+                if args_s[i] is None:
+                    name, controller = self.fieldcontrollers[i]
+                    x = controller.default_ctype_value()
+                    args_s[i] = bookkeeper.immutablevalue(x)
+        return CTypeController.ctrl_new(self, *args_s)
+
+    def rtype_new(self, hop, **kwds_i):
+        if kwds_i:
+            lst = range(hop.nb_args)
+            for key, index in kwds_i.items():
+                lst[index] = None
+            lst = self.insert_constructor_keywords(lst, 'i_', kwds_i)
+            hop2 = hop.copy()
+            hop2.nb_args = len(lst)
+            hop2.args_v = []
+            hop2.args_s = []
+            hop2.args_r = []
+            for i, index in enumerate(lst):
+                if index is not None:
+                    v = hop.args_v[index]
+                    s = hop.args_s[index]
+                    r = hop.args_r[index]
+                else:
+                    # must insert a default value
+                    from pypy.objspace.flow.model import Constant
+                    name, controller = self.fieldcontrollers[i]
+                    x = controller.default_ctype_value()
+                    v = Constant(x)
+                    s = hop.rtyper.annotator.bookkeeper.immutablevalue(x)
+                    r = hop.rtyper.getrepr(s)
+                hop2.args_v.append(v)
+                hop2.args_s.append(s)
+                hop2.args_r.append(r)
+            hop = hop2
+        return CTypeController.rtype_new(self, hop)
+
 
 StructCTypeController.register_for_metatype(StructType)
 

Modified: pypy/dist/pypy/rlib/rctypes/test/test_rstruct.py
==============================================================================
--- pypy/dist/pypy/rlib/rctypes/test/test_rstruct.py	(original)
+++ pypy/dist/pypy/rlib/rctypes/test/test_rstruct.py	Wed Jan  3 17:30:22 2007
@@ -179,26 +179,26 @@
         assert res == 289
 
     def test_specialize_constructor_args(self):
-        py.test.skip("in-progress")
+        #py.test.skip("in-progress")
         class S(Structure):
             _fields_ = [('x', c_int),
                         ('y', c_char)]
-        def func(x, y):
+        def func(x, y, n):
             s0 = S(x)
             s1 = S(x, y)
             s2 = S(y=y)
             s3 = S(x, y=y)
-            return (s0, s1, s2, s3)
+            s = [s0, s1, s2, s3][n]
+            return s.x * 100 + ord(s.y)
 
-        res = interpret(func, [4, '?'])
-        assert res.item0.c_data.c_x == 4
-        assert res.item0.c_data.c_y == '\x00'
-        assert res.item1.c_data.c_x == 4
-        assert res.item1.c_data.c_y == '?'
-        assert res.item2.c_data.c_x == 0
-        assert res.item2.c_data.c_y == '?'
-        assert res.item3.c_data.c_x == 4
-        assert res.item3.c_data.c_y == '?'
+        res = interpret(func, [4, '?', 0])
+        assert res == 400
+        res = interpret(func, [4, '?', 1])
+        assert res == 463
+        res = interpret(func, [4, '?', 2])
+        assert res ==  63
+        res = interpret(func, [4, '?', 3])
+        assert res == 463
 
     def test_specialize_bad_constructor_args(self):
         py.test.skip("in-progress")

Modified: pypy/dist/pypy/rpython/controllerentry.py
==============================================================================
--- pypy/dist/pypy/rpython/controllerentry.py	(original)
+++ pypy/dist/pypy/rpython/controllerentry.py	Wed Jan  3 17:30:22 2007
@@ -8,20 +8,19 @@
 
 class ControllerEntry(ExtRegistryEntry):
 
-    def compute_result_annotation(self, *args_s):
-        cls = self.instance
-        controller = self.getcontroller(*args_s)
-        return controller.ctrl_new(*args_s)
+    def compute_result_annotation(self, *args_s, **kwds_s):
+        controller = self.getcontroller(*args_s, **kwds_s)
+        return controller.ctrl_new_ex(self.bookkeeper, *args_s, **kwds_s)
 
-    def getcontroller(self, *args_s):
+    def getcontroller(self, *args_s, **kwds_s):
         return self._controller_()
 
-    def specialize_call(self, hop):
+    def specialize_call(self, hop, **kwds_i):
         if hop.s_result == annmodel.s_ImpossibleValue:
             raise TyperError("object creation always raises: %s" % (
                 hop.spaceop,))
         controller = hop.s_result.controller
-        return controller.rtype_new(hop)
+        return controller.rtype_new(hop, **kwds_i)
 
 
 
@@ -65,13 +64,19 @@
         return controlled_instance_is_box(self, obj)
     is_box._annspecialcase_ = 'specialize:arg(0)'
 
-    def ctrl_new(self, *args_s):
+    def ctrl_new(self, *args_s, **kwds_s):
+        if kwds_s:
+            raise TypeError("cannot handle keyword arguments in %s" % (
+                self.new,))
         s_real_obj = delegate(self.new, *args_s)
         if s_real_obj == annmodel.s_ImpossibleValue:
             return annmodel.s_ImpossibleValue
         else:
             return SomeControlledInstance(s_real_obj, controller=self)
 
+    def ctrl_new_ex(self, bookkeeper, *args_s, **kwds_s):
+        return self.ctrl_new(*args_s, **kwds_s)
+
     def rtype_new(self, hop):
         from pypy.rpython.rcontrollerentry import rtypedelegate
         return rtypedelegate(self.new, hop, revealargs=[], revealresult=True)



More information about the Pypy-commit mailing list