Compiler macro functions and FUNCALL forms.
The compiler macro functions created by CMUCL using DEFINE-COMPILER-MACRO do not correctly handle FUNCALL forms in cases where the compiler macro function returns the input form. This is demonstrated with the following example:
(defun square (x)
(expt x 2))
(define-compiler-macro square (&whole form arg)
(declare (ignore arg))
form)
(funcall (compiler-macro-function 'square) '(square x) nil)
=> (SQUARE X)
(funcall (compiler-macro-function 'square) '(funcall #'square x) nil)
=> (#'SQUARE X)
The cause of this error is due to a bug in the body argument returned by lisp::parse-defmacro.
(nth-value 0 (lisp::parse-defmacro '(&whole form arg) 'my-form '(form)
'square 'define-compiler-macro))
=> (let* ((my-form (if (progn
(not (and (listp my-form)
(eq 'funcall (car my-form)))))
my-form
(progn
(setf my-form (cdr my-form))))))
(unless (lisp::list-length-bounded-p (the list (cdr my-form)) 1 1)
(lisp::do-arg-count-error 'define-compiler-macro
'square
(cdr my-form)
'(&whole form arg)
1
1))
(let* ((form my-form) (arg (car (cdr my-form))))
form))
Consider the case where the above is evaluated in a lexical environment with MY-FORM bound to '(funcall #'square x). The first LET* binds MY-FORM to the value '(#'square x). The second LET binds this value to the &WHOLE symbol specified in the input lambda list to PARSE-DEFMACRO i.e. FORM.
This problem occurs in version "snapshot-2014-12 (20f Unicode)" of CMUCL.
Thanks Mark