I agree about time-frame being a danger. "Always scale up, not down." So 
might do a solution based on our own, custom __cgetitem__ first, and 
then try to generalize *that* afterwards if there's time. (But I'll 
still prototype __getitem__ just to see).

The only problem is that __cgetitem__ requires conventional overloading, 
which I was *not* currently planning on doing; I intended this to be a 
more Pythonic alternative ("don't introduce features that's not in 
Python "just because we can" -- compile time duck typing is really just 
Python behaviour at compile-time, normal overloading means a control 
flow that cannot be had in Python).

Robert Bradshaw wrote:
> On May 24, 2008, at 1:03 PM, Dag Sverre Seljebotn wrote:
> 
>> Instantiation (1) of the function is symmetric to this, raising an
>> exception if control reaches the place where the integer is returned.
>>
>> So the end result is that the "int-return-type" instantiation of
>> get_something returns the proper, native C int when called with
>> as_str=False, and raises a coercion exception when called with  
>> as_str=True.
>>
>> [1] Even if this may seem hard to wrap ones head around, the end of  
>> the
>> story for the end-user is rather pleasing; one gets more or less the
>> same behaviour as if get_something was declared with an "object"  
>> return
>> type. It should natural to use. But no object coercion is involved for
>> the compiler, so speed is maintained.
> 
> Interesting idea, I think Haskell has something like this. It's like  
> type coercion going the opposite direction--one wants an int result  
> so it changes the expression itself (perhaps after passing through  
> several layers? How feasible is this?). I'd rather be a bit more  
> explicit (especially for ease of doing type inference for statements  
> like "x = arr[5]").

There's not any "magic" or unfeasability involved as far as I can see.

Full algorithm:

- When calling a function with one or more generic types (possibly 
return type!), look it up in an instantiation dict.

- If the dict lookup misses, instantiate the function like this: a) 
mangle name, b) insert the exact types that were used in the call (void 
for return type if it is discarded), c) the body is copied literally, 
except for return statements which are changed according to (*).

- If the copied body contains calls to functions with generic types, 
recurse.

(*) If the return type is not "generic", return statements are handled 
like normal. If the return type is "generic", any return statements:

- When the (actual, instantiated) return type ended up being void, 
evaluate expression but discard result (as the caller obviously discards 
the result). In this case, returning multiple different types will just 
work.

- When the actual, instantiated return type is T != void, then treat 
return statements like normal (i.e. if returning from a function with 
return type T), except for the cases where coercion fails, in which 
case, rather than giving a compile-time error, one evaluates expression, 
discards result, and inserts instructions to raise runtime exception.


> Essentially, what you really want is __getitem__ to return a variety  
> of types, determined at compile time, and without coercion through an  
> object. For inlined functions perhaps we could have a phase  
> automatically optimizing away <type><object>x where there is a direct  
> conversion from x to type (if the <object> wasn't explicitly  
> requested by the user).

That's what I was hoping to avoid by doing something *simpler*. As long 
as <object> coercion is not a perfect round-trip this can have 
unintended side-effects etc. etc. that I'd have to sort out, and the 
above seems much simpler and more elegant (to me).

-- 
Dag Sverre
_______________________________________________
Cython-dev mailing list
[email protected]
http://codespeak.net/mailman/listinfo/cython-dev

Reply via email to