menu.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; This breaks abstractions left and right.
  4. ; Inspector state:
  5. ; menu ; cached result of (prepare-menu thing). This is a list of
  6. ; lists (<name-or-#f> <value>).
  7. ; position ; position within menu; modified by M (more) command
  8. ; stack ; list of other things
  9. ;
  10. ; The current thing being inspected is the focus object.
  11. (define (current-menu)
  12. (or (maybe-menu)
  13. (let ((menu (prepare-menu (focus-object))))
  14. (set-menu! menu)
  15. (set-menu-position! 0)
  16. menu)))
  17. (define (present-menu)
  18. (let ((menu (current-menu))) ; may set menu position
  19. (display-menu menu
  20. (menu-position)
  21. (command-output))))
  22. (define (present-more-menu)
  23. (let* ((menu (current-menu))
  24. (position (menu-position)))
  25. (if (> (menu-length menu)
  26. (+ (inspector-menu-limit) position))
  27. (begin
  28. (set-menu-position! (- (+ position
  29. (inspector-menu-limit))
  30. 1))
  31. (present-menu))
  32. (write-line "There is no more." (command-output)))))
  33. ;----------------
  34. ; These two are used by the inspector.
  35. (define (current-menu-length)
  36. (menu-length (current-menu)))
  37. (define (current-menu-ref n)
  38. (cadar (menu-refs (current-menu) n 1)))
  39. ; The menu ADT has two functions, length and refs. A menu is a list
  40. ; (<length> <refs-function>)
  41. (define (menu-length menu)
  42. (car menu))
  43. ; Return a list of the next COUNT items starting from N, where each items is
  44. ; a list (<name-or-#f> <thing>). The returned list may be shorter than N if
  45. ; there aren't N possible items, or longer, for no reason at all.
  46. (define (menu-refs menu n count)
  47. ((cadr menu) n count))
  48. (define (list->menu items)
  49. (list (length items)
  50. (lambda (i count)
  51. (list-tail items i))))
  52. (define (long-list->menu contents length)
  53. (list length
  54. (lambda (start count)
  55. (do ((i 0 (+ i 1))
  56. (contents (list-tail contents start) (cdr contents))
  57. (r '() (cons (list #f (car contents)) r)))
  58. ((or (= i count)
  59. (null? contents))
  60. (reverse r))))))
  61. (define (indexed->menu thing length ref)
  62. (list length
  63. (lambda (start count)
  64. (do ((i 0 (+ i 1))
  65. (r '() (cons (list #f (ref thing (+ start i))) r)))
  66. ((or (= i count)
  67. (= (+ i start) length))
  68. (reverse r))))))
  69. ; Get a menu for THING. We know about a fixed set of types.
  70. (define (prepare-menu thing)
  71. (cond ((vector? thing)
  72. (indexed->menu thing (vector-length thing) vector-ref))
  73. ((template? thing)
  74. (indexed->menu thing (template-length thing) template-ref))
  75. ((pair? thing)
  76. (let ((length (careful-length thing)))
  77. (if (eq? length 'improper)
  78. (list->menu `((car ,(car thing)) (cdr ,(cdr thing))))
  79. (long-list->menu thing
  80. (if (eq? length 'circular)
  81. 9999999
  82. length)))))
  83. (else
  84. (list->menu
  85. (cond ((closure? thing)
  86. (prepare-environment-menu
  87. (closure-env thing)
  88. (debug-data-env-shape (template-debug-data
  89. (closure-template thing))
  90. #f)))
  91. ((continuation? thing)
  92. (prepare-continuation-menu thing))
  93. ((record? thing)
  94. (prepare-record-menu thing))
  95. ((location? thing)
  96. `((id ,(location-id thing))
  97. (contents ,(contents thing))))
  98. ((cell? thing)
  99. `((ref ,(cell-ref thing))))
  100. ((weak-pointer? thing)
  101. `((ref ,(weak-pointer-ref thing))))
  102. ((transport-link-cell? thing)
  103. `((key ,(transport-link-cell-key thing))
  104. (value ,(transport-link-cell-value thing))
  105. (tconc ,(transport-link-cell-tconc thing))
  106. (next ,(transport-link-cell-next thing))))
  107. (else '()))))))
  108. (define (careful-length list)
  109. (let loop ((fast list) (len 0) (slow list) (move-slow? #f))
  110. (cond ((eq? '() fast)
  111. len)
  112. ((not (pair? fast))
  113. 'improper)
  114. ((not move-slow?)
  115. (loop (cdr fast) (+ len 1) slow #t))
  116. ((eq? fast slow)
  117. 'circular)
  118. (else
  119. (loop (cdr fast) (+ len 1) (cdr slow) #f)))))
  120. ; Some values in the operand stack are vectors that represent either the
  121. ; saved environment or a newly created one for recursive procedures.
  122. ; The debug data has names for some values in the stack and for those
  123. ; in the environments.
  124. (define (prepare-continuation-menu thing)
  125. (let ((shape (debug-data-env-shape (continuation-debug-data thing)
  126. (continuation-pc thing)))
  127. (args (do ((i 0 (+ i 1))
  128. (v '() (cons (continuation-arg thing i) v)))
  129. ((= i (continuation-arg-count thing))
  130. v))))
  131. (extend-cont-menu 0 args shape '())))
  132. (define (extend-cont-menu i args shape menu)
  133. (if (null? args)
  134. menu
  135. (let ((names (assq i shape)))
  136. (if (and names
  137. (not (null? (cdr names))))
  138. (extend-cont-menu-with-names (cdr names) i args shape menu)
  139. (extend-cont-menu (+ i 1)
  140. (cdr args)
  141. shape
  142. (cons (list #f (car args))
  143. menu))))))
  144. (define (extend-cont-menu-with-names names i args shape menu)
  145. (cond ((null? names)
  146. (extend-cont-menu i args shape menu))
  147. ((pair? (car names))
  148. (let ((values (car args)))
  149. (do ((ns (car names) (cdr ns))
  150. (j 0 (+ j 1))
  151. (menu menu (cons (list (car ns) (vector-ref values j))
  152. menu)))
  153. ((null? ns)
  154. (extend-cont-menu-with-names (cdr names)
  155. (+ i 1)
  156. (cdr args)
  157. shape
  158. menu)))))
  159. (else
  160. (extend-cont-menu-with-names (cdr names)
  161. (+ i 1)
  162. (cdr args)
  163. shape
  164. (cons (list (car names) (car args))
  165. menu)))))
  166. (define (continuation-debug-data thing)
  167. (let ((template (continuation-template thing)))
  168. (if template
  169. (template-debug-data template)
  170. #f)))
  171. ; Records that have record types get printed with the names of the fields.
  172. (define (prepare-record-menu thing)
  173. (let ((rt (record-type thing))
  174. (z (record-length thing)))
  175. (if (record-type? rt)
  176. (let loop ((names (record-type-field-names rt))
  177. (rev '())
  178. (i 1))
  179. (if (< i z)
  180. (call-with-values
  181. (lambda ()
  182. (if (pair? names)
  183. (values (car names) (cdr names))
  184. ;; the rest are all bases
  185. (values 'base '())))
  186. (lambda (name names)
  187. (loop names (cons (list name (record-ref thing i)) rev) (+ 1 i))))
  188. (reverse rev)))
  189. (do ((i (- z 1) (- i 1))
  190. (l '() (cons (list #f (record-ref thing i)) l)))
  191. ((< i 0) l)))))
  192. ; all field names, supertypes included
  193. (define (record-type-all-field-names rt)
  194. (let loop ((rt rt)
  195. (rev '()))
  196. (cond
  197. ((record-type-parent rt)
  198. => (lambda (prt)
  199. (loop prt (append (reverse (record-type-field-names rt)) rev))))
  200. (else
  201. (reverse (append (reverse (record-type-field-names rt)) rev))))))
  202. ; We may have the names (`shape') for environments, in which case they
  203. ; are used in the menus.
  204. (define (prepare-environment-menu env shape)
  205. (if (vector? env)
  206. (let ((values (rib-values env)))
  207. (if (pair? shape)
  208. (append (map list (car shape) values)
  209. (prepare-environment-menu (vector-ref env 0)
  210. (cdr shape)))
  211. (append (map (lambda (x)
  212. (list #f x))
  213. values)
  214. (prepare-environment-menu (vector-ref env 0)
  215. shape))))
  216. '()))
  217. (define (rib-values env)
  218. (let ((z (vector-length env)))
  219. (do ((i 0 (+ i 1))
  220. (l '() (cons (if (vector-unassigned? env i)
  221. 'unassigned
  222. (vector-ref env i))
  223. l)))
  224. ((>= i z)
  225. (reverse l)))))
  226. ;----------------
  227. ; Printing menus.
  228. ;
  229. ; If the current thing is a continuation we print its source code first.
  230. ; Then we step down the menu until we run out or we reach the menu limit.
  231. (define (display-menu menu start port)
  232. (newline port)
  233. (maybe-display-source (focus-object) #f)
  234. (let ((items (menu-refs menu start (+ (inspector-menu-limit) 1)))
  235. (limit (+ start (inspector-menu-limit))))
  236. (let loop ((i start) (items items))
  237. (with-limited-output
  238. (lambda ()
  239. (cond ((null? items))
  240. ((and (>= i limit)
  241. (not (null? items)))
  242. (display " [m] more..." port) (newline port))
  243. (else
  244. (let ((item (car items)))
  245. (display " [" port)
  246. (write i port)
  247. (if (car item)
  248. (begin (display ": " port)
  249. (write-carefully (car item) port)))
  250. (display "] " port)
  251. (write-carefully (cadr item) port)
  252. (newline port)
  253. (loop (+ i 1) (cdr items))))))))))
  254. ; Exception continuations don't have source, so we get the source from
  255. ; the next continuation if it is from the same procedure invocation.
  256. (define (maybe-display-source thing vm-exception?)
  257. (cond ((not (continuation? thing))
  258. (values))
  259. ((vm-exception-continuation? thing)
  260. (let ((next (continuation-cont thing)))
  261. (if (not (eq? next (continuation-cont thing)))
  262. (maybe-display-source next #t))))
  263. (else
  264. (let ((dd (continuation-debug-data thing)))
  265. (if dd
  266. (let ((source (assoc (continuation-pc thing)
  267. (debug-data-source dd))))
  268. (if source
  269. (display-source-info (cdr source) vm-exception?))))))))
  270. ; Show the source code for a continuation, if we have it.
  271. (define (display-source-info info vm-exception?)
  272. (let ((o-port (command-output)))
  273. (if (pair? info)
  274. (let ((exp (car info)))
  275. (display (if vm-exception?
  276. "Next call is "
  277. "Waiting for ")
  278. o-port)
  279. (limited-write exp o-port
  280. (inspector-writing-depth)
  281. (inspector-writing-length))
  282. (newline o-port)
  283. (if (and (pair? (cdr info))
  284. (integer? (cadr info)))
  285. (let ((i (cadr info))
  286. (parent (cddr info)))
  287. (display " in " o-port)
  288. (limited-write (append (sublist parent 0 i)
  289. (list '^^^)
  290. (list-tail parent (+ i 1)))
  291. o-port
  292. (inspector-writing-depth)
  293. (inspector-writing-length))
  294. (newline o-port)))))))
  295. ;----------------
  296. ; Selection commands
  297. (define (selection-command? x)
  298. (or (integer? x)
  299. (memq x '(u d template))))
  300. ;----------------
  301. ; I/O Utilities
  302. (define $write-depth (make-fluid -1))
  303. (define $write-length (make-fluid -1))
  304. (define (with-limited-output thunk . limits)
  305. (let-fluids $write-length (if (pair? limits)
  306. (car limits)
  307. (inspector-writing-length))
  308. $write-depth (if (and (pair? limits)
  309. (pair? (cdr limits)))
  310. (cadr limits)
  311. (inspector-writing-depth))
  312. thunk))
  313. (define (write-carefully x port)
  314. (if (error? (ignore-errors (lambda ()
  315. (limited-write x port
  316. (fluid $write-depth)
  317. (fluid $write-length))
  318. #f)))
  319. (display "<Error while printing.>" port)))
  320. (define (write-line string port)
  321. (display string port)
  322. (newline port))