Author: Philip Jenvey <[email protected]>
Branch: length-hint
Changeset: r57333:a3aafe08dbf0
Date: 2012-09-13 13:39 -0700
http://bitbucket.org/pypy/pypy/changeset/a3aafe08dbf0/
Log: merge default
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -834,7 +834,8 @@
return isinstance(obj, RequiredClass)
def unpackiterable(self, w_iterable, expected_length=-1):
- """Unpack an iterable object into a real (interpreter-level) list.
+ """Unpack an iterable into a real (interpreter-level) list.
+
Raise an OperationError(w_ValueError) if the length is wrong."""
w_iterator = self.iter(w_iterable)
if expected_length == -1:
@@ -854,12 +855,10 @@
def iteriterable(self, w_iterable):
return W_InterpIterable(self, w_iterable)
- @jit.dont_look_inside
def _unpackiterable_unknown_length(self, w_iterator, w_iterable):
- # Unpack a variable-size list of unknown length.
- # The JIT does not look inside this function because it
- # contains a loop (made explicit with the decorator above).
- #
+ """Unpack an iterable of unknown length into an interp-level
+ list.
+ """
# If we can guess the expected length we can preallocate.
from pypy.objspace.std.iterobject import length_hint
try:
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
# ____________________________________________________________
@@ -121,6 +123,14 @@
# ____________________________________________________________
+def _is_a_float(space, w_ob):
+ from pypy.module._cffi_backend.cdataobj import W_CData
+ from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveFloat
+ ob = space.interpclass_w(w_ob)
+ if isinstance(ob, W_CData):
+ return isinstance(ob.ctype, W_CTypePrimitiveFloat)
+ return space.isinstance_w(w_ob, space.w_float)
+
def as_long_long(space, w_ob):
# (possibly) convert and cast a Python object to a long long.
# This version accepts a Python int too, and does convertions from
@@ -132,7 +142,7 @@
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
- if space.isinstance_w(w_ob, space.w_float):
+ if _is_a_float(space, w_ob):
raise
bigint = space.bigint_w(space.int(w_ob))
try:
@@ -155,7 +165,7 @@
except OperationError, e:
if not e.match(space, space.w_TypeError):
raise
- if strict and space.isinstance_w(w_ob, space.w_float):
+ if strict and _is_a_float(space, w_ob):
raise
bigint = space.bigint_w(space.int(w_ob))
if strict:
@@ -173,6 +183,61 @@
# ____________________________________________________________
+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=["""
+#define pypy__is_nonnull_longdouble(x) ((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
@@ -2076,3 +2076,42 @@
assert not isinstance(nullchr, CType)
assert not isinstance(chrref, CType)
assert isinstance(BChar, CType)
+
+def test_no_cdata_float():
+ BInt = new_primitive_type("int")
+ BIntP = new_pointer_type(BInt)
+ BUInt = new_primitive_type("unsigned int")
+ BUIntP = new_pointer_type(BUInt)
+ 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
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit