
I've been thinking about a neat feature I think could be implemented in a pretty straightforward way to help with the debugging of macros. There would be a new minor mode for a buffer containing some random form. Selecting any given subform of the buffer's form would macroexpand that one form, in place. Of course, it would have to respect macrolet's and symbol-macrolet's (which isn't that hard, really). I already have the code written (included below) to expand such forms (perhaps buggy, perhaps incomplete). (One thing I know it doesn't do is find and respect macrolets that aren't present in the form until after some expansion. I don't know that this is a big deal.) What's missing is the hooks into slime and Emacs. I don't want to bother with these (because they'd be a lot more effort for me) until I find whether there are any similar features currently available for SLIME. So has anyone done anything like this yet? If not, I suppose SLIME would need another minor mode with some cool keybindings and code to figure out what to pass as the list-indexes variable based on the position in the buffer (perhaps the hardest part?). Chris Capel (defmacro expand (form &environment e) (list 'quote (macroexpand-1 form e))) (defun get-list-to-expand (list list-indexes) (flet ((recurse () (get-list-to-expand (nth (car list-indexes) list) (cdr list-indexes)))) (if (null list-indexes) (list 'expand list) (let ((sym (find (car list) '(macrolet symbol-macrolet)))) (if sym (list sym (cadr list) (recurse)) (recurse)))))) (get-list-to-expand '(symbol-macrolet ((s a)) s) '(2)) (defun nsubst-list (source substitution list-indexes) (if (null list-indexes) substitution (progn (setf (nth (car list-indexes) source) (nsubst-list (nth (car list-indexes) source) substitution (cdr list-indexes))) source))) (nsubst-list '(a b (c d)) '(e f) '(2 1)) (defun subst-all-tree (tree obj-a obj-b &key (test #'equal)) (mapcar (lambda (i) (if (consp i) (subst-all-tree i obj-a obj-b :test test) (if (funcall test obj-a i) obj-b i))) tree)) (subst-all-tree '(a b (c d)) 'd 'e) (defun expand-part (list &rest list-indexes) (nsubst-list list (eval (get-list-to-expand list list-indexes)) list-indexes)) (expand-part '(macrolet ((x (m) `(y ,m))) (x z)) 2) (expand-part '(let ((x 50)) (destructuring-bind (x y z) f (dolist (q y) x))) 2) ;; or "2 3)" for the dolist