[pypy-commit] pypy reflex-support: o) test for defaults of builtin types

wlav noreply at buildbot.pypy.org
Wed Jul 11 09:28:21 CEST 2012


Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r56021:d65a7f633e38
Date: 2012-07-10 15:53 -0700
http://bitbucket.org/pypy/pypy/changeset/d65a7f633e38/

Log:	o) test for defaults of builtin types o) tests for vector of double
	o) DoubleRefExecutor, following the lines of the IntRef one o)
	refactoring of executor.py

diff --git a/pypy/module/cppyy/executor.py b/pypy/module/cppyy/executor.py
--- a/pypy/module/cppyy/executor.py
+++ b/pypy/module/cppyy/executor.py
@@ -68,9 +68,25 @@
         return space.w_None
 
 
+class NumericExecutorMixin(object):
+    _mixin_ = True
+    _immutable_ = True
+
+    def _wrap_result(self, space, result):
+        return space.wrap(rffi.cast(self.c_type, result))
+
+    def execute(self, space, cppmethod, cppthis, num_args, args):
+        result = self.c_stubcall(cppmethod, cppthis, num_args, args)
+        return self._wrap_result(space, result)
+
+    def execute_libffi(self, space, libffifunc, argchain):
+        result = libffifunc.call(argchain, self.c_type)
+        return space.wrap(result)
+
+
 class BoolExecutor(FunctionExecutor):
     _immutable_ = True
-    libffitype = libffi.types.schar
+    libffitype  = libffi.types.schar
 
     def execute(self, space, cppmethod, cppthis, num_args, args):
         result = capi.c_call_b(cppmethod, cppthis, num_args, args)
@@ -80,112 +96,6 @@
         result = libffifunc.call(argchain, rffi.CHAR)
         return space.wrap(bool(ord(result)))
 
-class CharExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.schar
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_c(cppmethod, cppthis, num_args, args)
-        return space.wrap(result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.CHAR)
-        return space.wrap(result)
-
-class ShortExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.sshort
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_h(cppmethod, cppthis, num_args, args)
-        return space.wrap(result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.SHORT)
-        return space.wrap(result)
-
-class IntExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.sint
-
-    def _wrap_result(self, space, result):
-        return space.wrap(result)
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_i(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.INT)
-        return space.wrap(result)
-
-class UnsignedIntExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.uint
-
-    def _wrap_result(self, space, result):
-        return space.wrap(rffi.cast(rffi.UINT, result))
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_l(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.UINT)
-        return space.wrap(result)
-
-class LongExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.slong
-
-    def _wrap_result(self, space, result):
-        return space.wrap(result)
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_l(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.LONG)
-        return space.wrap(result)
-
-class UnsignedLongExecutor(LongExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.ulong
-
-    def _wrap_result(self, space, result):
-        return space.wrap(rffi.cast(rffi.ULONG, result))
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.ULONG)
-        return space.wrap(result)
-
-class LongLongExecutor(FunctionExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.sint64
-
-    def _wrap_result(self, space, result):
-        return space.wrap(result)
-
-    def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_ll(cppmethod, cppthis, num_args, args)
-        return self._wrap_result(space, result)
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.LONGLONG)
-        return space.wrap(result)
-
-class UnsignedLongLongExecutor(LongLongExecutor):
-    _immutable_ = True
-    libffitype = libffi.types.uint64
-
-    def _wrap_result(self, space, result):
-        return space.wrap(rffi.cast(rffi.ULONGLONG, result))
-
-    def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.ULONGLONG)
-        return space.wrap(result)
-
 class ConstIntRefExecutor(FunctionExecutor):
     _immutable_ = True
     libffitype = libffi.types.pointer
@@ -252,17 +162,31 @@
         result = libffifunc.call(argchain, rffi.FLOAT)
         return space.wrap(float(result))
 
-class DoubleExecutor(FunctionExecutor):
+class DoubleRefExecutor(FunctionExecutor):
     _immutable_ = True
-    libffitype = libffi.types.double
+    libffitype = libffi.types.pointer
+
+    def __init__(self, space, extra):
+        FunctionExecutor.__init__(self, space, extra)
+        self.do_assign = False
+        self.item = rffi.cast(rffi.DOUBLE, 0)
+
+    def set_item(self, space, w_item):
+        self.item = rffi.cast(rffi.DOUBLE, space.float_w(w_item))
+        self.do_assign = True
+
+    def _wrap_result(self, space, dptr):
+        if self.do_assign:
+            dptr[0] = self.item
+        return space.wrap(dptr[0])      # all paths, for rtyper
 
     def execute(self, space, cppmethod, cppthis, num_args, args):
-        result = capi.c_call_d(cppmethod, cppthis, num_args, args)
-        return space.wrap(result)
+        result = rffi.cast(rffi.DOUBLEP, capi.c_call_r(cppmethod, cppthis, num_args, args))
+        return self._wrap_result(space, result)
 
     def execute_libffi(self, space, libffifunc, argchain):
-        result = libffifunc.call(argchain, rffi.DOUBLE)
-        return space.wrap(result)
+        result = libffifunc.call(argchain, rffi.DOUBLEP)
+        return self._wrap_result(space, result)
 
 
 class CStringExecutor(FunctionExecutor):
@@ -420,7 +344,7 @@
         elif compound == "**" or compound == "*&":
             return InstancePtrPtrExecutor(space, cppclass)
     elif capi.c_is_enum(clean_name):
-        return UnsignedIntExecutor(space, None)
+        return _executors['unsigned int'](space, None)
 
     # 4) additional special cases
     # ... none for now
@@ -432,20 +356,11 @@
 _executors["void"]                = VoidExecutor
 _executors["void*"]               = PtrTypeExecutor
 _executors["bool"]                = BoolExecutor
-_executors["char"]                = CharExecutor
 _executors["const char*"]         = CStringExecutor
-_executors["short"]               = ShortExecutor
-_executors["unsigned short"]      = ShortExecutor
-_executors["int"]                 = IntExecutor
 _executors["const int&"]          = ConstIntRefExecutor
 _executors["int&"]                = IntRefExecutor
-_executors["unsigned"]            = UnsignedIntExecutor
-_executors["long"]                = LongExecutor
-_executors["unsigned long"]       = UnsignedLongExecutor
-_executors["long long"]           = LongLongExecutor
-_executors["unsigned long long"]  = UnsignedLongLongExecutor
 _executors["float"]               = FloatExecutor
-_executors["double"]              = DoubleExecutor
+_executors["double&"]             = DoubleRefExecutor
 
 _executors["constructor"]         = ConstructorExecutor
 
@@ -454,24 +369,37 @@
 
 _executors["PyObject*"]           = PyObjectExecutor
 
+# add basic (builtin) executors
+def _build_basic_executors():
+    "NOT_RPYTHON"
+    type_info = (
+        (rffi.CHAR,       libffi.types.schar,   capi.c_call_c,   ("char", "unsigned char")),
+        (rffi.SHORT,      libffi.types.sshort,  capi.c_call_h,   ("short", "short int", "unsigned short", "unsigned short int")),
+        (rffi.INT,        libffi.types.sint,    capi.c_call_i,   ("int",)),
+        (rffi.UINT,       libffi.types.uint,    capi.c_call_l,   ("unsigned", "unsigned int")),
+        (rffi.LONG,       libffi.types.slong,   capi.c_call_l,   ("long", "long int")),
+        (rffi.ULONG,      libffi.types.ulong,   capi.c_call_l,   ("unsigned long", "unsigned long int")),
+        (rffi.LONGLONG,   libffi.types.sint64,  capi.c_call_ll,  ("long long", "long long int")),
+        (rffi.ULONGLONG,  libffi.types.uint64,  capi.c_call_ll,  ("unsigned long long", "unsigned long long int")),
+        (rffi.DOUBLE,     libffi.types.double,  capi.c_call_d,   ("double",))
+    )
+
+    for t_rffi, t_ffi, stub, names in type_info:
+        class BasicExecutor(NumericExecutorMixin, FunctionExecutor):
+            _immutable_ = True
+            libffitype  = t_ffi
+            c_type      = t_rffi
+            c_stubcall  = staticmethod(stub)
+        for name in names:
+            _executors[name] = BasicExecutor
+_build_basic_executors()
+
 # add the set of aliased names
 def _add_aliased_executors():
     "NOT_RPYTHON"
     alias_info = (
-        ("char",                            ("unsigned char",)),
-
-        ("short",                           ("short int",)),
-        ("unsigned short",                  ("unsigned short int",)),
-        ("unsigned",                        ("unsigned int",)),
-        ("long",                            ("long int",)),
-        ("unsigned long",                   ("unsigned long int",)),
-        ("long long",                       ("long long int",)),
-        ("unsigned long long",              ("unsigned long long int",)),
-
         ("const char*",                     ("char*",)),
-
         ("std::basic_string<char>",         ("string",)),
-
         ("PyObject*",                       ("_object*",)),
     )
 
diff --git a/pypy/module/cppyy/test/advancedcpp.cxx b/pypy/module/cppyy/test/advancedcpp.cxx
--- a/pypy/module/cppyy/test/advancedcpp.cxx
+++ b/pypy/module/cppyy/test/advancedcpp.cxx
@@ -2,11 +2,20 @@
 
 
 // for testing of default arguments
-defaulter::defaulter(int a, int b, int c ) {
-   m_a = a;
-   m_b = b;
-   m_c = c;
+#define IMPLEMENT_DEFAULTER_CLASS(type, tname)                               \
+tname##_defaulter::tname##_defaulter(type a, type b, type c) {               \
+   m_a = a; m_b = b; m_c = c;                                                \
 }
+IMPLEMENT_DEFAULTER_CLASS(short, short)
+IMPLEMENT_DEFAULTER_CLASS(unsigned short, ushort)
+IMPLEMENT_DEFAULTER_CLASS(int, int)
+IMPLEMENT_DEFAULTER_CLASS(unsigned, uint)
+IMPLEMENT_DEFAULTER_CLASS(long, long)
+IMPLEMENT_DEFAULTER_CLASS(unsigned long, ulong)
+IMPLEMENT_DEFAULTER_CLASS(long long, llong)
+IMPLEMENT_DEFAULTER_CLASS(unsigned long long, ullong)
+IMPLEMENT_DEFAULTER_CLASS(float, float)
+IMPLEMENT_DEFAULTER_CLASS(double, double)
 
 
 // for esoteric inheritance testing
diff --git a/pypy/module/cppyy/test/advancedcpp.h b/pypy/module/cppyy/test/advancedcpp.h
--- a/pypy/module/cppyy/test/advancedcpp.h
+++ b/pypy/module/cppyy/test/advancedcpp.h
@@ -2,13 +2,24 @@
 
 
 //===========================================================================
-class defaulter {                 // for testing of default arguments
-public:
-    defaulter(int a = 11, int b = 22, int c = 33 );
-
-public:
-    int m_a, m_b, m_c;
+#define DECLARE_DEFAULTER_CLASS(type, tname)                                \
+class tname##_defaulter {                                                   \
+public:                                                                     \
+    tname##_defaulter(type a = 11, type b = 22, type c = 33);               \
+                                                                            \
+public:                                                                     \
+    type m_a, m_b, m_c;                                                     \
 };
+DECLARE_DEFAULTER_CLASS(short, short)   // for testing of default arguments
+DECLARE_DEFAULTER_CLASS(unsigned short, ushort)
+DECLARE_DEFAULTER_CLASS(int, int)
+DECLARE_DEFAULTER_CLASS(unsigned, uint)
+DECLARE_DEFAULTER_CLASS(long, long)
+DECLARE_DEFAULTER_CLASS(unsigned long, ulong)
+DECLARE_DEFAULTER_CLASS(long long, llong)
+DECLARE_DEFAULTER_CLASS(unsigned long long, ullong)
+DECLARE_DEFAULTER_CLASS(float, float)
+DECLARE_DEFAULTER_CLASS(double, double)
 
 
 //===========================================================================
diff --git a/pypy/module/cppyy/test/advancedcpp.xml b/pypy/module/cppyy/test/advancedcpp.xml
--- a/pypy/module/cppyy/test/advancedcpp.xml
+++ b/pypy/module/cppyy/test/advancedcpp.xml
@@ -1,6 +1,6 @@
 <lcgdict>
 
-  <class name="defaulter" />
+  <class pattern="*_defaulter" />
 
   <class name="base_class" />
   <class name="derived_class" />
diff --git a/pypy/module/cppyy/test/advancedcpp_LinkDef.h b/pypy/module/cppyy/test/advancedcpp_LinkDef.h
--- a/pypy/module/cppyy/test/advancedcpp_LinkDef.h
+++ b/pypy/module/cppyy/test/advancedcpp_LinkDef.h
@@ -4,7 +4,16 @@
 #pragma link off all classes;
 #pragma link off all functions;
 
-#pragma link C++ class defaulter;
+#pragma link C++ class short_defaulter;
+#pragma link C++ class ushort_defaulter;
+#pragma link C++ class int_defaulter;
+#pragma link C++ class uint_defaulter;
+#pragma link C++ class long_defaulter;
+#pragma link C++ class ulong_defaulter;
+#pragma link C++ class llong_defaulter;
+#pragma link C++ class ullong_defaulter;
+#pragma link C++ class float_defaulter;
+#pragma link C++ class double_defaulter;
 
 #pragma link C++ class base_class;
 #pragma link C++ class derived_class;
diff --git a/pypy/module/cppyy/test/stltypes.cxx b/pypy/module/cppyy/test/stltypes.cxx
--- a/pypy/module/cppyy/test/stltypes.cxx
+++ b/pypy/module/cppyy/test/stltypes.cxx
@@ -14,6 +14,7 @@
 
 //- explicit instantiations of used types
 STLTYPES_EXPLICIT_INSTANTIATION(vector, int)
+STLTYPES_EXPLICIT_INSTANTIATION(vector, double)
 STLTYPES_EXPLICIT_INSTANTIATION(vector, just_a_class)
 
 //- class with lots of std::string handling
diff --git a/pypy/module/cppyy/test/stltypes.h b/pypy/module/cppyy/test/stltypes.h
--- a/pypy/module/cppyy/test/stltypes.h
+++ b/pypy/module/cppyy/test/stltypes.h
@@ -25,6 +25,7 @@
 #ifndef __CINT__
 //- explicit instantiations of used types
 STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, int)
+STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, double)
 STLTYPES_EXPLICIT_INSTANTIATION_DECL(vector, just_a_class)
 #endif
 
diff --git a/pypy/module/cppyy/test/test_advancedcpp.py b/pypy/module/cppyy/test/test_advancedcpp.py
--- a/pypy/module/cppyy/test/test_advancedcpp.py
+++ b/pypy/module/cppyy/test/test_advancedcpp.py
@@ -31,31 +31,42 @@
         """Test usage of default arguments"""
 
         import cppyy
-        defaulter = cppyy.gbl.defaulter
+        def test_defaulter(n, t):
+            defaulter = getattr(cppyy.gbl, '%s_defaulter' % n)
 
-        d = defaulter()
-        assert d.m_a == 11
-        assert d.m_b == 22
-        assert d.m_c == 33
-        d.destruct()
+            d = defaulter()
+            assert d.m_a == t(11)
+            assert d.m_b == t(22)
+            assert d.m_c == t(33)
+            d.destruct()
 
-        d = defaulter(0)
-        assert d.m_a ==  0
-        assert d.m_b == 22
-        assert d.m_c == 33
-        d.destruct()
+            d = defaulter(0)
+            assert d.m_a ==  t(0)
+            assert d.m_b == t(22)
+            assert d.m_c == t(33)
+            d.destruct()
 
-        d = defaulter(1, 2)
-        assert d.m_a ==  1
-        assert d.m_b ==  2
-        assert d.m_c == 33
-        d.destruct()
+            d = defaulter(1, 2)
+            assert d.m_a ==  t(1)
+            assert d.m_b ==  t(2)
+            assert d.m_c == t(33)
+            d.destruct()
 
-        d = defaulter(3, 4, 5)
-        assert d.m_a ==  3
-        assert d.m_b ==  4
-        assert d.m_c ==  5
-        d.destruct()
+            d = defaulter(3, 4, 5)
+            assert d.m_a ==  t(3)
+            assert d.m_b ==  t(4)
+            assert d.m_c ==  t(5)
+            d.destruct()
+        test_defaulter('short', int)
+        test_defaulter('ushort', int)
+        test_defaulter('int', int)
+        test_defaulter('uint', int)
+        test_defaulter('long', long)
+        test_defaulter('ulong', long)
+        test_defaulter('llong', long)
+        test_defaulter('ullong', long)
+        test_defaulter('float', float)
+        test_defaulter('double', float)
 
     def test02_simple_inheritance(self):
         """Test binding of a basic inheritance structure"""
diff --git a/pypy/module/cppyy/test/test_cppyy.py b/pypy/module/cppyy/test/test_cppyy.py
--- a/pypy/module/cppyy/test/test_cppyy.py
+++ b/pypy/module/cppyy/test/test_cppyy.py
@@ -26,7 +26,7 @@
         func, = adddouble.functions
         assert func.executor is None
         func._setup(None)     # creates executor
-        assert isinstance(func.executor, executor.DoubleExecutor)
+        assert isinstance(func.executor, executor._executors['double'])
         assert func.arg_defs == [("double", "")]
 
 
diff --git a/pypy/module/cppyy/test/test_stltypes.py b/pypy/module/cppyy/test/test_stltypes.py
--- a/pypy/module/cppyy/test/test_stltypes.py
+++ b/pypy/module/cppyy/test/test_stltypes.py
@@ -24,8 +24,8 @@
             import cppyy
             return cppyy.load_reflection_info(%r)""" % (test_dct, ))
 
-    def test01_builtin_type_vector_type(self):
-        """Test access to an std::vector<int>"""
+    def test01_builtin_type_vector_types(self):
+        """Test access to std::vector<int>/std::vector<double>"""
 
         import cppyy
 
@@ -34,46 +34,54 @@
 
         assert callable(cppyy.gbl.std.vector)
 
-        tv1 = getattr(cppyy.gbl.std, 'vector<int>')
-        tv2 = cppyy.gbl.std.vector('int')
+        tv1i = getattr(cppyy.gbl.std, 'vector<int>')
+        tv2i = cppyy.gbl.std.vector(int)
+        assert tv1i is tv2i
+        assert cppyy.gbl.std.vector(int).iterator is cppyy.gbl.std.vector('int').iterator
 
-        assert tv1 is tv2
-
-        assert cppyy.gbl.std.vector(int).iterator is cppyy.gbl.std.vector(int).iterator
+        tv1d = getattr(cppyy.gbl.std, 'vector<double>')
+        tv2d = cppyy.gbl.std.vector('double')
+        assert tv1d is tv2d
+        assert tv1d.iterator is cppyy.gbl.std.vector('double').iterator
 
         #-----
-        v = tv1(self.N)
-        assert v.begin().__eq__(v.begin())
-        assert v.begin() == v.begin()
-        assert v.end() == v.end()
-        assert v.begin() != v.end()
-        assert v.end() != v.begin()
+        vi = tv1i(self.N)
+        vd = tv1d(); vd += range(self.N)     # default args from Reflex are useless :/
+        def test_v(v):
+            assert v.begin().__eq__(v.begin())
+            assert v.begin() == v.begin()
+            assert v.end() == v.end()
+            assert v.begin() != v.end()
+            assert v.end() != v.begin()
+        test_v(vi)
+        test_v(vd)
 
         #-----
-        for i in range(self.N):
-            v[i] = i
-            assert v[i] == i
-            assert v.at(i) == i
-            pass
+        def test_v(v):
+            for i in range(self.N):
+                v[i] = i
+                assert v[i] == i
+                assert v.at(i) == i
 
-        assert v.size() == self.N
-        assert len(v) == self.N
-        v.destruct()
+            assert v.size() == self.N
+            assert len(v) == self.N
+        test_v(vi)
+        test_v(vd)
 
         #-----
-        v = tv1()
-        for i in range(self.N):
-            v.push_back(i)
-            assert v.size() == i+1
-            assert v.at(i) == i
-            assert v[i] == i
+        vi = tv1i()
+        vd = tv1d()
+        def test_v(v):
+            for i in range(self.N):
+                v.push_back(i)
+                assert v.size() == i+1
+                assert v.at(i) == i
+                assert v[i] == i
 
-        return
-
-        assert v.size() == self.N
-        assert len(v) == self.N
-        v.destruct()
-
+            assert v.size() == self.N
+            assert len(v) == self.N
+        test_v(vi)
+        test_v(vd)
 
     def test02_user_type_vector_type(self):
         """Test access to an std::vector<just_a_class>"""


More information about the pypy-commit mailing list