avoid running the debugger during parsing or compilation at the repl
[bpt/guile.git] / module / system / repl / debug.scm
CommitLineData
33df2ec7
AW
1;;; Guile VM debugging facilities
2
3;;; Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
4;;;
5;;; This library is free software; you can redistribute it and/or
6;;; modify it under the terms of the GNU Lesser General Public
7;;; License as published by the Free Software Foundation; either
8;;; version 3 of the License, or (at your option) any later version.
9;;;
10;;; This library is distributed in the hope that it will be useful,
11;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;;; Lesser General Public License for more details.
14;;;
15;;; You should have received a copy of the GNU Lesser General Public
16;;; License along with this library; if not, write to the Free Software
17;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18
19;;; Code:
20
21(define-module (system repl debug)
22 #:use-module (system base pmatch)
23 #:use-module (system base syntax)
24 #:use-module (system base language)
25 #:use-module (system vm vm)
26 #:use-module (system vm frame)
27 #:use-module (ice-9 rdelim)
28 #:use-module (ice-9 pretty-print)
29 #:use-module (ice-9 format)
30 #:use-module ((system vm inspect) #:select ((inspect . %inspect)))
31 #:use-module (system vm program)
32 #:export (<debug>
33 make-debug debug? debug-frames debug-index
34 print-locals print-frame print-frames frame->module
35 stack->vector narrow-stack->vector))
36
37;;; FIXME: add more repl meta-commands: continue, inspect, etc...
38
39;;;
40;;; Debugger
41;;;
42;;; The actual interaction loop of the debugger is run by the repl. This module
43;;; simply exports a data structure to hold the debugger state, along with its
44;;; accessors, and provides some helper functions.
45;;;
46
47(define-record <debug> frames index)
48
49\f
50
51(define (reverse-hashq h)
52 (let ((ret (make-hash-table)))
53 (hash-for-each
54 (lambda (k v)
55 (hashq-set! ret v (cons k (hashq-ref ret v '()))))
56 h)
57 ret))
58
59(define* (print-locals frame #:optional (port (current-output-port))
97b3800e 60 #:key (width 72) (per-line-prefix " "))
33df2ec7
AW
61 (let ((bindings (frame-bindings frame)))
62 (cond
63 ((null? bindings)
64 (format port "~aNo local variables.~%" per-line-prefix))
65 (else
66 (format port "~aLocal variables:~%" per-line-prefix)
67 (for-each
68 (lambda (binding)
97b3800e
AW
69 (let ((v (let ((x (frame-local-ref frame (binding:index binding))))
70 (if (binding:boxed? binding)
71 (variable-ref x)
72 x))))
73 (display per-line-prefix port)
74 (run-hook before-print-hook v)
75 (format port "~a~:[~; (boxed)~] = ~v:@y\n"
76 (binding:name binding) (binding:boxed? binding) width v)))
33df2ec7
AW
77 (frame-bindings frame))))))
78
79(define* (print-frame frame #:optional (port (current-output-port))
80 #:key index (width 72) (full? #f) (last-source #f))
81 (define (source:pretty-file source)
82 (if source
83 (or (source:file source) "current input")
84 "unknown file"))
85 (let* ((source (frame-source frame))
86 (file (source:pretty-file source))
87 (line (and=> source source:line)))
88 (if (and file (not (equal? file (source:pretty-file last-source))))
89 (format port "~&In ~a:~&" file))
90 (format port "~:[~*~6_~;~5d:~]~:[~*~3_~;~3d~] ~v:@y~%"
91 line line index index width (frame-call-representation frame))
92 (if full?
93 (print-locals frame #:width width
94 #:per-line-prefix " "))))
95
96(define* (print-frames frames
97 #:optional (port (current-output-port))
98 #:key (width 72) (full? #f) (forward? #f) count)
99 (let* ((len (vector-length frames))
100 (lower-idx (if (or (not count) (positive? count))
101 0
102 (max 0 (+ len count))))
103 (upper-idx (if (and count (negative? count))
104 (1- len)
105 (1- (if count (min count len) len))))
106 (inc (if forward? 1 -1)))
107 (let lp ((i (if forward? lower-idx upper-idx))
108 (last-source #f))
109 (if (<= lower-idx i upper-idx)
110 (let* ((frame (vector-ref frames i)))
111 (print-frame frame port #:index i #:width width #:full? full?
112 #:last-source last-source)
113 (lp (+ i inc) (frame-source frame)))))))
114
115;; Ideally here we would have something much more syntactic, in that a set! to a
116;; local var that is not settable would raise an error, and export etc forms
117;; would modify the module in question: but alack, this is what we have now.
118;; Patches welcome!
119(define (frame->module frame)
120 (let ((proc (frame-procedure frame)))
121 (if (program? proc)
122 (let* ((mod (or (program-module proc) (current-module)))
123 (mod* (make-module)))
124 (module-use! mod* mod)
125 (for-each
126 (lambda (binding)
127 (let* ((x (frame-local-ref frame (binding:index binding)))
128 (var (if (binding:boxed? binding) x (make-variable x))))
129 (format #t
130 "~:[Read-only~;Mutable~] local variable ~a = ~70:@y\n"
131 (binding:boxed? binding)
132 (binding:name binding)
133 (if (variable-bound? var) (variable-ref var) var))
134 (module-add! mod* (binding:name binding) var)))
135 (frame-bindings frame))
136 mod*)
137 (current-module))))
138
139
140;; TODO:
141;;
142;; eval expression in context of frame
143;; set local variable in frame
144;; step until next instruction
145;; step until next function call/return
146;; step until return from frame
147;; step until different source line
148;; step until greater source line
149;; watch expression
150;; break on a function
151;; remove breakpoints
152;; set printing width
153;; display a truncated backtrace
154;; go to a frame by index
155;; (reuse gdb commands perhaps)
156;; disassemble a function
157;; disassemble the current function
158;; inspect any object
159;; hm, trace via reassigning global vars. tricksy.
160;; (state associated with vm ?)
161
162(define (stack->vector stack)
163 (let* ((len (stack-length stack))
164 (v (make-vector len)))
165 (if (positive? len)
166 (let lp ((i 0) (frame (stack-ref stack 0)))
167 (if (< i len)
168 (begin
169 (vector-set! v i frame)
170 (lp (1+ i) (frame-previous frame))))))
171 v))
172
173(define (narrow-stack->vector stack . args)
174 (stack->vector (apply make-stack (stack-ref stack 0) args)))
175