-;;; Hacky (duplicating machinery found elsewhere because this function
-;;; turns out to be on a critical path in the compiler) shorthand for
-;;; creating debug names from source names or other stems, e.g.
-;;;
-;;; (DEBUG-NAMIFY "FLET " SOURCE-NAME) -> "FLET FOO:BAR"
-;;; (DEBUG-NAMIFY "top level form " FORM) -> "top level form (QUUX :FOO)"
-;;;
-;;; If ALT is given it must be a string -- it is then used in place of
-;;; either HEAD or TAIL if either of them is EQ to SB-C::.ANONYMOUS.
-;;;
-(declaim (inline debug-namify))
-(defun debug-namify (head tail &optional alt)
- (declare (type (or null string) alt))
- (flet ((symbol-debug-name (symbol)
- ;; KLUDGE: (OAOOM warning) very much akin to OUTPUT-SYMBOL.
- (if (and alt (eq '.anonymous. symbol))
- alt
- (let ((package (symbol-package symbol))
- (name (symbol-name symbol)))
- (cond
- ((eq package *keyword-package*)
- (concatenate 'string ":" name))
- ((eq package *cl-package*)
- name)
- ((null package)
- (concatenate 'string "#:" name))
- (t
- (multiple-value-bind (symbol status)
- (find-symbol name package)
- (declare (ignore symbol))
- (concatenate 'string
- (package-name package)
- (if (eq status :external) ":" "::")
- name))))))))
- (cond ((and (stringp head) (stringp tail))
- (concatenate 'string head tail))
- ((and (stringp head) (symbolp tail))
- (concatenate 'string head (symbol-debug-name tail)))
- ((and (symbolp head) (stringp tail))
- (concatenate 'string (symbol-debug-name head) tail))
- (t
- (macrolet ((out (obj s)
- `(typecase ,obj
- (string (write-string ,obj ,s))
- (symbol (write-string (symbol-debug-name ,obj) ,s))
- (t (prin1 ,obj ,s)))))
- (with-standard-io-syntax
- (let ((*print-readably* nil)
- (*print-pretty* nil)
- (*package* *cl-package*)
- (*print-length* 3)
- (*print-level* 2))
- (with-output-to-string (s)
- (out head s)
- (out tail s)))))))))
+(def!struct (debug-name-marker (:make-load-form-fun dump-debug-name-marker)
+ (:print-function print-debug-name-marker)))
+
+(defvar *debug-name-level* 4)
+(defvar *debug-name-length* 12)
+(defvar *debug-name-punt*)
+(defvar *debug-name-sharp*)
+(defvar *debug-name-ellipsis*)
+
+(eval-when (#-sb-xc :compile-toplevel :load-toplevel :execute)
+ (defun dump-debug-name-marker (marker &optional env)
+ (declare (ignore env))
+ (cond ((eq marker *debug-name-sharp*)
+ `(if (boundp '*debug-name-sharp*)
+ *debug-name-sharp*
+ (make-debug-name-marker)))
+ ((eq marker *debug-name-ellipsis*)
+ `(if (boundp '*debug-name-ellipsis*)
+ *debug-name-ellipsis*
+ (make-debug-name-marker)))
+ (t
+ (warn "Dumping unknown debug-name marker.")
+ '(make-debug-name-marker)))))
+
+(defun print-debug-name-marker (marker stream level)
+ (declare (ignore level))
+ (cond ((eq marker *debug-name-sharp*)
+ (write-char #\# stream))
+ ((eq marker *debug-name-ellipsis*)
+ (write-string "..." stream))
+ (t
+ (write-string "???" stream))))
+
+(setf *debug-name-sharp* (make-debug-name-marker)
+ *debug-name-ellipsis* (make-debug-name-marker))
+
+(defun debug-name (type thing &optional context)
+ (let ((*debug-name-punt* nil))
+ (labels ((walk (x)
+ (typecase x
+ (cons
+ (if (plusp *debug-name-level*)
+ (let ((*debug-name-level* (1- *debug-name-level*)))
+ (do ((tail (cdr x) (cdr tail))
+ (name (cons (walk (car x)) nil)
+ (cons (walk (car tail)) name))
+ (n (1- *debug-name-length*) (1- n)))
+ ((or (not (consp tail))
+ (not (plusp n))
+ *debug-name-punt*)
+ (cond (*debug-name-punt*
+ (setf *debug-name-punt* nil)
+ (nreverse name))
+ ((atom tail)
+ (nconc (nreverse name) (walk tail)))
+ (t
+ (setf *debug-name-punt* t)
+ (nconc (nreverse name) (list *debug-name-ellipsis*)))))))
+ *debug-name-sharp*))
+ ((or symbol number string)
+ x)
+ (t
+ (type-of x)))))
+ (let ((name (list* type (walk thing) (when context (name-context)))))
+ (when (legal-fun-name-p name)
+ (bug "~S is a legal function name, and cannot be used as a ~
+ debug name." name))
+ name))))