Save 37% off PRO during our Black Friday Sale! »

Debuggers in Lispy Languages

Debuggers in Lispy Languages

This talk is about a unique way in which debuggers can be written in language which are lisp like.
With CIDER debug as an example, this talk takes you through how this approach works under the hood.
This talk was presented at Functional Conf 2019.

8c77aec628699d23d793ba6990dee89c?s=128

Suvrat Apte

November 16, 2019
Tweet

Transcript

  1. Debuggers in Lisps Suvrat Apte (with Clojure) (Helpshift Inc)

  2. Outline • Why we need debuggers • Demo: Clojure debugging

    • How GDB works • REPL middleware • How cider-debug works • Limitations • Questions
  3. Debuggers • Examine state of programs as they run •

    Halt execution • Step through execution • Modify state at runtime • Change flow of execution
  4. cider-nrepl Demo Clojure debugging

  5. GDB - GNU Debugger • Debugger runs as a separate

    process • Spawns the target program as a child • Examines state with process tracing calls • Implementing breakpoints is a trick! • Puts invalid instructions on breakpoints • Processor traps OS • OS signals the process which caused it • It passes the signal to its parent (GDB) • GDB checks IP and breaks • Some processors support breakpoints GDB Target OS Processor
  6. GDB - GNU Debugger • Dependence on OS for process

    tracing • Dependence on OS for signals • Dependence on processors for interrupts GDB Target OS Processor
  7. Lisps • Lisp has minimal syntax • Code is data

    • Code itself is a valid AST • Debuggers can use code as data (map sq-root (filter even? numbers)) map sq-root filter numbers even?
  8. Clojure debugger f (x) = y Debugger (code) = debuggable

    code
  9. What is a REPL? Read-Eval-Print-Loop (defn repl [] (let [input

    (read) result (eval input)] (println result) (recur)))
  10. Read Eval Print Loop (REPL) REPL Prompt: "=> (+ 1

    2) "=> 3 "=> REPL client REPL server Operation: “eval” Code: (+ 1 2)
  11. Read Eval Print Loop (REPL) REPL client REPL server Operation:

    “eval” Result: 3 REPL Prompt: "=> (+ 1 2) "=> 3 "=>
  12. nREPL Middleware nREPL CIDER nREPL CIDER Middleware

  13. cider-nrepl •CIDER uses cider-nrepl middleware •A collection of nREPL middleware

    • complete • info • debug • More. . .
  14. cider-nrepl Demo Client-server messaging

  15. Form based coords Coor: (3 1 1 1) (defn math-operations

    [n1 n2] (let [addition (+ n1 n2) subtraction (- n1 n2) exp (power n1 n2)] {:addition addition :subtraction subtraction :exp exp}))
  16. Coor: (3 1 1 1) (defn math-operations [n1 n2] (let

    [addition (+ n1 n2) subtraction (- n1 n2) exp (power n1 n2)] {:addition addition :subtraction subtraction :exp exp})) 0 1 2 3 Form based coords
  17. Coor: (3 1 1 1) (defn math-operations [n1 n2] (let

    [addition (+ n1 n2) subtraction (- n1 n2) exp (power n1 n2)] {:addition addition :subtraction subtraction :exp exp})) 0 1 2 Form based coords
  18. Coor: (3 1 1 1) (defn math-operations [n1 n2] (let

    [addition (+ n1 n2) subtraction (- n1 n2) exp (power n1 n2)] {:addition addition :subtraction subtraction :exp exp})) 0 1 2 3 4 5 Form based coords
  19. Coor: (3 1 1 1) (defn math-operations [n1 n2] (let

    [addition (+ n1 n2) subtraction (- n1 n2) exp (power n1 n2)] {:addition addition :subtraction subtraction :exp exp})) 0 1 2 Form based coords
  20. That’s why you should use Emacs!

  21. How does it work? 1. Walk through code 1. Mark

    forms/symbols with coordinates 2. Expand macros 3. Walk through code 1. Wrap forms/symbols with pre-breakpoint macro 4. Pre-breakpoint macro expansion 1. Put a breakpoint if necessary When a function is marked for debugging
  22. How does it work? 1. Necessary information is sent to

    client 1. Coordinates 2. Return value at current position 3. Values of local vars 4. Possible actions 2. Waits for response from client. . . When a breakpoint is hit
  23. How does it work? 1. Walk through code 1. Mark

    forms/symbols with coordinates 2. Expand macros 3. Walk through code 1. Wrap forms/symbols with pre-breakpoint macro 4. Pre-breakpoint macro expansion 1. Put a breakpoint if necessary When a function is marked for debugging
  24. How does it work? • Simple eval • Reader macro:

    #dbg • cider.nrepl.middleware.util.instrument/walk-indexed • Assigns coordinates to forms recursively
  25. How does it work? 1. Walk through code 1. Mark

    forms/symbols with coordinates 2. Expand macros 3. Walk through code 1. Wrap forms/symbols with pre-breakpoint macro 4. Pre-breakpoint macro expansion 1. Put a breakpoint if necessary When a function is marked for debugging
  26. How does it work? 1. Walk through code 1. Mark

    forms/symbols with coordinates 2. Expand macros 3. Walk through code 1. Wrap forms/symbols with pre-breakpoint macro 4. Pre-breakpoint macro expansion 1. Put a breakpoint if necessary When a function is marked for debugging
  27. How does it work? 1. Walk through code 1. Mark

    forms/symbols with coordinates 2. Expand macros 3. Walk through code 1. Wrap forms/symbols with pre-breakpoint macro 4. Pre-breakpoint macro expansion 1. Put a breakpoint if necessary When a function is marked for debugging
  28. How does it work? 1. Necessary information is sent to

    client 1. Coordinates 2. Return value at current position 3. Values of local vars 4. Possible actions 2. Waits for response from client. . . When a breakpoint is hit
  29. How does it work? 1. Necessary information is sent to

    client 1. Coordinates 2. Return value at current position 3. Values of local vars 4. Possible actions 2. Waits for response from client. . . When a breakpoint is hit
  30. Clojure debugger f (x) = y Debugger (code) = debuggable

    code
  31. Clojure debugger f (x) = y Debugger (code) = debuggable

    code Clojure Clojure
  32. GDB - GNU Debugger f (p, q, r) = y

    Debugger (code, os, processor) = debuggable code C Assembly
  33. Limitations • Cannot instrument bytecode • Cannot go back in

    time • Cannot replay
  34. cider-debug • Debug.clj: 655 lines • Instrument.clj: 372 lines •

    The code is very readable!
  35. cider-debug • Bozhidar Batsov • Artur Malabara • Vitalie Spinu

    • Chris Perkins • Neil Okamoto • Michael Griffiths • Lars Anderson • Dominic Monroe Thank you!
  36. Lisp is similar to Chess. It will take only a

    day to learn the rules. But years to master ! - Harold Abelson