Tracing the expansion of external macros
I have improved my trace-macroexpand system so you can say, in effect ‘trace the expansion of only the macros in the interface to a given package’. This is a fairly useful thing.
Tracing macroexpansion in Common Lisp is a pretty useful thing to be able to do, in my experience. It is completely possible to do this in portable CL via *macroexpand-hook*: you simply put your tracing function on this hook, making sure it actually does expand the macro. trace-macroexpand does just this, and lets you specify which macros you want to be traced.
It has always allowed you to say ‘trace all macros whose home package is this package’. That’s less useful than you might think:
- it means that not only macros whose names are exported from the packqge are traced, but any macros in its guts are also traced, which generally a user of the package should not be interested in;
- it doesn’t trace macros which are exported from a package but whose home package is not that package.
Very often the second thing is exactly what you want: you want to be able to say ‘let me see the expansion of macros in the public interface to this package, but I don’t care about the internal details of it’.
It can now do exactly that.
trace-macro-package now takes a list of package specifiers. If a package specifier is a list of one or more other package specifiers, then it changes their meaning to be ‘trace the exports of these packages only’.
Here is an example:
> (find-symbol "FOR" :org.tfeb.star)
for
:external
> (symbol-package *)
#<The ORG.TFEB.STAR/IMPL package, 188/512 internal, 6/16 external>
> (trace-macroexpand t)
nil
> (setf *trace-macroexpand-per-line-prefix* "| ")
"| "
> (trace-macro-package :org.tfeb.star)
("ORG.TFEB.STAR")
> (for ((_ (in-naturals 10))))
nil
> (untrace-macro-package :org.tfeb.star)
nil
> (trace-macro-package '(:org.tfeb.star))
(("ORG.TFEB.STAR"))
> (for ((_ (in-naturals 10))))
| (for (#))
| -> (multiple-value-bind (#:<v>) 0 ...)
nil
As well as this, both trace-macro-package and untrace-macro-package now canonicalise the specifiers they are given, which means, for instance that (trace-macro-package '("FOO" "BAR")) is exactly the same as (trace-macro-package '("FOO") '("BAR")): this means that things like
> (trace-macro-package '("FOO" "BAR"))
[...]
> (untrace-macro-package '("FOO"))
will work properly.
This change is in version 10.9.0 of the TFEB.ORG Lisp hax, git repo.