init_builtin_types()
init_builtin_structs()
global list_type, tuple_type, dict_type, set_type, type_type
- global bytes_type, str_type, unicode_type
+ global bytes_type, str_type, unicode_type, float_type
type_type = builtin_scope.lookup('type').type
list_type = builtin_scope.lookup('list').type
tuple_type = builtin_scope.lookup('tuple').type
bytes_type = builtin_scope.lookup('bytes').type
str_type = builtin_scope.lookup('str').type
unicode_type = builtin_scope.lookup('unicode').type
+ float_type = builtin_scope.lookup('float').type
init_builtins()
if result_type.is_extension_type:
return result_type
elif result_type.is_builtin_type:
- if function.entry.name in Builtin.types_that_construct_their_instance:
+ if function.entry.name == 'float':
+ return PyrexTypes.c_double_type
+ elif function.entry.name in Builtin.types_that_construct_their_instance:
return result_type
return py_object_type
self.arg_tuple = TupleNode(self.pos, args = self.args)
self.arg_tuple.analyse_types(env)
self.args = None
- if function.is_name and function.type_entry:
+ if func_type is Builtin.type_type and function.entry.is_builtin and \
+ function.entry.name in Builtin.types_that_construct_their_instance:
+ # calling a builtin type that returns a specific object type
+ if function.entry.name == 'float':
+ # the following will come true later on in a transform
+ self.type = PyrexTypes.c_double_type
+ self.result_ctype = PyrexTypes.c_double_type
+ else:
+ self.type = Builtin.builtin_types[function.entry.name]
+ self.result_ctype = py_object_type
+ elif function.is_name and function.type_entry:
# We are calling an extension type constructor. As
# long as we do not support __new__(), the result type
# is clear
return type1
elif type1.is_numeric and type2.is_numeric:
return widest_numeric_type(type1, type2)
+ elif type1.is_builtin_type and type1.name == 'float' and type2.is_numeric:
+ return widest_numeric_type(c_double_type, type2)
+ elif type2.is_builtin_type and type2.name == 'float' and type1.is_numeric:
+ return widest_numeric_type(type1, c_double_type)
elif type1.is_pyobject ^ type2.is_pyobject:
return py_object_type
elif type1.assignable_from(type2):
entry.type = py_object_type
def find_safe_type(result_type, which_types_to_infer):
+ if which_types_to_infer == 'none':
+ return py_object_type
+
+ if result_type in (PyrexTypes.c_double_type, PyrexTypes.c_float_type, Builtin.float_type):
+ # Python's float type is just a C double, so it's safe to
+ # use the C type instead
+ return PyrexTypes.c_double_type
+
if which_types_to_infer == 'all':
return result_type
elif which_types_to_infer == 'safe':
if result_type.is_pyobject:
# any specific Python type is always safe to infer
return result_type
- elif result_type in (PyrexTypes.c_double_type, PyrexTypes.c_float_type):
- # Python's float type is just a C double, so it's safe to
- # use the C type instead
- return PyrexTypes.c_double_type
elif result_type is PyrexTypes.c_bint_type:
# 'bint' should behave exactly like Python's bool type ...
return PyrexTypes.c_bint_type
cdef Py_ssize_t r = int(x)
return r
-@cython.test_assert_path_exists("//SingleAssignmentNode/CastNode")
-@cython.test_fail_if_path_exists("//SimpleCallNode")
-def double_to_pyssizet_float(double x):
- """
- >>> double_to_pyssizet_float(4.1)
- 4
- >>> double_to_pyssizet_float(4)
- 4
- """
- cdef Py_ssize_t r = float(x)
- return r
+## @cython.test_assert_path_exists("//SingleAssignmentNode/CastNode")
+## @cython.test_fail_if_path_exists("//SimpleCallNode")
+## def double_to_pyssizet_float(double x):
+## """
+## >>> double_to_pyssizet_float(4.1)
+## 4
+## >>> double_to_pyssizet_float(4)
+## 4
+## """
+## cdef Py_ssize_t r = float(x)
+## return r
@cython.test_assert_path_exists("//SingleAssignmentNode/CastNode")
@cython.test_fail_if_path_exists("//SimpleCallNode")
cdef double r = int(x)
return r
-@cython.test_fail_if_path_exists("//SimpleCallNode",
- "//SingleAssignmentNode/CastNode")
+@cython.test_fail_if_path_exists("//SimpleCallNode")
def float_to_float_float(float x):
"""
>>> 4.05 < float_to_float_float(4.1) < 4.15
assert typeof(a) == "long"
+@infer_types('safe')
+def double_inference():
+ """
+ >>> values, types = double_inference()
+ >>> values == (1.0, 1.0*2, 1.0*2.0+2.0*2.0, 1.0*2.0)
+ True
+ >>> types
+ ('double', 'double', 'double', 'Python object')
+ """
+ d_a = 1.0
+ d_b = d_a * float(2)
+ d_c = d_a * float(some_float_value()) + d_b * float(some_float_value())
+ o_d = d_a * some_float_value()
+ return (d_a,d_b,d_c,o_d), (typeof(d_a), typeof(d_b), typeof(d_c), typeof(o_d))
+
+cdef object some_float_value():
+ return 2.0
+
+
@cython.test_fail_if_path_exists('//NameNode[@type.is_pyobject = True]')
@cython.test_assert_path_exists('//InPlaceAssignmentNode/NameNode',
'//NameNode[@type.is_pyobject]',