On 9 February 2013 23:56, Stefan Behnel <stefan...@behnel.de> wrote: > mark florisson, 10.02.2013 03:25: >> On 9 February 2013 03:44, Stefan Behnel <stefan...@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?
It sounds this approach might be cleaner than catching this in a global coercion, but on the other hand you want full generality. For instance, there is also the cast syntax that can specialize a function. Or I might have a pointer to a known fused function or method, that I want to deference and specialize. Maybe we need a nicer way to deal with and register coercions, and with what an assignment expects and a value generates. A lot of assignment code seems similar but slightly different in tricky ways. > Stefan > > _______________________________________________ > cython-devel mailing list > cython-devel@python.org > http://mail.python.org/mailman/listinfo/cython-devel _______________________________________________ cython-devel mailing list cython-devel@python.org http://mail.python.org/mailman/listinfo/cython-devel