inspect.scm 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. ;;; Guile VM debugging facilities
  2. ;;; Copyright (C) 2001, 2009, 2010, 2011 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 ((language assembly disassemble)
  24. #:select ((disassemble . %disassemble)))
  25. #:use-module (ice-9 rdelim)
  26. #:use-module (ice-9 pretty-print)
  27. #:use-module (ice-9 format)
  28. #:use-module (system vm program)
  29. #:export (inspect))
  30. (define (reverse-hashq h)
  31. (let ((ret (make-hash-table)))
  32. (hash-for-each
  33. (lambda (k v)
  34. (hashq-set! ret v (cons k (hashq-ref ret v '()))))
  35. h)
  36. ret))
  37. (define (catch-bad-arguments thunk bad-args-thunk)
  38. (catch 'wrong-number-of-args
  39. (lambda ()
  40. (catch 'keyword-argument-error
  41. thunk
  42. (lambda (k . args)
  43. (bad-args-thunk))))
  44. (lambda (k . args)
  45. (bad-args-thunk))))
  46. (define (read-args prompt)
  47. (define (read* reader)
  48. (repl-reader prompt reader))
  49. (define (next)
  50. (read* read-char))
  51. (define (cmd chr)
  52. (cond
  53. ((eof-object? chr) (list chr))
  54. ((char=? chr #\newline) (cmd (next)))
  55. ((char-whitespace? chr) (cmd (next)))
  56. (else
  57. (unread-char chr)
  58. (let ((tok (read* read)))
  59. (args (list tok) (next))))))
  60. (define (args out chr)
  61. (cond
  62. ((eof-object? chr) (reverse out))
  63. ((char=? chr #\newline) (reverse out))
  64. ((char-whitespace? chr) (args out (next)))
  65. (else
  66. (unread-char chr)
  67. (let ((tok (read* read)))
  68. (args (cons tok out) (next))))))
  69. (cmd (next)))
  70. ;;;
  71. ;;; Inspector
  72. ;;;
  73. (define (inspect x)
  74. (define-syntax-rule (define-command ((mod cname alias ...) . args)
  75. body ...)
  76. (define cname
  77. (let ((c (lambda* args body ...)))
  78. (set-procedure-property! c 'name 'cname)
  79. (module-define! mod 'cname c)
  80. (module-add! mod 'alias (module-local-variable mod 'cname))
  81. ...
  82. c)))
  83. (let ((commands (make-module)))
  84. (define (prompt)
  85. (format #f "~20@y inspect> " x))
  86. (define-command ((commands quit q continue cont c))
  87. "Quit the inspector."
  88. (throw 'quit))
  89. (define-command ((commands print p))
  90. "Print the current object using `pretty-print'."
  91. (pretty-print x))
  92. (define-command ((commands write w))
  93. "Print the current object using `write'."
  94. (write x))
  95. (define-command ((commands display d))
  96. "Print the current object using `display'."
  97. (display x))
  98. (define-command ((commands disassemble x))
  99. "Disassemble the current object, which should be objcode or a procedure."
  100. (catch #t
  101. (lambda ()
  102. (%disassemble x))
  103. (lambda args
  104. (format #t "Error disassembling object: ~a\n" args))))
  105. (define-command ((commands help h ?) #:optional cmd)
  106. "Show this help message."
  107. (let ((rhash (reverse-hashq (module-obarray commands))))
  108. (define (help-cmd cmd)
  109. (let* ((v (module-local-variable commands cmd))
  110. (p (variable-ref v))
  111. (canonical-name (procedure-name p)))
  112. ;; la la la
  113. (format #t "~a~{ ~:@(~a~)~}~?~%~a~&~%"
  114. canonical-name (program-lambda-list p)
  115. "~#[~:;~40t(aliases: ~@{~a~^, ~})~]"
  116. (delq canonical-name (hashq-ref rhash v))
  117. (procedure-documentation p))))
  118. (cond
  119. (cmd
  120. (cond
  121. ((and (symbol? cmd) (module-local-variable commands cmd))
  122. (help-cmd cmd))
  123. (else
  124. (format #t "Invalid command ~s.~%" cmd)
  125. (format #t "Try `help' for a list of commands~%"))))
  126. (else
  127. (let ((names (sort
  128. (hash-map->list
  129. (lambda (k v)
  130. (procedure-name (variable-ref k)))
  131. rhash)
  132. (lambda (x y)
  133. (string<? (symbol->string x)
  134. (symbol->string y))))))
  135. (format #t "Available commands:~%~%")
  136. (for-each help-cmd names))))))
  137. (define (handle cmd . args)
  138. (cond
  139. ((and (symbol? cmd)
  140. (module-local-variable commands cmd))
  141. => (lambda (var)
  142. (let ((proc (variable-ref var)))
  143. (catch-bad-arguments
  144. (lambda ()
  145. (apply (variable-ref var) args))
  146. (lambda ()
  147. (format (current-error-port)
  148. "Invalid arguments to ~a. Try `help ~a'.~%"
  149. (procedure-name proc) (procedure-name proc)))))))
  150. ; ((and (integer? cmd) (exact? cmd))
  151. ; (nth cmd))
  152. ((eof-object? cmd)
  153. (newline)
  154. (throw 'quit))
  155. (else
  156. (format (current-error-port)
  157. "~&Unknown command: ~a. Try `help'.~%" cmd)
  158. *unspecified*)))
  159. (catch 'quit
  160. (lambda ()
  161. (let loop ()
  162. (apply
  163. handle
  164. (save-module-excursion
  165. (lambda ()
  166. (set-current-module commands)
  167. (read-args prompt))))
  168. (loop)))
  169. (lambda (k . args)
  170. (apply values args)))))