The most difficult part of this is not the transformation- it's determining under which cases those steps are actually valid. When the tail-recursive call uses keyword arguments or varargs (*) or kwargs (**), for example, it's trickier to come up with valid bytecode to correctly reinitialize the function. Default arguments cause another problem, since a code object has no way of knowing which default arguments are attached to it in a containing function object.
So the current requirements for taking advantage of Noodle's tail call optimization are thus:
- Tail call must be at the end of the function, in addition to being in a tail position (this restriction is expected to go away at some point)
- Tail call must be to the current function, by the same name
- Tail call must give arguments for all positional parameters and all default parameters, in order, and must not give any keyword arguments, varargs, or kwargs.
When you're writing a recursive function, these restrictions should in general be rather simple to get around.
I don't expect Noodle will be able to support any further tail call optimization, since Python bytecode is currently incapable of jumping between code objects. Jumping can only be done to elsewhere in the current code object.

1 comments:
Okay, the restriction on the tail call being at the end of the function is now gone. The first tail-call optimization implementation was a bit silly, and it's much better now.
Post a Comment