7

John Fremlin's blog: The output of compiler-macros is compiler macroexpanded

 2 years ago
source link: http://john.freml.in/lisp-compiler-macroexpand-wrong
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Posted 2009-07-26 07:22:00 GMT

A compiler macro (from define-compiler-macro) is a way of hooking into a normal function call at compile time, for example, to precompute something if the arguments are constants. As one would expect, the result of a compiler macro is compiler macroexpanded on SBCL.

Unfortunately, about two years ago I managed to wrongly get it into my head that SBCL did not compiler macroexpand the output of compiler macros. I have been running around telling everybody at work, and generally spreading misinformation about it ever since. The culmination of this stupidity was standing up and asserting it in a presentation to what felt like a hundred people and now that realise I said something so foolish, feels like more.

To be clear, the only case where SBCL does not compiler macroexpand the output of a compiler macro is when the output is eq to the input, i.e. if the compiler-macro did nothing. I was completely wrong. I'm very sorry about it as it is just the sort of FUD that I hate.

Many thanks to Luis Oliveira for extremely politely giving me a test case showing I was barking up the wrong end of the tree way off in cloud cuckoo land.

One issue, which possibly is the inspiration for my confusion, is that you may want to do the compiler-macroexpansion of your input. This makes perfect sense.

Maybe this is a nice way of doing it, as it plays well with the *macroexpand-hook*.

(defun compiler-macroexpand-1 (form &optional env)
  (let ((cm (and (listp form) (compiler-macro-function (first form) env))))
      (if cm
	  (funcall *macroexpand-hook* cm form env)
	  form)))
  
(defun macroexpand-and-compiler-macroexpand (form &optional env)
  (loop 
	for last-form = form then next-form
	for next-form = (compiler-macroexpand-1 (macroexpand last-form env) env)
	until (eq next-form last-form)
	finally (return next-form)))

The cl-irregsexp library used to define macros instead of compiler macros (in defun-consistent). This is now fixed to use compiler-macros.

Many thanks to Luis for setting me straight, and my humblest apologies to anybody who was misled by my utterly misguided confusion.


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK