inspect.scm 4.7 KB

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