Writing a Lisp: Debugger
To make debugging easier, I added a simple
pry-style debugger to my lisp.
It immediately spawns a new repl in the current envirment, allowing you to poke around at will.
Debug repl’s can be nested to arbitrary depth, and exited with
lisp=> (define (dbg-test x) (debug)) dbg-test lisp=> (dbg-test 10) debug=> x 10 debug=> :q nil lisp=>
Implementation was shockingly trivial once again.
debug is implemented as a special form, because the
repl function isn’t available in lisp code yet.
eval env val = case val of -- ... List [Symbol "debug"] -> do liftIO $ repl "debug=> " $ evalString env return Nil -- ...
I extracted the repl’s code into a separate Hackage package, because I often encounter the need for them in my projects. Idris includes a readline-like repl function in Prelude, which inspired me. A utility for printing text red is included as well.
repl prompt f = runInputT defaultSettings loop where loop = do line <- getInputLine prompt case line of Nothing -> return () Just ":q" -> return () Just input -> do liftIO $ f input loop printError err = do setSGR [SetColor Foreground Vivid Red] print err setSGR [Reset]
After yesterday’s post Max Bernstein notified me of his ‘Writing a Lisp’ series in OCaml. It was interesting to compare the ideas and implementation, so I’m sharing it here.
I’ll be investigating reader macro’s soon. If you have any suggestions for features or improvements, please don’t hesitate to let me know.