On Nov 11, 2004, at 9:44 AM, Michael Walter wrote:

On Thu, 11 Nov 2004 12:30:16 -0500, Dan Sugalski <[EMAIL PROTECTED]> wrote:
Tail calls should be explicit, compile-time things. Otherwise we're
going to run afoul of traceback requirements and suchlike things

Nah, that's just the difference between running optimized and unoptimized. Actually, with a tailcall op that's effectively a hint, it would be ideal to have 3 run modes: a "just obey the hints" mode (for those that trust their compiler), a "never do a tail call" mode (for debugging purposes), and a "do tail calls whenever possible" mode (independent of whether the tailcall op was used). Not sure if those are run modes or assembler (optimizer) modes, though.


Besides, it's a
lot easier in general for a language compiler to decide when a tail
call's in order than it is for us.

I think it's pretty straightforward to tell, at least at the PIR level. Even at the pasm level, the only requirement is that there's effectively no code between a call from foo to bar, and a return from foo. It's a pure optimization--good fodder for an optimizer.


Even further, it's necessary for some languages
(Scheme)/paradigms (loop by recursion) that a "tailcall" is not just a
hint but mandatory.

I think that actually doesn't matter. Even in the case where we think we can't do a full tail call optimization (because of a continuation that's been taken), we can still actually remove the calling frame from the call stack--we just can't immediately re-use the register frame. That satisfies the Scheme requirement, I would think. You can still do unbounded recursion, just that GC may need to run to clean up call frames.


Leo said:

$ time parrot  -j fact.imc 10000                  # [1]
maximum recursion depth exceeded

I'd think that long-term our max recursion depth limit should only apply to net frame depth--tail calls shouldn't increase the count. (Probably we'd need 2 counts--net depth and logical depth.)


JEff



Reply via email to