- (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 ~S."
- 'function-lambda-expression
- (%fun-name 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)))))
- ((#.sb-vm:simple-fun-header-widetag #.sb-vm:closure-fun-header-widetag)
- (%describe-fun-compiled x s kind name))
- (#.sb-vm:funcallable-instance-header-widetag
- ;; Only STANDARD-GENERIC-FUNCTION would be handled here, but
- ;; since it has its own DESCRIBE-OBJECT method, it should've been
- ;; picked off before getting here. So hopefully we never get here.
- (format s "~@:_It is an unknown type of funcallable instance."))
- (t
- (format s "~@:_It is an unknown type of function."))))
+ (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)))
+ (case (widetag-of x)
+ (#.sb-vm:closure-header-widetag
+ (%describe-fun-compiled (%closure-fun x) s kind name)
+ (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
+ ;; Only STANDARD-GENERIC-FUNCTION would be handled here, but
+ ;; since it has its own DESCRIBE-OBJECT method, it should've been
+ ;; picked off before getting here. So hopefully we never get here.
+ (format s "~@:_It is an unknown type of funcallable instance."))
+ (t
+ (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))