inspect.scm 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. ;;; Guile VM debugging facilities
  2. ;;; Copyright (C) 2001, 2009, 2010, 2011, 2013 Free Software Foundation, Inc.
  3. ;;;
  4. ;;; This library is free software; you can redistribute it and/or
  5. ;;; modify it under the terms of the GNU Lesser General Public
  6. ;;; License as published by the Free Software Foundation; either
  7. ;;; version 3 of the License, or (at your option) any later version.
  8. ;;;
  9. ;;; This library is distributed in the hope that it will be useful,
  10. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;; Lesser General Public License for more details.
  13. ;;;
  14. ;;; You should have received a copy of the GNU Lesser General Public
  15. ;;; License along with this library; if not, write to the Free Software
  16. ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;; Code:
  18. (define-module (system vm inspect)
  19. #:use-module (system base pmatch)
  20. #:use-module (system base syntax)
  21. #:use-module (system vm vm)
  22. #:use-module (system vm frame)
  23. #:use-module (system vm disassembler)
  24. #:use-module (ice-9 rdelim)
  25. #:use-module (ice-9 pretty-print)
  26. #:use-module (ice-9 format)
  27. #:use-module (system vm program)
  28. #:export (inspect))
  29. (define (reverse-hashq h)
  30. (let ((ret (make-hash-table)))
  31. (hash-for-each
  32. (lambda (k v)
  33. (hashq-set! ret v (cons k (hashq-ref ret v '()))))
  34. h)
  35. ret))
  36. (define (catch-bad-arguments thunk bad-args-thunk)
  37. (catch 'wrong-number-of-args
  38. (lambda ()
  39. (catch 'keyword-argument-error
  40. thunk
  41. (lambda (k . args)
  42. (bad-args-thunk))))
  43. (lambda (k . args)
  44. (bad-args-thunk))))
  45. (define (read-args prompt)
  46. (define (read* reader)
  47. (repl-reader prompt reader))
  48. (define (next)
  49. (read* read-char))
  50. (define (cmd chr)
  51. (cond
  52. ((eof-object? chr) (list chr))
  53. ((char=? chr #\newline) (cmd (next)))
  54. ((char-whitespace? chr) (cmd (next)))
  55. (else
  56. (unread-char chr)
  57. (let ((tok (read* read)))
  58. (args (list tok) (next))))))
  59. (define (args out chr)
  60. (cond
  61. ((eof-object? chr) (reverse out))
  62. ((char=? chr #\newline) (reverse out))
  63. ((char-whitespace? chr) (args out (next)))
  64. (else
  65. (unread-char chr)
  66. (let ((tok (read* read)))
  67. (args (cons tok out) (next))))))
  68. (cmd (next)))
  69. ;;;
  70. ;;; Inspector
  71. ;;;
  72. (define (inspect x)
  73. (define-syntax-rule (define-command ((mod cname alias ...) . args)
  74. body ...)
  75. (define cname
  76. (let ((c (lambda* args body ...)))
  77. (set-procedure-property! c 'name 'cname)
  78. (module-define! mod 'cname c)
  79. (module-add! mod 'alias (module-local-variable mod 'cname))
  80. ...
  81. c)))
  82. (let ((commands (make-module)))
  83. (define (prompt)
  84. (format #f "~20@y inspect> " x))
  85. (define-command ((commands quit q continue cont c))
  86. "Quit the inspector."
  87. (throw 'quit))
  88. (define-command ((commands print p))
  89. "Print the current object using `pretty-print'."
  90. (pretty-print x))
  91. (define-command ((commands write w))
  92. "Print the current object using `write'."
  93. (write x))
  94. (define-command ((commands display d))
  95. "Print the current object using `display'."
  96. (display x))
  97. (define-command ((commands disassemble x))
  98. "Disassemble the current object, which should be a procedure."
  99. (catch #t
  100. (lambda ()
  101. (disassemble-program x))
  102. (lambda args
  103. (format #t "Error disassembling object: ~a\n" args))))
  104. (define-command ((commands help h ?) #:optional cmd)
  105. "Show this help message."
  106. (let ((rhash (reverse-hashq (module-obarray commands))))
  107. (define (help-cmd cmd)
  108. (let* ((v (module-local-variable commands cmd))
  109. (p (variable-ref v))
  110. (canonical-name (procedure-name p)))
  111. ;; la la la
  112. (format #t "~a~{ ~:@(~a~)~}~?~%~a~&~%"
  113. canonical-name (program-lambda-list p)
  114. "~#[~:;~40t(aliases: ~@{~a~^, ~})~]"
  115. (delq canonical-name (hashq-ref rhash v))
  116. (procedure-documentation p))))
  117. (cond
  118. (cmd
  119. (cond
  120. ((and (symbol? cmd) (module-local-variable commands cmd))
  121. (help-cmd cmd))
  122. (else
  123. (format #t "Invalid command ~s.~%" cmd)
  124. (format #t "Try `help' for a list of commands~%"))))
  125. (else
  126. (let ((names (sort
  127. (hash-map->list
  128. (lambda (k v)
  129. (procedure-name (variable-ref k)))
  130. rhash)
  131. (lambda (x y)
  132. (string<? (symbol->string x)
  133. (symbol->string y))))))
  134. (format #t "Available commands:~%~%")
  135. (for-each help-cmd names))))))
  136. (define (handle cmd . args)
  137. (cond
  138. ((and (symbol? cmd)
  139. (module-local-variable commands cmd))
  140. => (lambda (var)
  141. (let ((proc (variable-ref var)))
  142. (catch-bad-arguments
  143. (lambda ()
  144. (apply (variable-ref var) args))
  145. (lambda ()
  146. (format (current-error-port)
  147. "Invalid arguments to ~a. Try `help ~a'.~%"
  148. (procedure-name proc) (procedure-name proc)))))))
  149. ; ((and (integer? cmd) (exact? cmd))
  150. ; (nth cmd))
  151. ((eof-object? cmd)
  152. (newline)
  153. (throw 'quit))
  154. (else
  155. (format (current-error-port)
  156. "~&Unknown command: ~a. Try `help'.~%" cmd)
  157. *unspecified*)))
  158. (catch 'quit
  159. (lambda ()
  160. (let loop ()
  161. (apply
  162. handle
  163. (save-module-excursion
  164. (lambda ()
  165. (set-current-module commands)
  166. (read-args prompt))))
  167. (loop)))
  168. (lambda (k . args)
  169. (apply values args)))))