[slime-devel] PATCH: Support for SBCL HEAD (and future 0.9.2)

Nikodemus Siivola nikodemus at random-state.net
Sat Jun 4 10:02:17 UTC 2005


The attached patch provides support for 0.9.1.25 (coming soon to an 
anoncvs near you), which includes the newfangled WITH-COMPILATION-UNIT 
:SOURCE-PLIST stuff -- and breaks unpatched Slime.

The patch should work with all versions between 0.9.1 and 0.9.1.25 as 
well. I also took the liberty of documenting Slime as supporting only the 
latest official release of SBCL, as opposed to a specific version....

Cheers,

  -- Nikodemus              Schemer: "Buddha is small, clean, and serious."
                   Lispnik: "Buddha is big, has hairy armpits, and laughs."
-------------- next part --------------
? slime.patch
Index: ChangeLog
===================================================================
RCS file: /project/slime/cvsroot/slime/ChangeLog,v
retrieving revision 1.708
diff -u -u -r1.708 ChangeLog
--- ChangeLog	3 Jun 2005 20:00:28 -0000	1.708
+++ ChangeLog	4 Jun 2005 09:51:47 -0000
@@ -1,3 +1,13 @@
+2005-06-04  Nikodemus Siivola <nikodemus at random-state.net>
+
+	* swank-sbcl.lisp: Patched for SBCL HEAD: utilize the new
+	:source-plist functionality; maintain compatibility with 0.9.1
+	till 0.9.2 is out. Removed cruft left over from previous excercises
+	in supporting both HEAD and latest release.
+
+	* doc/slime.texi: Document Slime as supporting the latest official 
+	release of SBCL, as opposed to a specific version number.
+	
 2005-06-03  Helmut Eller  <heller at common-lisp.net>
 
 	* slime.el (slime-background-activities-enabled-p): Allow
Index: swank-sbcl.lisp
===================================================================
RCS file: /project/slime/cvsroot/slime/swank-sbcl.lisp,v
retrieving revision 1.133
diff -u -u -r1.133 swank-sbcl.lisp
--- swank-sbcl.lisp	1 Jun 2005 12:22:45 -0000	1.133
+++ swank-sbcl.lisp	4 Jun 2005 09:51:47 -0000
@@ -14,6 +14,11 @@
 (eval-when (:compile-toplevel :load-toplevel :execute)
   (require 'sb-bsd-sockets)
   (require 'sb-introspect)
+  ;; KLUDGE: Support for 0.9.1 and older concurrently with 0.9.1.25
+  ;; and newer -- the #-swank-backend::source-plist cases can be
+  ;; deleted after SBCL 0.9.2 has been released.
+  (when (find-symbol "DEFINITION-SOURCE-PLIST" :sb-introspect)
+    (pushnew 'swank-backend::source-plist *features*))
   (require 'sb-posix))
 
 (in-package :swank-backend)
@@ -370,59 +375,89 @@
 
 ;;;; compile-string
 
-;;; We patch sb-c::debug-source-for-info so that we can dump our own
-;;; bits of source info.  Our *user-source-info* is stored in the
-;;; debug-source-info slot.
-
-(defvar *real-debug-source-for-info*)
-(defvar *user-source-info*)
+#-swank-backend::source-plist
+(progn
+  ;; We patch sb-c::debug-source-for-info so that we can dump our own
+  ;; bits of source info.  Our *user-source-info* is stored in the
+  ;; debug-source-info slot.  
+  (defvar *real-debug-source-for-info*)
+  (defvar *user-source-info*)
     
-(defun debug-source-for-info-advice (info)
-  (destructuring-bind (source) (funcall *real-debug-source-for-info* info)
-    (when (boundp '*user-source-info*)
-      (setf (sb-c::debug-source-info source) *user-source-info*))
-    (list source)))
-
-(defun install-debug-source-patch ()
-  (unless (boundp '*real-debug-source-for-info*)
-    (setq *real-debug-source-for-info* #'sb-c::debug-source-for-info))
-  (sb-ext:without-package-locks 
-    (setf (symbol-function 'sb-c::debug-source-for-info)
-	  #'debug-source-for-info-advice)))
+  (defun debug-source-for-info-advice (info)
+    (destructuring-bind (source) (funcall *real-debug-source-for-info* info)
+      (when (boundp '*user-source-info*)
+        (setf (sb-c::debug-source-info source) *user-source-info*))
+      (list source)))
+
+  (defun install-debug-source-patch ()
+    (unless (boundp '*real-debug-source-for-info*)
+      (setq *real-debug-source-for-info* #'sb-c::debug-source-for-info))
+    (sb-ext:without-package-locks 
+      (setf (symbol-function 'sb-c::debug-source-for-info)
+            #'debug-source-for-info-advice)))
+
+  (defimplementation swank-compile-string (string &key buffer position directory)
+    (declare (ignore directory))
+    (install-debug-source-patch)
+    (call/temp-file 
+     string
+     (lambda (filename)
+       (let ((*user-source-info* (list :emacs-buffer buffer :emacs-string string
+                                       :emacs-position position))
+             (*buffer-name* buffer)
+             (*buffer-offset* position)
+             (*buffer-substring* string))
+         (let ((fasl (with-compilation-hooks () 
+                       (compile-file filename))))
+           (load fasl)
+           (delete-file fasl))))))
+  
+  (defun call/temp-file (string fun)
+    (let ((filename (temp-file-name)))
+      (unwind-protect
+           (with-open-file (s filename :direction :output :if-exists :error)
+             (write-string string s)
+             (finish-output s)
+             (funcall fun filename))
+        (when (probe-file filename)
+          (delete-file filename)))))
+
+  (defun temp-file-name ()
+    "Return a temporary file name to compile strings into."
+    (sb-alien:alien-funcall 
+     (sb-alien:extern-alien 
+      "tmpnam" 
+      (function sb-alien:c-string sb-alien:system-area-pointer))
+     (sb-sys:int-sap 0)))
+
+  (defun find-temp-function-source-location (function)
+    (let ((info (function-debug-source-info function)))
+      (with-struct (sb-introspect::definition-source-
+                       form-path character-offset) 
+          (sb-introspect:find-definition-source function)
+        (destructuring-bind (&key emacs-buffer emacs-position emacs-string) info
+          (let ((pos (if form-path 
+                         (with-debootstrapping 
+                           (source-path-string-position
+                            form-path emacs-string))
+                         character-offset)))
+            (make-location `(:buffer ,emacs-buffer)
+                           `(:position ,(+ pos emacs-position))
+                           `(:snippet ,emacs-string))))))))
 
+#+swank-backend::source-plist
 (defimplementation swank-compile-string (string &key buffer position directory)
   (declare (ignore directory))
-  (install-debug-source-patch)
-  (call/temp-file 
-   string
-   (lambda (filename)
-     (let ((*user-source-info* (list :emacs-buffer buffer :emacs-string string
-                                     :emacs-position position))
-           (*buffer-name* buffer)
-           (*buffer-offset* position)
-           (*buffer-substring* string))
-       (let ((fasl (with-compilation-hooks () 
-                     (compile-file filename))))
-         (load fasl)
-         (delete-file fasl))))))
-
-(defun call/temp-file (string fun)
-  (let ((filename (temp-file-name)))
-    (unwind-protect
-         (with-open-file (s filename :direction :output :if-exists :error)
-           (write-string string s)
-           (finish-output s)
-           (funcall fun filename))
-      (when (probe-file filename)
-        (delete-file filename)))))
-
-(defun temp-file-name ()
-  "Return a temporary file name to compile strings into."
-  (sb-alien:alien-funcall 
-   (sb-alien:extern-alien 
-    "tmpnam" 
-    (function sb-alien:c-string sb-alien:system-area-pointer))
-   (sb-sys:int-sap 0)))
+  (let ((*buffer-name* buffer)
+        (*buffer-offset* position)
+        (*buffer-substring* string))
+      (with-compilation-hooks ()
+        (with-compilation-unit (:source-plist
+                                (list :emacs-buffer buffer 
+                                      :emacs-string string
+                                      :emacs-position position))
+          (with-input-from-string (s string)
+            (load s))))))
 
 ;;;; Definitions
 
@@ -464,6 +499,7 @@
 ;;; the position of the first code-location; for some reason, that
 ;;; doesn't seem to work.)
 
+#-swank-backend::source-plist
 (defun function-source-location (function &optional name)
   "Try to find the canonical source location of FUNCTION."
   (declare (type function function))
@@ -471,6 +507,12 @@
       (find-temp-function-source-location function)
       (find-function-source-location function)))
 
+#+swank-backend::source-plist
+(defun function-source-location (function &optional name)
+  "Try to find the canonical source location of FUNCTION."
+  (declare (type function function))
+  (find-function-source-location function))
+
 (defun safe-function-source-location (fun name)
   (if *debug-definition-finding*
       (function-source-location fun name)
@@ -478,6 +520,7 @@
         (error (e) 
           (list :error (format nil "Error: ~A" e))))))
 
+#-swank-backend::source-plist
 (defun find-function-source-location (function)
   (cond #+(or) ;; doesn't work for unknown reasons
         ((function-has-start-location-p function)
@@ -491,6 +534,33 @@
                           `(:position ,pos)
                           `(:snippet ,snippet))))))
 
+#+swank-backend::source-plist
+(defun find-function-source-location (function)
+  (with-struct (sb-introspect::definition-source- form-path character-offset plist)
+      (sb-introspect:find-definition-source function)
+    (destructuring-bind (&key emacs-buffer emacs-position emacs-string) plist
+      (if emacs-buffer
+          (let ((pos (if form-path 
+                         (with-debootstrapping 
+                           (source-path-string-position
+                            form-path emacs-string))
+                         character-offset)))
+            (make-location `(:buffer ,emacs-buffer)
+                           `(:position ,(+ pos emacs-position))
+                           `(:snippet ,emacs-string)))
+          (cond #+(or) 
+                ;; doesn't work for unknown reasons
+                ((function-has-start-location-p function)
+                 (code-location-source-location (function-start-location function)))
+                ((not (function-source-filename function))
+                 (error "Source filename not recorded for ~A" function))
+                (t
+                 (let* ((pos (function-source-position function))
+                        (snippet (function-hint-snippet function pos)))
+                   (make-location `(:file ,(function-source-filename function))
+                                  `(:position ,pos)
+                                  `(:snippet ,snippet)))))))))
+
 (defun function-source-position (function)
   ;; We only consider the toplevel form number here.
   (let* ((tlf (function-toplevel-form-number function))
@@ -507,8 +577,8 @@
        (sb-introspect:find-definition-source function))))))
 
 (defun function-source-write-date (function)
-  (definition-source-file-write-date
-   (sb-introspect:find-definition-source function)))
+  (sb-introspect:definition-source-file-write-date
+      (sb-introspect:find-definition-source function)))
 
 (defun function-toplevel-form-number (function)
   (car
@@ -528,27 +598,6 @@
   (let ((dfun (sb-di:fun-debug-fun function)))
     (and dfun (sb-di:debug-fun-start-location dfun))))
 
-(defun find-temp-function-source-location (function)
-  (let ((info (function-debug-source-info function)))
-    (with-struct (sb-introspect::definition-source-
-                  form-path character-offset) 
-        (sb-introspect:find-definition-source function)
-      (destructuring-bind (&key emacs-buffer emacs-position emacs-string) info
-        (let ((pos (if form-path 
-                       (with-debootstrapping 
-                         (source-path-string-position
-                          form-path emacs-string))
-                       character-offset)))
-          (make-location `(:buffer ,emacs-buffer)
-                         `(:position ,(+ pos emacs-position))
-                         `(:snippet ,emacs-string)))))))
-
-;; FIXME: Symbol doesn't exist in released SBCL (0.8.20) yet.
-(defun definition-source-file-write-date (def)
-  (let ((sym (find-symbol "DEFINITION-SOURCE-FILE-WRITE-DATE"
-                          (find-package "SB-INTROSPECT"))))
-    (when sym (funcall sym def))))
-
 (defun method-definitions (gf)
   (let ((methods (sb-mop:generic-function-methods gf))
         (name (sb-mop:generic-function-name gf)))
@@ -692,26 +741,7 @@
 	  collect f)))
 
 (defimplementation print-frame (frame stream)
-  (macrolet ((printer-form ()
-               ;; MEGAKLUDGE: As SBCL 0.8.20.1 fixed its debug IO style
-               ;; our usage of unexported interfaces came back to haunt
-               ;; us. And since we still use the same interfaces it will
-               ;; haunt us again.
-               (let ((print-sym (find-symbol "PRINT-FRAME-CALL" :sb-debug)))
-                 (if (fboundp print-sym)
-                     (let* ((args (sb-introspect:function-arglist print-sym))
-                            (key-pos (position '&key args)))
-                       (cond ((eql 2 key-pos)
-                              `(,print-sym frame stream))
-                             ((eql 1 key-pos)
-                              `(let ((*standard-output* stream))
-                                 (,print-sym frame)))
-                             (t
-                              (error "*THWAP* SBCL changes internals ~
-                                       again!"))))
-                     (error "You're in a twisty little maze of unsupported
-                              SBCL interfaces, all different.")))))
-    (printer-form)))
+  (sb-debug::print-frame-call frame stream))
 
 ;;;; Code-location -> source-location translation
 
@@ -721,12 +751,33 @@
 ;;; If there's no debug-block info, we return the (less precise)
 ;;; source-location of the corresponding function.
 
+#-swank-backend::source-plist
 (defun code-location-source-location (code-location)
   (let ((dsource (sb-di:code-location-debug-source code-location)))
     (ecase (sb-di:debug-source-from dsource)
       (:file (file-source-location code-location))
       (:lisp (lisp-source-location code-location)))))
 
+#+swank-backend::source-plist
+(defun code-location-source-location (code-location)
+  (let* ((dsource (sb-di:code-location-debug-source code-location))
+         (plist (sb-c::debug-source-plist dsource)))
+    (if (getf plist :emacs-buffer)
+        (emacs-buffer-source-location code-location plist)
+        (ecase (sb-di:debug-source-from dsource)
+          (:file (file-source-location code-location))
+          (:lisp (lisp-source-location code-location))))))
+
+;;; FIXME: The naming policy of source-location functions is a bit
+;;; fuzzy: we have FUNCTION-SOURCE-LOCATION which returns the
+;;; source-location for a function, and we also have FILE-SOURCE-LOCATION &co
+;;; which returns the source location for a _code-location_.
+;;; 
+;;; Maybe these should be named code-location-file-source-location,
+;;; etc, turned into generic functions, or something. In the very least the names
+;;; should indicate the main entry point vs. helper status.
+
+#-swank-backend::source-plist
 (defun file-source-location (code-location)
   (cond ((code-location-has-debug-block-info-p code-location)
          (if (code-location-from-emacs-buffer-p code-location)
@@ -738,11 +789,23 @@
                  (t (error "Cannot find source location for: ~A "
                            code-location)))))))
 
+#+swank-backend::source-plist
+(defun file-source-location (code-location)
+  (if (code-location-has-debug-block-info-p code-location)
+      (source-file-source-location code-location)
+      (fallback-source-location code-location)))
+
+(defun fallback-source-location (code-location)
+  (let ((fun (code-location-debug-fun-fun code-location)))
+    (cond (fun (function-source-location fun))
+          (t (error "Cannot find source location for: ~A " code-location)))))
+
 (defun lisp-source-location (code-location)
-  (let ((source (with-output-to-string (*standard-output*)
-                  (print-code-location-source-form code-location 100))))
+  (let ((source (prin1-to-string 
+                 (sb-debug::code-location-source-form code-location 100))))
     (make-location `(:source-form ,source) '(:position 0))))
 
+#-swank-backend::source-plist
 (defun temp-file-source-location (code-location)
   (let ((info (code-location-debug-source-info code-location)))
     (destructuring-bind (&key emacs-buffer emacs-position emacs-string) info
@@ -753,6 +816,18 @@
                        `(:position ,(+ emacs-position pos)) 
                        `(:snippet ,snipped))))))
 
+#+swank-backend::source-plist
+(defun emacs-buffer-source-location (code-location plist)
+  (if (code-location-has-debug-block-info-p code-location)
+      (destructuring-bind (&key emacs-buffer emacs-position emacs-string) plist
+        (let* ((pos (string-source-position code-location emacs-string))
+               (snipped (with-input-from-string (s emacs-string)
+                          (read-snippet s pos))))
+          (make-location `(:buffer ,emacs-buffer) 
+                         `(:position ,(+ emacs-position pos)) 
+                         `(:snippet ,snipped))))
+      (fallback-source-location code-location)))
+
 (defun source-file-source-location (code-location)
   (let* ((code-date (code-location-debug-source-created code-location))
          (filename (code-location-debug-source-name code-location))
@@ -764,8 +839,27 @@
                      `(:position ,(1+ pos))
                      `(:snippet ,snippet))))))
 
-(defun code-location-debug-source-info (code-location)
-  (sb-c::debug-source-info (sb-di::code-location-debug-source code-location)))
+#-swank-backend::source-plist
+(progn
+  (defun code-location-debug-source-info (code-location)
+    (sb-c::debug-source-info (sb-di::code-location-debug-source code-location)))
+
+  (defun code-location-from-emacs-buffer-p (code-location)
+    (info-from-emacs-buffer-p (code-location-debug-source-info code-location)))
+
+  (defun function-from-emacs-buffer-p (function)
+    (info-from-emacs-buffer-p (function-debug-source-info function)))
+  
+  (defun function-debug-source-info (function)
+    (let* ((comp (sb-di::compiled-debug-fun-component
+                  (sb-di::fun-debug-fun function))))
+      (sb-c::debug-source-info (car (sb-c::debug-info-source 
+                                     (sb-kernel:%code-debug-info comp))))))
+  
+  (defun info-from-emacs-buffer-p (info)
+    (and info 
+         (consp info)
+         (eq :emacs-buffer (car info)))))
 
 (defun code-location-debug-source-name (code-location)
   (sb-c::debug-source-name (sb-di::code-location-debug-source code-location)))
@@ -777,23 +871,6 @@
 (defun code-location-debug-fun-fun (code-location)
   (sb-di:debug-fun-fun (sb-di:code-location-debug-fun code-location)))
 
-(defun code-location-from-emacs-buffer-p (code-location)
-  (info-from-emacs-buffer-p (code-location-debug-source-info code-location)))
-
-(defun function-from-emacs-buffer-p (function)
-  (info-from-emacs-buffer-p (function-debug-source-info function)))
-
-(defun function-debug-source-info (function)
-  (let* ((comp (sb-di::compiled-debug-fun-component
-                (sb-di::fun-debug-fun function))))
-    (sb-c::debug-source-info (car (sb-c::debug-info-source 
-                                   (sb-kernel:%code-debug-info comp))))))
-
-(defun info-from-emacs-buffer-p (info)
-  (and info 
-       (consp info)
-       (eq :emacs-buffer (car info))))
-
 (defun code-location-has-debug-block-info-p (code-location)
   (handler-case 
       (progn (sb-di:code-location-debug-block code-location)
@@ -818,30 +895,6 @@
     (stream-source-position code-location s)))
 
 ;;; source-path-file-position and friends are in swank-source-path-parser
-
-(defun print-code-location-source-form (code-location context)
-  (macrolet ((printer-form ()
-               ;; KLUDGE: These are both unexported interfaces, used
-               ;; by different versions of SBCL. ...sooner or later
-               ;; this will change again: hopefully by then we have
-               ;; figured out the interface we want to drive the
-               ;; debugger with and requested it from the SBCL
-               ;; folks.
-               (let ((print-code-sym
-                      (find-symbol "PRINT-CODE-LOCATION-SOURCE-FORM"
-                                   :sb-debug))
-                     (code-sym
-                      (find-symbol "CODE-LOCATION-SOURCE-FORM"
-                                   :sb-debug)))
-                 (cond ((fboundp print-code-sym)
-                        `(,print-code-sym code-location context))
-                       ((fboundp code-sym)
-                        `(prin1 (,code-sym code-location context)))
-                       (t
-                        (error 
-                         "*THWAP* SBCL changes its debugger interface ~
-                          again!"))))))
-    (printer-form)))
 
 (defun safe-source-location-for-emacs (code-location)
   (if *debug-definition-finding*
Index: doc/slime.texi
===================================================================
RCS file: /project/slime/cvsroot/slime/doc/slime.texi,v
retrieving revision 1.37
diff -u -u -r1.37 slime.texi
--- doc/slime.texi	18 Apr 2005 18:58:12 -0000	1.37
+++ doc/slime.texi	4 Jun 2005 09:51:48 -0000
@@ -214,8 +214,7 @@
 @item
 CMU Common Lisp (@acronym{CMUCL}), 18e or newer
 @item
-Steel Bank Common Lisp (@acronym{SBCL}), from version 0.8.15 to 0.8.21
-(newer versions may or may not work)
+Steel Bank Common Lisp (@acronym{SBCL}), latest official release
 @item
 OpenMCL, version 0.14.3
 @item


More information about the slime-devel mailing list