Commit f99ecc90 authored by Mark Florisson's avatar Mark Florisson

Support casting and assignment of fused functions to specialized functions

parent a9b16e3b
...@@ -586,6 +586,17 @@ class ExprNode(Node): ...@@ -586,6 +586,17 @@ class ExprNode(Node):
dst_type = dst_type.ref_base_type dst_type = dst_type.ref_base_type
if src_type.is_fused or dst_type.is_fused: if src_type.is_fused or dst_type.is_fused:
# See if we are coercing a fused function to a pointer to a
# specialized function
if (src_type.is_cfunction and not dst_type.is_fused and
dst_type.is_ptr and dst_type.base_type.is_cfunction):
dst_type = dst_type.base_type
for signature in src_type.get_all_specific_function_types():
if signature.same_as(dst_type):
return CoerceFusedToSpecific(src, signature)
error(self.pos, "Type is not specific") error(self.pos, "Type is not specific")
self.type = error_type self.type = error_type
return self return self
...@@ -5577,6 +5588,9 @@ class TypecastNode(ExprNode): ...@@ -5577,6 +5588,9 @@ class TypecastNode(ExprNode):
self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True) self.operand = PyTypeTestNode(self.operand, self.type, env, notnone=True)
elif self.type.is_complex and self.operand.type.is_complex: elif self.type.is_complex and self.operand.type.is_complex:
self.operand = self.operand.coerce_to_simple(env) self.operand = self.operand.coerce_to_simple(env)
elif self.operand.type.is_fused:
self.operand = self.operand.coerce_to(self.type, env)
self.type = self.operand.type
def is_simple(self): def is_simple(self):
# either temp or a C cast => no side effects # either temp or a C cast => no side effects
...@@ -7294,6 +7308,18 @@ class CoercionNode(ExprNode): ...@@ -7294,6 +7308,18 @@ class CoercionNode(ExprNode):
file, line, col = self.pos file, line, col = self.pos
code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type))) code.annotate((file, line, col-1), AnnotationItem(style='coerce', tag='coerce', text='[%s] to [%s]' % (self.arg.type, self.type)))
class CoerceFusedToSpecific(CoercionNode):
def __init__(self, arg, dst_type):
super(CoerceFusedToSpecific, self).__init__(arg)
self.type = dst_type
self.specialized_cname = dst_type.entry.cname
def calculate_result_code(self):
return self.specialized_cname
def generate_result_code(self, code):
pass
class CastNode(CoercionNode): class CastNode(CoercionNode):
# Wrap a node in a C type cast. # Wrap a node in a C type cast.
......
...@@ -72,3 +72,10 @@ assert add_simple(myunion, 5.0).a == 10.0 ...@@ -72,3 +72,10 @@ assert add_simple(myunion, 5.0).a == 10.0
assert add_to_simple(mystruct, 5.0) == 10.0 assert add_to_simple(mystruct, 5.0) == 10.0
assert add_to_simple(myunion, b"spamhameggs") == b"ameggs" assert add_to_simple(myunion, b"spamhameggs") == b"ameggs"
assert add_to_simple(myext, 5) == 10 assert add_to_simple(myext, 5) == 10
cdef mystruct_t (*f)(mystruct_t, int)
f = add_simple
assert f(mystruct, 5).a == 10
f = <mystruct_t (*)(mystruct_t, int)> add_simple
assert f(mystruct, 5).a == 10
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment