[racket] Racket non-gui debugger

From: John Clements (clements at brinckerhoff.org)
Date: Wed May 29 13:17:25 EDT 2013

On May 28, 2013, at 7:00 AM, Piotr Klibert wrote:

> Hello,
> 
> I like an idea of setting breakpoint and when it is reached during runtime dropping into the interactive shell. It's done in Python with pdb and in one of the Schemes (Gambit?). I tried, but I couldn't make anything similar for Racket.
> 
> At first I looked at namespaces and (read-eval-print-loop), but that didn't work. I could "load" the top-level module namespace, but I couldn't hook into the namespace inside the function (if it even exists as a namespace).
> 
> Then I tried to look inside the GUI debugger, and I realized that it uses a macro which inserts some function call before and after every expression. The debugger code was too hard for me to comprehend fully and I couldn't make it work the way I wanted, too.
> 
> It was some time ago, so sorry for the lack of specifics, but my question is: is it possible, and how, to do something like this in Racket:
> 
>     (define (fun)
>       (define a 9)
>       (define b '(a b c))
>       (let
>           ([d display])
>         (set-trace))
>       (displayln "We're here!"))
> 
>     (fun) ;; starts repl, where
> 
>     > a
>     9
>     >(d b)
>     (a b c)> (continue)
>     We're here!


Yep, you can definitely do this. 

To show this, I've just built a simple proof-of-concept command-line debugger; it's barely functional (NPI), but there shouldn't be any huge conceptual hurdles (and I don't have time to spend more time on it right now (unless I get a lot of interest :))).

I've pushed "command-line-debugger-example.rkt" in the stepper collection to the plt repo. As an alternative to compiling the whole tree (or waiting for a nightly build), I've also created a gist:

https://gist.github.com/jbclements/5671991

You can copy this file into the "collects/stepper" directory.

Here's an example of using it (this example also appears in the file itself):

Put the following code in /tmp/foo.rkt:

#lang racket

(define (f x) (+ x 14))

(f 9)

Then, you might run it from the command line like this:

jclements-09740:~/plt/collects/stepper clements> racket
Welcome to Racket v5.3.4.7.
> (require "command-line-debugger-example.rkt")
> (run-program "/tmp/foo.rkt")
> *ding* a new step has arrived:
'#s(step #f expr-finished-break ((#<procedure:...ate/annotate.rkt:1061:62> #f #<procedure>)))
(srcloc)
step-srcloc: no source contexts in this step
  context...:
   /Users/clements/plt/collects/racket/private/misc.rkt:87:7
> (continue)
> *ding* a new step has arrived:
'#s(step (#<procedure> #<procedure> #<procedure>) normal-break #f)
(srcloc)
#<syntax:5:1 f>
> (continue)
> *ding* a new step has arrived:
'#s(step (#<procedure> #<procedure> #<procedure>) result-value-break (#<procedure>))
(srcloc)
#<syntax:5:1 f>
> (continue)
> *ding* a new step has arrived:
'#s(step (#<procedure> #<procedure>) normal-break #f)
(srcloc)
#<syntax:5:0 (#%app f (quote 9))>
> (exit)

Note that while I spent the five minutes required to extract some semblance of source locations, I have not spent the additional five minutes required to expose variable bindings… I'd be happy to do this, if people are actually interested in it.

Best,

John 



Posted on the users mailing list.