1.0.18.10: Record filenames in DEBUG-SOURCEs during EVAL-WHEN, LOAD.
[sbcl.git] / src / code / describe.lisp
index 17aba76..47a8af2 100644 (file)
@@ -95,7 +95,7 @@
               count (zerop count))
       (let ((n 0))
         (declare (type index n))
-        (dohash (k v x)
+        (dohash ((k v) x :locked t)
           (unless (zerop n)
             (write-char #\space s))
           (incf n)
                   ;; any nondefault options.
                   (format-universal-time nil (sb-c::debug-source-compiled source)
                                          :style :abbreviated))
-          (let ((name (sb-c::debug-source-name source)))
-            (ecase (sb-c::debug-source-from source)
-              (:file
-               (format s "~&~A~@:_  Created: " (namestring name))
-               (format-universal-time s (sb-c::debug-source-created source)))
-              (:lisp (format s "~&~S" name)))))))))
+          (let ((name (sb-c::debug-source-namestring source)))
+            (cond (name
+                   (format s "~&~A~@:_  Created: " name)
+                   (format-universal-time s (sb-c::debug-source-created source)))
+                  ((sb-di:debug-source-form source)
+                   (format s "~&  ~S" (sb-di:debug-source-form source)))
+                  (t (bug "Don't know how to use a DEBUG-SOURCE without ~
+                           a namestring or a form.")))))))))
 
 ;;; Describe a compiled function. The closure case calls us to print
 ;;; the guts.
       (%describe-fun-name name s (%simple-fun-type x))))
   (%describe-compiled-from (sb-kernel:fun-code-header x) s))
 
+(defun %describe-fun (x s &optional (kind :function) (name nil))
+  (etypecase x
+    #+sb-eval
+    (sb-eval:interpreted-function
+     (%describe-interpreted-fun x s kind name))
+    (function
+     (%describe-compiled-fun x s kind name))))
+
 ;;; Describe a function object. KIND and NAME provide some information
 ;;; about where the function came from.
-(defun %describe-fun (x s &optional (kind :function) (name nil))
+(defun %describe-compiled-fun (x s &optional (kind :function) (name nil))
   (declare (type function x))
   (declare (type stream s))
   (declare (type (member :macro :function) kind))
                      (format s "~S is a function." x))))
     (format s "~@:_~@<Its associated name (as in ~S) is ~2I~_~S.~:>"
             'function-lambda-expression
-            (%fun-name x))
+            (nth-value 2 (function-lambda-expression x)))
     (case (widetag-of x)
       (#.sb-vm:closure-header-widetag
        (%describe-fun-compiled (%closure-fun x) s kind name)
-       (format s "~@:_Its closure environment is:")
-       (pprint-logical-block (s nil)
-         (pprint-indent :current 8)
-         (dotimes (i (- (get-closure-length x) (1- sb-vm:closure-info-offset)))
-           (format s "~@:_~S: ~S" i (%closure-index-ref x i)))))
+       (format s "~&Its closure environment is:")
+       (loop for value in (%closure-values x)
+          for i = 0 then (1+ i)
+          do (format s "~&  ~S: ~S" i value)))
       (#.sb-vm:simple-fun-header-widetag
        (%describe-fun-compiled x s kind name))
       (#.sb-vm:funcallable-instance-header-widetag
        (format s "~@:_It is an unknown type of function."))))
   (terpri s))
 
+;; Describe an interpreted function.
+#+sb-eval
+(defun %describe-interpreted-fun (x s &optional (kind :function) (name nil))
+  (declare (type sb-eval:interpreted-function x))
+  (declare (type stream s))
+  (declare (type (member :macro :function) kind))
+  (fresh-line s)
+  (pprint-logical-block (s nil)
+    (ecase kind
+      (:macro (format s "Macro-function: ~S" x))
+      (:function (if name
+                     (format s "Function: ~S" x)
+                     (format s "~S is a function." x))))
+    (format s "~@:_~@<Its associated name (as in ~S) is ~2I~_~S.~:>"
+            'function-lambda-expression
+            (nth-value 2 (function-lambda-expression x)))
+    (format s "~&It is an interpreted function.~%")
+    (let ((args (sb-eval:interpreted-function-lambda-list x)))
+      (cond ((not args)
+             (write-string "There are no arguments." s))
+            (t
+             (format s "~&~@(The ~@[~A's ~]arguments are:~@:_~)" kind)
+             (write-string "  " s)
+             (let ((*print-pretty* t)
+                   (*print-escape* t)
+                   (*print-base* 10)
+                   (*print-radix* nil))
+               (pprint-logical-block (s nil)
+                 (pprint-indent :current 2)
+                 (format s "~A" args)))))
+      (format s "~&It was defined as: ")
+      (let ((*print-pretty* t)
+            (*print-escape* t)
+            (*print-base* 10)
+            (*print-radix* nil))
+        (pprint-logical-block (s nil)
+          (pprint-indent :current 2)
+          (format s "~A" (function-lambda-expression x))))))
+  (terpri s))
+
 (defmethod describe-object ((x function) s)
   (%describe-fun x s :function))
 
   (%describe-doc x s 'type "Type")
   (%describe-doc x s 'setf "Setf macro")
   (dolist (assoc (info :random-documentation :stuff x))
-    (format s
-            "~&~@<Documentation on the ~(~A~):~@:_~A~:>"
-            (car assoc)
-            (cdr assoc)))
+    (let ((type (car assoc)))
+      (format s
+              "~&~@<Documentation on the ~(~A~):~@:_~A~:>"
+              (case type
+                ((optimize) "optimize quality")
+                (t (car assoc)))
+              (cdr assoc))))
 
   ;; Mention the associated type information, if any.
   ;;