123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- ;;; Guile VM debugging facilities
- ;;; Copyright (C) 2001, 2009, 2010, 2011, 2013 Free Software Foundation, Inc.
- ;;;
- ;;; This library is free software; you can redistribute it and/or
- ;;; modify it under the terms of the GNU Lesser General Public
- ;;; License as published by the Free Software Foundation; either
- ;;; version 3 of the License, or (at your option) any later version.
- ;;;
- ;;; This library is distributed in the hope that it will be useful,
- ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
- ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ;;; Lesser General Public License for more details.
- ;;;
- ;;; You should have received a copy of the GNU Lesser General Public
- ;;; License along with this library; if not, write to the Free Software
- ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- ;;; Code:
- (define-module (system vm inspect)
- #:use-module (system base pmatch)
- #:use-module (system base syntax)
- #:use-module (system vm vm)
- #:use-module (system vm frame)
- #:use-module (system vm disassembler)
- #:use-module (ice-9 rdelim)
- #:use-module (ice-9 pretty-print)
- #:use-module (ice-9 format)
- #:use-module (system vm program)
- #:export (inspect))
- (define (reverse-hashq h)
- (let ((ret (make-hash-table)))
- (hash-for-each
- (lambda (k v)
- (hashq-set! ret v (cons k (hashq-ref ret v '()))))
- h)
- ret))
- (define (catch-bad-arguments thunk bad-args-thunk)
- (catch 'wrong-number-of-args
- (lambda ()
- (catch 'keyword-argument-error
- thunk
- (lambda (k . args)
- (bad-args-thunk))))
- (lambda (k . args)
- (bad-args-thunk))))
- (define (read-args prompt)
- (define (read* reader)
- (repl-reader prompt reader))
- (define (next)
- (read* read-char))
- (define (cmd chr)
- (cond
- ((eof-object? chr) (list chr))
- ((char=? chr #\newline) (cmd (next)))
- ((char-whitespace? chr) (cmd (next)))
- (else
- (unread-char chr)
- (let ((tok (read* read)))
- (args (list tok) (next))))))
- (define (args out chr)
- (cond
- ((eof-object? chr) (reverse out))
- ((char=? chr #\newline) (reverse out))
- ((char-whitespace? chr) (args out (next)))
- (else
- (unread-char chr)
- (let ((tok (read* read)))
- (args (cons tok out) (next))))))
- (cmd (next)))
- ;;;
- ;;; Inspector
- ;;;
- (define (inspect x)
- (define-syntax-rule (define-command ((mod cname alias ...) . args)
- body ...)
- (define cname
- (let ((c (lambda* args body ...)))
- (set-procedure-property! c 'name 'cname)
- (module-define! mod 'cname c)
- (module-add! mod 'alias (module-local-variable mod 'cname))
- ...
- c)))
- (let ((commands (make-module)))
- (define (prompt)
- (format #f "~20@y inspect> " x))
-
- (define-command ((commands quit q continue cont c))
- "Quit the inspector."
- (throw 'quit))
-
- (define-command ((commands print p))
- "Print the current object using `pretty-print'."
- (pretty-print x))
-
- (define-command ((commands write w))
- "Print the current object using `write'."
- (write x))
-
- (define-command ((commands display d))
- "Print the current object using `display'."
- (display x))
-
- (define-command ((commands disassemble x))
- "Disassemble the current object, which should be a procedure."
- (catch #t
- (lambda ()
- (disassemble-program x))
- (lambda args
- (format #t "Error disassembling object: ~a\n" args))))
-
- (define-command ((commands help h ?) #:optional cmd)
- "Show this help message."
- (let ((rhash (reverse-hashq (module-obarray commands))))
- (define (help-cmd cmd)
- (let* ((v (module-local-variable commands cmd))
- (p (variable-ref v))
- (canonical-name (procedure-name p)))
- ;; la la la
- (format #t "~a~{ ~:@(~a~)~}~?~%~a~&~%"
- canonical-name (program-lambda-list p)
- "~#[~:;~40t(aliases: ~@{~a~^, ~})~]"
- (delq canonical-name (hashq-ref rhash v))
- (procedure-documentation p))))
- (cond
- (cmd
- (cond
- ((and (symbol? cmd) (module-local-variable commands cmd))
- (help-cmd cmd))
- (else
- (format #t "Invalid command ~s.~%" cmd)
- (format #t "Try `help' for a list of commands~%"))))
- (else
- (let ((names (sort
- (hash-map->list
- (lambda (k v)
- (procedure-name (variable-ref k)))
- rhash)
- (lambda (x y)
- (string<? (symbol->string x)
- (symbol->string y))))))
- (format #t "Available commands:~%~%")
- (for-each help-cmd names))))))
- (define (handle cmd . args)
- (cond
- ((and (symbol? cmd)
- (module-local-variable commands cmd))
- => (lambda (var)
- (let ((proc (variable-ref var)))
- (catch-bad-arguments
- (lambda ()
- (apply (variable-ref var) args))
- (lambda ()
- (format (current-error-port)
- "Invalid arguments to ~a. Try `help ~a'.~%"
- (procedure-name proc) (procedure-name proc)))))))
- ; ((and (integer? cmd) (exact? cmd))
- ; (nth cmd))
- ((eof-object? cmd)
- (newline)
- (throw 'quit))
- (else
- (format (current-error-port)
- "~&Unknown command: ~a. Try `help'.~%" cmd)
- *unspecified*)))
- (catch 'quit
- (lambda ()
- (let loop ()
- (apply
- handle
- (save-module-excursion
- (lambda ()
- (set-current-module commands)
- (read-args prompt))))
- (loop)))
- (lambda (k . args)
- (apply values args)))))
|