On Fri, Oct 30, 2009 at 3:19 PM, Stefan Monnier <address@hidden>
> I have started to rewrite gud from the ground up.
That's interesting. I hope you will start with the assumption that
there are several active GUD sessions (each using potentially different
debuggers for different languages). It's a kind of change that's
difficult to make after the fact, but that's fairly easy to build-in
from the beginning.
Yep. It has been annoying to me as well. And what makes this deja vu is that some of the same problems in gud, you typically find in debuggers in general: they too assume that there is just one debugger, install one trace hook without bothering to care about others that might be set. (In some systems, profiling and debugging share the same trace hook mechanism). And too often the debuggers are also monolithic like gud, poorly understood, and badly maintained.
As a small small example of how both miss the mark in about the same way from opposite ends, debuggers often refer to a breakpoint location in terms of a line in a file. This is inadequate given that several statements can span a line (especially in functional programs). An in the presence of optimization, statements may get distributed in the code and moved around with respect to the order that they appear in the source. For the VM-based programming language debugger I am working on, I am experimenting with making breakpoint be a particular VM instruction; you then have other tables that tell you how to map that from/to a source language position. A position might include ranges of lines with column offset(s) and how to map the instruction to a "file" which might not be a file in a filesystem at all but could be a string variable which got eval'ed or a member of some sort of code package.
As for gud, it uses this global variable "gud-last-frame' -- actually pair of variables if you include gud-last-last-frame. And what's in that lofty sounding "frame" thing? A cons node of a file name and a line number. But emacs has had since day one this wonderful object called a "marker". And as one edits text, markers move around. From the marker you can get the buffer, and file name (if any) and its line number, or better, a column for those systems like LLVM which support better position information. And from day one LISP has had lists, so why the global two variable thing? Right now I use this other data structure in emacs called a ring to store a sequence of locations. So when I am stopped I can just go back in history to the last n positions that I've stopped on.
In general I'm going to try to remove as many of the global variables as possible in favor of buffer-local variables. And I'll assume Emacs 23 which has structs, hash tables, rings, common lisp features and whatever newer greater functions and packages that are commonly distributed in Emacs 23.
But here are things in particular to address the problem you mention which stems partly from globalness. There will be process buffer(s) which interacts with some sort of debugger(s) outside of Emacs. These will have buffer-local variables which contain some of the state information that in gud is stored globally. However the source buffers that are referred to by the debugger(s), need a buffer-local object which refers back to all of the debugger process buffers that the source buffer currently "belongs" to.
In an earlier work that Anders Lindgren and I did (but really it was mostly Anders), there were temporary buffers that contained collections: call stack information, breakpoint information, local variable information. I may eventually get to that stage, but for the first cut I think I will try to work with just the debugger process buffer(s) and a little bit of information in the "source" buffers which the debuggers refer to.
> 1. I can stick with comint.el. It seems the most creaky.
> 2. term.el is pretty cool, but it doesn't provide a hook to run when
> output is produced and this is something I need. I use it both in
> comint.el and eshell.el in "shell tracker" (think pdb-track) mode. So
> this leads to the last choice ...
In order to make a choice, I think we need to know what problems we're
trying to address.
Perhaps some of this is addressed above.
I think of this as the same situation as comes up in any Emacs package that interacts with some sort of process or remote process. For example TeXing a buffer, perhaps compiling a file, or getting a directory listing. Where I guess it is a little bit different is those things one largely thinks of as batch jobs: you run something, get some output and that's it or maybe iterate some more. Perhaps dired is a little bit different here.
Here there is more interaction between the back-end and front-end process. But surely there must be other packages that have this back-and-forth interactive feel to it too.
If this doesn't answer the question, please ask another more detailed question.