use an environment holding the Slime I/O connection
Rather than having a bare io argument everywhere, encapsulate it in an
environment. (An environment is just about the only thing I can find
in R that isn't copy-on-write; this isn't helpful for the i/o
connection, but will be once we start implementing inspectors and
presentations...)
implement swank:interactive-eval and swank:eval-and-grab-output
This allows C-c : and C-u C-c : to work, modulo the printing of an
unnecessary [1]. The evaluation semantics of R are not what a Lisper might
expect; printToString(eval(parse(...))) does not necessarily perform the
evaluation before altering the output stream with sink() -- so capturing
all sorts of incidental output if something goes wrong.
Implement swank:frame-locals-and-catch-tags. There are problems:
1. it seems that some names can be present in an environment but not have
a value, causing eval to blow up;
2. the default printing routines aren't really adapted to the constraints
of rendering in sldb;
3. trying to display locals of some of the swank frames (perhaps anything
with a tryCatch or similar block?) causes R to complain about a promise
already in the process of evaluation;
4. (probably) other things I haven't yet found
Rather than do complicated stuff to keep track of where we are in the
stack, simply store the interesting frames and calls in the sldb state
structure.
R doesn't have much in the way of dynamic binding; you can fake it by
messing with environments, but that's not fun.
So instead, pass around the connection (`io') and an object
representing the SLDB state (`sldbState') to all functions.
Poor-man's explicit continuation-passing-style...
We need to call some of the mainLoop internal functions from elsewhere
now, so make them not-internal any more.
Fix ridiculous thinko in the logical branch of writeSexpToString
use simpleCondition rather than simpleError in swank:throw-to-toplevel
implement swank:debugger-info-for-emacs
Now `q' in sldb (sldb-quit) works. Things that don't work:
1. the backtrace is the wrong way up.
2. calling any restarts
3. frame locals
4. returning from frames (dunno if R actually supports this)
5. zoom to source
6. probably other things
We get far enough to start up a swank server in R and connect to it from
emacs; we get a REPL which formats the R-style results from parsing and
evaluating the input it receives. Debugging, stepping, documentation,
arglist and so on is basically entirely missing.