fix ,traps REPL command
[bpt/guile.git] / module / system / repl / command.scm
CommitLineData
ea9c5dab 1;;; Repl commands
17e90c5e 2
6f3b0cc2 3;; Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc.
17e90c5e 4
eb721799
AW
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.
54d9a994 9;;
eb721799 10;; This library is distributed in the hope that it will be useful,
17e90c5e 11;; but WITHOUT ANY WARRANTY; without even the implied warranty of
eb721799
AW
12;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;; Lesser General Public License for more details.
54d9a994 14;;
eb721799
AW
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
18;; 02110-1301 USA
17e90c5e
KN
19
20;;; Code:
21
22(define-module (system repl command)
8239263f 23 #:use-module (system base syntax)
1a1a10d3
AW
24 #:use-module (system base pmatch)
25 #:use-module (system base compile)
26 #:use-module (system repl common)
33df2ec7 27 #:use-module (system repl debug)
1a1a10d3
AW
28 #:use-module (system vm objcode)
29 #:use-module (system vm program)
b9badc35 30 #:use-module (system vm trap-state)
1a1a10d3 31 #:use-module (system vm vm)
eb721799 32 #:autoload (system base language) (lookup-language language-reader)
7e9f9602 33 #:autoload (system vm trace) (vm-trace)
1a1a10d3
AW
34 #:autoload (system vm profile) (vm-profile)
35 #:use-module (ice-9 format)
36 #:use-module (ice-9 session)
37 #:use-module (ice-9 documentation)
38 #:use-module (ice-9 and-let-star)
eb721799 39 #:use-module (ice-9 rdelim)
33df2ec7
AW
40 #:use-module (ice-9 control)
41 #:use-module ((ice-9 pretty-print) #:select ((pretty-print . pp)))
42 #:use-module ((system vm inspect) #:select ((inspect . %inspect)))
a6dc56a7 43 #:use-module (statprof)
1a1a10d3 44 #:export (meta-command))
4bfb26f5
KN
45
46\f
47;;;
8f5cfc81 48;;; Meta command interface
4bfb26f5
KN
49;;;
50
51(define *command-table*
33df2ec7
AW
52 '((help (help h) (show s) (apropos a) (describe d))
53 (module (module m) (import use) (load l) (binding b))
4bfb26f5
KN
54 (language (language L))
55 (compile (compile c) (compile-file cc)
56 (disassemble x) (disassemble-file xx))
33df2ec7
AW
57 (profile (time t) (profile pr) (trace tr))
58 (debug (backtrace bt) (up) (down) (frame fr)
b9badc35 59 (procedure proc) (locals) (error-message error)
fb5c4dc5
AW
60 (break br bp) (break-at-source break-at bs)
61 (tracepoint tp)
589520bc 62 (traps) (delete del) (disable) (enable))
33df2ec7
AW
63 (inspect (inspect i) (pretty-print pp))
64 (system (gc) (statistics stat) (option o)
65 (quit q continue cont))))
4bfb26f5 66
dca9a4d6
AW
67(define *show-table*
68 '((show (warranty w) (copying c) (version v))))
69
4bfb26f5
KN
70(define (group-name g) (car g))
71(define (group-commands g) (cdr g))
72
73(define *command-module* (current-module))
74(define (command-name c) (car c))
33df2ec7 75(define (command-abbrevs c) (cdr c))
4bfb26f5
KN
76(define (command-procedure c) (module-ref *command-module* (command-name c)))
77(define (command-doc c) (procedure-documentation (command-procedure c)))
78
79(define (command-usage c)
80 (let ((doc (command-doc c)))
81 (substring doc 0 (string-index doc #\newline))))
82
83(define (command-summary c)
84 (let* ((doc (command-doc c))
85 (start (1+ (string-index doc #\newline))))
86 (cond ((string-index doc #\newline start)
87 => (lambda (end) (substring doc start end)))
88 (else (substring doc start)))))
89
90(define (lookup-group name)
91 (assq name *command-table*))
92
dca9a4d6
AW
93(define* (lookup-command key #:optional (table *command-table*))
94 (let loop ((groups table) (commands '()))
4bfb26f5
KN
95 (cond ((and (null? groups) (null? commands)) #f)
96 ((null? commands)
97 (loop (cdr groups) (cdar groups)))
98 ((memq key (car commands)) (car commands))
99 (else (loop groups (cdr commands))))))
100
dca9a4d6 101(define* (display-group group #:optional (abbrev? #t))
33df2ec7 102 (format #t "~:(~A~) Commands~:[~; [abbrev]~]:~2%" (group-name group) abbrev?)
4bfb26f5
KN
103 (for-each (lambda (c)
104 (display-summary (command-usage c)
33df2ec7 105 (if abbrev? (command-abbrevs c) '())
4bfb26f5
KN
106 (command-summary c)))
107 (group-commands group))
108 (newline))
109
110(define (display-command command)
111 (display "Usage: ")
112 (display (command-doc command))
113 (newline))
114
33df2ec7
AW
115(define (display-summary usage abbrevs summary)
116 (let* ((usage-len (string-length usage))
117 (abbrevs (if (pair? abbrevs)
118 (format #f "[,~A~{ ,~A~}]" (car abbrevs) (cdr abbrevs))
119 ""))
120 (abbrevs-len (string-length abbrevs)))
121 (format #t " ,~A~A~A - ~A\n"
122 usage
123 (cond
124 ((> abbrevs-len 32)
125 (error "abbrevs too long" abbrevs))
126 ((> (+ usage-len abbrevs-len) 32)
127 (format #f "~%~v_" (+ 2 (- 32 abbrevs-len))))
128 (else
129 (format #f "~v_" (- 32 abbrevs-len usage-len))))
130 abbrevs
131 summary)))
132
133(define (read-command repl)
134 (catch #t
3ae78d95 135 (lambda () (read (repl-inport repl)))
33df2ec7
AW
136 (lambda (key . args)
137 (pmatch args
138 ((,subr ,msg ,args . ,rest)
139 (format #t "Throw to key `~a' while reading command:\n" key)
140 (display-error #f (current-output-port) subr msg args rest))
141 (else
142 (format #t "Throw to key `~a' with args `~s' while reading command.\n"
143 key args)))
144 (force-output)
145 *unspecified*)))
eb721799
AW
146
147(define read-line
148 (let ((orig-read-line read-line))
149 (lambda (repl)
5b27d9d2 150 (orig-read-line (repl-inport repl)))))
eb721799
AW
151
152(define (meta-command repl)
33df2ec7
AW
153 (let ((command (read-command repl)))
154 (cond
155 ((eq? command *unspecified*)) ; read error, already signalled; pass.
156 ((not (symbol? command))
157 (format #t "Meta-command not a symbol: ~s~%" command))
158 ((lookup-command command)
159 => (lambda (c) ((command-procedure c) repl)))
160 (else
161 (format #t "Unknown meta command: ~A~%" command)))))
eb721799
AW
162
163(define-syntax define-meta-command
164 (syntax-rules ()
165 ((_ (name repl (expression0 ...) . datums) docstring b0 b1 ...)
166 (define (name repl)
167 docstring
33df2ec7
AW
168 (define (handle-read-error form-name key args)
169 (pmatch args
170 ((,subr ,msg ,args . ,rest)
171 (format #t "Throw to key `~a' while reading ~@[argument `~A' of ~]command `~A':\n"
172 key form-name 'name)
173 (display-error #f (current-output-port) subr msg args rest))
174 (else
175 (format #t "Throw to key `~a' with args `~s' while reading ~@[ argument `~A' of ~]command `~A'.\n"
176 key args form-name 'name)))
177 (abort))
54d9a994 178
33df2ec7
AW
179 (% (let* ((expression0
180 (catch #t
181 (lambda ()
182 (repl-reader ""
183 (lambda* (#:optional (port (repl-inport repl)))
184 ((language-reader (repl-language repl))
185 port (current-module)))))
186 (lambda (k . args)
187 (handle-read-error 'expression0 k args))))
188 ...)
189 (apply (lambda* datums
190 (with-output-to-port (repl-outport repl)
191 (lambda () b0 b1 ...)))
192 (catch #t
193 (lambda ()
194 (let ((port (open-input-string (read-line repl))))
195 (let lp ((out '()))
196 (let ((x (read port)))
197 (if (eof-object? x)
198 (reverse out)
199 (lp (cons x out)))))))
200 (lambda (k . args)
201 (handle-read-error #f k args)))))
202 (lambda (k) #f)))) ; the abort handler
203
eb721799
AW
204 ((_ (name repl . datums) docstring b0 b1 ...)
205 (define-meta-command (name repl () . datums)
206 docstring b0 b1 ...))))
207
4bfb26f5
KN
208
209\f
210;;;
211;;; Help commands
212;;;
213
eb721799 214(define-meta-command (help repl . args)
33df2ec7
AW
215 "help [all | GROUP | [-c] COMMAND]
216Show help.
eb721799
AW
217
218With one argument, tries to look up the argument as a group name, giving
219help on that group if successful. Otherwise tries to look up the
220argument as a command, giving help on the command.
221
222If there is a command whose name is also a group name, use the ,help
223-c COMMAND form to give help on the command instead of the group.
224
8f5cfc81 225Without any argument, a list of help commands and command groups
eb721799 226are displayed."
e429de1e 227 (pmatch args
4bfb26f5
KN
228 (()
229 (display-group (lookup-group 'help))
230 (display "Command Groups:\n\n")
231 (display-summary "help all" #f "List all commands")
232 (for-each (lambda (g)
233 (let* ((name (symbol->string (group-name g)))
234 (usage (string-append "help " name))
235 (header (string-append "List " name " commands")))
236 (display-summary usage #f header)))
237 (cdr *command-table*))
238 (newline)
019fdc97
AW
239 (display
240 "Type `,help -c COMMAND' to show documentation of a particular command.")
4bfb26f5 241 (newline))
e429de1e 242 ((all)
4bfb26f5 243 (for-each display-group *command-table*))
e429de1e 244 ((,group) (guard (lookup-group group))
4bfb26f5 245 (display-group (lookup-group group)))
eb721799
AW
246 ((,command) (guard (lookup-command command))
247 (display-command (lookup-command command)))
248 ((-c ,command) (guard (lookup-command command))
249 (display-command (lookup-command command)))
250 ((,command)
33df2ec7 251 (format #t "Unknown command or group: ~A~%" command))
eb721799 252 ((-c ,command)
33df2ec7 253 (format #t "Unknown command: ~A~%" command))
8f5cfc81 254 (else
33df2ec7 255 (format #t "Bad arguments: ~A~%" args))))
4bfb26f5 256
dca9a4d6 257(define-meta-command (show repl . args)
33df2ec7 258 "show [TOPIC]
dca9a4d6
AW
259Gives information about Guile.
260
261With one argument, tries to show a particular piece of information;
262
263currently supported topics are `warranty' (or `w'), `copying' (or `c'),
264and `version' (or `v').
265
266Without any argument, a list of topics is displayed."
267 (pmatch args
268 (()
269 (display-group (car *show-table*) #f)
270 (newline))
271 ((,topic) (guard (lookup-command topic *show-table*))
272 ((command-procedure (lookup-command topic *show-table*)) repl))
273 ((,command)
33df2ec7 274 (format #t "Unknown topic: ~A~%" command))
dca9a4d6 275 (else
33df2ec7 276 (format #t "Bad arguments: ~A~%" args))))
dca9a4d6
AW
277
278(define (warranty repl)
279 "show warranty
280Details on the lack of warranty."
281 (display *warranty*)
282 (newline))
283
284(define (copying repl)
285 "show copying
286Show the LGPLv3."
287 (display *copying*)
288 (newline))
289
290(define (version repl)
291 "show version
292Version information."
293 (display *version*)
294 (newline))
295
8f5cfc81 296(define guile:apropos apropos)
eb721799 297(define-meta-command (apropos repl regexp)
8f5cfc81 298 "apropos REGEXP
4bfb26f5 299Find bindings/modules/packages."
8f5cfc81 300 (guile:apropos (->string regexp)))
4bfb26f5 301
eb721799 302(define-meta-command (describe repl (form))
4bfb26f5
KN
303 "describe OBJ
304Show description/documentation."
eb721799 305 (display (object-documentation (repl-eval repl (repl-parse repl form))))
8f5cfc81 306 (newline))
4bfb26f5 307
eb721799 308(define-meta-command (option repl . args)
8f5cfc81 309 "option [KEY VALUE]
4bfb26f5 310List/show/set options."
e429de1e 311 (pmatch args
f21dfea6 312 (()
c27d140a
AW
313 (for-each (lambda (spec)
314 (format #t " ~A~24t~A\n" (car spec) (cadr spec)))
ce0925e1 315 (repl-options repl)))
e429de1e 316 ((,key)
f21dfea6
KN
317 (display (repl-option-ref repl key))
318 (newline))
e429de1e 319 ((,key ,val)
7e9f9602 320 (repl-option-set! repl key val))))
4bfb26f5 321
eb721799 322(define-meta-command (quit repl)
4bfb26f5
KN
323 "quit
324Quit this session."
325 (throw 'quit))
326
327\f
328;;;
329;;; Module commands
330;;;
331
eb721799 332(define-meta-command (module repl . args)
4bfb26f5
KN
333 "module [MODULE]
334Change modules / Show current module."
e429de1e 335 (pmatch args
db917b41 336 (() (puts (module-name (current-module))))
482015af
AW
337 ((,mod-name) (guard (list? mod-name))
338 (set-current-module (resolve-module mod-name)))
339 (,mod-name (set-current-module (resolve-module mod-name)))))
4bfb26f5 340
eb721799 341(define-meta-command (import repl . args)
4bfb26f5
KN
342 "import [MODULE ...]
343Import modules / List those imported."
9246a486
AW
344 (let ()
345 (define (use name)
346 (let ((mod (resolve-interface name)))
347 (if mod
348 (module-use! (current-module) mod)
33df2ec7 349 (format #t "No such module: ~A~%" name))))
9246a486
AW
350 (if (null? args)
351 (for-each puts (map module-name (module-uses (current-module))))
352 (for-each use args))))
4bfb26f5 353
84012ef4 354(define guile:load load)
019fdc97 355(define-meta-command (load repl file)
8f5cfc81 356 "load FILE
019fdc97
AW
357Load a file in the current module."
358 (guile:load (->string file)))
4bfb26f5 359
eb721799 360(define-meta-command (binding repl)
8f5cfc81 361 "binding
4bfb26f5 362List current bindings."
db917b41
AW
363 (module-for-each (lambda (k v) (format #t "~23A ~A\n" k v))
364 (current-module)))
4bfb26f5
KN
365
366\f
367;;;
368;;; Language commands
369;;;
370
eb721799 371(define-meta-command (language repl name)
4bfb26f5
KN
372 "language LANGUAGE
373Change languages."
dca9a4d6
AW
374 (let ((lang (lookup-language name))
375 (cur (repl-language repl)))
4d75554d 376 (format #t "Happy hacking with ~a! To switch back, type `,L ~a'.\n"
dca9a4d6
AW
377 (language-title lang) (language-name cur))
378 (set! (repl-language repl) lang)))
4bfb26f5
KN
379
380\f
381;;;
382;;; Compile commands
383;;;
384
35d70ecc 385(define-meta-command (compile repl (form))
33df2ec7 386 "compile EXP
35d70ecc
AW
387Generate compiled code."
388 (let ((x (repl-compile repl (repl-parse repl form))))
81e002fc 389 (cond ((objcode? x) (guile:disassemble x))
b0b180d5 390 (else (repl-print repl x)))))
4bfb26f5 391
f21dfea6 392(define guile:compile-file compile-file)
eb721799 393(define-meta-command (compile-file repl file . opts)
8f5cfc81 394 "compile-file FILE
4bfb26f5 395Compile a file."
b0b180d5 396 (guile:compile-file (->string file) #:opts opts))
4bfb26f5 397
9bb8012d
AW
398(define (guile:disassemble x)
399 ((@ (language assembly disassemble) disassemble) x))
400
eb721799 401(define-meta-command (disassemble repl (form))
33df2ec7
AW
402 "disassemble EXP
403Disassemble a compiled procedure."
eb721799 404 (guile:disassemble (repl-eval repl (repl-parse repl form))))
4bfb26f5 405
eb721799 406(define-meta-command (disassemble-file repl file)
4bfb26f5
KN
407 "disassemble-file FILE
408Disassemble a file."
9bb8012d 409 (guile:disassemble (load-objcode (->string file))))
4bfb26f5
KN
410
411\f
412;;;
413;;; Profile commands
414;;;
415
eb721799 416(define-meta-command (time repl (form))
33df2ec7 417 "time EXP
8f5cfc81 418Time execution."
e5f5113c 419 (let* ((gc-start (gc-run-time))
8f5cfc81 420 (tms-start (times))
b0b180d5 421 (result (repl-eval repl (repl-parse repl form)))
8f5cfc81 422 (tms-end (times))
e5f5113c 423 (gc-end (gc-run-time)))
8f5cfc81 424 (define (get proc start end)
17d1b4bf 425 (exact->inexact (/ (- (proc end) (proc start)) internal-time-units-per-second)))
8f5cfc81
KN
426 (repl-print repl result)
427 (display "clock utime stime cutime cstime gctime\n")
428 (format #t "~5,2F ~5,2F ~5,2F ~6,2F ~6,2F ~6,2F\n"
429 (get tms:clock tms-start tms-end)
430 (get tms:utime tms-start tms-end)
431 (get tms:stime tms-start tms-end)
432 (get tms:cutime tms-start tms-end)
433 (get tms:cstime tms-start tms-end)
434 (get identity gc-start gc-end))
435 result))
436
a6dc56a7 437(define-meta-command (profile repl (form) . opts)
33df2ec7 438 "profile EXP
4bfb26f5 439Profile execution."
a6dc56a7 440 ;; FIXME opts
01c0082f 441 (apply statprof
d8e2ba23 442 (repl-prepare-eval-thunk repl (repl-parse repl form))
01c0082f 443 opts))
a6dc56a7 444
01c0082f 445(define-meta-command (trace repl (form) . opts)
33df2ec7 446 "trace EXP
737caee8 447Trace execution."
7e9f9602 448 ;; FIXME: doc options, or somehow deal with them better
737caee8 449 (apply vm-trace
01c0082f 450 (the-vm)
d8e2ba23 451 (repl-prepare-eval-thunk repl (repl-parse repl form))
b0b180d5 452 opts))
4bfb26f5 453
33df2ec7
AW
454\f
455;;;
456;;; Debug commands
457;;;
458
459(define-syntax define-stack-command
460 (lambda (x)
461 (syntax-case x ()
462 ((_ (name repl . args) docstring body body* ...)
463 #`(define-meta-command (name repl . args)
464 docstring
465 (let ((debug (repl-debug repl)))
466 (if debug
467 (letrec-syntax
468 ((#,(datum->syntax #'repl 'frames)
469 (identifier-syntax (debug-frames debug)))
54d9a994
JOR
470 (#,(datum->syntax #'repl 'message)
471 (identifier-syntax (debug-error-message debug)))
33df2ec7
AW
472 (#,(datum->syntax #'repl 'index)
473 (identifier-syntax
474 (id (debug-index debug))
475 ((set! id exp) (set! (debug-index debug) exp))))
476 (#,(datum->syntax #'repl 'cur)
477 (identifier-syntax
478 (vector-ref #,(datum->syntax #'repl 'frames)
479 #,(datum->syntax #'repl 'index)))))
480 body body* ...)
481 (format #t "Nothing to debug.~%"))))))))
482
483(define-stack-command (backtrace repl #:optional count
484 #:key (width 72) full?)
485 "backtrace [COUNT] [#:width W] [#:full? F]
486Print a backtrace.
487
488Print a backtrace of all stack frames, or innermost COUNT frames.
489If COUNT is negative, the last COUNT frames will be shown."
54d9a994 490 (print-frames frames
33df2ec7
AW
491 #:count count
492 #:width width
493 #:full? full?))
54d9a994 494
33df2ec7
AW
495(define-stack-command (up repl #:optional (count 1))
496 "up [COUNT]
497Select a calling stack frame.
498
499Select and print stack frames that called this one.
500An argument says how many frames up to go."
501 (cond
502 ((or (not (integer? count)) (<= count 0))
503 (format #t "Invalid argument to `up': expected a positive integer for COUNT.~%"))
504 ((>= (+ count index) (vector-length frames))
505 (cond
506 ((= index (1- (vector-length frames)))
507 (format #t "Already at outermost frame.\n"))
508 (else
509 (set! index (1- (vector-length frames)))
510 (print-frame cur #:index index))))
511 (else
512 (set! index (+ count index))
513 (print-frame cur #:index index))))
514
515(define-stack-command (down repl #:optional (count 1))
516 "down [COUNT]
517Select a called stack frame.
518
519Select and print stack frames called by this one.
520An argument says how many frames down to go."
521 (cond
522 ((or (not (integer? count)) (<= count 0))
523 (format #t "Invalid argument to `down': expected a positive integer for COUNT.~%"))
524 ((< (- index count) 0)
525 (cond
526 ((zero? index)
527 (format #t "Already at innermost frame.\n"))
528 (else
529 (set! index 0)
530 (print-frame cur #:index index))))
531 (else
532 (set! index (- index count))
533 (print-frame cur #:index index))))
534
535(define-stack-command (frame repl #:optional idx)
536 "frame [IDX]
537Show a frame.
538
539Show the selected frame.
540With an argument, select a frame by index, then show it."
541 (cond
542 (idx
543 (cond
544 ((or (not (integer? idx)) (< idx 0))
545 (format #t "Invalid argument to `frame': expected a non-negative integer for IDX.~%"))
546 ((< idx (vector-length frames))
547 (set! index idx)
548 (print-frame cur #:index index))
549 (else
550 (format #t "No such frame.~%"))))
551 (else (print-frame cur #:index index))))
552
553(define-stack-command (procedure repl)
554 "procedure
0ddbd883 555Print the procedure for the selected frame."
33df2ec7 556 (repl-print repl (frame-procedure cur)))
54d9a994 557
33df2ec7
AW
558(define-stack-command (locals repl)
559 "locals
560Show local variables.
561
562Show locally-bound variables in the selected frame."
563 (print-locals cur))
54d9a994 564
b9badc35
AW
565(define-stack-command (error-message repl)
566 "error-message
567Show error message.
568
569Display the message associated with the error that started the current
570debugging REPL."
571 (format #t "~a~%" (if (string? message) message "No error message")))
572
573(define-meta-command (break repl (form))
574 "break PROCEDURE
575Break on calls to PROCEDURE.
576
577Starts a recursive prompt when PROCEDURE is called."
578 (let ((proc (repl-eval repl (repl-parse repl form))))
579 (if (not (procedure? proc))
580 (error "Not a procedure: ~a" proc)
581 (let ((idx (add-trap-at-procedure-call! proc)))
95720533 582 (format #t "Trap ~a: ~a.~%" idx (trap-name idx))))))
b9badc35 583
fb5c4dc5
AW
584(define-meta-command (break-at-source repl file line)
585 "break-at-source FILE LINE
586Break when control reaches the given source location.
587
588Starts a recursive prompt when control reaches line LINE of file FILE.
589Note that the given source location must be inside a procedure."
590 (let ((file (if (symbol? file) (symbol->string file) file)))
591 (let ((idx (add-trap-at-source-location! file line)))
592 (format #t "Trap ~a: ~a.~%" idx (trap-name idx)))))
593
25361a80
AW
594(define-meta-command (tracepoint repl (form))
595 "tracepoint PROCEDURE
596Add a tracepoint to PROCEDURE.
597
598A tracepoint will print out the procedure and its arguments, when it is
599called, and its return value(s) when it returns."
600 (let ((proc (repl-eval repl (repl-parse repl form))))
601 (if (not (procedure? proc))
602 (error "Not a procedure: ~a" proc)
603 (let ((idx (add-trace-at-procedure-call! proc)))
95720533 604 (format #t "Trap ~a: ~a.~%" idx (trap-name idx))))))
25361a80 605
589520bc
AW
606(define-meta-command (traps repl)
607 "traps
608Show the set of currently attached traps.
609
66519688 610Show the set of currently attached traps (breakpoints and tracepoints)."
589520bc
AW
611 (let ((traps (list-traps)))
612 (if (null? traps)
66519688 613 (format #t "No traps set.~%")
3e2c5f1e 614 (for-each (lambda (idx)
589520bc 615 (format #t " ~a: ~a~a~%"
66519688 616 idx (trap-name idx)
589520bc 617 (if (trap-enabled? idx) "" " (disabled)")))
3e2c5f1e 618 traps))))
589520bc
AW
619
620(define-meta-command (delete repl idx)
621 "delete IDX
622Delete a trap.
623
624Delete a trap."
625 (if (not (integer? idx))
626 (error "expected a trap index (a non-negative integer)" idx)
627 (delete-trap! idx)))
628
629(define-meta-command (disable repl idx)
630 "disable IDX
631Disable a trap.
632
633Disable a trap."
634 (if (not (integer? idx))
635 (error "expected a trap index (a non-negative integer)" idx)
636 (disable-trap! idx)))
637
638(define-meta-command (enable repl idx)
639 "enable IDX
640Enable a trap.
641
642Enable a trap."
643 (if (not (integer? idx))
644 (error "expected a trap index (a non-negative integer)" idx)
645 (enable-trap! idx)))
646
b9badc35 647
33df2ec7
AW
648\f
649;;;
650;;; Inspection commands
651;;;
652
653(define-stack-command (inspect repl (form))
654 "inspect EXP
655Inspect the result(s) of evaluating EXP."
d8e2ba23 656 (call-with-values (repl-prepare-eval-thunk repl (repl-parse repl form))
33df2ec7
AW
657 (lambda args
658 (for-each %inspect args))))
659
660(define-meta-command (pretty-print repl (form))
661 "pretty-print EXP
662Pretty-print the result(s) of evaluating EXP."
d8e2ba23 663 (call-with-values (repl-prepare-eval-thunk repl (repl-parse repl form))
33df2ec7
AW
664 (lambda args
665 (for-each
666 (lambda (x)
667 (run-hook before-print-hook x)
668 (pp x))
669 args))))
4bfb26f5
KN
670
671\f
672;;;
54d9a994 673;;; System commands
4bfb26f5
KN
674;;;
675
8f5cfc81 676(define guile:gc gc)
eb721799 677(define-meta-command (gc repl)
4bfb26f5
KN
678 "gc
679Garbage collection."
8f5cfc81 680 (guile:gc))
4bfb26f5 681
eb721799 682(define-meta-command (statistics repl)
4bfb26f5
KN
683 "statistics
684Display statistics."
685 (let ((this-tms (times))
4bfb26f5 686 (this-gcs (gc-stats))
ce0925e1 687 (last-tms (repl-tm-stats repl))
ce0925e1 688 (last-gcs (repl-gc-stats repl)))
4bfb26f5
KN
689 ;; GC times
690 (let ((this-times (assq-ref this-gcs 'gc-times))
691 (last-times (assq-ref last-gcs 'gc-times)))
692 (display-diff-stat "GC times:" #t this-times last-times "times")
693 (newline))
694 ;; Memory size
695 (let ((this-cells (assq-ref this-gcs 'cells-allocated))
696 (this-heap (assq-ref this-gcs 'cell-heap-size))
697 (this-bytes (assq-ref this-gcs 'bytes-malloced))
698 (this-malloc (assq-ref this-gcs 'gc-malloc-threshold)))
699 (display-stat-title "Memory size:" "current" "limit")
700 (display-stat "heap" #f this-cells this-heap "cells")
701 (display-stat "malloc" #f this-bytes this-malloc "bytes")
702 (newline))
703 ;; Cells collected
704 (let ((this-marked (assq-ref this-gcs 'cells-marked))
705 (last-marked (assq-ref last-gcs 'cells-marked))
706 (this-swept (assq-ref this-gcs 'cells-swept))
707 (last-swept (assq-ref last-gcs 'cells-swept)))
708 (display-stat-title "Cells collected:" "diff" "total")
709 (display-diff-stat "marked" #f this-marked last-marked "cells")
710 (display-diff-stat "swept" #f this-swept last-swept "cells")
711 (newline))
712 ;; GC time taken
713 (let ((this-mark (assq-ref this-gcs 'gc-mark-time-taken))
714 (last-mark (assq-ref last-gcs 'gc-mark-time-taken))
4bfb26f5
KN
715 (this-total (assq-ref this-gcs 'gc-time-taken))
716 (last-total (assq-ref last-gcs 'gc-time-taken)))
717 (display-stat-title "GC time taken:" "diff" "total")
718 (display-time-stat "mark" this-mark last-mark)
4bfb26f5
KN
719 (display-time-stat "total" this-total last-total)
720 (newline))
721 ;; Process time spent
722 (let ((this-utime (tms:utime this-tms))
723 (last-utime (tms:utime last-tms))
724 (this-stime (tms:stime this-tms))
725 (last-stime (tms:stime last-tms))
726 (this-cutime (tms:cutime this-tms))
727 (last-cutime (tms:cutime last-tms))
728 (this-cstime (tms:cstime this-tms))
729 (last-cstime (tms:cstime last-tms)))
730 (display-stat-title "Process time spent:" "diff" "total")
731 (display-time-stat "user" this-utime last-utime)
732 (display-time-stat "system" this-stime last-stime)
733 (display-time-stat "child user" this-cutime last-cutime)
734 (display-time-stat "child system" this-cstime last-cstime)
735 (newline))
4bfb26f5
KN
736 ;; Save statistics
737 ;; Save statistics
ce0925e1 738 (set! (repl-tm-stats repl) this-tms)
ce0925e1 739 (set! (repl-gc-stats repl) this-gcs)))
cb4cca12
KN
740
741(define (display-stat title flag field1 field2 unit)
742 (let ((str (format #f "~~20~AA ~~10@A /~~10@A ~~A~~%" (if flag "" "@"))))
743 (format #t str title field1 field2 unit)))
744
745(define (display-stat-title title field1 field2)
746 (display-stat title #t field1 field2 ""))
747
748(define (display-diff-stat title flag this last unit)
749 (display-stat title flag (- this last) this unit))
750
751(define (display-time-stat title this last)
752 (define (conv num)
b9d8ed05 753 (format #f "~10,2F" (exact->inexact (/ num internal-time-units-per-second))))
cb4cca12
KN
754 (display-stat title #f (conv (- this last)) (conv this) "s"))
755
756(define (display-mips-stat title this-time this-clock last-time last-clock)
757 (define (mips time clock)
b9d8ed05 758 (if (= time 0) "----" (format #f "~10,2F" (/ clock time 1000000.0))))
cb4cca12
KN
759 (display-stat title #f
760 (mips (- this-time last-time) (- this-clock last-clock))
761 (mips this-time this-clock) "mips"))