Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

Outline • Why we need debuggers • Demo: Clojure debugging • How GDB works • REPL middleware • How cider-debug works • Limitations • Questions

Slide 3

Slide 3 text

Debuggers • Examine state of programs as they run • Halt execution • Step through execution • Modify state at runtime • Change flow of execution

Slide 4

Slide 4 text

cider-nrepl Demo Clojure debugging

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

GDB - GNU Debugger • Dependence on OS for process tracing • Dependence on OS for signals • Dependence on processors for interrupts GDB Target OS Processor

Slide 7

Slide 7 text

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?

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

What is a REPL? Read-Eval-Print-Loop (defn repl [] (let [input (read) result (eval input)] (println result) (recur)))

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

nREPL Middleware nREPL CIDER nREPL CIDER Middleware

Slide 13

Slide 13 text

cider-nrepl •CIDER uses cider-nrepl middleware •A collection of nREPL middleware • complete • info • debug • More. . .

Slide 14

Slide 14 text

cider-nrepl Demo Client-server messaging

Slide 15

Slide 15 text

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}))

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

That’s why you should use Emacs!

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

How does it work? • Simple eval • Reader macro: #dbg • cider.nrepl.middleware.util.instrument/walk-indexed • Assigns coordinates to forms recursively

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

GDB - GNU Debugger f (p, q, r) = y Debugger (code, os, processor) = debuggable code C Assembly

Slide 33

Slide 33 text

Limitations • Cannot instrument bytecode • Cannot go back in time • Cannot replay

Slide 34

Slide 34 text

cider-debug • Debug.clj: 655 lines • Instrument.clj: 372 lines • The code is very readable!

Slide 35

Slide 35 text

cider-debug • Bozhidar Batsov • Artur Malabara • Vitalie Spinu • Chris Perkins • Neil Okamoto • Michael Griffiths • Lars Anderson • Dominic Monroe Thank you!

Slide 36

Slide 36 text

Lisp is similar to Chess. It will take only a day to learn the rules. But years to master ! - Harold Abelson