PageRenderTime 53ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/local-lisp/slime/swank-sbcl.lisp

https://bitbucket.org/sakito/dot.emacs.d/
Lisp | 1659 lines | 1318 code | 229 blank | 112 comment | 29 complexity | 9c414af76aeda3a83ac5a441390e7000 MD5 | raw file
Possible License(s): GPL-3.0, CC-BY-SA-4.0, GPL-2.0, Unlicense

Large files files are truncated, but you can click here to view the full file

  1. ;;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
  2. ;;;
  3. ;;; swank-sbcl.lisp --- SLIME backend for SBCL.
  4. ;;;
  5. ;;; Created 2003, Daniel Barlow <dan@metacircles.com>
  6. ;;;
  7. ;;; This code has been placed in the Public Domain. All warranties are
  8. ;;; disclaimed.
  9. ;;; Requires the SB-INTROSPECT contrib.
  10. ;;; Administrivia
  11. (in-package :swank-backend)
  12. (eval-when (:compile-toplevel :load-toplevel :execute)
  13. (require 'sb-bsd-sockets)
  14. (require 'sb-introspect)
  15. (require 'sb-posix)
  16. (require 'sb-cltl2))
  17. (declaim (optimize (debug 2)
  18. (sb-c::insert-step-conditions 0)
  19. (sb-c::insert-debug-catch 0)
  20. (sb-c::merge-tail-calls 2)))
  21. (import-from :sb-gray *gray-stream-symbols* :swank-backend)
  22. ;;; backwards compability tests
  23. (eval-when (:compile-toplevel :load-toplevel :execute)
  24. ;; Generate a form suitable for testing for stepper support (0.9.17)
  25. ;; with #+.
  26. (defun sbcl-with-new-stepper-p ()
  27. (with-symbol 'enable-stepping 'sb-impl))
  28. ;; Ditto for weak hash-tables
  29. (defun sbcl-with-weak-hash-tables ()
  30. (with-symbol 'hash-table-weakness 'sb-ext))
  31. ;; And for xref support (1.0.1)
  32. (defun sbcl-with-xref-p ()
  33. (with-symbol 'who-calls 'sb-introspect))
  34. ;; ... for restart-frame support (1.0.2)
  35. (defun sbcl-with-restart-frame ()
  36. (with-symbol 'frame-has-debug-tag-p 'sb-debug)))
  37. ;;; swank-mop
  38. (import-swank-mop-symbols :sb-mop '(:slot-definition-documentation))
  39. (defun swank-mop:slot-definition-documentation (slot)
  40. (sb-pcl::documentation slot t))
  41. ;;; Connection info
  42. (defimplementation lisp-implementation-type-name ()
  43. "sbcl")
  44. ;; Declare return type explicitly to shut up STYLE-WARNINGS about
  45. ;; %SAP-ALIEN in ENABLE-SIGIO-ON-FD below.
  46. (declaim (ftype (function () (values (signed-byte 32) &optional)) getpid))
  47. (defimplementation getpid ()
  48. (sb-posix:getpid))
  49. ;;; TCP Server
  50. (defimplementation preferred-communication-style ()
  51. (cond
  52. ;; fixme: when SBCL/win32 gains better select() support, remove
  53. ;; this.
  54. ((member :win32 *features*) nil)
  55. ((member :sb-thread *features*) :spawn)
  56. (t :fd-handler)))
  57. (defun resolve-hostname (name)
  58. (car (sb-bsd-sockets:host-ent-addresses
  59. (sb-bsd-sockets:get-host-by-name name))))
  60. (defimplementation create-socket (host port)
  61. (let ((socket (make-instance 'sb-bsd-sockets:inet-socket
  62. :type :stream
  63. :protocol :tcp)))
  64. (setf (sb-bsd-sockets:sockopt-reuse-address socket) t)
  65. (sb-bsd-sockets:socket-bind socket (resolve-hostname host) port)
  66. (sb-bsd-sockets:socket-listen socket 5)
  67. socket))
  68. (defimplementation local-port (socket)
  69. (nth-value 1 (sb-bsd-sockets:socket-name socket)))
  70. (defimplementation close-socket (socket)
  71. (sb-sys:invalidate-descriptor (socket-fd socket))
  72. (sb-bsd-sockets:socket-close socket))
  73. (defimplementation accept-connection (socket &key
  74. external-format
  75. buffering timeout)
  76. (declare (ignore timeout))
  77. (make-socket-io-stream (accept socket)
  78. (or external-format :iso-latin-1-unix)
  79. (or buffering :full)))
  80. #-win32
  81. (defimplementation install-sigint-handler (function)
  82. (sb-sys:enable-interrupt sb-unix:sigint
  83. (lambda (&rest args)
  84. (declare (ignore args))
  85. (sb-sys:invoke-interruption
  86. (lambda ()
  87. (sb-sys:with-interrupts
  88. (funcall function)))))))
  89. (defvar *sigio-handlers* '()
  90. "List of (key . fn) pairs to be called on SIGIO.")
  91. (defun sigio-handler (signal code scp)
  92. (declare (ignore signal code scp))
  93. (mapc (lambda (handler)
  94. (funcall (the function (cdr handler))))
  95. *sigio-handlers*))
  96. (defun set-sigio-handler ()
  97. (sb-sys:enable-interrupt sb-unix:sigio (lambda (signal code scp)
  98. (sigio-handler signal code scp))))
  99. (defun enable-sigio-on-fd (fd)
  100. (sb-posix::fcntl fd sb-posix::f-setfl sb-posix::o-async)
  101. (sb-posix::fcntl fd sb-posix::f-setown (getpid))
  102. (values))
  103. (defimplementation add-sigio-handler (socket fn)
  104. (set-sigio-handler)
  105. (let ((fd (socket-fd socket)))
  106. (enable-sigio-on-fd fd)
  107. (push (cons fd fn) *sigio-handlers*)))
  108. (defimplementation remove-sigio-handlers (socket)
  109. (let ((fd (socket-fd socket)))
  110. (setf *sigio-handlers* (delete fd *sigio-handlers* :key #'car))
  111. (sb-sys:invalidate-descriptor fd))
  112. (close socket))
  113. (defimplementation add-fd-handler (socket fun)
  114. (let ((fd (socket-fd socket))
  115. (handler nil))
  116. (labels ((add ()
  117. (setq handler (sb-sys:add-fd-handler fd :input #'run)))
  118. (run (fd)
  119. (sb-sys:remove-fd-handler handler) ; prevent recursion
  120. (unwind-protect
  121. (funcall fun)
  122. (when (sb-unix:unix-fstat fd) ; still open?
  123. (add)))))
  124. (add))))
  125. (defimplementation remove-fd-handlers (socket)
  126. (sb-sys:invalidate-descriptor (socket-fd socket)))
  127. (defimplementation socket-fd (socket)
  128. (etypecase socket
  129. (fixnum socket)
  130. (sb-bsd-sockets:socket (sb-bsd-sockets:socket-file-descriptor socket))
  131. (file-stream (sb-sys:fd-stream-fd socket))))
  132. (defimplementation command-line-args ()
  133. sb-ext:*posix-argv*)
  134. (defimplementation dup (fd)
  135. (sb-posix:dup fd))
  136. (defvar *wait-for-input-called*)
  137. (defimplementation wait-for-input (streams &optional timeout)
  138. (assert (member timeout '(nil t)))
  139. (when (boundp '*wait-for-input-called*)
  140. (setq *wait-for-input-called* t))
  141. (let ((*wait-for-input-called* nil))
  142. (loop
  143. (let ((ready (remove-if-not #'input-ready-p streams)))
  144. (when ready (return ready)))
  145. (when timeout (return nil))
  146. (when (check-slime-interrupts) (return :interrupt))
  147. (when *wait-for-input-called* (return :interrupt))
  148. (sleep 0.2))))
  149. #-win32
  150. (defun input-ready-p (stream)
  151. (let ((c (read-char-no-hang stream nil :eof)))
  152. (etypecase c
  153. (character (unread-char c stream) t)
  154. (null nil)
  155. ((member :eof) t))))
  156. #+win32
  157. (progn
  158. (defun input-ready-p (stream)
  159. (or (has-buffered-input-p stream)
  160. (handle-listen (sockint::fd->handle
  161. (sb-impl::fd-stream-fd stream)))))
  162. (defun has-buffered-input-p (stream)
  163. (let ((ibuf (sb-impl::fd-stream-ibuf stream)))
  164. (/= (sb-impl::buffer-head ibuf)
  165. (sb-impl::buffer-tail ibuf))))
  166. (sb-alien:define-alien-routine ("WSACreateEvent" wsa-create-event)
  167. sb-win32:handle)
  168. (sb-alien:define-alien-routine ("WSACloseEvent" wsa-close-event)
  169. sb-alien:int
  170. (event sb-win32:handle))
  171. (defconstant +fd-read+ #.(ash 1 0))
  172. (defconstant +fd-close+ #.(ash 1 5))
  173. (sb-alien:define-alien-routine ("WSAEventSelect" wsa-event-select)
  174. sb-alien:int
  175. (fd sb-alien:int)
  176. (handle sb-win32:handle)
  177. (mask sb-alien:long))
  178. (sb-alien:load-shared-object "kernel32.dll")
  179. (sb-alien:define-alien-routine ("WaitForSingleObjectEx"
  180. wait-for-single-object-ex)
  181. sb-alien:int
  182. (event sb-win32:handle)
  183. (milliseconds sb-alien:long)
  184. (alertable sb-alien:int))
  185. ;; see SB-WIN32:HANDLE-LISTEN
  186. (defun handle-listen (handle)
  187. (sb-alien:with-alien ((avail sb-win32:dword)
  188. (buf (array char #.sb-win32::input-record-size)))
  189. (unless (zerop (sb-win32:peek-named-pipe handle nil 0 nil
  190. (sb-alien:alien-sap
  191. (sb-alien:addr avail))
  192. nil))
  193. (return-from handle-listen (plusp avail)))
  194. (unless (zerop (sb-win32:peek-console-input handle
  195. (sb-alien:alien-sap buf)
  196. sb-win32::input-record-size
  197. (sb-alien:alien-sap
  198. (sb-alien:addr avail))))
  199. (return-from handle-listen (plusp avail))))
  200. (let ((event (wsa-create-event)))
  201. (wsa-event-select handle event (logior +fd-read+ +fd-close+))
  202. (let ((val (wait-for-single-object-ex event 0 0)))
  203. (wsa-close-event event)
  204. (unless (= val -1)
  205. (return-from handle-listen (zerop val)))))
  206. nil)
  207. )
  208. (defvar *external-format-to-coding-system*
  209. '((:iso-8859-1
  210. "latin-1" "latin-1-unix" "iso-latin-1-unix"
  211. "iso-8859-1" "iso-8859-1-unix")
  212. (:utf-8 "utf-8" "utf-8-unix")
  213. (:euc-jp "euc-jp" "euc-jp-unix")
  214. (:us-ascii "us-ascii" "us-ascii-unix")))
  215. ;; C.f. R.M.Kreuter in <20536.1219412774@progn.net> on sbcl-general, 2008-08-22.
  216. (defvar *physical-pathname-host* (pathname-host (user-homedir-pathname)))
  217. (defimplementation filename-to-pathname (filename)
  218. (sb-ext:parse-native-namestring filename *physical-pathname-host*))
  219. (defimplementation find-external-format (coding-system)
  220. (car (rassoc-if (lambda (x) (member coding-system x :test #'equal))
  221. *external-format-to-coding-system*)))
  222. (defun make-socket-io-stream (socket external-format buffering)
  223. (sb-bsd-sockets:socket-make-stream socket
  224. :output t
  225. :input t
  226. :element-type 'character
  227. :buffering buffering
  228. #+sb-unicode :external-format
  229. #+sb-unicode external-format
  230. ))
  231. (defun accept (socket)
  232. "Like socket-accept, but retry on EAGAIN."
  233. (loop (handler-case
  234. (return (sb-bsd-sockets:socket-accept socket))
  235. (sb-bsd-sockets:interrupted-error ()))))
  236. ;;;; Support for SBCL syntax
  237. ;;; SBCL's source code is riddled with #! reader macros. Also symbols
  238. ;;; containing `!' have special meaning. We have to work long and
  239. ;;; hard to be able to read the source. To deal with #! reader
  240. ;;; macros, we use a special readtable. The special symbols are
  241. ;;; converted by a condition handler.
  242. (defun feature-in-list-p (feature list)
  243. (etypecase feature
  244. (symbol (member feature list :test #'eq))
  245. (cons (flet ((subfeature-in-list-p (subfeature)
  246. (feature-in-list-p subfeature list)))
  247. (ecase (first feature)
  248. (:or (some #'subfeature-in-list-p (rest feature)))
  249. (:and (every #'subfeature-in-list-p (rest feature)))
  250. (:not (destructuring-bind (e) (cdr feature)
  251. (not (subfeature-in-list-p e)))))))))
  252. (defun shebang-reader (stream sub-character infix-parameter)
  253. (declare (ignore sub-character))
  254. (when infix-parameter
  255. (error "illegal read syntax: #~D!" infix-parameter))
  256. (let ((next-char (read-char stream)))
  257. (unless (find next-char "+-")
  258. (error "illegal read syntax: #!~C" next-char))
  259. ;; When test is not satisfied
  260. ;; FIXME: clearer if order of NOT-P and (NOT NOT-P) were reversed? then
  261. ;; would become "unless test is satisfied"..
  262. (when (let* ((*package* (find-package "KEYWORD"))
  263. (*read-suppress* nil)
  264. (not-p (char= next-char #\-))
  265. (feature (read stream)))
  266. (if (feature-in-list-p feature *features*)
  267. not-p
  268. (not not-p)))
  269. ;; Read (and discard) a form from input.
  270. (let ((*read-suppress* t))
  271. (read stream t nil t))))
  272. (values))
  273. (defvar *shebang-readtable*
  274. (let ((*readtable* (copy-readtable nil)))
  275. (set-dispatch-macro-character #\# #\!
  276. (lambda (s c n) (shebang-reader s c n))
  277. *readtable*)
  278. *readtable*))
  279. (defun shebang-readtable ()
  280. *shebang-readtable*)
  281. (defun sbcl-package-p (package)
  282. (let ((name (package-name package)))
  283. (eql (mismatch "SB-" name) 3)))
  284. (defun sbcl-source-file-p (filename)
  285. (when filename
  286. (loop for (nil pattern) in (logical-pathname-translations "SYS")
  287. thereis (pathname-match-p filename pattern))))
  288. (defun guess-readtable-for-filename (filename)
  289. (if (sbcl-source-file-p filename)
  290. (shebang-readtable)
  291. *readtable*))
  292. (defvar *debootstrap-packages* t)
  293. (defun call-with-debootstrapping (fun)
  294. (handler-bind ((sb-int:bootstrap-package-not-found
  295. #'sb-int:debootstrap-package))
  296. (funcall fun)))
  297. (defmacro with-debootstrapping (&body body)
  298. `(call-with-debootstrapping (lambda () ,@body)))
  299. (defimplementation call-with-syntax-hooks (fn)
  300. (cond ((and *debootstrap-packages*
  301. (sbcl-package-p *package*))
  302. (with-debootstrapping (funcall fn)))
  303. (t
  304. (funcall fn))))
  305. (defimplementation default-readtable-alist ()
  306. (let ((readtable (shebang-readtable)))
  307. (loop for p in (remove-if-not #'sbcl-package-p (list-all-packages))
  308. collect (cons (package-name p) readtable))))
  309. ;;; Utilities
  310. #+#.(swank-backend:with-symbol 'function-lambda-list 'sb-introspect)
  311. (defimplementation arglist (fname)
  312. (sb-introspect:function-lambda-list fname))
  313. #-#.(swank-backend:with-symbol 'function-lambda-list 'sb-introspect)
  314. (defimplementation arglist (fname)
  315. (sb-introspect:function-arglist fname))
  316. (defimplementation function-name (f)
  317. (check-type f function)
  318. (sb-impl::%fun-name f))
  319. (defmethod declaration-arglist ((decl-identifier (eql 'optimize)))
  320. (flet ((ensure-list (thing) (if (listp thing) thing (list thing))))
  321. (let* ((flags (sb-cltl2:declaration-information decl-identifier)))
  322. (if flags
  323. ;; Symbols aren't printed with package qualifiers, but the FLAGS would
  324. ;; have to be fully qualified when used inside a declaration. So we
  325. ;; strip those as long as there's no better way. (FIXME)
  326. `(&any ,@(remove-if-not #'(lambda (qualifier)
  327. (find-symbol (symbol-name (first qualifier)) :cl))
  328. flags :key #'ensure-list))
  329. (call-next-method)))))
  330. #+#.(swank-backend:with-symbol 'deftype-lambda-list 'sb-introspect)
  331. (defmethod type-specifier-arglist :around (typespec-operator)
  332. (multiple-value-bind (arglist foundp)
  333. (sb-introspect:deftype-lambda-list typespec-operator)
  334. (if foundp arglist (call-next-method))))
  335. (defvar *buffer-name* nil)
  336. (defvar *buffer-offset*)
  337. (defvar *buffer-substring* nil)
  338. (defvar *previous-compiler-condition* nil
  339. "Used to detect duplicates.")
  340. (defun handle-notification-condition (condition)
  341. "Handle a condition caused by a compiler warning.
  342. This traps all compiler conditions at a lower-level than using
  343. C:*COMPILER-NOTIFICATION-FUNCTION*. The advantage is that we get to
  344. craft our own error messages, which can omit a lot of redundant
  345. information."
  346. (unless (or (eq condition *previous-compiler-condition*))
  347. ;; First resignal warnings, so that outer handlers -- which may choose to
  348. ;; muffle this -- get a chance to run.
  349. (when (typep condition 'warning)
  350. (signal condition))
  351. (setq *previous-compiler-condition* condition)
  352. (signal-compiler-condition (real-condition condition)
  353. (sb-c::find-error-context nil))))
  354. (defun signal-compiler-condition (condition context)
  355. (signal (make-condition
  356. 'compiler-condition
  357. :original-condition condition
  358. :severity (etypecase condition
  359. (sb-ext:compiler-note :note)
  360. (sb-c:compiler-error :error)
  361. (reader-error :read-error)
  362. (error :error)
  363. #+#.(swank-backend:with-symbol redefinition-warning sb-kernel)
  364. (sb-kernel:redefinition-warning
  365. :redefinition)
  366. (style-warning :style-warning)
  367. (warning :warning))
  368. :references (condition-references condition)
  369. :message (brief-compiler-message-for-emacs condition)
  370. :source-context (compiler-error-context context)
  371. :location (compiler-note-location condition context))))
  372. (defun real-condition (condition)
  373. "Return the encapsulated condition or CONDITION itself."
  374. (typecase condition
  375. (sb-int:encapsulated-condition (sb-int:encapsulated-condition condition))
  376. (t condition)))
  377. (defun condition-references (condition)
  378. (if (typep condition 'sb-int:reference-condition)
  379. (externalize-reference
  380. (sb-int:reference-condition-references condition))))
  381. (defun compiler-note-location (condition context)
  382. (flet ((bailout ()
  383. (return-from compiler-note-location
  384. (make-error-location "No error location available"))))
  385. (cond (context
  386. (locate-compiler-note
  387. (sb-c::compiler-error-context-file-name context)
  388. (compiler-source-path context)
  389. (sb-c::compiler-error-context-original-source context)))
  390. ((typep condition 'reader-error)
  391. (let* ((stream (stream-error-stream condition))
  392. (file (pathname stream)))
  393. (unless (open-stream-p stream)
  394. (bailout))
  395. (if (compiling-from-buffer-p file)
  396. ;; The stream position for e.g. "comma not inside backquote"
  397. ;; is at the character following the comma, :offset is 0-based,
  398. ;; hence the 1-.
  399. (make-location (list :buffer *buffer-name*)
  400. (list :offset *buffer-offset*
  401. (1- (file-position stream))))
  402. (progn
  403. (assert (compiling-from-file-p file))
  404. ;; No 1- because :position is 1-based.
  405. (make-location (list :file (namestring file))
  406. (list :position (file-position stream)))))))
  407. (t (bailout)))))
  408. (defun compiling-from-buffer-p (filename)
  409. (and *buffer-name*
  410. ;; The following is to trigger COMPILING-FROM-GENERATED-CODE-P
  411. ;; in LOCATE-COMPILER-NOTE.
  412. (not (eq filename :lisp))))
  413. (defun compiling-from-file-p (filename)
  414. (and (pathnamep filename) (null *buffer-name*)))
  415. (defun compiling-from-generated-code-p (filename source)
  416. (and (eq filename :lisp) (stringp source)))
  417. (defun locate-compiler-note (file source-path source)
  418. (cond ((compiling-from-buffer-p file)
  419. (make-location (list :buffer *buffer-name*)
  420. (list :offset *buffer-offset*
  421. (source-path-string-position
  422. source-path *buffer-substring*))))
  423. ((compiling-from-file-p file)
  424. (make-location (list :file (namestring file))
  425. (list :position (1+ (source-path-file-position
  426. source-path file)))))
  427. ((compiling-from-generated-code-p file source)
  428. (make-location (list :source-form source)
  429. (list :position 1)))
  430. (t
  431. (error "unhandled case in compiler note ~S ~S ~S" file source-path source))))
  432. (defun brief-compiler-message-for-emacs (condition)
  433. "Briefly describe a compiler error for Emacs.
  434. When Emacs presents the message it already has the source popped up
  435. and the source form highlighted. This makes much of the information in
  436. the error-context redundant."
  437. (let ((sb-int:*print-condition-references* nil))
  438. (princ-to-string condition)))
  439. (defun compiler-error-context (error-context)
  440. "Describe a compiler error for Emacs including context information."
  441. (declare (type (or sb-c::compiler-error-context null) error-context))
  442. (multiple-value-bind (enclosing source)
  443. (if error-context
  444. (values (sb-c::compiler-error-context-enclosing-source error-context)
  445. (sb-c::compiler-error-context-source error-context)))
  446. (and (or enclosing source)
  447. (format nil "~@[--> ~{~<~%--> ~1:;~A~> ~}~%~]~@[~{==>~%~A~%~}~]"
  448. enclosing source))))
  449. (defun compiler-source-path (context)
  450. "Return the source-path for the current compiler error.
  451. Returns NIL if this cannot be determined by examining internal
  452. compiler state."
  453. (cond ((sb-c::node-p context)
  454. (reverse
  455. (sb-c::source-path-original-source
  456. (sb-c::node-source-path context))))
  457. ((sb-c::compiler-error-context-p context)
  458. (reverse
  459. (sb-c::compiler-error-context-original-source-path context)))))
  460. (defimplementation call-with-compilation-hooks (function)
  461. (declare (type function function))
  462. (handler-bind
  463. ;; N.B. Even though these handlers are called HANDLE-FOO they
  464. ;; actually decline, i.e. the signalling of the original
  465. ;; condition continues upward.
  466. ((sb-c:fatal-compiler-error #'handle-notification-condition)
  467. (sb-c:compiler-error #'handle-notification-condition)
  468. (sb-ext:compiler-note #'handle-notification-condition)
  469. (error #'handle-notification-condition)
  470. (warning #'handle-notification-condition))
  471. (funcall function)))
  472. (defvar *trap-load-time-warnings* nil)
  473. (defun compiler-policy (qualities)
  474. "Return compiler policy qualities present in the QUALITIES alist.
  475. QUALITIES is an alist with (quality . value)"
  476. #+#.(swank-backend:with-symbol 'restrict-compiler-policy 'sb-ext)
  477. (loop with policy = (sb-ext:restrict-compiler-policy)
  478. for (quality) in qualities
  479. collect (cons quality
  480. (or (cdr (assoc quality policy))
  481. 0))))
  482. (defun (setf compiler-policy) (policy)
  483. (declare (ignorable policy))
  484. #+#.(swank-backend:with-symbol 'restrict-compiler-policy 'sb-ext)
  485. (loop for (qual . value) in policy
  486. do (sb-ext:restrict-compiler-policy qual value)))
  487. (defmacro with-compiler-policy (policy &body body)
  488. (let ((current-policy (gensym)))
  489. `(let ((,current-policy (compiler-policy ,policy)))
  490. (setf (compiler-policy) ,policy)
  491. (unwind-protect (progn ,@body)
  492. (setf (compiler-policy) ,current-policy)))))
  493. (defimplementation swank-compile-file (input-file output-file
  494. load-p external-format
  495. &key policy)
  496. (multiple-value-bind (output-file warnings-p failure-p)
  497. (with-compiler-policy policy
  498. (with-compilation-hooks ()
  499. (compile-file input-file :output-file output-file
  500. :external-format external-format)))
  501. (values output-file warnings-p
  502. (or failure-p
  503. (when load-p
  504. ;; Cache the latest source file for definition-finding.
  505. (source-cache-get input-file
  506. (file-write-date input-file))
  507. (not (load output-file)))))))
  508. ;;;; compile-string
  509. ;;; We copy the string to a temporary file in order to get adequate
  510. ;;; semantics for :COMPILE-TOPLEVEL and :LOAD-TOPLEVEL EVAL-WHEN forms
  511. ;;; which the previous approach using
  512. ;;; (compile nil `(lambda () ,(read-from-string string)))
  513. ;;; did not provide.
  514. (locally (declare (sb-ext:muffle-conditions sb-ext:compiler-note))
  515. (sb-alien:define-alien-routine (#-win32 "tempnam" #+win32 "_tempnam" tempnam)
  516. sb-alien:c-string
  517. (dir sb-alien:c-string)
  518. (prefix sb-alien:c-string))
  519. )
  520. (defun temp-file-name ()
  521. "Return a temporary file name to compile strings into."
  522. (tempnam nil nil))
  523. (defimplementation swank-compile-string (string &key buffer position filename
  524. policy)
  525. (let ((*buffer-name* buffer)
  526. (*buffer-offset* position)
  527. (*buffer-substring* string)
  528. (temp-file-name (temp-file-name)))
  529. (flet ((load-it (filename)
  530. (when filename (load filename)))
  531. (compile-it (cont)
  532. (with-compilation-hooks ()
  533. (with-compilation-unit
  534. (:source-plist (list :emacs-buffer buffer
  535. :emacs-filename filename
  536. :emacs-string string
  537. :emacs-position position))
  538. (multiple-value-bind (output-file warningsp failurep)
  539. (compile-file temp-file-name)
  540. (declare (ignore warningsp))
  541. (unless failurep
  542. (funcall cont output-file)))))))
  543. (with-open-file (s temp-file-name :direction :output :if-exists :error)
  544. (write-string string s))
  545. (unwind-protect
  546. (with-compiler-policy policy
  547. (if *trap-load-time-warnings*
  548. (compile-it #'load-it)
  549. (load-it (compile-it #'identity))))
  550. (ignore-errors
  551. (delete-file temp-file-name)
  552. (delete-file (compile-file-pathname temp-file-name)))))))
  553. ;;;; Definitions
  554. (defparameter *definition-types*
  555. '(:variable defvar
  556. :constant defconstant
  557. :type deftype
  558. :symbol-macro define-symbol-macro
  559. :macro defmacro
  560. :compiler-macro define-compiler-macro
  561. :function defun
  562. :generic-function defgeneric
  563. :method defmethod
  564. :setf-expander define-setf-expander
  565. :structure defstruct
  566. :condition define-condition
  567. :class defclass
  568. :method-combination define-method-combination
  569. :package defpackage
  570. :transform :deftransform
  571. :optimizer :defoptimizer
  572. :vop :define-vop
  573. :source-transform :define-source-transform)
  574. "Map SB-INTROSPECT definition type names to Slime-friendly forms")
  575. (defun definition-specifier (type name)
  576. "Return a pretty specifier for NAME representing a definition of type TYPE."
  577. (if (and (symbolp name)
  578. (eq type :function)
  579. (sb-int:info :function :ir1-convert name))
  580. :def-ir1-translator
  581. (getf *definition-types* type)))
  582. (defun make-dspec (type name source-location)
  583. (let ((spec (definition-specifier type name))
  584. (desc (sb-introspect::definition-source-description source-location)))
  585. (if (eq :define-vop spec)
  586. ;; The first part of the VOP description is the name of the template
  587. ;; -- which is actually good information and often long. So elide the
  588. ;; original name in favor of making the interesting bit more visible.
  589. ;;
  590. ;; The second part of the VOP description is the associated compiler note, or
  591. ;; NIL -- which is quite uninteresting and confuses the eye when reading the actual
  592. ;; name which usually has a worthwhile postfix. So drop the note.
  593. (list spec (car desc))
  594. (list* spec name desc))))
  595. (defimplementation find-definitions (name)
  596. (loop for type in *definition-types* by #'cddr
  597. for defsrcs = (sb-introspect:find-definition-sources-by-name name type)
  598. append (loop for defsrc in defsrcs collect
  599. (list (make-dspec type name defsrc)
  600. (converting-errors-to-error-location
  601. (definition-source-for-emacs defsrc type name))))))
  602. (defimplementation find-source-location (obj)
  603. (flet ((general-type-of (obj)
  604. (typecase obj
  605. (method :method)
  606. (generic-function :generic-function)
  607. (function :function)
  608. (structure-class :structure-class)
  609. (class :class)
  610. (method-combination :method-combination)
  611. (package :package)
  612. (condition :condition)
  613. (structure-object :structure-object)
  614. (standard-object :standard-object)
  615. (t :thing)))
  616. (to-string (obj)
  617. (typecase obj
  618. (package (princ-to-string obj)) ; Packages are possibly named entities.
  619. ((or structure-object standard-object condition)
  620. (with-output-to-string (s)
  621. (print-unreadable-object (obj s :type t :identity t))))
  622. (t (princ-to-string obj)))))
  623. (converting-errors-to-error-location
  624. (let ((defsrc (sb-introspect:find-definition-source obj)))
  625. (definition-source-for-emacs defsrc
  626. (general-type-of obj)
  627. (to-string obj))))))
  628. (defun categorize-definition-source (definition-source)
  629. (with-struct (sb-introspect::definition-source-
  630. pathname form-path character-offset plist)
  631. definition-source
  632. (cond ((getf plist :emacs-buffer) :buffer)
  633. ((and pathname (or form-path character-offset)) :file)
  634. (pathname :file-without-position)
  635. (t :invalid))))
  636. (defun definition-source-for-emacs (definition-source type name)
  637. (with-struct (sb-introspect::definition-source-
  638. pathname form-path character-offset plist
  639. file-write-date)
  640. definition-source
  641. (ecase (categorize-definition-source definition-source)
  642. (:buffer
  643. (destructuring-bind (&key emacs-buffer emacs-position emacs-directory
  644. emacs-string &allow-other-keys)
  645. plist
  646. (let ((*readtable* (guess-readtable-for-filename emacs-directory)))
  647. (multiple-value-bind (start end)
  648. (if form-path
  649. (with-debootstrapping
  650. (source-path-string-position form-path emacs-string))
  651. (values character-offset most-positive-fixnum))
  652. (make-location
  653. `(:buffer ,emacs-buffer)
  654. `(:offset ,emacs-position ,start)
  655. `(:snippet
  656. ,(subseq emacs-string
  657. start
  658. (min end (+ start *source-snippet-size*)))))))))
  659. (:file
  660. (let* ((namestring (namestring (translate-logical-pathname pathname)))
  661. (pos (if form-path
  662. (source-file-position namestring file-write-date form-path)
  663. character-offset))
  664. (snippet (source-hint-snippet namestring file-write-date pos)))
  665. (make-location `(:file ,namestring)
  666. ;; /file positions/ in Common Lisp start from
  667. ;; 0, buffer positions in Emacs start from 1.
  668. `(:position ,(1+ pos))
  669. `(:snippet ,snippet))))
  670. (:file-without-position
  671. (make-location `(:file ,(namestring (translate-logical-pathname pathname)))
  672. '(:position 1)
  673. (when (eql type :function)
  674. `(:snippet ,(format nil "(defun ~a " (symbol-name name))))))
  675. (:invalid
  676. (error "DEFINITION-SOURCE of ~A ~A did not contain ~
  677. meaningful information."
  678. (string-downcase type) name)))))
  679. (defun source-file-position (filename write-date form-path)
  680. (let ((source (get-source-code filename write-date))
  681. (*readtable* (guess-readtable-for-filename filename)))
  682. (with-debootstrapping
  683. (source-path-string-position form-path source))))
  684. (defun source-hint-snippet (filename write-date position)
  685. (read-snippet-from-string (get-source-code filename write-date) position))
  686. (defun function-source-location (function &optional name)
  687. (declare (type function function))
  688. (definition-source-for-emacs (sb-introspect:find-definition-source function)
  689. :function
  690. (or name (function-name function))))
  691. (defimplementation describe-symbol-for-emacs (symbol)
  692. "Return a plist describing SYMBOL.
  693. Return NIL if the symbol is unbound."
  694. (let ((result '()))
  695. (flet ((doc (kind)
  696. (or (documentation symbol kind) :not-documented))
  697. (maybe-push (property value)
  698. (when value
  699. (setf result (list* property value result)))))
  700. (maybe-push
  701. :variable (multiple-value-bind (kind recorded-p)
  702. (sb-int:info :variable :kind symbol)
  703. (declare (ignore kind))
  704. (if (or (boundp symbol) recorded-p)
  705. (doc 'variable))))
  706. (when (fboundp symbol)
  707. (maybe-push
  708. (cond ((macro-function symbol) :macro)
  709. ((special-operator-p symbol) :special-operator)
  710. ((typep (fdefinition symbol) 'generic-function)
  711. :generic-function)
  712. (t :function))
  713. (doc 'function)))
  714. (maybe-push
  715. :setf (if (or (sb-int:info :setf :inverse symbol)
  716. (sb-int:info :setf :expander symbol))
  717. (doc 'setf)))
  718. (maybe-push
  719. :type (if (sb-int:info :type :kind symbol)
  720. (doc 'type)))
  721. result)))
  722. (defimplementation describe-definition (symbol type)
  723. (case type
  724. (:variable
  725. (describe symbol))
  726. (:function
  727. (describe (symbol-function symbol)))
  728. (:setf
  729. (describe (or (sb-int:info :setf :inverse symbol)
  730. (sb-int:info :setf :expander symbol))))
  731. (:class
  732. (describe (find-class symbol)))
  733. (:type
  734. (describe (sb-kernel:values-specifier-type symbol)))))
  735. #+#.(swank-backend::sbcl-with-xref-p)
  736. (progn
  737. (defmacro defxref (name &optional fn-name)
  738. `(defimplementation ,name (what)
  739. (sanitize-xrefs
  740. (mapcar #'source-location-for-xref-data
  741. (,(find-symbol (symbol-name (if fn-name
  742. fn-name
  743. name))
  744. "SB-INTROSPECT")
  745. what)))))
  746. (defxref who-calls)
  747. (defxref who-binds)
  748. (defxref who-sets)
  749. (defxref who-references)
  750. (defxref who-macroexpands)
  751. #+#.(swank-backend:with-symbol 'who-specializes-directly 'sb-introspect)
  752. (defxref who-specializes who-specializes-directly))
  753. (defun source-location-for-xref-data (xref-data)
  754. (destructuring-bind (name . defsrc) xref-data
  755. (list name (converting-errors-to-error-location
  756. (definition-source-for-emacs defsrc 'function name)))))
  757. (defimplementation list-callers (symbol)
  758. (let ((fn (fdefinition symbol)))
  759. (sanitize-xrefs
  760. (mapcar #'function-dspec (sb-introspect:find-function-callers fn)))))
  761. (defimplementation list-callees (symbol)
  762. (let ((fn (fdefinition symbol)))
  763. (sanitize-xrefs
  764. (mapcar #'function-dspec (sb-introspect:find-function-callees fn)))))
  765. (defun sanitize-xrefs (xrefs)
  766. (remove-duplicates
  767. (remove-if (lambda (f)
  768. (member f (ignored-xref-function-names)))
  769. (loop for entry in xrefs
  770. for name = (car entry)
  771. collect (if (and (consp name)
  772. (member (car name)
  773. '(sb-pcl::fast-method
  774. sb-pcl::slow-method
  775. sb-pcl::method)))
  776. (cons (cons 'defmethod (cdr name))
  777. (cdr entry))
  778. entry))
  779. :key #'car)
  780. :test (lambda (a b)
  781. (and (eq (first a) (first b))
  782. (equal (second a) (second b))))))
  783. (defun ignored-xref-function-names ()
  784. #-#.(swank-backend::sbcl-with-new-stepper-p)
  785. '(nil sb-c::step-form sb-c::step-values)
  786. #+#.(swank-backend::sbcl-with-new-stepper-p)
  787. '(nil))
  788. (defun function-dspec (fn)
  789. "Describe where the function FN was defined.
  790. Return a list of the form (NAME LOCATION)."
  791. (let ((name (function-name fn)))
  792. (list name (converting-errors-to-error-location
  793. (function-source-location fn name)))))
  794. ;;; macroexpansion
  795. (defimplementation macroexpand-all (form)
  796. (let ((sb-walker:*walk-form-expand-macros-p* t))
  797. (sb-walker:walk-form form)))
  798. ;;; Debugging
  799. ;;; Notice that SB-EXT:*INVOKE-DEBUGGER-HOOK* is slightly stronger
  800. ;;; than just a hook into BREAK. In particular, it'll make
  801. ;;; (LET ((*DEBUGGER-HOOK* NIL)) ..error..) drop into SLDB rather
  802. ;;; than the native debugger. That should probably be considered a
  803. ;;; feature.
  804. (defun make-invoke-debugger-hook (hook)
  805. (when hook
  806. #'(sb-int:named-lambda swank-invoke-debugger-hook
  807. (condition old-hook)
  808. (if *debugger-hook*
  809. nil ; decline, *DEBUGGER-HOOK* will be tried next.
  810. (funcall hook condition old-hook)))))
  811. (defun set-break-hook (hook)
  812. (setq sb-ext:*invoke-debugger-hook* (make-invoke-debugger-hook hook)))
  813. (defun call-with-break-hook (hook continuation)
  814. (let ((sb-ext:*invoke-debugger-hook* (make-invoke-debugger-hook hook)))
  815. (funcall continuation)))
  816. (defimplementation install-debugger-globally (function)
  817. (setq *debugger-hook* function)
  818. (set-break-hook function))
  819. (defimplementation condition-extras (condition)
  820. (cond #+#.(swank-backend::sbcl-with-new-stepper-p)
  821. ((typep condition 'sb-impl::step-form-condition)
  822. `((:show-frame-source 0)))
  823. ((typep condition 'sb-int:reference-condition)
  824. (let ((refs (sb-int:reference-condition-references condition)))
  825. (if refs
  826. `((:references ,(externalize-reference refs))))))))
  827. (defun externalize-reference (ref)
  828. (etypecase ref
  829. (null nil)
  830. (cons (cons (externalize-reference (car ref))
  831. (externalize-reference (cdr ref))))
  832. ((or string number) ref)
  833. (symbol
  834. (cond ((eq (symbol-package ref) (symbol-package :test))
  835. ref)
  836. (t (symbol-name ref))))))
  837. (defvar *sldb-stack-top*)
  838. (defimplementation call-with-debugging-environment (debugger-loop-fn)
  839. (declare (type function debugger-loop-fn))
  840. (let* ((*sldb-stack-top* (if *debug-swank-backend*
  841. (sb-di:top-frame)
  842. (or sb-debug:*stack-top-hint* (sb-di:top-frame))))
  843. (sb-debug:*stack-top-hint* nil))
  844. (handler-bind ((sb-di:debug-condition
  845. (lambda (condition)
  846. (signal (make-condition
  847. 'sldb-condition
  848. :original-condition condition)))))
  849. (funcall debugger-loop-fn))))
  850. #+#.(swank-backend::sbcl-with-new-stepper-p)
  851. (progn
  852. (defimplementation activate-stepping (frame)
  853. (declare (ignore frame))
  854. (sb-impl::enable-stepping))
  855. (defimplementation sldb-stepper-condition-p (condition)
  856. (typep condition 'sb-ext:step-form-condition))
  857. (defimplementation sldb-step-into ()
  858. (invoke-restart 'sb-ext:step-into))
  859. (defimplementation sldb-step-next ()
  860. (invoke-restart 'sb-ext:step-next))
  861. (defimplementation sldb-step-out ()
  862. (invoke-restart 'sb-ext:step-out)))
  863. (defimplementation call-with-debugger-hook (hook fun)
  864. (let ((*debugger-hook* hook)
  865. #+#.(swank-backend::sbcl-with-new-stepper-p)
  866. (sb-ext:*stepper-hook*
  867. (lambda (condition)
  868. (typecase condition
  869. (sb-ext:step-form-condition
  870. (let ((sb-debug:*stack-top-hint* (sb-di::find-stepped-frame)))
  871. (sb-impl::invoke-debugger condition)))))))
  872. (handler-bind (#+#.(swank-backend::sbcl-with-new-stepper-p)
  873. (sb-ext:step-condition #'sb-impl::invoke-stepper))
  874. (call-with-break-hook hook fun))))
  875. (defun nth-frame (index)
  876. (do ((frame *sldb-stack-top* (sb-di:frame-down frame))
  877. (i index (1- i)))
  878. ((zerop i) frame)))
  879. (defimplementation compute-backtrace (start end)
  880. "Return a list of frames starting with frame number START and
  881. continuing to frame number END or, if END is nil, the last frame on the
  882. stack."
  883. (let ((end (or end most-positive-fixnum)))
  884. (loop for f = (nth-frame start) then (sb-di:frame-down f)
  885. for i from start below end
  886. while f collect f)))
  887. (defimplementation print-frame (frame stream)
  888. (sb-debug::print-frame-call frame stream))
  889. (defimplementation frame-restartable-p (frame)
  890. #+#.(swank-backend::sbcl-with-restart-frame)
  891. (not (null (sb-debug:frame-has-debug-tag-p frame))))
  892. (defimplementation frame-call (frame-number)
  893. (multiple-value-bind (name args)
  894. (sb-debug::frame-call (nth-frame frame-number))
  895. (with-output-to-string (stream)
  896. (pprint-logical-block (stream nil :prefix "(" :suffix ")")
  897. (let ((*print-length* nil)
  898. (*print-level* nil))
  899. (prin1 (sb-debug::ensure-printable-object name) stream))
  900. (let ((args (sb-debug::ensure-printable-object args)))
  901. (if (listp args)
  902. (format stream "~{ ~_~S~}" args)
  903. (format stream " ~S" args)))))))
  904. ;;;; Code-location -> source-location translation
  905. ;;; If debug-block info is avaibale, we determine the file position of
  906. ;;; the source-path for a code-location. If the code was compiled
  907. ;;; with C-c C-c, we have to search the position in the source string.
  908. ;;; If there's no debug-block info, we return the (less precise)
  909. ;;; source-location of the corresponding function.
  910. (defun code-location-source-location (code-location)
  911. (let* ((dsource (sb-di:code-location-debug-source code-location))
  912. (plist (sb-c::debug-source-plist dsource)))
  913. (if (getf plist :emacs-buffer)
  914. (emacs-buffer-source-location code-location plist)
  915. #+#.(swank-backend:with-symbol 'debug-source-from 'sb-di)
  916. (ecase (sb-di:debug-source-from dsource)
  917. (:file (file-source-location code-location))
  918. (:lisp (lisp-source-location code-location)))
  919. #-#.(swank-backend:with-symbol 'debug-source-from 'sb-di)
  920. (if (sb-di:debug-source-namestring dsource)
  921. (file-source-location code-location)
  922. (lisp-source-location code-location)))))
  923. ;;; FIXME: The naming policy of source-location functions is a bit
  924. ;;; fuzzy: we have FUNCTION-SOURCE-LOCATION which returns the
  925. ;;; source-location for a function, and we also have FILE-SOURCE-LOCATION &co
  926. ;;; which returns the source location for a _code-location_.
  927. ;;;
  928. ;;; Maybe these should be named code-location-file-source-location,
  929. ;;; etc, turned into generic functions, or something. In the very
  930. ;;; least the names should indicate the main entry point vs. helper
  931. ;;; status.
  932. (defun file-source-location (code-location)
  933. (if (code-location-has-debug-block-info-p code-location)
  934. (source-file-source-location code-location)
  935. (fallback-source-location code-location)))
  936. (defun fallback-source-location (code-location)
  937. (let ((fun (code-location-debug-fun-fun code-location)))
  938. (cond (fun (function-source-location fun))
  939. (t (error "Cannot find source location for: ~A " code-location)))))
  940. (defun lisp-source-location (code-location)
  941. (let ((source (prin1-to-string
  942. (sb-debug::code-location-source-form code-location 100))))
  943. (make-location `(:source-form ,source) '(:position 1))))
  944. (defun emacs-buffer-source-location (code-location plist)
  945. (if (code-location-has-debug-block-info-p code-location)
  946. (destructuring-bind (&key emacs-buffer emacs-position emacs-string
  947. &allow-other-keys)
  948. plist
  949. (let* ((pos (string-source-position code-location emacs-string))
  950. (snipped (read-snippet-from-string emacs-string pos)))
  951. (make-location `(:buffer ,emacs-buffer)
  952. `(:offset ,emacs-position ,pos)
  953. `(:snippet ,snipped))))
  954. (fallback-source-location code-location)))
  955. (defun source-file-source-location (code-location)
  956. (let* ((code-date (code-location-debug-source-created code-location))
  957. (filename (code-location-debug-source-name code-location))
  958. (*readtable* (guess-readtable-for-filename filename))
  959. (source-code (get-source-code filename code-date)))
  960. (with-debootstrapping
  961. (with-input-from-string (s source-code)
  962. (let* ((pos (stream-source-position code-location s))
  963. (snippet (read-snippet s pos)))
  964. (make-location `(:file ,filename)
  965. `(:position ,pos)
  966. `(:snippet ,snippet)))))))
  967. (defun code-location-debug-source-name (code-location)
  968. (namestring (truename (#+#.(swank-backend:with-symbol
  969. 'debug-source-name 'sb-di)
  970. sb-c::debug-source-name
  971. #-#.(swank-backend:with-symbol
  972. 'debug-source-name 'sb-di)
  973. sb-c::debug-source-namestring
  974. (sb-di::code-location-debug-source code-location)))))
  975. (defun code-location-debug-source-created (code-location)
  976. (sb-c::debug-source-created
  977. (sb-di::code-location-debug-source code-location)))
  978. (defun code-location-debug-fun-fun (code-location)
  979. (sb-di:debug-fun-fun (sb-di:code-location-debug-fun code-location)))
  980. (defun code-location-has-debug-block-info-p (code-location)
  981. (handler-case
  982. (progn (sb-di:code-location-debug-block code-location)
  983. t)
  984. (sb-di:no-debug-blocks () nil)))
  985. (defun stream-source-position (code-location stream)
  986. (let* ((cloc (sb-debug::maybe-block-start-location code-location))
  987. (tlf-number (sb-di::code-location-toplevel-form-offset cloc))
  988. (form-number (sb-di::code-location-form-number cloc)))
  989. (multiple-value-bind (tlf pos-map) (read-source-form tlf-number stream)
  990. (let* ((path-table (sb-di::form-number-translations tlf 0))
  991. (path (cond ((<= (length path-table) form-number)
  992. (warn "inconsistent form-number-translations")
  993. (list 0))
  994. (t
  995. (reverse (cdr (aref path-table form-number)))))))
  996. (source-path-source-position path tlf pos-map)))))
  997. (defun string-source-position (code-location string)
  998. (with-input-from-string (s string)
  999. (stream-source-position code-location s)))
  1000. ;;; source-path-file-position and friends are in swank-source-path-parser
  1001. (defimplementation frame-source-location (index)
  1002. (converting-errors-to-error-location
  1003. (code-location-source-location
  1004. (sb-di:frame-code-location (nth-frame index)))))
  1005. (defun frame-debug-vars (frame)
  1006. "Return a vector of debug-variables in frame."
  1007. (sb-di::debug-fun-debug-vars (sb-di:frame-debug-fun frame)))
  1008. (defun debug-var-value (var frame location)
  1009. (ecase (sb-di:debug-var-validity var location)
  1010. (:valid (sb-di:debug-var-value var frame))
  1011. ((:invalid :unknown) ':<not-available>)))
  1012. (defimplementation frame-locals (index)
  1013. (let* ((frame (nth-frame index))
  1014. (loc (sb-di:frame-code-location frame))
  1015. (vars (frame-debug-vars frame)))
  1016. (when vars
  1017. (loop for v across vars collect
  1018. (list :name (sb-di:debug-var-symbol v)
  1019. :id (sb-di:debug-var-id v)
  1020. :value (debug-var-value v frame loc))))))
  1021. (defimplementation frame-var-value (frame var)
  1022. (let* ((frame (nth-frame frame))
  1023. (dvar (aref (frame-debug-vars frame) var)))
  1024. (debug-var-value dvar frame (sb-di:frame-code-location frame))))
  1025. (defimplementation frame-catch-tags (index)
  1026. (mapcar #'car (sb-di:frame-catches (nth-frame index))))
  1027. (defimplementation eval-in-frame (form index)
  1028. (let ((frame (nth-frame index)))
  1029. (funcall (the function
  1030. (sb-di:preprocess-for-eval form
  1031. (sb-di:frame-code-location frame)))
  1032. frame)))
  1033. #+#.(swank-backend::sbcl-with-restart-frame)
  1034. (progn
  1035. (defimplementation return-from-frame (index form)
  1036. (let* ((frame (nth-frame index)))
  1037. (cond ((sb-debug:frame-has-debug-tag-p frame)
  1038. (let ((values (multiple-value-list (eval-in-frame form index))))
  1039. (sb-debug:unwind-to-frame-and-call frame
  1040. (lambda ()
  1041. (values-list values)))))
  1042. (t (format nil "Cannot return from frame: ~S" frame)))))
  1043. (defimplementation restart-frame (index)
  1044. (let* ((frame (nth-frame index)))
  1045. (cond ((sb-debug:frame-has-debug-tag-p frame)
  1046. (let* ((call-list (sb-debug::frame-call-as-list frame))
  1047. (fun (fdefinition (car call-list)))
  1048. (thunk (lambda ()
  1049. ;; Ensure that the thunk gets tail-call-optimized
  1050. (declare (optimize (debug 1)))
  1051. (apply fun (cdr call-list)))))
  1052. (sb-debug:unwind-to-frame-and-call frame thunk)))
  1053. (t (format nil "Cannot restart frame: ~S" frame))))))
  1054. ;; FIXME: this implementation doesn't unwind the stack before
  1055. ;; re-invoking the function, but it's better than no implementation at
  1056. ;; all.
  1057. #-#.(swank-backend::sbcl-with-restart-frame)
  1058. (progn
  1059. (defun sb-debug-catch-tag-p (tag)
  1060. (and (symbolp tag)
  1061. (not (symbol-package tag))
  1062. (string= tag :sb-debug-catch-tag)))
  1063. (defimplementation return-from-frame (index form)
  1064. (let* ((frame (nth-frame index))
  1065. (probe (assoc-if #'sb-debug-catch-tag-p
  1066. (sb-di::frame-catches frame))))
  1067. (cond (probe (throw (car probe) (eval-in-frame form index)))
  1068. (t (format nil "Cannot return from frame: ~S" frame)))))
  1069. (defimplementation restart-frame (index)
  1070. (let ((frame (nth-frame index)))
  1071. (return-from-frame index (sb-debug::frame-call-as-list frame)))))
  1072. ;;;;; reference-conditions
  1073. (defimplementation format-sldb-condition (condition)
  1074. (let ((sb-int:*print-condition-references* nil))
  1075. (princ-to-string condition)))
  1076. ;;;; Profiling
  1077. (defimplementation profile (fname)
  1078. (when fname (eval `(sb-profile:profile ,fname))))
  1079. (defimplementation unprofile (fname)
  1080. (when fname (eval `(sb-profile:unprofile ,fname))))
  1081. (defimplementation unprofile-all ()
  1082. (sb-profile:unprofile)
  1083. "All functions unprofiled.")
  1084. (defimplementation profile-report ()
  1085. (sb-profile:report))
  1086. (defimplementation profile-reset ()
  1087. (sb-profile:reset)
  1088. "Reset profiling counters.")
  1089. (defimplementation profiled-functions ()
  1090. (sb-profile:profile))
  1091. (defimplementation profile-package (package callers methods)
  1092. (declare (ignore callers methods))
  1093. (eval `(sb-profile:profile ,(package-name (find-package package)))))
  1094. ;;;; Inspector
  1095. (defme

Large files files are truncated, but you can click here to view the full file