> It's very easy to unwind the stack a few places, then resume execution
That's what some Lisp systems do, too.
> The debugger would execute the code in the context in which it was evaluated, so this could be absolutely awesome
That's what Lisp debuggers would do, too.
> launch into an exception, then fill in everything in the debugger until the system was complete.
That's actually an old story about Marvin Minsky:
---
Here's an anecdote I heard once about Minsky. He was showing a
student how to use ITS to write a program. ITS was an unusual
operating system in that the `shell' was the DDT debugger. You ran
programs by loading them into memory and jumping to the entry point.
But you can also just start writing assembly code directly into memory
from the DDT prompt. Minsky started with the null program.
Obviously, it needs an entry point, so he defined a label for that.
He then told the debugger to jump to that label. This immediately
raised an error of there being no code at the jump target. So he
wrote a few lines of code and restarted the jump instruction. This
time it succeeded and the first few instructions were executed. When
the debugger again halted, he looked at the register contents and
wrote a few more lines. Again proceeding from where he left off he
watched the program run the few more instructions. He developed the
entire program by `debugging' the null program.
---
One of the main debugging differences between Lisp and Smalltalk though is that Lisp systems often can run interpreted Lisp code (where Smalltalk runs bytecode) and then the debugger can see and change the actual source code while it is running. A Lisp Interpreter runs of Lisp source code - which still is data, since in Lisp source = structured data.
Useful Lisp debugging experiences existed as early as late 60s / early 70s in BBN Lisp.
That's what some Lisp systems do, too.
> The debugger would execute the code in the context in which it was evaluated, so this could be absolutely awesome
That's what Lisp debuggers would do, too.
> launch into an exception, then fill in everything in the debugger until the system was complete.
That's actually an old story about Marvin Minsky:
--- Here's an anecdote I heard once about Minsky. He was showing a student how to use ITS to write a program. ITS was an unusual operating system in that the `shell' was the DDT debugger. You ran programs by loading them into memory and jumping to the entry point. But you can also just start writing assembly code directly into memory from the DDT prompt. Minsky started with the null program. Obviously, it needs an entry point, so he defined a label for that. He then told the debugger to jump to that label. This immediately raised an error of there being no code at the jump target. So he wrote a few lines of code and restarted the jump instruction. This time it succeeded and the first few instructions were executed. When the debugger again halted, he looked at the register contents and wrote a few more lines. Again proceeding from where he left off he watched the program run the few more instructions. He developed the entire program by `debugging' the null program. ---
One of the main debugging differences between Lisp and Smalltalk though is that Lisp systems often can run interpreted Lisp code (where Smalltalk runs bytecode) and then the debugger can see and change the actual source code while it is running. A Lisp Interpreter runs of Lisp source code - which still is data, since in Lisp source = structured data.
Useful Lisp debugging experiences existed as early as late 60s / early 70s in BBN Lisp.
http://www.bitsavers.org/pdf/bbn/tenex/TenexLispRef_Aug72.pd...
The BBN Lisp development then moved to Xerox PARC and was renamed to Xerox Interlisp.