Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

870 regels
26 KiB

4 jaren geleden
  1. ;;; swank-mit-scheme.scm --- SLIME server for MIT Scheme
  2. ;;
  3. ;; Copyright (C) 2008 Helmut Eller
  4. ;;
  5. ;; This file is licensed under the terms of the GNU General Public
  6. ;; License as distributed with Emacs (press C-h C-c for details).
  7. ;;;; Installation:
  8. #|
  9. 1. You need MIT Scheme 9.2
  10. 2. The Emacs side needs some fiddling. I have the following in
  11. my .emacs:
  12. (setq slime-lisp-implementations
  13. '((mit-scheme ("mit-scheme") :init mit-scheme-init)))
  14. (defun mit-scheme-init (file encoding)
  15. (format "%S\n\n"
  16. `(begin
  17. (load-option 'format)
  18. (load-option 'sos)
  19. (eval
  20. '(create-package-from-description
  21. (make-package-description '(swank) (list (list))
  22. (vector) (vector) (vector) false))
  23. (->environment '(package)))
  24. (load ,(expand-file-name
  25. ".../contrib/swank-mit-scheme.scm" ; <-- insert your path
  26. slime-path)
  27. (->environment '(swank)))
  28. (eval '(start-swank ,file) (->environment '(swank))))))
  29. (defun mit-scheme ()
  30. (interactive)
  31. (slime 'mit-scheme))
  32. (defun find-mit-scheme-package ()
  33. (save-excursion
  34. (let ((case-fold-search t))
  35. (and (re-search-backward "^[;]+ package: \\((.+)\\).*$" nil t)
  36. (match-string-no-properties 1)))))
  37. (setq slime-find-buffer-package-function 'find-mit-scheme-package)
  38. (add-hook 'scheme-mode-hook (lambda () (slime-mode 1)))
  39. The `mit-scheme-init' function first loads the SOS and FORMAT
  40. libraries, then creates a package "(swank)", and loads this file
  41. into that package. Finally it starts the server.
  42. `find-mit-scheme-package' tries to figure out which package the
  43. buffer belongs to, assuming that ";;; package: (FOO)" appears
  44. somewhere in the file. Luckily, this assumption is true for many of
  45. MIT Scheme's own files. Alternatively, you could add Emacs style
  46. -*- slime-buffer-package: "(FOO)" -*- file variables.
  47. 4. Start everything with `M-x mit-scheme'.
  48. |#
  49. ;;; package: (swank)
  50. (if (< (car (get-subsystem-version "Release"))
  51. '9)
  52. (error "This file requires MIT Scheme Release 9"))
  53. (define (swank port)
  54. (accept-connections (or port 4005) #f))
  55. ;; ### hardcoded port number for now. netcat-openbsd doesn't print
  56. ;; the listener port anymore.
  57. (define (start-swank port-file)
  58. (accept-connections 4055 port-file)
  59. )
  60. ;;;; Networking
  61. (define (accept-connections port port-file)
  62. (let ((sock (open-tcp-server-socket port (host-address-loopback))))
  63. (format #t "Listening on port: ~s~%" port)
  64. (if port-file (write-port-file port port-file))
  65. (dynamic-wind
  66. (lambda () #f)
  67. (lambda () (serve (tcp-server-connection-accept sock #t #f)))
  68. (lambda () (close-tcp-server-socket sock)))))
  69. (define (write-port-file portnumber filename)
  70. (call-with-output-file filename (lambda (p) (write portnumber p))))
  71. (define *top-level-restart* #f)
  72. (define (serve socket)
  73. (with-simple-restart
  74. 'disconnect "Close connection."
  75. (lambda ()
  76. (with-keyboard-interrupt-handler
  77. (lambda () (main-loop socket))))))
  78. (define (disconnect)
  79. (format #t "Disconnecting ...~%")
  80. (invoke-restart (find-restart 'disconnect)))
  81. (define (main-loop socket)
  82. (do () (#f)
  83. (with-simple-restart
  84. 'abort "Return to SLIME top-level."
  85. (lambda ()
  86. (fluid-let ((*top-level-restart* (find-restart 'abort)))
  87. (dispatch (read-packet socket) socket 0))))))
  88. (define (with-keyboard-interrupt-handler fun)
  89. (define (set-^G-handler exp)
  90. (eval `(vector-set! keyboard-interrupt-vector (char->ascii #\G) ,exp)
  91. (->environment '(runtime interrupt-handler))))
  92. (dynamic-wind
  93. (lambda () #f)
  94. (lambda ()
  95. (set-^G-handler
  96. `(lambda (char) (with-simple-restart
  97. 'continue "Continue from interrupt."
  98. (lambda () (error "Keyboard Interrupt.")))))
  99. (fun))
  100. (lambda ()
  101. (set-^G-handler '^G-interrupt-handler))))
  102. ;;;; Reading/Writing of SLIME packets
  103. (define (read-packet in)
  104. "Read an S-expression from STREAM using the SLIME protocol."
  105. (let* ((len (read-length in))
  106. (buffer (make-string len)))
  107. (fill-buffer! in buffer)
  108. (read-from-string buffer)))
  109. (define (write-packet message out)
  110. (let* ((string (write-to-string message)))
  111. (log-event "WRITE: [~a]~s~%" (string-length string) string)
  112. (write-length (string-length string) out)
  113. (write-string string out)
  114. (flush-output out)))
  115. (define (fill-buffer! in buffer)
  116. (read-string! buffer in))
  117. (define (read-length in)
  118. (if (eof-object? (peek-char in)) (disconnect))
  119. (do ((len 6 (1- len))
  120. (sum 0 (+ (* sum 16) (char->hex-digit (read-char in)))))
  121. ((zero? len) sum)))
  122. (define (ldb size position integer)
  123. "LoaD a Byte of SIZE bits at bit position POSITION from INTEGER."
  124. (fix:and (fix:lsh integer (- position))
  125. (1- (fix:lsh 1 size))))
  126. (define (write-length len out)
  127. (do ((pos 20 (- pos 4)))
  128. ((< pos 0))
  129. (write-hex-digit (ldb 4 pos len) out)))
  130. (define (write-hex-digit n out)
  131. (write-char (hex-digit->char n) out))
  132. (define (hex-digit->char n)
  133. (digit->char n 16))
  134. (define (char->hex-digit c)
  135. (char->digit c 16))
  136. ;;;; Event dispatching
  137. (define (dispatch request socket level)
  138. (log-event "READ: ~s~%" request)
  139. (case (car request)
  140. ((:emacs-rex) (apply emacs-rex socket level (cdr request)))))
  141. (define (swank-package)
  142. (or (name->package '(swank))
  143. (name->package '(user))))
  144. (define *buffer-package* #f)
  145. (define (find-buffer-package name)
  146. (if (elisp-false? name)
  147. #f
  148. (let ((v (ignore-errors
  149. (lambda () (name->package (read-from-string name))))))
  150. (and (package? v) v))))
  151. (define swank-env (->environment (swank-package)))
  152. (define (user-env buffer-package)
  153. (cond ((string? buffer-package)
  154. (let ((p (find-buffer-package buffer-package)))
  155. (if (not p) (error "Invalid package name: " buffer-package))
  156. (package/environment p)))
  157. (else (nearest-repl/environment))))
  158. ;; quote keywords
  159. (define (hack-quotes list)
  160. (map (lambda (x)
  161. (cond ((symbol? x) `(quote ,x))
  162. (#t x)))
  163. list))
  164. (define (emacs-rex socket level sexp package thread id)
  165. (let ((ok? #f) (result #f) (condition #f))
  166. (dynamic-wind
  167. (lambda () #f)
  168. (lambda ()
  169. (bind-condition-handler
  170. (list condition-type:serious-condition)
  171. (lambda (c) (set! condition c) (invoke-sldb socket (1+ level) c))
  172. (lambda ()
  173. (fluid-let ((*buffer-package* package))
  174. (set! result
  175. (eval (cons* (car sexp) socket (hack-quotes (cdr sexp)))
  176. swank-env))
  177. (set! ok? #t)))))
  178. (lambda ()
  179. (write-packet `(:return
  180. ,(if ok? `(:ok ,result)
  181. `(:abort
  182. ,(if condition
  183. (format #f "~a"
  184. (condition/type condition))
  185. "<unknown reason>")))
  186. ,id)
  187. socket)))))
  188. (define (swank:connection-info _)
  189. (let ((p (environment->package (user-env #f))))
  190. `(:pid ,(unix/current-pid)
  191. :package (:name ,(write-to-string (package/name p))
  192. :prompt ,(write-to-string (package/name p)))
  193. :lisp-implementation
  194. (:type "MIT Scheme" :version ,(get-subsystem-version-string "release"))
  195. :encoding (:coding-systems ("iso-8859-1"))
  196. )))
  197. (define (swank:quit-lisp _)
  198. (%exit))
  199. ;;;; Evaluation
  200. (define (swank-repl:listener-eval socket string)
  201. ;;(call-with-values (lambda () (eval-region string socket))
  202. ;; (lambda values `(:values . ,(map write-to-string values))))
  203. `(:values ,(write-to-string (eval-region string socket))))
  204. (define (eval-region string socket)
  205. (let ((sexp (read-from-string string)))
  206. (if (eof-object? exp)
  207. (values)
  208. (with-output-to-repl socket
  209. (lambda () (eval sexp (user-env *buffer-package*)))))))
  210. (define (with-output-to-repl socket fun)
  211. (let ((p (make-port repl-port-type socket)))
  212. (dynamic-wind
  213. (lambda () #f)
  214. (lambda () (with-output-to-port p fun))
  215. (lambda () (flush-output p)))))
  216. (define (swank:interactive-eval socket string)
  217. ;;(call-with-values (lambda () (eval-region string)) format-for-echo-area)
  218. (format-values (eval-region string socket))
  219. )
  220. (define (format-values . values)
  221. (if (null? values)
  222. "; No value"
  223. (with-string-output-port
  224. (lambda (out)
  225. (write-string "=> " out)
  226. (do ((vs values (cdr vs))) ((null? vs))
  227. (write (car vs) out)
  228. (if (not (null? (cdr vs)))
  229. (write-string ", " out)))))))
  230. (define (swank:pprint-eval _ string)
  231. (pprint-to-string (eval (read-from-string string)
  232. (user-env *buffer-package*))))
  233. (define (swank:interactive-eval-region socket string)
  234. (format-values (eval-region string socket)))
  235. (define (swank:set-package _ package)
  236. (set-repl/environment! (nearest-repl)
  237. (->environment (read-from-string package)))
  238. (let* ((p (environment->package (user-env #f)))
  239. (n (write-to-string (package/name p))))
  240. (list n n)))
  241. (define (repl-write-substring port string start end)
  242. (cond ((< start end)
  243. (write-packet `(:write-string ,(substring string start end))
  244. (port/state port))))
  245. (- end start))
  246. (define (repl-write-char port char)
  247. (write-packet `(:write-string ,(string char))
  248. (port/state port)))
  249. (define repl-port-type
  250. (make-port-type `((write-substring ,repl-write-substring)
  251. (write-char ,repl-write-char)) #f))
  252. (define (swank-repl:create-repl socket . _)
  253. (let* ((env (user-env #f))
  254. (name (format #f "~a" (package/name (environment->package env)))))
  255. (list name name)))
  256. ;;;; Compilation
  257. (define (swank:compile-string-for-emacs _ string . x)
  258. (apply
  259. (lambda (errors seconds)
  260. `(:compilation-result ,errors t ,seconds nil nil))
  261. (call-compiler
  262. (lambda ()
  263. (let* ((sexps (snarf-string string))
  264. (env (user-env *buffer-package*))
  265. (scode (syntax `(begin ,@sexps) env))
  266. (compiled-expression (compile-scode scode #t)))
  267. (scode-eval compiled-expression env))))))
  268. (define (snarf-string string)
  269. (with-input-from-string string
  270. (lambda ()
  271. (let loop ()
  272. (let ((e (read)))
  273. (if (eof-object? e) '() (cons e (loop))))))))
  274. (define (call-compiler fun)
  275. (let ((time #f))
  276. (with-timings fun
  277. (lambda (run-time gc-time real-time)
  278. (set! time real-time)))
  279. (list 'nil (internal-time/ticks->seconds time))))
  280. (define (swank:compiler-notes-for-emacs _) nil)
  281. (define (swank:compile-file-for-emacs socket file load?)
  282. (apply
  283. (lambda (errors seconds)
  284. (list ':compilation-result errors 't seconds load?
  285. (->namestring (pathname-name file))))
  286. (call-compiler
  287. (lambda () (with-output-to-repl socket (lambda () (compile-file file)))))))
  288. (define (swank:load-file socket file)
  289. (with-output-to-repl socket
  290. (lambda ()
  291. (pprint-to-string
  292. (load file (user-env *buffer-package*))))))
  293. (define (swank:disassemble-form _ string)
  294. (let ((sexp (let ((sexp (read-from-string string)))
  295. (cond ((and (pair? sexp) (eq? (car sexp) 'quote))
  296. (cadr sexp))
  297. (#t sexp)))))
  298. (with-output-to-string
  299. (lambda ()
  300. (compiler:disassemble
  301. (eval sexp (user-env *buffer-package*)))))))
  302. (define (swank:disassemble-symbol _ string)
  303. (with-output-to-string
  304. (lambda ()
  305. (compiler:disassemble
  306. (eval (read-from-string string)
  307. (user-env *buffer-package*))))))
  308. ;;;; Macroexpansion
  309. (define (swank:swank-macroexpand-all _ string)
  310. (with-output-to-string
  311. (lambda ()
  312. (pp (syntax (read-from-string string)
  313. (user-env *buffer-package*))))))
  314. (define swank:swank-macroexpand-1 swank:swank-macroexpand-all)
  315. (define swank:swank-macroexpand swank:swank-macroexpand-all)
  316. ;;; Arglist
  317. (define (swank:operator-arglist socket name pack)
  318. (let ((v (ignore-errors
  319. (lambda ()
  320. (string-trim-right
  321. (with-output-to-string
  322. (lambda ()
  323. (carefully-pa
  324. (eval (read-from-string name) (user-env pack))))))))))
  325. (if (condition? v) 'nil v)))
  326. (define (carefully-pa o)
  327. (cond ((arity-dispatched-procedure? o)
  328. ;; MIT Scheme crashes for (pa /)
  329. (display "arity-dispatched-procedure"))
  330. ((procedure? o) (pa o))
  331. (else (error "Not a procedure"))))
  332. ;;; Some unimplemented stuff.
  333. (define (swank:buffer-first-change . _) nil)
  334. (define (swank:filename-to-modulename . _) nil)
  335. (define (swank:swank-require . _) nil)
  336. ;; M-. is beyond my capabilities.
  337. (define (swank:find-definitions-for-emacs . _) nil)
  338. ;;; Debugger
  339. (define-structure (sldb-state (conc-name sldb-state.)) condition restarts)
  340. (define *sldb-state* #f)
  341. (define (invoke-sldb socket level condition)
  342. (fluid-let ((*sldb-state* (make-sldb-state condition (bound-restarts))))
  343. (dynamic-wind
  344. (lambda () #f)
  345. (lambda ()
  346. (write-packet `(:debug 0 ,level ,@(sldb-info *sldb-state* 0 20))
  347. socket)
  348. (sldb-loop level socket))
  349. (lambda ()
  350. (write-packet `(:debug-return 0 ,level nil) socket)))))
  351. (define (sldb-loop level socket)
  352. (write-packet `(:debug-activate 0 ,level) socket)
  353. (with-simple-restart
  354. 'abort (format #f "Return to SLDB level ~a." level)
  355. (lambda () (dispatch (read-packet socket) socket level)))
  356. (sldb-loop level socket))
  357. (define (sldb-info state start end)
  358. (let ((c (sldb-state.condition state))
  359. (rs (sldb-state.restarts state)))
  360. (list (list (condition/report-string c)
  361. (format #f " [~a]" (%condition-type/name (condition/type c)))
  362. nil)
  363. (sldb-restarts rs)
  364. (sldb-backtrace c start end)
  365. ;;'((0 "dummy frame"))
  366. '())))
  367. (define %condition-type/name
  368. (eval '%condition-type/name (->environment '(runtime error-handler))))
  369. (define (sldb-restarts restarts)
  370. (map (lambda (r)
  371. (list (symbol->string (restart/name r))
  372. (with-string-output-port
  373. (lambda (p) (write-restart-report r p)))))
  374. restarts))
  375. (define (swank:throw-to-toplevel . _)
  376. (invoke-restart *top-level-restart*))
  377. (define (swank:sldb-abort . _)
  378. (abort (sldb-state.restarts *sldb-state*)))
  379. (define (swank:sldb-continue . _)
  380. (continue (sldb-state.restarts *sldb-state*)))
  381. (define (swank:invoke-nth-restart-for-emacs _ _sldb-level n)
  382. (invoke-restart (list-ref (sldb-state.restarts *sldb-state*) n)))
  383. (define (swank:debugger-info-for-emacs _ from to)
  384. (sldb-info *sldb-state* from to))
  385. (define (swank:backtrace _ from to)
  386. (sldb-backtrace (sldb-state.condition *sldb-state*) from to))
  387. (define (sldb-backtrace condition from to)
  388. (sldb-backtrace-aux (condition/continuation condition) from to))
  389. (define (sldb-backtrace-aux k from to)
  390. (let ((l (map frame>string (substream (continuation>frames k) from to))))
  391. (let loop ((i from) (l l))
  392. (if (null? l)
  393. '()
  394. (cons (list i (car l)) (loop (1+ i) (cdr l)))))))
  395. ;; Stack parser fails for this:
  396. ;; (map (lambda (x) x) "/tmp/x.x")
  397. (define (continuation>frames k)
  398. (let loop ((frame (continuation->stack-frame k)))
  399. (cond ((not frame) (stream))
  400. (else
  401. (let ((next (ignore-errors
  402. (lambda () (stack-frame/next-subproblem frame)))))
  403. (cons-stream frame
  404. (if (condition? next)
  405. (stream next)
  406. (loop next))))))))
  407. (define (frame>string frame)
  408. (if (condition? frame)
  409. (format #f "Bogus frame: ~a ~a" frame
  410. (condition/report-string frame))
  411. (with-string-output-port (lambda (p) (print-frame frame p)))))
  412. (define (print-frame frame port)
  413. (define (invalid-subexpression? subexpression)
  414. (or (debugging-info/undefined-expression? subexpression)
  415. (debugging-info/unknown-expression? subexpression)))
  416. (define (invalid-expression? expression)
  417. (or (debugging-info/undefined-expression? expression)
  418. (debugging-info/compiled-code? expression)))
  419. (with-values (lambda () (stack-frame/debugging-info frame))
  420. (lambda (expression environment subexpression)
  421. (cond ((debugging-info/compiled-code? expression)
  422. (write-string ";unknown compiled code" port))
  423. ((not (debugging-info/undefined-expression? expression))
  424. (fluid-let ((*unparse-primitives-by-name?* #t))
  425. (write
  426. (unsyntax (if (invalid-subexpression? subexpression)
  427. expression
  428. subexpression))
  429. port)))
  430. ((debugging-info/noise? expression)
  431. (write-string ";" port)
  432. (write-string ((debugging-info/noise expression) #f)
  433. port))
  434. (else
  435. (write-string ";undefined expression" port))))))
  436. (define (substream s from to)
  437. (let loop ((i 0) (l '()) (s s))
  438. (cond ((or (= i to) (stream-null? s)) (reverse l))
  439. ((< i from) (loop (1+ i) l (stream-cdr s)))
  440. (else (loop (1+ i) (cons (stream-car s) l) (stream-cdr s))))))
  441. (define (swank:frame-locals-and-catch-tags _ frame)
  442. (list (map frame-var>elisp (frame-vars (sldb-get-frame frame)))
  443. '()))
  444. (define (frame-vars frame)
  445. (with-values (lambda () (stack-frame/debugging-info frame))
  446. (lambda (expression environment subexpression)
  447. (cond ((environment? environment)
  448. (environment>frame-vars environment))
  449. (else '())))))
  450. (define (environment>frame-vars environment)
  451. (let loop ((e environment))
  452. (cond ((environment->package e) '())
  453. (else (append (environment-bindings e)
  454. (if (environment-has-parent? e)
  455. (loop (environment-parent e))
  456. '()))))))
  457. (define (frame-var>elisp b)
  458. (list ':name (write-to-string (car b))
  459. ':value (cond ((null? (cdr b)) "{unavailable}")
  460. (else (>line (cadr b))))
  461. ':id 0))
  462. (define (sldb-get-frame index)
  463. (stream-ref (continuation>frames
  464. (condition/continuation
  465. (sldb-state.condition *sldb-state*)))
  466. index))
  467. (define (frame-var-value frame var)
  468. (let ((binding (list-ref (frame-vars frame) var)))
  469. (cond ((cdr binding) (cadr binding))
  470. (else unspecific))))
  471. (define (swank:inspect-frame-var _ frame var)
  472. (reset-inspector)
  473. (inspect-object (frame-var-value (sldb-get-frame frame) var)))
  474. ;;;; Completion
  475. (define (swank:simple-completions _ string package)
  476. (let ((strings (all-completions string (user-env package) string-prefix?)))
  477. (list (sort strings string<?)
  478. (longest-common-prefix strings))))
  479. (define (all-completions pattern env match?)
  480. (let ((ss (map %symbol->string (environment-names env))))
  481. (keep-matching-items ss (lambda (s) (match? pattern s)))))
  482. ;; symbol->string is too slow
  483. (define %symbol->string symbol-name)
  484. (define (environment-names env)
  485. (append (environment-bound-names env)
  486. (if (environment-has-parent? env)
  487. (environment-names (environment-parent env))
  488. '())))
  489. (define (longest-common-prefix strings)
  490. (define (common-prefix s1 s2)
  491. (substring s1 0 (string-match-forward s1 s2)))
  492. (reduce common-prefix "" strings))
  493. ;;;; Apropos
  494. (define (swank:apropos-list-for-emacs _ name #!optional
  495. external-only case-sensitive package)
  496. (let* ((pkg (and (string? package)
  497. (find-package (read-from-string package))))
  498. (parent (and (not (default-object? external-only))
  499. (elisp-false? external-only)))
  500. (ss (append-map (lambda (p)
  501. (map (lambda (s) (cons p s))
  502. (apropos-list name p (and pkg parent))))
  503. (if pkg (list pkg) (all-packages))))
  504. (ss (sublist ss 0 (min (length ss) 200))))
  505. (map (lambda (e)
  506. (let ((p (car e)) (s (cdr e)))
  507. (list ':designator (format #f "~a ~a" s (package/name p))
  508. ':variable (>line
  509. (ignore-errors
  510. (lambda () (package-lookup p s)))))))
  511. ss)))
  512. (define (swank:list-all-package-names . _)
  513. (map (lambda (p) (write-to-string (package/name p)))
  514. (all-packages)))
  515. (define (all-packages)
  516. (define (package-and-children package)
  517. (append (list package)
  518. (append-map package-and-children (package/children package))))
  519. (package-and-children system-global-package))
  520. ;;;; Inspector
  521. (define-structure (inspector-state (conc-name istate.))
  522. object parts next previous content)
  523. (define istate #f)
  524. (define (reset-inspector)
  525. (set! istate #f))
  526. (define (swank:init-inspector _ string)
  527. (reset-inspector)
  528. (inspect-object (eval (read-from-string string)
  529. (user-env *buffer-package*))))
  530. (define (inspect-object o)
  531. (let ((previous istate)
  532. (content (inspect o))
  533. (parts (make-eqv-hash-table)))
  534. (set! istate (make-inspector-state o parts #f previous content))
  535. (if previous (set-istate.next! previous istate))
  536. (istate>elisp istate)))
  537. (define (istate>elisp istate)
  538. (list ':title (>line (istate.object istate))
  539. ':id (assign-index (istate.object istate) (istate.parts istate))
  540. ':content (prepare-range (istate.parts istate)
  541. (istate.content istate)
  542. 0 500)))
  543. (define (assign-index o parts)
  544. (let ((i (hash-table/count parts)))
  545. (hash-table/put! parts i o)
  546. i))
  547. (define (prepare-range parts content from to)
  548. (let* ((cs (substream content from to))
  549. (ps (prepare-parts cs parts)))
  550. (list ps
  551. (if (< (length cs) (- to from))
  552. (+ from (length cs))
  553. (+ to 1000))
  554. from to)))
  555. (define (prepare-parts ps parts)
  556. (define (line label value)
  557. `(,(format #f "~a: " label)
  558. (:value ,(>line value) ,(assign-index value parts))
  559. "\n"))
  560. (append-map (lambda (p)
  561. (cond ((string? p) (list p))
  562. ((symbol? p) (list (symbol->string p)))
  563. (#t
  564. (case (car p)
  565. ((line) (apply line (cdr p)))
  566. (else (error "Invalid part:" p))))))
  567. ps))
  568. (define (swank:inspect-nth-part _ index)
  569. (inspect-object (hash-table/get (istate.parts istate) index 'no-such-part)))
  570. (define (swank:quit-inspector _)
  571. (reset-inspector))
  572. (define (swank:inspector-pop _)
  573. (cond ((istate.previous istate)
  574. (set! istate (istate.previous istate))
  575. (istate>elisp istate))
  576. (else 'nil)))
  577. (define (swank:inspector-next _)
  578. (cond ((istate.next istate)
  579. (set! istate (istate.next istate))
  580. (istate>elisp istate))
  581. (else 'nil)))
  582. (define (swank:inspector-range _ from to)
  583. (prepare-range (istate.parts istate)
  584. (istate.content istate)
  585. from to))
  586. (define-syntax stream*
  587. (syntax-rules ()
  588. ((stream* tail) tail)
  589. ((stream* e1 e2 ...) (cons-stream e1 (stream* e2 ...)))))
  590. (define (iline label value) `(line ,label ,value))
  591. (define-generic inspect (o))
  592. (define-method inspect ((o <object>))
  593. (cond ((environment? o) (inspect-environment o))
  594. ((vector? o) (inspect-vector o))
  595. ((procedure? o) (inspect-procedure o))
  596. ((compiled-code-block? o) (inspect-code-block o))
  597. ;;((system-pair? o) (inspect-system-pair o))
  598. ((probably-scode? o) (inspect-scode o))
  599. (else (inspect-fallback o))))
  600. (define (inspect-fallback o)
  601. (let* ((class (object-class o))
  602. (slots (class-slots class)))
  603. (stream*
  604. (iline "Class" class)
  605. (let loop ((slots slots))
  606. (cond ((null? slots) (stream))
  607. (else
  608. (let ((n (slot-name (car slots))))
  609. (stream* (iline n (slot-value o n))
  610. (loop (cdr slots))))))))))
  611. (define-method inspect ((o <pair>))
  612. (if (or (pair? (cdr o)) (null? (cdr o)))
  613. (inspect-list o)
  614. (inspect-cons o)))
  615. (define (inspect-cons o)
  616. (stream (iline "car" (car o))
  617. (iline "cdr" (cdr o))))
  618. (define (inspect-list o)
  619. (let loop ((i 0) (o o))
  620. (cond ((null? o) (stream))
  621. ((or (pair? (cdr o)) (null? (cdr o)))
  622. (stream* (iline i (car o))
  623. (loop (1+ i) (cdr o))))
  624. (else
  625. (stream (iline i (car o))
  626. (iline "tail" (cdr o)))))))
  627. (define (inspect-environment o)
  628. (stream*
  629. (iline "(package)" (environment->package o))
  630. (let loop ((bs (environment-bindings o)))
  631. (cond ((null? bs)
  632. (if (environment-has-parent? o)
  633. (stream (iline "(<parent>)" (environment-parent o)))
  634. (stream)))
  635. (else
  636. (let* ((b (car bs)) (s (car b)))
  637. (cond ((null? (cdr b))
  638. (stream* s " {" (environment-reference-type o s) "}\n"
  639. (loop (cdr bs))))
  640. (else
  641. (stream* (iline s (cadr b))
  642. (loop (cdr bs)))))))))))
  643. (define (inspect-vector o)
  644. (let ((len (vector-length o)))
  645. (let loop ((i 0))
  646. (cond ((= i len) (stream))
  647. (else (stream* (iline i (vector-ref o i))
  648. (loop (1+ i))))))))
  649. (define (inspect-procedure o)
  650. (cond ((primitive-procedure? o)
  651. (stream (iline "name" (primitive-procedure-name o))
  652. (iline "arity" (primitive-procedure-arity o))
  653. (iline "doc" (primitive-procedure-documentation o))))
  654. ((compound-procedure? o)
  655. (stream (iline "arity" (procedure-arity o))
  656. (iline "lambda" (procedure-lambda o))
  657. (iline "env" (ignore-errors
  658. (lambda () (procedure-environment o))))))
  659. (else
  660. (stream
  661. (iline "block" (compiled-entry/block o))
  662. (with-output-to-string (lambda () (compiler:disassemble o)))))))
  663. (define (inspect-code-block o)
  664. (stream-append
  665. (let loop ((i (compiled-code-block/constants-start o)))
  666. (cond ((>= i (compiled-code-block/constants-end o)) (stream))
  667. (else
  668. (stream*
  669. (iline i (system-vector-ref o i))
  670. (loop (+ i compiled-code-block/bytes-per-object))))))
  671. (stream (iline "debuginfo" (compiled-code-block/debugging-info o))
  672. (iline "env" (compiled-code-block/environment o))
  673. (with-output-to-string (lambda () (compiler:disassemble o))))))
  674. (define (inspect-scode o)
  675. (stream (pprint-to-string o)))
  676. (define (probably-scode? o)
  677. (define tests (list access? assignment? combination? comment?
  678. conditional? definition? delay? disjunction? lambda?
  679. quotation? sequence? the-environment? variable?))
  680. (let loop ((tests tests))
  681. (cond ((null? tests) #f)
  682. (((car tests) o))
  683. (else (loop (cdr tests))))))
  684. (define (inspect-system-pair o)
  685. (stream (iline "car" (system-pair-car o))
  686. (iline "cdr" (system-pair-cdr o))))
  687. ;;;; Auxilary functions
  688. (define nil '())
  689. (define t 't)
  690. (define (elisp-false? o) (member o '(nil ())))
  691. (define (elisp-true? o) (not (elisp-false? o)))
  692. (define (>line o)
  693. (let ((r (write-to-string o 100)))
  694. (cond ((not (car r)) (cdr r))
  695. (else (string-append (cdr r) " ..")))))
  696. ;; Must compile >line otherwise we can't write unassigend-reference-traps.
  697. (set! >line (compile-procedure >line))
  698. (define (read-from-string s) (with-input-from-string s read))
  699. (define (pprint-to-string o)
  700. (with-string-output-port
  701. (lambda (p)
  702. (fluid-let ((*unparser-list-breadth-limit* 10)
  703. (*unparser-list-depth-limit* 4)
  704. (*unparser-string-length-limit* 100))
  705. (pp o p)))))
  706. ;(define (1+ n) (+ n 1))
  707. (define (1- n) (- n 1))
  708. (define (package-lookup package name)
  709. (let ((p (if (package? package) package (find-package package))))
  710. (environment-lookup (package/environment p) name)))
  711. (define log-port (current-output-port))
  712. (define (log-event fstring . args)
  713. ;;(apply format log-port fstring args)
  714. #f
  715. )
  716. ;;; swank-mit-scheme.scm ends here