(setf *print-circle* t)
(defvar *symbol-test-equivalents*)
(defmacro with-symbol-test (&body forms)
`(call-with-symbol-test #'(lambda () ,@forms)))
(defparameter *print-gensym-mapping* nil)
(defun call-with-symbol-test (thunk)
(let* ((*symbol-test-equivalents* (make-hash-table))
(called (funcall thunk)))
(if *print-gensym-mapping*
(maphash (lambda (k v) (format t "~&~s -> ~s" k v))
*symbol-test-equivalents*))
(values
called
*symbol-test-equivalents*)))
(defun gensym-p (x)
(and (symbolp x)
(not (symbol-package x))))
(defun equivalent-gensym (x)
(and (gensym-p x)
(gethash x *symbol-test-equivalents*)))
(defun register-equivalent-gensym (x y)
(setf (gethash x *symbol-test-equivalents*) y))
(defun symbol-test-equal (x y)
(or (equal x y)
(let ((eqv (equivalent-gensym x)))
(if eqv
(eq eqv y)
(when (and (gensym-p x) (gensym-p y))
(register-equivalent-gensym x y)
t)))))
#|
;;; This should return T
(with-symbol-test
(tree-equal '(ZOOP #1=#:X #2=#:X #1#)
(let ((a (make-symbol "X")) (b (make-symbol "X")))
`(zoop ,a ,b ,a))
:test #'symbol-test-equal))
;;; This should return NIL
(with-symbol-test
(tree-equal '(ZOOP #1=#:X #2=#:X #1#)
(let ((a (make-symbol "X")) (b (make-symbol "X")))
`(zoop ,a ,a ,b))
:test #'symbol-test-equal))
|#