[pypy-commit] pypy default: Import and pass the test about _Bool.

arigo noreply at buildbot.pypy.org
Thu Sep 13 18:40:47 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r57324:c5f0e18c0b8c
Date: 2012-09-13 18:40 +0200
http://bitbucket.org/pypy/pypy/changeset/c5f0e18c0b8c/

Log:	Import and pass the test about _Bool.

diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py
--- a/pypy/module/_cffi_backend/ctypeprim.py
+++ b/pypy/module/_cffi_backend/ctypeprim.py
@@ -52,19 +52,25 @@
         if (isinstance(ob, cdataobj.W_CData) and
                isinstance(ob.ctype, ctypeptr.W_CTypePtrOrArray)):
             value = rffi.cast(lltype.Signed, ob._cdata)
-            value = r_ulonglong(value)
+            value = self._cast_result(value)
         elif space.isinstance_w(w_ob, space.w_str):
             value = self.cast_str(w_ob)
-            value = r_ulonglong(value)
+            value = self._cast_result(value)
         elif space.isinstance_w(w_ob, space.w_unicode):
             value = self.cast_unicode(w_ob)
-            value = r_ulonglong(value)
+            value = self._cast_result(value)
         else:
-            value = misc.as_unsigned_long_long(space, w_ob, strict=False)
+            value = self._cast_generic(w_ob)
         w_cdata = cdataobj.W_CDataMem(space, self.size, self)
         w_cdata.write_raw_integer_data(value)
         return w_cdata
 
+    def _cast_result(self, intvalue):
+        return r_ulonglong(intvalue)
+
+    def _cast_generic(self, w_ob):
+        return misc.as_unsigned_long_long(self.space, w_ob, strict=False)
+
     def _overflow(self, w_ob):
         space = self.space
         s = space.str_w(space.str(w_ob))
@@ -203,8 +209,11 @@
         W_CTypePrimitive.__init__(self, *args)
         self.value_fits_long = self.size < rffi.sizeof(lltype.Signed)
         if self.size < rffi.sizeof(lltype.SignedLongLong):
-            sh = self.size * 8
-            self.vrangemax = (r_ulonglong(1) << sh) - 1
+            self.vrangemax = self._compute_vrange_max()
+
+    def _compute_vrange_max(self):
+        sh = self.size * 8
+        return (r_ulonglong(1) << sh) - 1
 
     def int(self, cdata):
         return self.convert_to_object(cdata)
@@ -231,6 +240,23 @@
         return self
 
 
+class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned):
+    _attrs_ = []
+
+    def _compute_vrange_max(self):
+        return r_ulonglong(1)
+
+    def _cast_result(self, intvalue):
+        return r_ulonglong(intvalue != 0)
+
+    def _cast_generic(self, w_ob):
+        return misc.object_as_bool(self.space, w_ob)
+
+    def string(self, cdataobj, maxlen):
+        # bypass the method 'string' implemented in W_CTypePrimitive
+        return W_CType.string(self, cdataobj, maxlen)
+
+
 class W_CTypePrimitiveFloat(W_CTypePrimitive):
     _attrs_ = []
 
diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py
--- a/pypy/module/_cffi_backend/misc.py
+++ b/pypy/module/_cffi_backend/misc.py
@@ -3,7 +3,9 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rlib.rarithmetic import r_ulonglong
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib import jit
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
 # ____________________________________________________________
 
@@ -181,6 +183,63 @@
 
 # ____________________________________________________________
 
+class _NotStandardObject(Exception):
+    pass
+
+def _standard_object_as_bool(space, w_ob):
+    if space.isinstance_w(w_ob, space.w_int):
+        return space.int_w(w_ob) != 0
+    if space.isinstance_w(w_ob, space.w_long):
+        return space.bigint_w(w_ob).tobool()
+    if space.isinstance_w(w_ob, space.w_float):
+        return space.float_w(w_ob) != 0.0
+    raise _NotStandardObject
+
+# hackish, but the most straightforward way to know if a LONGDOUBLE object
+# contains the value 0 or not.
+eci = ExternalCompilationInfo(post_include_bits=["""
+static bool_t pypy__is_nonnull_longdouble(long double x) {
+    return x != 0.0;
+}
+"""])
+is_nonnull_longdouble = rffi.llexternal(
+    "pypy__is_nonnull_longdouble", [rffi.LONGDOUBLE], lltype.Bool,
+    compilation_info=eci, _nowrapper=True, elidable_function=True,
+    sandboxsafe=True)
+
+def object_as_bool(space, w_ob):
+    # convert and cast a Python object to a boolean.  Accept an integer
+    # or a float object, up to a CData 'long double'.
+    try:
+        return _standard_object_as_bool(space, w_ob)
+    except _NotStandardObject:
+        pass
+    #
+    from pypy.module._cffi_backend.cdataobj import W_CData
+    from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveFloat
+    from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveLongDouble
+    ob = space.interpclass_w(w_ob)
+    is_cdata = isinstance(ob, W_CData)
+    if is_cdata and isinstance(ob.ctype, W_CTypePrimitiveFloat):
+        if isinstance(ob.ctype, W_CTypePrimitiveLongDouble):
+            result = is_nonnull_longdouble(read_raw_longdouble_data(ob._cdata))
+        else:
+            result = read_raw_float_data(ob._cdata, ob.ctype.size) != 0.0
+        keepalive_until_here(ob)
+        return result
+    #
+    if not is_cdata and space.lookup(w_ob, '__float__') is not None:
+        w_io = space.float(w_ob)
+    else:
+        w_io = space.int(w_ob)
+    try:
+        return _standard_object_as_bool(space, w_io)
+    except _NotStandardObject:
+        raise OperationError(space.w_TypeError,
+                             space.wrap("integer/float expected"))
+
+# ____________________________________________________________
+
 def _raw_memcopy(source, dest, size):
     if jit.isconstant(size):
         # for the JIT: first handle the case where 'size' is known to be
diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py
--- a/pypy/module/_cffi_backend/newtype.py
+++ b/pypy/module/_cffi_backend/newtype.py
@@ -38,6 +38,7 @@
 eptype("float",  rffi.FLOAT,  ctypeprim.W_CTypePrimitiveFloat)
 eptype("double", rffi.DOUBLE, ctypeprim.W_CTypePrimitiveFloat)
 eptype("long double", rffi.LONGDOUBLE, ctypeprim.W_CTypePrimitiveLongDouble)
+eptype("_Bool",  lltype.Bool,          ctypeprim.W_CTypePrimitiveBool)
 
 @unwrap_spec(name=str)
 def new_primitive_type(space, name):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -2085,3 +2085,33 @@
     BFloat = new_primitive_type("float")
     py.test.raises(TypeError, newp, BIntP, cast(BFloat, 0.0))
     py.test.raises(TypeError, newp, BUIntP, cast(BFloat, 0.0))
+
+def test_bool():
+    BBool = new_primitive_type("_Bool")
+    BBoolP = new_pointer_type(BBool)
+    assert int(cast(BBool, False)) == 0
+    assert int(cast(BBool, True)) == 1
+    assert bool(cast(BBool, False)) is True    # warning!
+    assert int(cast(BBool, 3)) == 1
+    assert int(cast(BBool, long(3))) == 1
+    assert int(cast(BBool, long(10)**4000)) == 1
+    assert int(cast(BBool, -0.1)) == 1
+    assert int(cast(BBool, -0.0)) == 0
+    assert int(cast(BBool, '\x00')) == 0
+    assert int(cast(BBool, '\xff')) == 1
+    assert newp(BBoolP, False)[0] == 0
+    assert newp(BBoolP, True)[0] == 1
+    assert newp(BBoolP, 0)[0] == 0
+    assert newp(BBoolP, 1)[0] == 1
+    py.test.raises(TypeError, newp, BBoolP, 1.0)
+    py.test.raises(TypeError, newp, BBoolP, '\x00')
+    py.test.raises(OverflowError, newp, BBoolP, 2)
+    py.test.raises(OverflowError, newp, BBoolP, -1)
+    BCharP = new_pointer_type(new_primitive_type("char"))
+    p = newp(BCharP, 'X')
+    q = cast(BBoolP, p)
+    assert q[0] == ord('X')
+    py.test.raises(TypeError, string, cast(BBool, False))
+    BDouble = new_primitive_type("double")
+    assert int(cast(BBool, cast(BDouble, 0.1))) == 1
+    assert int(cast(BBool, cast(BDouble, 0.0))) == 0


More information about the pypy-commit mailing list