[Cython] How does a fused function differ from an overloaded function?

Stefan Behnel stefan_ml at behnel.de
Sun Feb 10 06:56:04 CET 2013


mark florisson, 10.02.2013 03:25:
> On 9 February 2013 03:44, Stefan Behnel <stefan_ml at behnel.de> wrote:
>> Hi,
>>
>> I noticed that Cython currently fails to do this:
>>
>>    cdef int (*int_abs)(int x)
>>    cdef object py_abs
>>    py_abs = int_abs = abs
>>
>> Here, abs() is an overloaded function with a couple of C signatures (fabs()
>> and friends) and a Python signature (the builtin). While there is code in
>> NameNode.coerce_to() that figures out that the RHS can be replaced by the
>> Python builtin, the same is lacking for the general case of overloaded entries.
>>
>> While working on fixing this problem (and after turning ProxyNode into an
>> actual node proxy when it comes to coercion), I thought it would be a good
>> idea to make NameNode generally aware of alternative entries and just build
>> a new NameNode with the right entry in its coerce_to() method. Then I
>> noticed that the generic coerce_to() contains this code:
>>
>>     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_specialized_function_types():
>>                 if signature.same_as(dst_type):
>>                     src.type = signature
>>                     src.entry = src.type.entry
>>                     src.entry.used = True
>>                     return self
>>
>> This is essentially the same idea, just done a bit differently (with the
>> drawback that it modifies the node in place, which coerce_to() must *never*
>> do).
>>
>> So, two questions:
>>
>> 1) why is the above code in the generic coerce_to() method and not in
>> NameNode? It doesn't seem to do anything sensible for most other nodes,
>> potentially not even AttributeNode. And it might fail silently when working
>> on things like CloneNode that don't care about entries. Are there other
>> nodes where it does what it should?
> 
> I think it works for names and attributes, it allows you to retrieve a
> specialized version of the fused c(p)def functions and methods.

That's what I figured. I might have to take a look at AttributeNode a bit
more to see if it really does the right thing in all cases.

I would like to avoid having this in the generic coerce_to() method because
if it's anything but a NameNode or AttributeNode, it can only have one type
(unless I'm missing something), so coercion to different signatures won't
be possible anyway. And I wouldn't mind letting the above two nodes share a
bit more code, in one way or another.

I also think that the idea of having a ProxyNode for reuse was quite right.
I've started playing with it a little to let it support coercion
delegation, i.e. it would have it's own coerce_to() method that builds
CloneNodes at need and coerces either directly its argument or the
CloneNode to the target type, depending on is_simple() and maybe other
criteria.


>> 2) couldn't fused functions be mapped to a set of overloaded functions
>> (read: entries) before hand, instead of special casing both in places like
>> this?
> 
> Quite possibly, although I'd have to dig in the codebase some more to
> verify that. You can give it a try, it'd be nice to unify the
> approaches under the same model.

What I would like to see, eventually, is that NameNode basically just looks
up its entry on type analysis (including all overloaded entries), and then
whatever uses the node (to call or assign it) would pass in the right
signature/type into its coerce_to() method, which would then select the
right entry and return a new NameNode for it (or fail if the signature
can't be matched to any entry).

AttributeNode would essentially do the same thing, just return either an
AttributeNode or a NameNode on type analysis and/or coercion, depending on
what entry it finds (and if more than one).

Does this sound like it could work for fused types?

Stefan



More information about the cython-devel mailing list