File: command-line-debugger-example.rkt

package info (click to toggle)
racket 7.2%2Bdfsg1-2
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 125,432 kB
  • sloc: ansic: 258,980; pascal: 59,975; sh: 33,650; asm: 13,558; lisp: 7,124; makefile: 3,329; cpp: 2,889; exp: 499; python: 274; xml: 11
file content (94 lines) | stat: -rw-r--r-- 2,819 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#lang racket

;; this file shows how you might build a command-line debugger. It doesn't provide much in
;; the way of convenience functions....

(provide (contract-out [run-program (-> path-string? void?)]
                       [continue (-> void?)]
                       [this-step (or/c false? step?)]
                       [srcloc (-> any)])
         (struct-out step)
         )

(require "external-interface.rkt"
         "private/marks.rkt")

(struct step (context-thunks break-kind values-returned) #:prefab)

;; for convenience, we just provide mutable top-level bindings for some functions. This
;; will cause terrible problems if you try to debug two programs at once...
(define this-step #f)
(define debugged-program-semaphore (make-semaphore))
;; in case you want to kill it...:
(define debugged-program-thread #f)

;; this function gets invoked on the debugged program's thread each time a step
;; arrives.
(define (step-receiver a b c)
  ;; if you wanted breakpoints, you could check if this is the
  ;; desired step before halting...
  (set! this-step (step a b c))
  (printf "*ding* a new step has arrived:\n~e\n" this-step)
  (semaphore-wait debugged-program-semaphore))

;; given a program path, run the debugger
(define (run-program program-path)
  (set!
   debugged-program-thread
   (thread
    (lambda ()
      (step-program-file program-path step-receiver)))))

;; continue running the debugger:
(define (continue)
  (semaphore-post debugged-program-semaphore))

;; show the innermost source location associated with the current-step
(define (srcloc)
  (match this-step
    [#f (error 'step-srcloc "no steps yet")]
    [(struct step ((cons first-mark _) _ _))
     (mark-source first-mark)]
    [other (error 'step-srcloc "no source contexts in this step")]))

;; EXAMPLE:

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

|#