[cmucl-imp] define-compiler-macro and funcall forms.

Mark Cox markcox80 at gmail.com
Sun Mar 15 04:26:09 UTC 2015


G'day,

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))

The body above is evaluated in a lexical environment where MY-FORM is
bound to '(funcall #'square x). A new binding of MY-FORM is introduced
by the first LET* in the body above such that MY-FORM is (cdr '(#'square x)).
This value is then bound to the &WHOLE symbol FORM specified in the input
lambda list to PARSE-DEFMACRO.

Thanks
Mark

[1]. http://www.lispworks.com/documentation/HyperSpec/Body/m_define.htm



More information about the cmucl-imp mailing list