3 ms·
It is straightforward to provide the type of stack trace information people want for debugging in the presence of tail call elimination (not optimization ;) ) h
by thinkmoore 11y ago
It is straightforward to provide the type of stack trace information people want for debugging in the presence of tail call elimination (not optimization ;) )
http://www.brinckerhoff.org/clements/papers/cf-toplas04.pdf http://www.brinckerhoff.org/clements/papers/cf-toplas04.pdf
You can even try it out in Racket.
Edit: to clarify, my parenthetical was meant to say tail call optimization is not an optimization but a matter of correctness (so best to call it elimination instead), not to make a distinction between the two.
Also, that isn't quite the right paper but I don't have time to find the one I meant right now...
- ridiculous_fish 11y agoHow does it work? There have been bugs I could not diagnose because the caller was optimized out in the stack trace. I took a look at the paper. It's very dense but seems to be a technique for annotating stack frames with permissions? That sounds interesting but is no help for debugging.
- thinkmoore 11y agoYes, the paper is about showing that you can do the equivalent of annotating stack frames for security in a language with tail calls. The same ideas work debugging though. Basically, the key idea is that you can manage the debugging information yourself. So for simple tail recursion, you can have the first call push a marker on the stack and subsequent calls update a count on the marker (if you care about the depth). For more complicated interactions, you can record whatever debugging information you need, even a full stack by associating the information with a cell under the top-most stack frame. (Of course, this debugging information may grow with the depth of recursion, depending on whether you try to keep the full stack or not, but will still be more space efficient than keeping around all of the stack frames.) The main point is that keeping track of your execution context doesn't have to be done by walking the call stack, you just need to have a protocol for maintaining whatever state you want on entry/exit.