inspect.scm 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; A dirty little inspector.
  3. ; Look and feel shamelessly plagiarized from the Lucid Lisp inspector.
  4. ; There are three commands for invoking the inspector with different
  5. ; initial objects:
  6. ; ,inspect -> focus object
  7. ; ,inspect <exp> -> value of <exp>
  8. ; ,debug -> continuation of stopped thread(s), preferentially
  9. ; chooses the thread with the most recent error
  10. ; ,threads -> list of current command level's threads
  11. (define-command-syntax 'inspect "[<exp>]" "invoke the inspector"
  12. '(&opt form))
  13. (define-command-syntax 'debug "" "inspect the current continuation" '())
  14. (define-command-syntax 'threads "" "inspect stopped threads" '())
  15. (define (debug)
  16. (new-selection (or (command-continuation)
  17. (command-threads)))
  18. (set-command-results! (list (focus-object)) #f) ; force menu printing
  19. (if (not (value-stack))
  20. (set-value-stack! '())))
  21. (define (threads)
  22. (set-focus-object! (command-threads))
  23. (set-command-results! (focus-object) #f)
  24. (if (not (value-stack))
  25. (set-value-stack! '())))
  26. (define (inspect . maybe-exp)
  27. (if (null? maybe-exp)
  28. (set-command-results! (list (focus-object)) #f) ; force menu printing
  29. (evaluate-and-select (car maybe-exp)
  30. (environment-for-commands)))
  31. (if (not (value-stack))
  32. (set-value-stack! '())))
  33. ;----------------
  34. ; Menu commands.
  35. (define-command-syntax 'menu "" "print a selection menu for the focus object"
  36. '())
  37. (define menu present-menu)
  38. (define-command-syntax 'm #f #f '())
  39. (define m present-more-menu)
  40. ; Leaving.
  41. (define-command-syntax 'q "" "leave inspection mode" '())
  42. (define (q)
  43. (set-command-results! (list (focus-object)) #f)
  44. (set-value-stack! #f))
  45. ; Menu selection
  46. (define (select-menu-item . selection-commands)
  47. (execute-selection-commands selection-commands))
  48. (define (execute-selection-commands commands)
  49. (for-each execute-selection-command commands))
  50. (define (new-selection value)
  51. (set-focus-object! value)
  52. (set-command-results! (list value) #f))
  53. (define (execute-selection-command name)
  54. (if (integer? name)
  55. (begin
  56. (if (and (>= name 0)
  57. (< name (current-menu-length)))
  58. (new-selection (current-menu-ref name))
  59. (write-line "Invalid choice." (command-output))))
  60. (case name
  61. ((u)
  62. (let ((stack (value-stack)))
  63. (cond ((null? stack)
  64. (write-line "Can't go up from here." (command-output)))
  65. ((not stack)
  66. (write-line "No value stack: not in inspection mode."
  67. (command-output)))
  68. (else
  69. (pop-value-stack!)
  70. (set-command-results! (list (focus-object)))))))
  71. ((d)
  72. (if (continuation? (focus-object))
  73. (new-selection (continuation-cont (focus-object)))
  74. (write-line "Can't go down from a non-continuation."
  75. (command-output))))
  76. ((template)
  77. (let ((template (coerce-to-template (focus-object))))
  78. (if template
  79. (new-selection template)
  80. (write-line
  81. (if (continuation? (focus-object))
  82. "Unable to locate a template in this continuation."
  83. "Not a procedure or a continuation.")
  84. (command-output)))))
  85. (else
  86. (error "bad selection command" name)))))
  87. (define (coerce-to-template obj)
  88. (cond ((template? obj)
  89. obj)
  90. ((closure? obj)
  91. (closure-template obj))
  92. ((continuation? obj)
  93. (continuation-template obj))
  94. (else
  95. #f)))
  96. (define (selection-command name)
  97. (lambda more-commands
  98. (execute-selection-commands (cons name more-commands))))
  99. (define template (selection-command 'template))
  100. (define u (selection-command 'u))
  101. (define d (selection-command 'd))
  102. (define-command-syntax 'template "" "inspect template" '(&rest selection-command))
  103. (define-command-syntax 'u "" "pop inspector stack" '(&rest selection-command))
  104. (define-command-syntax 'd "" "down stack" '(&rest selection-command))
  105. ;----------------
  106. ; A command to print out the file in which a procedure is defined.
  107. ; Why is this here and not in debug.scm?
  108. (define-command-syntax 'where "[<procedure>]"
  109. "show procedure's source file name"
  110. '(&opt expression))
  111. (define (where . maybe-exp)
  112. (let ((proc (if (null? maybe-exp)
  113. (focus-object)
  114. (eval (car maybe-exp) (environment-for-commands))))
  115. (port (command-output)))
  116. (if (procedure? proc)
  117. (let ((probe (where-defined proc)))
  118. (if probe
  119. (display probe port)
  120. (display "Source file not recorded" port)))
  121. (display "Not a procedure" port))
  122. (newline port)))
  123. (define (where-defined thing)
  124. (let loop ((dd (template-debug-data (closure-template thing))))
  125. (if (debug-data? dd)
  126. (if (string? (debug-data-name dd))
  127. (debug-data-name dd)
  128. (loop (debug-data-parent dd)))
  129. #f)))